My $SHELL, mostly bash, works everywhere, *nix, osx, wsl.
The bootstrap script will create symlinks in the home directory to the proper files. The script will also create *.bak files for backups of existing files.
This will by default install dotfiles in the home directory with all options enabled
curl -fsSL https://raw.githubusercontent.com/weikinhuang/dotfiles/master/bootstrap.sh | bash# Additional arguments can be passed to the bootstrap script
curl -fsSL https://raw.githubusercontent.com/weikinhuang/dotfiles/master/bootstrap.sh | bash -s -- [args]You can clone the repository wherever you want, the home (~/) directory is recommended.
Because the installed files are symlinked into your home directory, pulling updates in the repo takes effect in new shells.
# args can be passed to the bootstrap script
git clone https://github.com/weikinhuang/dotfiles.git ~/.dotfiles && ~/.dotfiles/bootstrap.shTo update later on, just run git pull in ~/.dotfiles.
To install or update without git installed, run:
cd; mkdir -p ~/.dotfiles \
&& curl -#L https://github.com/weikinhuang/dotfiles/tarball/master \
| tar -C ~/.dotfiles -xzv --strip-components 1 \
&& ~/.dotfiles/bootstrap.sh| Arg | Description |
|---|---|
--dir PATH |
Change the install directory |
--no-git |
Skip setting up .gitconfig |
--no-vim |
Skip setting up .vimrc and .vim |
- REFERENCE.md — canonical list of every alias, function, env var, and
gitsubcommand added by these dotfiles. - PROMPT.md — prompt format, symbols, and customization options.
- TESTING.md — bats test framework, helpers, and writing conventions.
chpwd,precmd, andpreexechooks with similar behavior to Zshsudoworks on aliasesrmcpmvare always interactive-i(use-fto override)lsandgrepdefault to color when the local implementation supports itwhichexpands aliases and full paths when the local implementation supports itgdiffuses git's diff command with color when possiblepbcopyandpbpastefor cross-platform copy/paste from cli, and optionally over sshopenfor cross-platform open in native applicationchattr,mklink,is-elevated-session,winstart,winsudoWSL tools
Examples:
cd --lists the directory stack (current directory plus up to 10 previous entries)lessdoes not clear the screen upon exit and processes colors- the prompt can render git status when the git plugin is active
See PROMPT.md for configuration options.
To use these variables, export them to ~/.bash_local.
# EXAMPLE
export DOT_AUTOLOAD_SSH_AGENT=1| exported ENV var | Default | Description |
|---|---|---|
BASHRC_NONINTERACTIVE_BYPASS |
UNSET |
Allow bashrc.sh to continue loading in non-interactive shells |
DOT_AUTOLOAD_SSH_AGENT |
UNSET |
When the SSH plugin is enabled, automatically start ssh-agent or reuse an existing agent |
DOT_BASH_RESOLVE_PATHS |
UNSET |
Set Bash option set -o physical to avoid resolving symlink paths |
DOT_DISABLE_EDITOR_AUTODETECT |
UNSET |
Skip autodetecting VS Code, Cursor, or npp as the editor; falls through to nvim/vim (in-terminal VS Code-family detection and the SSH skip are unaffected) |
DOT_DISABLE_HYPERLINKS |
UNSET |
Suppress OSC 8 hyperlinks emitted by ls, eza, rg, fd, and delta |
DOT_DISABLE_PREEXEC |
UNSET |
Skip loading bash-preexec.sh, disabling preexec hooks and command timing features |
DOT_DISABLE_PS1 |
UNSET |
Disable the custom Bash prompt |
DOT_GIT_PROMPT_CACHE_MAX_AGE_MS |
10000 |
Maximum milliseconds to reuse unchanged git prompt status before forcing a refresh |
DOT_GIT_PROMPT_CACHE_TTL_MS |
1000 |
Milliseconds to reuse cached git prompt status before checking the current repo again |
DOT_GIT_PROMPT_INVALIDATE_ON_GIT |
1 |
Set to 0 to disable automatic git prompt cache invalidation after git commands |
DOT_HYPERLINK_SCHEME |
UNSET |
Override the auto-detected editor terminal (e.g. vscode, cursor, vscode-insiders); when set, SSH hyperlink suppression is relaxed since the editor terminal can resolve file:// paths through the remote connection |
DOT_HYPERLINK_SSH_HOST |
UNSET |
Set to your VS Code SSH remote name (e.g. the Host alias in ~/.ssh/config) to enable vscode-remote://ssh-remote+{host} hyperlinks in rg and delta that open files directly in the editor |
DOT_INCLUDE_BREW_PATH |
UNSET |
On macOS with built-in plugins enabled, prepend Homebrew and GNU tool paths and extend MANPATH |
DOT_INCLUDE_BUILTIN_PLUGINS |
UNSET |
Load the full built-in plugins/*.sh set instead of only 00-bash-opts.sh and 00-chpwd-hook.sh |
DOT_PLUGIN_DISABLE_<name> |
UNSET |
Disable one built-in plugin or local .plugin file; leading numeric ordering prefixes are stripped before the disable name is derived |
DOT_SOLARIZED_DARK |
UNSET |
Choose Solarized Dark where theme-aware integrations support it |
DOT_SOLARIZED_LIGHT |
UNSET |
Choose Solarized Light where theme-aware integrations support it |
If ~/.bash_local exists, it will be sourced before the built-ins are sourced. Env vars, configuration vars, and hooks can be placed in this file.
All files ending with .sh located in ~/.bash_local.d are loaded right after ~/.bash_local and before the repo's built-ins. This is a good place to split local environment setup into separate files.
If a file ~/.gitconfig.local exists, it will be included in addition to the built-in git settings. Configurations in this file have the highest priority.
Plugins are scripts that are loaded near the end of the dotfiles initialization process. They usually contain hooks, setup, or configuration for external programs.
By default only plugins/00-bash-opts.sh and plugins/00-chpwd-hook.sh load. Set DOT_INCLUDE_BUILTIN_PLUGINS=1 before startup to load the full built-in plugin set.
See the plugins/ directory for the built-in examples.
Plugins are also loaded from ~/.bash_local.d/ with any file ending in .plugin. Local .plugin files load in the plugin phase and interleave with built-ins by basename.
Example plugin for direnv:
# check if direnv exists
if ! command -v direnv &>/dev/null; then
return
fi
# load direnv program hook
eval "$(direnv hook bash 2>/dev/null)"Specific plugins can be disabled with an environment variable named after the plugin basename without its numeric prefix. Examples: DOT_PLUGIN_DISABLE_direnv=1, DOT_PLUGIN_DISABLE_fzf=1.
Example disable direnv hook:
export DOT_PLUGIN_DISABLE_direnv=1Hooks are available before and after each part of the dotfiles repo is loaded. This allows for customization between steps or overrides at point in time loading. They should be declared in ~/.bash_local or ~/.bash_local.d/*.sh so that they are available by the time the dotfiles are loaded.
Hook points are available before and after the following steps:
aliasescompletionenvexportsextrafunctionspluginprompt
They can be declared as either a single function dotfiles_hook_${PHASE}_{pre,post} or pushed into the arrays dotfiles_hook_${PHASE}_{pre,post}_functions.
Example
# add a hook to run before the "functions" segment is loaded
function dotfiles_hook_functions_pre() {
echo "I'm loading before functions"
export FOO=123
}
# add a hook to run after the "aliases" segment is loaded
function foobar() {
echo "I'm loading after aliases"
alias curl-help="curl --help"
}
# append to array
dotfiles_hook_aliases_post_functions+=(foobar)Setup and configuration of Windows WSL is documented in utils/wsl/README.md.
You can try out this repo in docker easily to test your plugins or hooks.
$ docker run -it --rm -v "$(pwd):/root/.dotfiles:ro" -v "$HOME/.bash_local:/root/.bash_local:ro" -v "$HOME/.bash_local.d:/root/.bash_local.d:ro" -v "$(pwd)/dev/docker-entrypoint.sh:/docker-entrypoint.sh:ro" --entrypoint /docker-entrypoint.sh bash:latest bash
# OR with overrides set locally in the dotfiles repo
mkdir -p bash_local_d_sample
touch bash_local_d_sample/bash_local
$ docker run -it --rm -v "$(pwd):/root/.dotfiles:ro" -v "$(pwd)/bash_local_d_sample/bash_local:/root/.bash_local:ro" -v "$(pwd)/bash_local_d_sample:/root/.bash_local.d:ro" -v "$(pwd)/dev/docker-entrypoint.sh:/docker-entrypoint.sh:ro" -v "$(pwd)/bash_local_d_sample/.bash_history:/root/.bash_history" --entrypoint /docker-entrypoint.sh bash:latest bash
# in the docker shell
$ (cd ~ && .dotfiles/bootstrap.sh)
# install any dependencies you might need, ex.
$ apk add --no-cache coreutils curl git tar nodejs
# start a new shell with the dotfiles loaded, to reload, exit this shell and run this command again
$ env -i PS1=1 TERM="$TERM" PATH="$PATH" HOME="$HOME" SHELL="$SHELL" bash -l
$ CTRL+d
$ env -i PS1=1 TERM="$TERM" PATH="$PATH" HOME="$HOME" SHELL="$SHELL" bash -l
...A Brewfile is included for declaratively managing core Homebrew packages on macOS. Install with:
brew bundle --file=~/.dotfiles/Brewfileshellcheck and shfmt are used to ensure consistency of the scripts in this repo. Files in external/ are excluded since they are third-party. .bats tests are also checked with ShellCheck using its Bats parser.
Validate the codebase locally:
$ ./dev/lint.sh
OKThe loader recognizes the following phase files in dotenv/ and in any active platform-specific subdirectory. Only create the files you need.
| File | Description |
|---|---|
aliases |
bash aliases declared via alias name="some command" |
completion |
bash completion functions for complete |
env |
any additional bash-isms that don't fall in the above category |
exports |
environment vars that are exported via export |
extra |
any additional bash-isms that don't fall in the above category |
functions |
bash function declarations, can be exported via export -f FN_NAME |
prompt |
scripts to generate or modify the prompt vars PS1, PS2, SUDO_PS1 |
Supporting directories:
dotenv/bin/anddotenv/bin.$(uname -m)are added toPATHon all platforms.- Active platform directories can also contribute
bin/andbin.$(uname -m). dotenv/lib/contains internal helpers used by the loader, prompt, and shared shell code.
Supported platform directories:
| Path | Used when |
|---|---|
dotenv/ |
always |
dotenv/darwin/ |
on macOS |
dotenv/linux/ |
on Linux |
dotenv/wsl/ |
on WSL |
dotenv/wsl2/ |
on WSL 2 |
dotenv/tmux/ |
inside tmux |
dotenv/screen/ |
inside screen |
dotenv/ssh/ |
in SSH sessions |
Local overrides load first:
~/.bash_local~/.bash_local.d/*.sh
Then each phase resolves in the following order:
dotenv/*.shdotenv/${DOTENV}/*.shdotenv/wsl/*.shon WSLdotenv/wsl2/*.shon WSL 2dotenv/tmux/*.shin tmuxdotenv/screen/*.shin screendotenv/ssh/*.shover SSH~/.<phase>
Phases run in the following order:
exportsfunctionsaliasesextraenvcompletionwhen Bash completion is availablepluginsprompt
Built-in plugins load only when DOT_INCLUDE_BUILTIN_PLUGINS=1 is set before startup, except for 00-bash-opts.sh and 00-chpwd-hook.sh, which load by default. Local ~/.bash_local.d/*.plugin files load in the plugin phase and interleave with built-ins by basename.