Project-specific instructions for Claude Code working on this dotfiles repository.
GNU Stow-managed dotfiles. Each top-level directory is a stow package that
symlinks into $HOME via stow <package> from the repo root.
_agents/ → Shared agent skills, linked into ~/.agents/skills by _install/ (not a stow package)
_docs/ → Documentation and screenshots (not a stow package)
_images/ → Docker build files: nvim/, devenv/, devenv-web/ (not a stow package)
_install/ → Setup scripts (not a stow package)
_macOS/ → macOS system settings scripts (not a stow package)
_planning/ → Project planning docs (not a stow package)
asdf/ → asdf version manager plugins
brew/ → Split Brewfiles (Brewfile.00-taps … Brewfile.90-mas, not a stow package)
claude/ → ~/.claude/ (Claude Code user config, MCP servers)
clauth/ → ~/.clauth/ (multi-account manager for Claude Code; NOT stowed —
copied like claude/settings.json, see clauth/AGENTS.md)
cursor/ → Cursor editor config
ghostty/ → ~/.config/ghostty/ (terminal emulator)
git/ → ~/.config/git/ + ~/.gitconfig
herdr/ → ~/.config/herdr/ (AI agent multiplexer)
hunk/ → ~/.config/hunk/ (review-first diff viewer)
k9s/ → ~/.config/k9s/ (Kubernetes TUI)
lazygit/ → ~/.config/lazygit/
nvim/ → ~/.config/nvim/ (NeoVim)
obsidian/ → Obsidian vault structure
opencode/ → ~/.config/opencode/ (AI coding agent)
tmux/ → ~/.config/tmux/
tuicr/ → ~/.config/tuicr/ (code-review TUI)
worktrunk/ → ~/.config/worktrunk/ (wt — git worktree manager)
zed/ → ~/.config/zed/ (Zed editor)
zsh/ → Zsh shell config (conf.d/, functions/, themes/)
- Language: English for all commits, comments, and documentation
- Commits: Conventional Commits with gitmoji prefix
- Format:
<gitmoji> <type>(scope): <description> - Scopes match package directories:
zsh,nvim,zed,brew,git, etc.
- Format:
- Stow:
~/.stow-global-ignorehandles .git, .DS_Store, README, LICENSE, AGENTS.md, CLAUDE.md. Package-specific ignores go in.stow-local-ignore.
Detailed rules live in each package's AGENTS.md:
| File | Scope |
|---|---|
brew/AGENTS.md |
Brewfile changes and cross-package sync obligations |
zsh/AGENTS.md |
Zsh config structure, atuin stats maintenance |
nvim/AGENTS.md |
NeoVim config, keybindings, cross-sync with Zed |
zed/AGENTS.md |
Zed editor config, keybindings, cross-sync with NeoVim |
claude/AGENTS.md |
Claude Code settings.json copy/sync (not symlinked) |
clauth/AGENTS.md |
clauth profiles.toml copy/sync, guardrails, git pin |
Both justfile and Makefile expose identical targets. When adding or modifying
a target, always update both files. The Justfile is the primary interface;
the Makefile is the universal fallback for environments without just.
Run just --list or make help to verify targets match after changes.
The brew/ directory is not a stow package — it contains split Brewfile
source files that are concatenated into ~/.Brewfile at shell startup.
zsh/conf.d/00-init.zshsetsHOMEBREW_BUNDLE_FILE=~/.Brewfilezsh/conf.d/15-brew.zshregenerates~/.Brewfilefrombrew/Brewfile.*when any source file is newer (runs on every new shell, fast no-op otherwise)- All
brew bundlecommands work without--fileflags
Taps (00) must come first. Add new tools to the matching category file.
See brew/AGENTS.md for the full file list and sync obligations.
| Command | Description |
|---|---|
brew bundle |
Install all packages (uses ~/.Brewfile automatically) |
brew bundle check |
Show missing packages |
brew bundle cleanup |
Show packages not in Brewfile |
just brew-install |
Regenerate + install |
just brew-dump |
Dump installed packages for comparison |
The Docker devenv image (_images/devenv/Dockerfile) mirrors the macOS CLI
environment as closely as possible. It uses a multi-stage build:
- Brew stage: COPYs
brew/Brewfile.*into ahomebrew/brewbuilder, extracts allbrewformulae, filters out packages listed inbrew/docker-exclude, then installs everything. The entire/home/linuxbrew/.linuxbrewprefix is carried over to the final image (no patchelf — scripts, Python tools, and runtimes all work natively). - Final stage: Based on
snic/nvim, adds the Homebrew prefix toPATH, then layers zsh, tmux, dotfile configs, and TUI tool themes.
When adding a new CLI tool, just add it to the matching Brewfile.*. It will
automatically be included in the next Docker build. To exclude a formula from
Docker (macOS-only, hardware-dependent, or too large), add it to
brew/docker-exclude.
Rust crates are inventoried in two places, and the split is a rule, not a preference:
- A Homebrew formula exists → the crate belongs in
brew/Brewfile.*(currentlycargo-binstall,cargo-edit,cargo-nextest,cargo-zigbuildinBrewfile.20-dev-tools). Only then canbrew bundle cleanupaccount for it. - No formula exists → declare it in
_install/cargo-tools.list, one crate per line,crate@1.2.3to pin._install/cargo-tools.shinstalls from that manifest viacargo binstall(prebuilt binary) and falls back tocargo installwhen no artifact matches.
Always run brew info <crate> before adding to the list — the manifest is for
the remainder, not the default.
_install/rust.sh installs no cargo tools; it only sets up rustup,
toolchains, and components. That separation exists because the old imperative
cargo install lines in it silently drifted — none of the three tools they
claimed to install were ever present.
| Command | Description |
|---|---|
just cargo-tools |
Install missing crates from the manifest |
just cargo-tools-update |
Upgrade every unpinned crate |
just cargo-dump |
List installed crates for drift comparison |
update rust |
rustup update + cargo-tools update in one go |
A unified keybindings reference lives at _docs/keybindings.md. When adding,
removing, or changing keybindings in any tool config, always update the
cheatsheet to reflect the change. This applies to:
ghostty/.config/ghostty/config— Ghostty keybindingstmux/.config/tmux/tmux.conf— Tmux bindings and popup launchersnvim/.config/nvim/lua/config/keymaps.lua— NeoVim keymapsnvim/.config/nvim/lua/plugins/*.lua— Plugin-specific keybindingszed/.config/zed/keymap.json— Zed keybindingszsh/conf.d/50-keybindings.zsh— Shell keybindingszsh/conf.d/40-fzf.zsh— FZF keybindingsk9s/.config/k9s/plugins.yaml— K9s plugin shortcuts
The cheatsheet groups shortcuts by tool and includes a cross-tool consistency table at the bottom. Keep it in sync.
Changes in one package often require updates in another. The AGENTS.md in
each package documents these dependencies. Key relationships:
brew/Brewfile.*↔zsh/.config/atuin/config.toml: New CLI tools must be categorized for Atuin shell history stats. Seebrew/AGENTS.md. The split Brewfiles are concatenated into~/.Brewfilebyzsh/conf.d/15-brew.zshon shell startup, sobrew bundleworks without--file.nvim/↔zed/: Keybindings, LSP settings, and formatters should stay in sync. Seenvim/AGENTS.mdandzed/AGENTS.md.