Skip to content

Latest commit

 

History

History
219 lines (178 loc) · 17.7 KB

AI-Tools.md

File metadata and controls

219 lines (178 loc) · 17.7 KB

AI Tool Configuration

This document describes how this chezmoi repo configures AI coding assistants and what a new system setup requires. AGENTS.md holds the maintenance rules; this is the map.

Where the Content Comes From

Rules, the git-commit command, and skills have one source each:

Content Source Delivered by
Rules .rulesync/rules/*.md rulesync, from run_onchange_rulesync-generate
Commands .rulesync/commands/*.md rulesync, from run_onchange_rulesync-generate
Skills home/dot_claude/skills/*/ chezmoi for Claude Code; rulesync for the others

.rulesync/rules/AGENTS.md is the root rule (root: true). Each tool receives it under its own root file name. .rulesync/skills/*/ are symlinks back to home/dot_claude/skills/*/.

The rulesync script reruns on any chezmoi apply where a file under .rulesync/ or home/dot_claude/skills/ changed. Never edit generated files; edit the source and apply.

Claude Code

Target Source Notes
~/.claude/CLAUDE.md .rulesync/rules/AGENTS.md Generated root rule
~/.claude/rules/*.md .rulesync/rules/*.md Generated
~/.claude/rules/environment.md home/dot_claude/rules/encrypted_environment.md.age Age-encrypted; deployed only where the personal key exists
~/.claude/commands/git-commit.md .rulesync/commands/git-commit.md Generated
~/.claude/skills/*/ home/dot_claude/skills/*/ Plain chezmoi files
~/.claude/settings.json home/dot_claude/modify_private_settings.json Merges ACTIVE_AGENT, status line, vim mode, rtk hook, md-format hook
~/.claude/statusline-command.sh home/dot_claude/executable_statusline-command.sh Status line script

The settings script only edits the keys it owns. The rtk PreToolUse hook is added when rtk is on PATH and removed when it is not. The md-format PostToolUse hook (see Markdown Formatting) is always present. Both are rebuilt idempotently, so other hooks in the file survive every apply.

GitHub Copilot

Target Source Notes
~/.copilot/copilot-instructions.md .rulesync/rules/AGENTS.md Generated root rule
~/.copilot/instructions/*.instructions.md .rulesync/rules/*.md Generated
~/.copilot/instructions/git-commit.prompt.md home/dot_copilot/instructions/git-commit.prompt.md Hand-maintained (see below)
~/.copilot/skills/*/ home/dot_claude/skills/*/ Generated
VS Code terminal profile home/run_onchange_configure-vscode-copilot-terminal.sh.tmpl Sets ACTIVE_AGENT=Copilot
~/.copilot/hooks/md-format.json home/dot_copilot/hooks/md-format.json.tmpl md-format hook for Copilot CLI and VS Code

rulesync has no global-scope command support for Copilot, so its git-commit prompt is maintained by hand. It sets model: claude-haiku-4-5 to run commits on a cheaper model; Claude Code and OpenCode command files have no per-command model setting.

Cursor

Target Source Notes
~/.cursor/rules/*.mdc home/dot_cursor/rules/*.mdc Hand-maintained (see below)
~/.cursor/skills/*/ home/dot_claude/skills/*/ Generated
~/.cursor/hooks.json home/dot_cursor/hooks.json.tmpl md-format hook (afterFileEdit)

rulesync has no global-scope rule support for Cursor, so home/dot_cursor/rules/*.mdc is kept in sync with .rulesync/rules/ by hand. Cursor .mdc frontmatter uses globs and alwaysApply.

Cursor also reads these natively, with no copies needed:

  • Commands: ~/.claude/commands/, so /git-commit works without a Cursor copy.
  • Agents: ~/.claude/agents/.
  • Project instructions: AGENTS.md in a project root.

Cursor's global User Rules live in a SQLite database (~/Library/Application Support/Cursor/User/globalStorage/state.vscdb, key aicontext.personalContext), not a file chezmoi can manage. Set them once under Cursor Settings → Rules by pasting ~/.claude/rules/general-behavior.md.

OpenCode

Target Source Notes
~/.config/opencode/AGENTS.md .rulesync/rules/AGENTS.md Generated root rule, with an index of the rules
~/.config/opencode/memories/*.md .rulesync/rules/*.md Generated
~/.config/opencode/opencode.jsonc .rulesync/rules/*.md rulesync writes instructions; other keys survive
~/.config/opencode/commands/git-commit.md .rulesync/commands/git-commit.md Generated
~/.config/opencode/skills/*/ home/dot_claude/skills/*/ Generated
~/.config/opencode/plugins/active-agent.ts home/dot_config/opencode/plugins/active-agent.ts Sets ACTIVE_AGENT, PAGER, GIT_PAGER
~/.config/opencode/plugins/rtk.ts home/dot_config/opencode/plugins/rtk.ts.tmpl Deployed only when rtk is on PATH
~/.config/opencode/plugins/md-format.ts home/dot_config/opencode/plugins/md-format.ts md-format hook; appends lint problems to the tool result
OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 available/opencode.sh Shell module, enabled when opencode is installed

OpenCode is installed through devbox global on every host, pinned to a nixpkgs-unstable commit because herdr needs 1.18.29 or newer and devbox's package index stopped at 1.18.21. See herdr.

  • Instructions list: rulesync replaces the whole instructions array in opencode.jsonc on every run, so add instruction files through .rulesync/rules/, not by editing that array.
  • Pager variables: opencode run shells do not read .zshrc and inherit the launching terminal's pager, so the plugin sets PAGER and GIT_PAGER itself instead of relying on the agent branch of .zshrc.
  • Skills: OpenCode also loads skills from ~/.claude/skills/, including claude.ai-synced skills that need Claude-only tools. The shell module turns that off. Skills in ~/.agents/skills/ still load, so install third-party skills there (or with --agent opencode) to keep them visible.
  • Encrypted rule: the environment rule reaches Claude Code only.

herdr

herdr is a terminal multiplexer for coding agents. It comes from devbox global on every host, pinned to the same nixpkgs-unstable commit as OpenCode. home/.chezmoiscripts/run_onchange_after_herdr-setup.sh.tmpl does the rest, and its hash inputs are the herdr and OpenCode versions and whether claude and copilot are present:

Target Written by Condition
~/.claude/hooks/herdr-agent-state.sh herdr integration install claude claude on PATH
SessionStart entries in ~/.claude/settings.json herdr integration install claude claude on PATH
~/.config/opencode/plugins/herdr-agent-state.js herdr integration install opencode opencode 1.18.29 or newer
~/.config/opencode/herdr-tui-session.js, herdr-opencode/tui.js herdr integration install opencode opencode 1.18.29 or newer
plugin in tui.jsonc, plugins in cli.json herdr integration install opencode opencode 1.18.29 or newer
~/.copilot/hooks/herdr-agent-state.sh herdr integration install copilot copilot on PATH
SessionStart entry in ~/.copilot/settings.json herdr integration install copilot copilot on PATH
~/.copilot/skills/herdr/SKILL.md herdr --skill copilot on PATH
~/.claude/skills/herdr/SKILL.md herdr --skill claude on PATH
~/.config/opencode/skills/herdr/SKILL.md herdr --skill opencode on PATH
  • Nothing here is in the chezmoi source. herdr owns these files, and none of them collide with managed ones. Copilot's settings.json is unmanaged, and its hook script sits beside the managed hooks/md-format.json. The settings script passes the SessionStart entries through, the plugins directory isn't exact_, and rulesync doesn't delete skills it didn't generate.
  • First install takes two applies. The apply that adds herdr to devbox.json runs the script before devbox installs herdr, so it renders as "absent" and skips. Run devbox global install, then chezmoi apply again.
  • Upgrades: moving the nixpkgs pin changes the herdr version, which re-runs the script and reinstalls the integrations, as herdr's docs require. Restart OpenCode TUIs and any shared OpenCode servers afterward, or an old reporter can overwrite pane state.
  • Skill: written from the binary unedited, so it matches the installed release and keeps its HERDR_ENV=1 guard. npx skills add is not used.
  • Config: home/dot_config/herdr/config.toml is a plain file that sets the dracula theme and keeps onboarding = false. herdr also writes this file (onboarding, theme selection in Settings, herdr config reset-keys), so keep wanted changes in the source or the next apply reverts them. Run herdr server reload-config to load a change into a running server.
  • tmux: no shell file here auto-attaches tmux, so no HERDR_ENV guard is needed.

Agent Shells

Each tool sets ACTIVE_AGENT so .zshrc/.bashrc take the minimal branch: no history, plugins, completions, prompt, or pager.

Tool Set by
Claude Code env in ~/.claude/settings.json
Copilot VS Code terminal profile
OpenCode plugins/active-agent.ts
Cursor Not set by this repo

Markdown Formatting

Line filling and table alignment are enforced by tools, not left to the model. Two reasons: markdownlint never flags a line that stops short of 100 (and, before stern was set on MD013 in home/dot_markdownlint-cli2.jsonc, it also passed overlong lines whenever nothing after column 100 was whitespace), and Claude Code skips the path-scoped markdown.md rule when it creates a new file with Write. markdown.md still covers what a tool can't decide: title-case headings, no unprompted emoji, not pasting whole files.

Three scripts in home/dot_local/bin/ deploy to ~/.local/bin/:

  • md-format [--check] FILE... reflows prose to 100 columns, then runs align-tables. It leaves frontmatter, code, tables, headings, blockquotes, and reference-link definitions alone, keeps hard line breaks, and keeps links and code spans whole when they fit on one line. It refuses to write if anything other than whitespace would change. --check writes nothing and exits 1 if a file would change.
  • md-format-hook is what every tool calls after an edit. It finds the edited Markdown files in the tool's hook payload (including apply_patch text), runs md-format, then lints with markdownlint-cli2 --config "${HOME}/.markdownlint-cli2.jsonc", and returns remaining problems to the model. It skips files not modified in the last 60 seconds and anything under ~/.claude/projects/.
  • md-precommit is a git pre-commit hook that refuses a commit whose staged Markdown isn't formatted or lint-clean. Git hooks aren't versioned, so install it per repo: ln -s ~/.local/bin/md-precommit .git/hooks/pre-commit.
Tool Hook Lint problems reach the model through
Claude Code PostToolUse, matcher Write|Edit|MultiEdit Exit 2 and stderr
OpenCode plugins/md-format.ts Text appended to the edit tool's result
Cursor afterFileEdit in ~/.cursor/hooks.json Nothing; Cursor's after-edit hook cannot reply
Copilot CLI PostToolUse, matcher edit|create|apply_patch additionalContext JSON on stdout
VS Code The same ~/.copilot/hooks file; matchers are ignored, so it runs after every tool Exit 2 and stderr

The hooks are not delivered through rulesync's hooks feature: in global mode it replaces the entire hooks block in ~/.claude/settings.json, which would remove the rtk and other hooks there.

Chezmoi Scripts

Script Runs when Effect
home/.chezmoiscripts/run_onchange_rulesync-generate.sh.tmpl .rulesync/ or a skill changes Generates rules, commands, and skills for all targets
home/.chezmoiscripts/run_onchange_after_herdr-setup.sh.tmpl herdr, OpenCode, claude, or copilot changes Installs herdr's agent integrations and skill
home/.chezmoiscripts/run_onchange_mklinks.sh.tmpl enabled/mklinks.sh changes Rebuilds enabled/ symlinks for the shell module loader
home/run_onchange_after_install-packages.sh.tmpl Brewfile changes Installs Homebrew packages from the Brewfile
home/run_onchange_configure-vscode-copilot-terminal.sh.tmpl The script changes Writes the Copilot terminal profile into VS Code settings
home/run_onchange_configure-macos-defaults.sh The script changes Applies macOS system defaults
home/run_once_init-devbox-local.sh.tmpl First apply only Initializes the devbox local environment

Supporting Tools

home/dot_local/bin/executable_align-tables deploys to ~/.local/bin/align-tables. It reformats Markdown tables to the MD060 aligned style the markdown rule requires, padding cells to display width, skipping fenced code blocks, and treating \| in a cell as a literal pipe. md-format runs it automatically. It is stdlib-only Python invoked through a uv-run shebang.

New System Setup

  1. Install chezmoi and clone this repo as the source directory.
  2. Run chezmoi apply. This deploys all managed files, installs packages, and runs the scripts above, including rulesync generation.
  3. Cursor: paste ~/.claude/rules/general-behavior.md into Cursor Settings → Rules.
  4. OpenCode: run opencode auth login and choose a provider, then set a default model in ~/.config/opencode/opencode.jsonc if wanted. Restart OpenCode to load the plugins.
  5. Restart Claude Code, Cursor, and VS Code so they load the md-format hooks.
  6. In each repo that should refuse unformatted Markdown at commit time, run ln -s ~/.local/bin/md-precommit .git/hooks/pre-commit.