Personal macOS configuration management system with automated dotfiles synchronization, security scanning, and one-command setup/rollback capabilities.
This repository manages configurations for the following applications:
| Category | Application | Config Location |
|---|---|---|
| Shell | Zsh + Oh-My-Zsh | ~/.zshrc, ~/.zsh/ |
| Terminal | Ghostty, iTerm2 | ~/.config/ghostty/config, iterm2/ |
| Editor | Neovim, Vim | via Homebrew |
| Version Control | Git, Tig | ~/.gitconfig, ~/.tigrc |
| Multiplexer | tmux | ~/.tmux.conf |
| Fuzzy Finder | fzf | ~/.fzf.zsh |
| Packages | Homebrew | Brewfile |
| Runtimes | mise | ~/.config/mise/config.toml |
| Launcher | Raycast | raycast/*.rayconfig |
| AI Assistant | Claude Code | ~/.claude/ (settings, hooks, agents, skills) |
Brewfile includes:
- 100+ CLI tools (aws, gh, ripgrep, bat, jq, etc.)
- 40+ GUI applications (Cursor, Ghostty, Arc, Raycast, etc.)
- 80+ VSCode/Cursor extensions
Configuration files reside in this repository and symlink to their standard locations:
~/.zshrc → laptop/zsh/.zshrc
~/.gitconfig → laptop/git/.gitconfig
~/.config/ghostty → laptop/ghostty/config
Why symlinks?
- Git tracks actual content, not just symlink paths
- No specialized tooling required (stow, chezmoi, etc.)
- Easy to understand and debug
- Industry-standard approach
laptop/
├── install.sh # Main installer
├── rollback.sh # Restore from backup
├── Brewfile # Homebrew packages manifest
│
├── zsh/ # Shell configuration
│ ├── .zshrc # Main config (loads below in order)
│ ├── .aliases # Shell aliases
│ ├── functions/ # Custom zsh functions (5)
│ └── configs/ # Modular configs
│ ├── *.zsh # Main configs (color, editor, history, etc.)
│ └── post/ # Loaded last (PATH, completion, mise)
│
├── git/ # Git configuration
│ ├── .gitconfig # Main git config
│ ├── .gitignore # Global gitignore
│ ├── .gitmessage # Commit message template
│ └── .git_template # Git hooks template
│
├── ghostty/ # Ghostty terminal config
├── iterm2/ # iTerm2 settings plist
├── tmux/ # tmux configuration
├── tig/ # Tig (git TUI) config
├── fzf/ # Fuzzy finder config
├── mise/ # mise runtime manager config
├── bin/ # Executable scripts (tat)
├── raycast/ # Raycast settings export
├── claude/ # Claude Code configuration → ~/.claude/
│ ├── CLAUDE.md # User global instructions (Workflow Orchestration, §1–6)
│ ├── settings.json # Hooks, plugins, permissions
│ ├── statusline.sh # Custom status line script
│ ├── loop.md # Default no-arg /loop maintenance routine
│ ├── skills/ # Global personal skills → ~/.claude/skills/
│ └── hooks/ # Lifecycle hooks (7)
│
├── .claude/ # Project-local config (NOT symlinked to ~/.claude/)
│ ├── agents/ # Project agents (1): diagnose-dotfiles (dotfiles-specific)
│ └── skills/ # Local skills (see table in Claude Code Configuration)
│
├── evals/ # Behavioral eval suite (lessons.md-sourced; see evals/README.md)
│
├── tests/
│ └── test-install.sh # Install behavior tests (run by scripts/verify.sh's install-tests gate)
│
├── specs/ # Spec-pipeline artifacts (one dir per spec; see specs/README.md)
│
├── scripts/
│ ├── auto-sync.sh # Manual dotfiles sync script (commit & push)
│ ├── sync-claude.sh # Claude symlink sync + plugin sync
│ ├── sync-claude-plugins.sh # Materialize marketplaces/plugins declared in settings.json
│ ├── verify.sh # Unified check entrypoint (the Closing Gate: shellcheck/pre-commit/symlink/hook-tests)
│ ├── lint-shell.sh # shellcheck wrapper over every git-tracked shell script
│ └── dream.sh # "Dreaming" dry-run: reads session transcripts → lessons.candidate.md (read-only, no apply)
│
├── docs/
│ ├── evals-for-ai-agents.md # Eval methodology — basis for claude/CLAUDE.md §4
│ ├── fable5-vs-opus48.html # Model comparison report (evidence for model routing)
│ ├── claude-code-context-supply-the-boris-way.md # Boris Cherny: context supply notes
│ ├── claude-code-daily-workflow-the-boris-way.md # Boris Cherny: daily workflow notes
│ ├── claude-code-practical-tips-boris-cherny.md # Boris Cherny: practical tips notes
│ └── TODO-routine-plugin-skill-verification.md # TODO: routine/plugin skill verification
│
├── .codegraph/ # CodeGraph index (code intelligence, auto-maintained)
│
├── .github/
│ └── workflows/main.yml # CI/CD (gitleaks + shellcheck)
│
├── .pre-commit-config.yaml # Pre-commit hooks
├── .gitleaks.toml # Secret scanning rules
└── .gitignore # Security-focused ignore patterns
-
Pre-commit Hooks - Runs before every commit:
gitleaks- Scans for secrets and credentialsdetect-private-key- Catches SSH/PGP keystrailing-whitespace,end-of-file-fixer- Code hygiene
-
Comprehensive .gitignore - Blocks 30+ sensitive patterns:
- Environment files (
.env,.secrets.env) - Cloud credentials (AWS, GCP, Azure)
- SSH/GPG keys (
id_rsa*,*.pem) - Terraform state (
*.tfstate,*.tfvars)
- Environment files (
-
Secrets Template - API keys belong in
~/.secrets.env:# ~/.secrets.env (gitignored, created by install.sh) export OPENAI_API_KEY="" export ANTHROPIC_API_KEY="" export GITHUB_TOKEN=""
# Manual gitleaks scan
gitleaks detect --source=. --no-git
# Run all pre-commit hooks
pre-commit run --all-filesSyncing is manual — run scripts/auto-sync.sh yourself whenever you want to
push local config changes. No background agent commits anything automatically.
./scripts/auto-sync.shThe script:
- Regenerates
Brewfilefrom current installations - Runs
gitleaksscan (aborts if secrets detected) - Executes pre-commit hooks
- Commits and pushes changes
Note: This previously ran hourly via a
launchdagent (com.dotfiles.autosync). The agent has been removed;install.shno longer installs it. The script name is kept asauto-sync.shfor continuity but it is invoked manually now.
# Clone repository
git clone https://github.com/snkrheadz/laptop.git ~/ghq/github.com/snkrheadz/laptop
# Run installer
cd ~/ghq/github.com/snkrheadz/laptop
./install.shWhat install.sh does:
- Checks macOS and installs Xcode CLI tools
- Installs Homebrew (if not present)
- Creates timestamped backup of existing configs
- Creates symlinks to repository configs
- Installs all Homebrew packages from Brewfile
- Sets up mise and installs runtimes (Go, Node.js, Python, Ruby)
- Sets up gitleaks + pre-commit hooks
- Creates
~/.secrets.envtemplate
# List available backups
./rollback.sh
# Restore specific backup
./rollback.sh 20231223_120000What rollback.sh does:
- Disables auto-sync launchd agent
- Removes all symlinks
- Restores files from backup
# Dump current installations to Brewfile
brew bundle dump --force --file=Brewfile
# Install packages from Brewfile
brew bundle --file=Brewfilemise manages programming language runtimes (Go, Node.js, Python, Ruby).
| Runtime | Version |
|---|---|
| Go | 1.24.3 |
| Node.js | 25.2.1, 22.16.0 |
| Python | 3.13.x |
| Ruby | 3.4.8 |
# List installed runtimes
mise list
# Install all runtimes from config
mise install
# Install specific runtime
mise use go@1.23.1
# Update to latest versions
mise upgradeEdit mise/config.toml to change versions:
[tools]
go = "1.24.3"
node = "25.2.1"
python = "3.13"
ruby = "3.4.8"Create ~/.zshrc_local for machine-specific settings (automatically sourced, not tracked):
# ~/.zshrc_local
export WORK_PROJECT_PATH="/path/to/work"
alias deploy="./scripts/deploy-work.sh"- Add config file to appropriate directory (e.g.,
tool/.toolrc) - Update
install.shto create symlink:safe_ln "$DOTFILES_DIR/tool/.toolrc" "$HOME/.toolrc"
- Update
rollback.shsymlinks array - Commit and push
The spec pipeline ships as the spec@the-boris-way marketplace pack: it takes a
change from a one-line idea to a mergeable PR through human-approved gates, one phase
per command, favoring observable acceptance criteria and an isolated-context
adversarial review before any PR.
See specs/README.md for the flow diagram and this repo's
artifact layout, and the pack's guide (spec/README.md in snkrheadz/the-boris-way)
for full usage.
1. zsh/functions/* # Custom functions
2. zsh/configs/pre/* # Pre-configs (code exists in .zshrc but directory unused)
3. zsh/configs/*.zsh # Main configs
4. zsh/configs/post/* # Post-configs (PATH, completion, mise)
5. ~/.aliases # Shell aliases
6. oh-my-zsh # Plugins: git, zsh-autosuggestions
- Don't create functions with names that conflict with oh-my-zsh aliases
- Example:
gis already defined by the git plugin
- Example:
- Run
aliasafter installation to check for conflicts
install.sh uses safe_ln() which removes existing symlinks before creating new ones. This prevents circular references when running install.sh multiple times.
This repository manages Claude Code settings via symlinks to ~/.claude/:
claude/
├── CLAUDE.md # User global instructions (Workflow Orchestration, §1–6)
├── settings.json # Hooks, plugins, permissions
├── statusline.sh # Custom status line script
├── loop.md # Default no-arg /loop maintenance routine
├── skills/ # Global personal skills → ~/.claude/skills/ (gcp-cost, memory-vault-sync, unknowns)
└── hooks/ # Lifecycle hooks (7) — each has a *_test.sh suite run by scripts/verify.sh
├── validate-shell.sh # PostToolUse: shellcheck validation
├── cost-alert.sh # Stop: native notification when session/daily cost crosses a threshold
├── notify.sh # Notification: voice cue branched on notification_type (finish vs needs-input)
├── check-pr-base.sh # PreToolUse (Bash): block gh pr create on a stale base
├── check-pr-reviewed.sh # PreToolUse (Bash): block gh pr create without a session code review
├── check-pr-verify-warn.sh # PreToolUse (Bash): warn (never block) if verify.sh wasn't run before gh pr create
└── weekly-maintenance.sh # SessionStart: weekly broken-symlink + repo-drift sweep (detection only)
side-job-researcheris personal → kept machine-local in~/.claude/agents/(not here). Shareable skills AND agents (incl.verify-subagent-result, research pack) live in the snkrheadz/the-boris-way marketplace (core/pm/eng/research/strategy/writing/spec/craft packs); invoked as/<pack>:<skill>or enabled per role via/plugin install <pack>@the-boris-way.
| Component | Description |
|---|---|
CLAUDE.md |
User global instructions (Workflow Orchestration, §1–6) |
settings.json |
Hooks, plugins, permissions |
statusline.sh |
Status line: model, dir+branch, duration, braille bars (ctx/5h*/7d*) — cost/lines moved to cost-alert.sh |
hooks/ |
7 lifecycle hooks (PreToolUse ×3, PostToolUse, Stop, SessionStart, Notification), each with a behavior-test suite |
skills/ |
Global personal skills symlinked to ~/.claude/skills/ (gcp-cost, memory-vault-sync, unknowns) |
| shareable agents | eng/research packs in the snkrheadz/the-boris-way marketplace |
Displays in Claude Code CLI (segments joined by |, conditional ones shown only when data exists):
Opus 4.8 | laptop 🌿main | ⏱ 5m | ctx ⣿⣿⣄ 45% | 5h* ⣄⠀⠀ 12% | 7d* ⣶⠀⠀ 18%
| Segment | Meaning |
|---|---|
Opus 4.8 |
Model display name |
laptop 🌿main |
Current directory + git branch |
⏱ 5m |
Session duration |
ctx ⣿⣿⣄ 45% |
Context window usage (braille bar, green→yellow→red gradient) |
5h* ⣄⠀⠀ 12% |
5-hour rate limit usage — all models combined (* = not Sonnet-only; shown if available) |
7d* ⣶⠀⠀ 18% |
7-day rate limit usage — all models combined (* = not Sonnet-only; shown if available) |
Cost and lines-changed are not shown — they aren't signals for whether to keep trusting the
agent's autonomous run. hooks/cost-alert.sh fires a native notification instead, once per
session, when cost crosses a threshold (defaults: $5 session / $20 daily; see below).
Vim mode and 🤖<agent> (subagent name) segments are appended when active.
| Hook | Lifecycle Event | Description |
|---|---|---|
validate-shell.sh |
PostToolUse | Runs shellcheck on .sh files after Write/Edit |
cost-alert.sh |
Stop | Native notification, once per session, when session/daily cost crosses a threshold (env-overridable, default $5/$20) |
notify.sh |
Notification | Voice cue (say) branched on notification_type: agent_completed announces a finish, auth_success stays silent, everything else keeps "Claude needs input". Fails open (missing jq/say, bad JSON) and always exits 0 |
check-pr-base.sh |
PreToolUse (Bash) | Blocks a gh … pr create invocation on a stale base (origin/<default-branch> not an ancestor of HEAD). Self-syncing blocks like /eng:create-pr pass; Bash-tool calls only; fails open on any anomaly |
check-pr-reviewed.sh |
PreToolUse (Bash) | Blocks a gh … pr create invocation when the session transcript holds no review evidence (ReportFindings / code-review / security-review). Fails open on any anomaly; deliberate skip via CLAUDE_SKIP_REVIEW=1 |
check-pr-verify-warn.sh |
PreToolUse (Bash) | Warns (never blocks — always exits 0) at gh … pr create when the session transcript shows no scripts/verify.sh run. Warning-only by design: verify.sh's "clean" verdict is environment-dependent, so a hard gate would false-block. Fails open silently on any anomaly |
weekly-maintenance.sh |
SessionStart | Weekly (throttled) sweep for broken dotfiles symlinks and repo drift; reports into the session as context, changes nothing |
Every hook has a *_test.sh behavior suite next to it; scripts/verify.sh discovers and runs all of them (claude/hooks/*_test.sh glob — no hand-maintained list).
This repo ships no global agents of its own — shareable agents (including
verify-subagent-result, now in the research pack) live in the
snkrheadz/the-boris-way marketplace.
Project agent (real file in .claude/agents/, this repo only): diagnose-dotfiles.
Personal agents (machine-local real files in ~/.claude/agents/, not dotfiles-managed):
side-job-researcher — mirrors the machine-local side-job-search skill, so it is
neither synced nor published.
Role agents (eng/research) ship via the snkrheadz/the-boris-way marketplace;
enable a pack with /plugin install <pack>@the-boris-way to make its agents available
in every project — e.g. eng provides code-architect, architecture-reviewer,
verify-shell, migration-assistant, oncall-guide, state-machine-diagram,
aws-best-practices-advisor, gcp-best-practices-advisor.
All shareable skills migrated to the snkrheadz/the-boris-way marketplace
(core / pm / eng / research / strategy / writing / spec / craft packs) and are invoked as /<pack>:<skill> after
/plugin install <pack>@the-boris-way — e.g. /eng:test-and-fix,
/eng:refactor-swarm, /core:first-principles.
The .claude/skills/ directory contains the project-specific skills listed below, only available in this repository (not symlinked to ~/.claude/). They are tailored for managing this dotfiles repository; scripts/verify.sh fails when a skill on disk is missing from this table.
| Skill | Description |
|---|---|
brew-manage |
Homebrew package management (add/remove/search, Brewfile update) |
claude-config |
Claude Code configuration (settings.json, hooks, agents, skills) |
dotfiles-rollback |
Backup confirmation and rollback to previous state |
dotfiles-sync |
Manual dotfiles sync (Brewfile update, commit, push) |
git-config |
Git config files (.gitconfig, .gitmessage, .gitignore) |
health-check |
Dotfiles health check (symlinks, configs, dependencies) |
hf-spaces |
HuggingFace Spaces search (research demos, model prototypes) |
mise-runtime |
Runtime management with mise (Go, Node.js, Python, Ruby) |
new-machine-setup |
New machine setup guide (macOS → dotfiles) |
security-check |
Security scanning (gitleaks, pre-commit, secrets) |
symlink-manage |
Symlink status check and repair (broken link detection) |
tmux-config |
tmux configuration (.tmux.conf, keybindings) |
zsh-config |
zsh configuration (functions, configs, aliases) |
Usage: These skills are invoked using slash commands (e.g., /brew-manage, /health-check) when working in this repository with Claude Code.
CodeGraph は tree-sitter で全シンボルを事前解析し SQLite に格納するコード知識グラフです。MCP 経由で Claude Code に提供することで、grep + ファイル読み込みループを 1 回のクエリに圧縮します。
MCP デーモンが稼働中は FS ウォッチャー(FSEvents)が 2 秒デバウンスで自動同期するため、通常は手動操作不要です。
| コマンド | タイミング |
|---|---|
codegraph index |
初回セットアップ後 / .codegraph/ を削除した後 / 完全再構築したいとき |
codegraph sync |
デーモン外(スクリプト等)から差分更新したいとき |
codegraph status |
インデックスの状態確認・未同期ファイルの確認 |
.codegraph/ ディレクトリは .gitignore で除外済みです(マシンローカルなインデックスであり、コミット対象外)。
MIT