On this page

How Configuration Works

The repo manages application configs through two mechanisms: symlinks for files you edit directly, and templates for files generated from environment variables.

Symlinked Configs

These config files are symlinked from their system location to the repo. Editing either side changes the same file.

Application System Path Repo Path
Zsh ~/.zshrc configs/shell/.zshrc
Starship ~/.config/starship.toml configs/shell/starship.toml
Mise ~/.config/mise/config.toml configs/mise/config.toml
Ghostty ~/.config/ghostty/config configs/ghostty/config
Zed ~/.config/zed/settings.json configs/zed/settings.json
Claude ~/.claude/settings.json configs/claude/settings.json
GitHub CLI ~/.config/gh/config.yml configs/gh/config.yml
btop ~/.config/btop/btop.conf configs/btop/btop.conf
AWS ~/.aws/config configs/aws/config
Colima ~/.colima/default.yaml configs/colima/default.yaml
VS Code ~/Library/Application Support/Code/User/settings.json configs/vscode/settings.json

~/.zshenv is not symlinked. The shell role copies configs/shell/.zshenv.example to ~/.zshenv only on first run (when it does not exist) so each machine keeps its own secrets. The .zprofile that bootstraps Homebrew is generated by the shell role on first run as well.

When the playbook runs, it creates symbolic links so the system path points to the file inside the repo. Because both paths reference the same underlying file:

  • Editing the file in its system location (e.g., ~/.config/ghostty/config) changes the repo copy.
  • Editing the file in the repo (e.g., configs/ghostty/config) changes what the application sees.

To propagate changes to another machine:

Terminal window
# On the machine where you made changes
git add . && git commit -m "update ghostty config" && git push
# On the other machine
git pull && make update

Templated Configs

These files are generated from Jinja2 templates using values from your ~/.zshenv. They are re-rendered on every playbook run, so direct edits will be overwritten.

File Template Source
~/.gitconfig roles/git/templates/gitconfig.j2
~/.config/git-configs/personal.gitconfig roles/git/templates/gitconfig-personal.j2
~/.config/git-configs/work.gitconfig roles/git/templates/gitconfig-work.j2
~/.ssh/config roles/ssh/templates/config.j2

To change these configs, either:

  • Edit the Jinja2 template in the repo, or
  • Change the variable values in ~/.zshenv and re-run make setup

Environment Variables (~/.zshenv)

The ~/.zshenv file is never committed to the repo. It holds personal data that varies per machine and per user. On first run, setup.sh copies .zshenv.example to ~/.zshenv as a starting point.

Required Variables (fill before running setup)

Variable Purpose
GIT_USER_NAME Full name used in git commits
GIT_ORGS CSV of <github-org>:<folder>:<email> triples (first entry = default identity)
SSH_KEY Filename of the single SSH key used everywhere (default: id_ed25519)

The example file also prepends ~/.local/share/mise/shims to PATH so mise-managed runtimes (Node, Python, Java, Bun, etc.) are visible to GUI apps and login shells.

Variable Purpose
GIT_ORGS CSV of <github-org>:<folder>:<email> triples. First entry is the default identity.

Example:

Terminal window
export GIT_ORGS="sujeet-pro:~/personal:sujeet@personal.com,Quince-Engineering:~/work:sujeet@quince.com"

Optional Variables (configure later)

Secret env vars all carry the _CRED suffix and live in per-service files under $CREDS_HOME/<svc>/creds.sh — never in ~/.zshenv. Non-secret per-service config lives next to them in $CREDS_HOME/<svc>/config.sh. Both are auto-sourced by $CREDS_HOME/loader.sh (which ~/.zshenv sources at the end). The currently-configured services are: anthropic, atlassian, datadog, github, google, looker, mixpanel, npm, okta, slack, snowflake, statsig.

See configs/creds/README.md for the layout and the per-service env-var matrix.

Multi-org Separation

Git is configured with conditional includes based on directory path and remote URL — driven entirely by GIT_ORGS:

Directory-based matching

Each GIT_ORGS entry maps one folder to one identity. Any repo under that folder uses the org’s email automatically.

Remote URL-based matching

The same identity also applies to repos cloned outside the mapped folder, as long as the remote URL matches github.com:<org>/... (SSH or HTTPS). This means you never have to remember to switch git identities.

How it works

The first GIT_ORGS entry is the default identity used for repos that don’t match any folder or remote. The per-org overrides are emitted as ~/.config/git-configs/<org>.gitconfig and loaded via includeIf in ~/.gitconfig.