This file provides guidance to AI coding agents when working with code in this repository.
Personal dotfiles repository using GNU Stow for symlink management. Supports macOS and WSL (Windows Subsystem for Linux) with platform-aware configuration.
# Install dotfiles to $HOME (default)
bash ./install.sh
# Options:
# --dry-run Show stow actions without applying
# --verbose Verbose stow output
# --no-restow Use stow (not --restow)
# TARGET_DIR=/custom/path ./install.sh # Custom target directoryThe install script auto-detects platform (macOS/WSL) and stows appropriate packages.
# Format files (Lua, brew-formulae.txt)
make format # or make format-lua, make format-brew-formulae
# Lint shell scripts
make lint # or make lint-shell
# Run tests
make test # or make test-batsCode conventions:
.editorconfigenforces:- UTF-8 charset, final newlines, trim trailing whitespace (all files)
- 4-space indentation (default, explicitly set for Lua)
- Tab indentation (Makefiles only)
- Shell scripts and Lua files use vim foldmarkers (
# vim: foldmethod=markerwith{{{/}}}sections)
Each tool lives in its own directory (e.g., fish/, neovim/, git/). When stowed, files are symlinked to $HOME preserving their relative paths.
Example:
fish/.config/fish/config.fish→~/.config/fish/config.fishgit/.config/git/config→~/.config/git/config
Common packages (always installed):
- agents - Universal AI agent instructions (AGENTS.md)
- bash - Bash shell configuration (.bashrc, .bash_profile, .inputrc)
- bat - Cat clone with syntax highlighting
- dircolors - Color scheme for ls/directory listings
- editorconfig - Cross-editor configuration (.editorconfig)
- fish - Interactive shell (primary shell)
- git - Version control configuration with aliases and platform-specific includes
- neovim - Primary editor with LSP, tree-sitter, and native plugin management
- tmux - Terminal multiplexer
- vim - Lean fallback editor when Neovim is unavailable
Optional packages:
- claude - Claude Code settings and custom status line script
- gemini - Gemini CLI settings and instructions
- opencode - OpenCode AI agent TUI configuration
- quilt - Debian patch management tool configuration
Platform-specific packages:
- macOS: kitty (terminal emulator with theme support), linearmouse (mouse configuration), macos (macOS-specific settings)
- WSL: wsl (WSL-specific configuration)
Important architectural principle: Base packages handle cross-platform logic internally via runtime detection. Platform-specific packages (macos/, wsl/) should ONLY contain configuration that cannot be handled cross-platform.
Examples:
- ✅ Homebrew path detection in
fish/.config/fish/config.fish(detects/opt/homebrewvs/home/linuxbrew) - ✅ Git credential helpers in
macos/.config/git/platformandwsl/.config/git/platform(different paths per OS) - ❌ Duplicating Homebrew initialization across base and platform-specific fish configs
General principle: Prefer EditorConfig (.editorconfig) for cross-editor settings like indentation, charset, and whitespace. Use editor-specific ftplugin files only for settings that EditorConfig cannot handle.
claude/.claude/settings.json- Claude Code settings (attribution, theme, editor mode, status line command)claude/.claude/statusline.sh- Custom two-line status line script
The status line displays two lines of context:
- Line 1 (workspace): vim mode indicator, current directory, git worktree, branch, ahead/behind upstream, staged/unstaged/untracked/deleted file counts, line insertions/deletions vs HEAD
- Line 2 (session): model name, session name, cost with lines added/removed,
context window percentage (color-coded: waveAqua1 < 60%, roninYellow ≥ 60%,
samuraiRed ≥ 80% — thresholds account for the ~33k autocompact buffer) with
a warning icon (
⚠️ ) at ≥ 80%, cumulative session token count (compact k/M format)
Colors use the Kanagawa Wave palette (24-bit ANSI). Git status colors mirror the palette's designated diff colors: autumnGreen (staged/added), autumnYellow (modified), autumnRed (deleted), springViolet1 (untracked).
GEMINI.md- Root-level instructions that importAGENTS.mdto guide the Gemini agentgemini/.gemini/settings.json- Gemini CLI settings (theme, editor mode)gemini/.gemini/GEMINI.md- Package-level instructions importingAGENTS.md
- Base config:
git/.config/git/config - Platform-specific config included via
[include] path = platform - Platform files:
macos/.config/git/platform,wsl/.config/git/platform - Work-specific config:
[includeIf "gitdir:~/work/"] path = work core.hooksPath = ~/.config/git/hooksapplies hooks globally to all reposgit/.config/git/hooks/commit-msg- Thin wrapper invokingformat-commit-msg.shgit/.config/git/hooks/format-commit-msg.sh- Validates and formats commit messages: rejects empty subjects, subjects over 72 characters, uncapitalized subjects, and missing blank lines between subject and non-comment body; git template comments directly after the subject are treated as an empty body (blank separator auto-inserted); wraps body lines greedily at 72 characters usingfmt -w 72 -g 72
Uses Neovim's built-in package manager (vim.pack.add()).
Modular Lua structure in neovim/.config/nvim/:
init.lua- Entry point that requires moduleslua/config/- Core configuration (options, keymaps, autocmds, plugins, LSP, diagnostics, platform)lua/config/plugins.lua- Plugin specifications loaded viavim.pack.add()(UI, editor, filetype support, tree-sitter, LSP, linting)ftplugin/- Filetype-specific settingscolors/- Color scheme files
Key plugins auto-update tree-sitter parsers via PackChanged hook when nvim-treesitter is installed/updated.
Platform-specific logic in lua/config/platform.lua.
Philosophy: Vim serves as a lean, reliable fallback when Neovim is unavailable.
Configuration principles:
- Backport essential features from Neovim (fuzzy completion, enhanced cursor restoration, auto-create directories)
- Use simple defaults - avoid complex plugin configurations (e.g., no custom theme settings for lightline)
- Prefer EditorConfig for language-specific settings over ftplugin files
- Remove unused language configs - don't maintain ftplugin files for languages not actively developed
- Auto-create directories - backup/undo directories created at runtime instead of tracking empty directories via Stow
- Custom colorscheme - Uses
dim-ansi(Nord theme is no longer maintained)
Structure:
.vimrc- Single file configuration with vim-plug for plugin managementftplugin/- Minimal filetype settings (gitcommit, gitconfig, mail only)colors/- Custom color schemes
- Main config:
fish/.config/fish/config.fish - Organized with vim foldmarkers for sections
- Platform detection for Homebrew paths (
/opt/homebrewvs/home/linuxbrew/.linuxbrew) - Tool initialization: pyenv, fnm (Fast Node Manager), dircolors, keychain
This project requires a scope prefix on every commit — the global guidelines make prefixes optional, but here they are mandatory.
Format:
<scope>: <subject>
[optional body, each line max 72 characters]
Scope: Stow package name for changes within a package (neovim, fish, git, vim, opencode, etc.) or filename for root-level files (AGENTS.md, Makefile, install.sh, etc.).
Examples:
opencode: Encourage thoughtful recommendations from AI agents
AGENTS.md: Document Vim as lean fallback and EditorConfig preference
neovim: Remove Go ftplugin
git: Add platform-specific credential helper configuration
Configures osxkeychain for macOS and manager-core for WSL to enable
secure credential storage appropriate to each platform.
Body wrapping and subject validation are enforced automatically by the
commit-msg hook.
Homebrew formulae listed in brew-formulae.txt. Key dependencies:
stow- Required for installationstylua- Lua formattingshellcheck- Shell script lintingneovim- Primary editorfish- Interactive shellpyenv,pyenv-virtualenv- Python version management- Development tools: bat, gh, tree-sitter-cli
After modifying configs:
- Shell scripts:
make lint(runs shellcheck on*.sh) - Lua files, brew-formulae.txt:
make format(runs stylua, sort) - commit-msg formatter:
make test(runs bats tests intests/)