Skip to content

Repository files navigation

dotfiles

One repo for the whole machine: a Nix-declared macOS setup (nix-darwin + home-manager flake, Homebrew for casks, a one-shot bootstrap) and portable AI coding-harness configs — shared skills, commands, rules, agents, and settings — provisioned from one source of truth across multiple Claude Code profiles, pi, Devin CLI, and GitHub Copilot CLI.

A personal repo, published so others can borrow the architecture. Paths are hardcoded to one machine — adapt before adopting (see Adopt it).

New Mac quick start

curl -fsSL https://raw.githubusercontent.com/sanketsudake/dotfiles/main/bootstrap.sh -o /tmp/bootstrap.sh
bash /tmp/bootstrap.sh

The script is idempotent: Xcode CLT, Homebrew, and Determinate Nix if missing, clone to ~/personal/dotfiles, one darwin-rebuild switch (packages, dotfile links, macOS defaults; pre-existing files are moved to a timestamped ~/.dotfiles-backup-* dir), harness links, tools, and make doctor. Afterwards run the printed manual steps (gh auth login, atuin login, git lfs install) and open a new terminal. On an existing machine, clone the repo and run make install.

Omarchy (Arch Linux) quick start

curl -fsSL https://raw.githubusercontent.com/sanketsudake/dotfiles/main/bootstrap-omarchy.sh -o /tmp/bootstrap-omarchy.sh
bash /tmp/bootstrap-omarchy.sh

Same repo, same make install, different system layer — see Omarchy host.

Ideas worth stealing

  • One source of truth, many harnesses. A single skills/ tree feeds Claude Code, pi, Devin CLI, and Copilot CLI; edit once, every harness sees it immediately. Devin reads ~/.agents/skills and Copilot reads ~/.copilot/skills; both links point at the same tree, and the same agents/*.md files link into each CLI under the name it expects.
  • Two Claude profiles via CLAUDE_CONFIG_DIR. pclaude / wclaude wrappers keep personal and work accounts isolated while sharing the same skills and rules.
  • Per-resource source tracking. Every skill and agent source lives in one sources.toml manifest; vendored skills are pinned there (repo, subpath, commit) and materialized on install — so an upstream update is one command and a bare clone stays reproducible.
  • Generated catalog, enforced by a doctor. skills/README.md is generated from that metadata; make skills-doctor fails when anything drifts.
  • Guardrails as code, not hope. Extensions for pi confirm before destructive actions, block dirty-repo commits, and protect paths; a PreToolUse safety hook does the same for Claude Code (deny/ask on dangerous shell, secrets, and VCS internals); plugins.txt declares the plugin set and make plugins-check reports drift per profile.
  • Skills are scanned before they land. make skills-scan runs NVIDIA SkillSpector over every skill, skills-fetch/skills-update refuse a skill that fails, and accepted findings carry a reason in skills/.security/skillspector/.
  • Measured, not assumed. make context-budget reports the always-loaded context per session (capped by the doctor), and a SubagentStop/Stop telemetry hook plus make usage-report show spend by agent type × model and cache-hit ratio. CI runs the doctor, catalog, script tests, and the security scan on every push.

Layout

dotfiles/
├── Makefile        # primary interface — every <resource>-<action> target
├── CLAUDE.md       # guide for agents working IN this repo (full Makefile reference)
├── bootstrap.sh    # new-Mac entry point
├── flake.nix       # nix entry point; flake.lock pins nixpkgs/nix-darwin/home-manager
├── nix/            # darwin/ system config (defaults, homebrew) + home/ user env
├── manifests/      # non-brew tools: go-tools.txt, npm-globals.txt, pipx-tools.txt
├── macos/          # deliberately-changed macOS defaults (make macos-apply)
├── packages/       # dotfile sources for $HOME (zsh, git, atuin, btop, gh, bin), linked by home-manager
│   ├── agents/     #   AGENTS.md — global rules shared by Devin CLI + Copilot CLI
│   ├── devin/      #   Devin CLI config.json
│   └── copilot/    #   Copilot CLI settings.json
├── claude/         # Claude Code config, symlinked into both profiles
│   ├── CLAUDE.md   #   shared global user instructions
│   ├── commands/   #   slash commands
│   ├── agents/     #   subagents
│   ├── rules/      #   model routing, git hygiene, delegation
│   ├── scripts/    #   hooks (routing, safety guard, usage telemetry) + statusline
│   └── plugins.txt #   desired-state plugin list
├── skills/         # shared skills for Claude + pi — the source of truth
│   ├── README.md   #   generated catalog — start here
│   └── .security/  #   SkillSpector baselines (accepted findings, with reasons)
├── suites/         # curated skill-suite landing pages
├── pi/             # pi agent config, linked into ~/.pi
└── scripts/        # repo tooling (doctor, drift, resource manager — not symlinked)

make install links skills/ and claude/* into both Claude profiles, pi/ into ~/.pi, and the shared skills, agents, and configs into Devin CLI and Copilot CLI (home-manager out-of-store symlinks) — safe to re-run. Because everything is symlinked, one edit here applies to every profile and both harnesses at once.

What's inside

Skills — browse the catalog (grouped by category, generated from each skill's metadata). Most are authored here; the rest are vendored from pi-skills, cursor-team-kit, anthropics/skills, and the skills.sh ecosystem — each linked to its upstream source at a pinned commit.

Suites — curated skill sets with their own landing pages:

  • Go CI Health — Keep a Go repo’s CI green, fast, and secure
  • Agent-Maintained Hugo Site — Write, illustrate, verify, optimize, and measure a Hugo blog with an agent
  • OSS Maintainer Copilot — Backlog triage, CodeQL remediation, and security advisories for repos you maintain
  • PR Shepherding — Get a pull request from pushed to merged: clean diff, green CI, resolved reviews
  • Second Brain — An Obsidian knowledge base your agent maintains for you

Agents

Agent Purpose
plan-reviewer Pre-execution plan review against the actual codebase; APPROVE/REVISE with evidence.
bulk-mechanic Haiku executor for mechanical, judgment-free batches.
pr-shepherd Drives the push → CI → bot-review loop to green.
skill-auditor Audits a skill directory against this repo's conventions.

Rules

Rule Governs
model-routing.md Cheapest reliable model tier per task, and effort calibration.
git-hygiene.md Staging, commit, and push discipline.
delegation.md When to hand work to the agents above instead of doing it inline.

Plus the shared CLAUDE.md (secrets hygiene, semantic-line-break markdown per sembr.org), the /history command, helper scripts, and pi guardrail extensions vendored from pi-mono.

Adopt it

Prerequisites: git, jq (plus gh / python3 / npx for the skills that use them).

git clone https://github.com/sanketsudake/dotfiles.git
cd dotfiles
# Before installing:
#   1. Edit CLAUDE_CONFIG_DIRS in the Makefile (your profiles)
#   2. Copy the pclaude/wclaude snippets from scripts/claude-multi-account.sh into your shell profile
#   3. Make claude/CLAUDE.md yours — it's opinionated
#   4. Review nix/, manifests/, and packages/ — they describe one person's machine
make install      # nix-switch (packages + dotfiles + defaults + harness links) + skills-materialize + tools
make skills-list  # see each skill's source and status

make uninstall reverses it.

Working with it

Everyday targets — CLAUDE.md carries the full <resource>-<action> reference, and every skills-* target has an agents-* twin.

Target Does
install / uninstall Apply the declared system and links, or reverse it.
skills-find / skills-add Discover skills on skills.sh and vendor them.
skills-catalog / skills-doctor Regenerate the catalog / validate every skill and its freshness.
skills-update[-all] Re-fetch vendored skills whose upstream moved.
plugins-check / plugins-sync Report plugin drift per profile / emit the /plugin install lines.

Two gotchas: vendored skills/ and packages/pi/extensions/ are overwritten on re-sync — diverge intentionally and note it durably; and use SUBPATH=, never PATH=, on fetch targets (the latter clobbers the shell PATH). Plugin installation stays manual per profile — Claude Code has no headless /plugin install.

Plan review with Plannotator

Plannotator opens each Claude Code plan in Helium before Claude may leave plan mode. It has three parts, pinned to the same release: the binary (nix/home/plannotator.nix), the plannotator@plannotator plugin that adds the ExitPlanMode hook (first run /plugin marketplace add backnotprop/plannotator), and the vendored plannotator-review, plannotator-annotate, and plannotator-last skills. The nix wrapper selects Helium, keeps the server on 127.0.0.1, and turns off share links and AI features; set a PLANNOTATOR_* variable in the environment to override one.

The review loop:

  1. Claude runs plan-reviewer, then calls ExitPlanMode; Helium opens the plan.
  2. Annotate — delete, comment, labels, global comments, or direct edits — then click Send Feedback.
  3. Claude revises and resubmits. The +N/-M badge shows the diff; the Version Browser compares any earlier version.
  4. Repeat. Click Approve only when nothing needs action: Approve drops unsent notes and sets the session permission mode (select auto in the first-run dialog).

Also: /plannotator-review [PR URL] for code review, /plannotator-annotate <file> for a Markdown file, /plannotator-last for Claude's last reply, and plannotator archive for past decisions. These three skills work in Claude Code only: they use its !`command` injection, so pi, Devin, and Copilot see them as inert text.

Machine setup

Target Does
install nix-switch + harness links + tools-install
nix-switch / nix-build Apply the whole declared system / build-only preview
nix-check / nix-fmt Flake check + statix lint / format the nix files
nix-update Bump flake.lock; review the diff like a Brewfile re-curation
nix-rollback Switch back to the previous system generation
tools-install go-install + npm-install + pipx-install from manifests/
brew-check Verify installed brew state against the nix-generated brewfile
brew-dump Regenerate gitignored Brewfile.dump to diff against nix/darwin/homebrew.nix
cask-adopt Take over apps installed outside brew (pkg casks prompt for sudo)
macos-apply Run macos/defaults.sh (Helium-only; system defaults live in nix)
doctor Run all health checks
drift Report divergence between recorded config and the live system, both directions
raycast-export Open Raycast's encrypted settings export; save the file privately (never committed)

The nix model

The machine is declared once and applied with make nix-switch: flake.nix pins nixpkgs, nix-darwin, and home-manager in flake.lock, nix/darwin/ declares the system (macOS defaults, and every brew/cask/mas/vscode entry via the homebrew module), and nix/home/ declares the user environment (dotfile links and CLI packages). Dotfile sources stay in packages/ with their dot- names; home-manager links each file individually into $HOME, so ~/.config/<tool> stays a real directory and credential files written beside managed configs (e.g. gh's hosts.yml) can never land in the repo — the old --no-folding invariant, kept. Never declare files from credential-bearing dirs (gcloud, 1Password, op, github-copilot) or credential-bearing files (gh/hosts.yml, ~/.copilot/config.json). Every switch is a numbered generation; make nix-rollback returns to the previous one. Homebrew remains for casks/taps/mas (declared in nix/darwin/homebrew.nix, applied by the same switch, cleanup = "uninstall": an undeclared install is removed on the next switch — promote keepers first).

Two rules with no exceptions: flakes only see git-tracked files, so git add new .nix files before building; and never let home-manager own a directory that holds mutable files.

Omarchy host

A Linux laptop running Omarchy is a homeConfigurations."<user>@<hostname>" entry (mkHomeHost in flake.nix, host module in nix/hosts/): standalone home-manager on top of the distro, not NixOS and not a system module. The split is deliberate:

  • Nix (Determinate installer, as on the Mac) owns the user CLI set in nix/home/packages.nix and every dotfile/harness link — the same modules the Mac uses. Mac-only packages sit behind pkgs.stdenv.hostPlatform.isDarwin; targets.genericLinux.enable supplies the non-NixOS session glue.
  • pacman/yay and Omarchy own the kernel, drivers, Hyprland and the desktop, GUI apps, docker, and the login shell. manifests/arch-packages.txt (make pacman-install) declares the few system packages this repo needs, starting with zsh.
  • mise keeps Omarchy's claude/codex/gh CLIs, but not Node.js: node comes from nix on both hosts, so run mise rm -g node after an Omarchy install (and after omarchy-install-dev-env, which adds it back); 05-omarchy.zsh activates it ahead of the nix profile and ports the rest of Omarchy's bash rc (env bootstrap, editor/browser exports, starship, eza aliases). The module is a no-op on macOS.

Omarchy-owned paths are never linked over: ~/.config/hypr and the desktop, ~/.config/git/config (Omarchy writes it; ~/.gitconfig wins), and btop.conf (its theme switcher repoints color_theme) — dotfiles.omarchy = true skips btop and the macOS-only bin/ helpers. The exception is Omarchy's personal-override file ~/.config/hypr/input.lua (Num Lock off at login), linked per file into the store by nix/home/omarchy.nix (edits apply on make nix-switch), which also runs the lock-keys-osd user service: an Omarchy OSD whenever Caps Lock or Num Lock changes. Omarchy also seeds ~/.agents/skills with its own skills, so there the skills are linked per skill (names from sources.toml, plus Omarchy's omarchy and diagnose-crash) into a directory that stays real; a newly fetched skill shows up after the next make nix-switch. The Claude profiles are per host too (dotfiles.claudeProfiles); the laptop has only ~/.claude-personal, and plain claude goes straight to it.

make nix-switch runs the flake-pinned home-manager (switch -b hm-backup), make nix-build previews, and nix run .#home-manager -- generations lists what to roll back to. CI evaluates every homeConfigurations entry alongside the darwin hosts.

Harness links

The harness targets (~/.claude-*, ~/.pi, ~/.agents, ~/.config/devin, ~/.copilot) are home-manager out-of-store symlinks into the repo working tree (nix/home/harness.nix) — the linked content stays mutable, so vendored skills materialize in place and repo edits apply live. ~/.pi/agent, ~/.pi/extensions, and the Devin/Copilot agent dirs link per-file on purpose: those tools write state beside them, and a whole-dir link would let a tool write into the repo.

Devin CLI reads personal skills from ~/.agents/skills; Copilot CLI 0.0.417 scans ~/.copilot/skills (plus ~/.claude/skills and the project dirs) and does not look at ~/.agents/skills yet. Each CLI therefore gets its own link to the same skills/ tree — the paths never collide, so no skill is discovered twice. The subagents in packages/claude/agents/ link into ~/.config/devin/agents/<name>.md and ~/.copilot/agents/<name>.agent.md — same file, two names. Global always-on rules come from packages/agents/AGENTS.md, linked as ~/.config/devin/AGENTS.md and ~/.copilot/copilot-instructions.md. Of each CLI's own config, only the user-editable file is managed (~/.config/devin/config.json, ~/.copilot/settings.json); ~/.copilot/config.json holds login state and the two herdr-agent-state.sh hook scripts are installed by herdr, so all three stay local files.

Verifying what each CLI actually loaded

make doctor checks that the links resolve into the repo; these commands check that the tools use them.

Check Devin CLI Copilot CLI
Subagents devin doctor — lists the loaded profiles and warns on unknown frontmatter keys copilot --agent <name> -p 'reply OK' — the run header names the agent
Skills devin skills list — each skill with its ~/personal/dotfiles/skills/... path /skills list in an interactive session — it prints the dirs it scanned
Global rules devin rules list — AGENTS [Standard] always-on copilot -s -p '…answer from your instructions only…' — it answers from copilot-instructions.md
Own config read at ~/.config/devin/config.json (--config overrides it) /settings in an interactive session

Copilot has no skill subcommand and no non-interactive readback, so /skills list inside a session is the check that counts — its "No skills found" message names the dirs it scanned, which is how the ~/.copilot/skills link was found to be necessary. Do not trust the ~/.agents/skills path from the GitHub docs alone; the running binary is the authority. For the rest, copilot --log-level debug --log-dir /tmp/cop -p 'hi' is the ground truth: the log warns per agent file on an unknown frontmatter key (effort is Claude-only, and both CLIs ignore it), and records that model: haiku maps to claude-haiku-4.5.

zsh keeps its drop-in idea: ~/.zshrc is a thin loader sourcing ~/.config/zsh/*.zsh in NN- prefix order, and machine-local uncommitted overrides go in ~/.config/zsh/90-local.zsh (a plain untracked file; see 90-local.zsh.example).

Adding a new tool config

  1. mkdir -p packages/<tool>/dot-config/<tool> and copy the non-secret config file(s) in, using dot- names for anything dotted.
  2. Add a home.file entry for each file in a new nix/home/<tool>.nix, import it from nix/home/default.nix, and add <tool> to HM_PACKAGES in the Makefile (drives doctor's link checks).
  3. git add the new files, make nix-switch, review, then commit.

Secrets policy

Nothing outside packages/ is ever linked into $HOME, and no package references a credential-bearing file. .gitignore blocks secret-like filenames as a second layer, and make doctor fails on secret-pattern filenames, credential-looking content in tracked files, or a ~/.config dir that has become a symlink. Nothing imports live machine files automatically any more; copy configs into packages/ by hand and review git diff before committing.

License

Apache-2.0. Vendored skills and extensions remain under their upstream licenses; see each resource's source metadata.

About

Portable AI coding-harness configs: shared skills, commands, rules, agents & settings for Claude Code and the pi agent, stowed across profiles.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages