The installer resolves the repository from its own path, so it can be run from any directory:
bash /path/to/dotfiles/install.shExisting files that conflict with managed links are moved under ~/.dotfiles-backup/<timestamp>/. Re-running the installer leaves correct links unchanged.
macOS keyboard defaults are intentionally separate from link installation:
bash /path/to/dotfiles/install.sh --macos-defaultsEach shell keeps its complete environment setup in its own login profile. The portable PATH and helper declarations are intentionally duplicated so either profile can be understood on its own. Interactive integrations remain shell-specific:
- Zsh:
.zprofileand.zshrc - Bash:
.bash_profileand.bashrc
Machine-specific paths and secrets can be placed in the untracked file:
~/.config/dotfiles/local.sh
PATH changes are idempotent, so nested shells do not multiply entries.
python and python3 resolve to the same lightweight, locked uv environment when no virtualenv is active. It uses Python 3.14.6 and contains only these direct dependencies:
asyncpghttpxpydanticpython-dotenv
The manifest and lock are tracked in python/. Runtime files live outside the repository under ~/.local/share/dotfiles/python.
The first python invocation creates or synchronizes the environment. It can also be prepared explicitly:
UV_PROJECT_ENVIRONMENT="$HOME/.local/share/dotfiles/python" \
uv sync --locked --project "$HOME/.config/dotfiles/python"After activating a project virtualenv, python and python3 use that environment directly:
createvenv
venv
python -c 'import sys; print(sys.executable)'Use the commands according to their scope:
python/python3— shared lightweight environment, or the active virtualenvuv run python— Python and dependencies from the current uv projectuvx <tool>— isolated CLI tools, for exampleuvx ansible-lint
Heavy ML/data frameworks are intentionally not part of the shared environment.
docker run --rm -it ghcr.io/awnion/dotfilesdocker build -t dotfiles .
docker run --rm -it dotfiles