Personal dotfiles for macOS β automated setup for Neovim, Zsh, and Tmux using dotbot.
π Docs: https://klee1611.github.io/dotfiles/
dotfiles/
βββ _scripts/
β βββ init.sh # Install Homebrew packages, Go, Python, Node
β βββ zsh_init.sh # Install oh-my-zsh and plugins
β βββ nvim_cleanup.sh # Remove corrupted Neovim caches
βββ nvim/ # Neovim configuration (Lua)
β βββ init.lua
β βββ lua/
β βββ core/ # options, keymaps
β βββ plugins/ # one file per plugin
βββ tmux/
β βββ tmux.conf # Base config (gpakosz/.tmux)
β βββ tmux.conf.local # Local overrides
βββ zsh/
β βββ aliases # Shell aliases
β βββ zsh_functions # Shell functions
β βββ load_secrets # Keychain secret helpers (secret-set, secret-run, β¦)
β βββ secrets.list # Names of secrets stored in Keychain
βββ website/ # Documentation site (VitePress)
βββ dotbot/ # Dotbot submodule
βββ install.conf.yaml # Symlink manifest
βββ install.sh # Entry point
- macOS
- Homebrew
git clone https://github.com/klee1611/dotfiles.git
cd dotfiles
./install.shThis will:
- Install Homebrew packages (
git,nvim,nvm,pyenv,pnpm,asdf,curl,wget,ripgrep,pipx,uv) - Install gvm and Go 1.25.7 (binary install) as the default
- Install Python 3.10.0 via pyenv as the global version
- Set up oh-my-zsh with plugins
- Symlink all config files via dotbot
Then restart your shell:
source ~/.zshrc| Symlink | Source |
|---|---|
~/.zshrc |
zshrc |
~/.config/zsh/ |
zsh/* |
~/.config/nvim/ |
nvim/* |
~/.tmux.conf |
tmux/tmux.conf |
~/.tmux.conf.local |
tmux/tmux.conf.local |
Shell framework: oh-my-zsh
Plugins: zsh-completions, zsh-syntax-highlighting, zsh-autosuggestions, git, autojump, asdf
Startup optimizations:
HOMEBREW_PREFIXdetected via path check β nobrew --prefixsubprocess- NVM default node version prepended to
PATHdirectly from$NVM_DIR/alias/defaultβ node is available to all processes (including nvim plugins) without sourcing nvm.sh nvmcommand lazy-loads full NVM shell integration on first usepyenvshims prepended toPATHdirectly β noeval "$(pyenv init --path)"subprocess- GVM lazy-loaded on first use of
gvmorgo
Editor: vi, vim, $EDITOR, $VISUAL all point to nvim
Static API tokens live in macOS Keychain and are handed to one command at a time. Nothing is exported into your shell, nothing is written to files, and values are never passed as command arguments.
zsh/secrets.list (committed) lists only the names you expect to have stored.
Where a CLI has a login flow, use it β there is no long-lived secret to store or leak:
| Service | Login |
|---|---|
| Claude Code / Avante | claude login |
| AWS | aws configure sso once, then aws sso login (short-lived credentials) |
| Google Cloud | gcloud auth login and gcloud auth application-default login |
Only tokens with no login flow (e.g. KAGGLE_API_TOKEN) belong in secrets.list.
secret-set KAGGLE_API_TOKEN # prompts for the value (hidden, with confirmation)secret-run KAGGLE_API_TOKEN -- python train.pyOnly that command (and what it starts) sees the token. Each read shows a macOS
Keychain dialog asking for your login password β choose Allow, not
Always Allow (that re-trusts security and makes reads silent again).
Only approve a dialog right after running something that needs a secret.
| Command | Description |
|---|---|
secret-set VAR |
Store or replace a secret (prompts; never pass the value inline) |
secret-run VAR... -- cmd |
Run one command with those secrets in its environment |
secret-get VAR |
Print a secret's value |
secret-del VAR |
Remove a secret from Keychain |
secret-list |
Show which tracked secrets are stored (never reads values) |
To add a token, append its name to zsh/secrets.list and run secret-set once.
Based on gpakosz/.tmux. Customizations in tmux/tmux.conf.local:
| Keybinding | Action |
|---|---|
Ctrl+b / Ctrl+a |
Prefix (either works) |
prefix h j k l |
Move between panes |
prefix - / | |
Split top-bottom / side-by-side |
prefix n / p |
Next / previous window (p restored from the base config's paste) |
prefix P |
Choose a buffer to paste |
Mouse support and vi copy mode are enabled. Selection is copied to the system clipboard via pbcopy.
Plugin manager: lazy.nvim
Leader key: ,
| Key | Action |
|---|---|
F2 |
Toggle file explorer (nvim-tree) |
F3 |
Toggle code outline (aerial) |
,f |
Refresh file explorer |
,n |
Find current file in explorer |
,ff |
File browser (Telescope) |
,fg |
Live grep (Telescope) |
,fb |
Buffers (Telescope) |
,fh |
Help tags (Telescope) |
,t |
Open terminal in split |
Ctrl+β / β |
Increase / decrease split height |
Ctrl+β / β |
Increase / decrease split width |
tc / tn / tp / tk |
New / next / previous / close tab |
t1βt9, t0 |
Jump to tab 1β10 |
| Plugin | Purpose |
|---|---|
| lazy.nvim | Plugin manager |
| mason.nvim | LSP/DAP/formatter/linter installer |
| nvim-lspconfig | LSP server configs (basedpyright, gopls, lua_ls, β¦) |
| nvim-cmp | Completion engine |
| nvim-treesitter | Syntax highlighting |
| conform.nvim | Formatting (prettier, stylua, ruff) |
| nvim-lint | Linting (ruff, mypy, eslint_d) |
| nvim-dap | Debugger |
| telescope.nvim | Fuzzy finder |
| nvim-tree | File explorer |
| aerial.nvim | Code outline |
| diffview.nvim | Git diff viewer |
| copilot.lua + copilot-cmp | GitHub Copilot in completion |
| avante.nvim | AI sidebar; drives Claude Code over ACP |
nvim/lua/plugins/ai.lua points avante.nvim
at the local Claude Code CLI over ACP (Agent
Client Protocol), so the sidebar runs the same agent as the claude terminal β
same tools, same session history, same claude login credentials. No
ANTHROPIC_API_KEY required.
Prerequisite (once):
npm install -g @agentclientprotocol/claude-agent-acp
claude login # if you have not already| Key | Action |
|---|---|
,aa |
Ask β open the sidebar and prompt Claude Code |
,an |
New conversation |
,at |
Toggle the sidebar |
,af |
Focus the sidebar |
,az |
Zen mode (full-screen, CLI-like) |
,ae |
Edit the visual selection in place |
,aS |
Stop the running agent |
,ar |
Refresh the sidebar |
,ac |
Add the current buffer as context |
,aB |
Add all open buffers as context |
,ah |
Browse conversation history |
,aM |
Pick the Claude Code model |
,am |
Pick the permission mode (default, acceptEdits, plan, auto, bypassPermissions) |
,aC |
Toggle selection hints |
,as |
Toggle inline suggestions |
,ad |
Toggle debug output |
,aR |
Toggle the repo map |
Inside the sidebar:
| Key | Action |
|---|---|
<CR> / Ctrl+s |
Submit (normal / insert mode) |
Tab / Shift+Tab |
Switch between input and response windows |
Shift+Tab |
Expand a tool-use block |
A / a |
Apply all diffs / apply diff at cursor |
r / e |
Retry / edit your last request |
@ / d |
Add / remove a context file |
x |
Toggle the code window |
q |
Close the sidebar |
Reviewing the diffs Claude produces:
| Key | Action |
|---|---|
]x / [x |
Next / previous conflict |
co / ct |
Keep ours / theirs |
ca / cb / cc |
Keep all theirs / both / the block at the cursor |
:AvanteSwitchProvider claude falls back to the plain Anthropic HTTP API
(needs ANTHROPIC_API_KEY β run secret-set ANTHROPIC_API_KEY and paste it at
the prompt; Avante reads it from Keychain on demand);
:AvanteSwitchProvider claude-code returns to ACP.
nvim # lazy.nvim installs all plugins automaticallyThen install LSP servers, formatters, and linters:
:MasonMason fails to install gopls:
go version # should show go1.25.7
go install golang.org/x/tools/gopls@latestTreesitter parser errors:
./_scripts/nvim_cleanup.sh
nvim # reinstalls parsers on next launchMIT
If you find this project helpful, consider supporting its development:
Or visit: https://www.buymeacoffee.com/klee1611
Happy coding! π
