Claude Code skills, rules, and per-language project bundles.
Layout
| Directory | Purpose |
|---|---|
claude-rules/ |
Generic rules symlinked into ~/.claude/rules/ (apply globally) |
<skill>/ |
Skill directories symlinked into ~/.claude/skills/ |
languages/ |
Per-language project bundles (rules + hooks + settings) |
scripts/ |
Install helpers |
Two install modes
Global (machine-wide)
Symlinks skills and generic rules into ~/.claude/. Run once per machine.
make install # symlink skills and rules into ~/.claude/
make uninstall # remove the symlinks
make list # show what's installedSkills and generic rules apply to every Claude Code session on this machine.
Per-project language bundles
Copies a language-specific ruleset into a target project. Re-run to refresh.
make install-elisp PROJECT=~/code/my-elisp-thing
# or, explicit:
make install-lang LANG=elisp PROJECT=~/code/my-elisp-thing
make list-languages # show available bundlesWhat gets installed:
.claude/rules/*.md— project-scoped rules (language-specific + verification).claude/hooks/— PostToolUse validation scripts.claude/settings.json— permission allowlist + hook wiringgithooks/— git hooks (activated viacore.hooksPath)CLAUDE.md— seeded on first install only (useFORCE=1to overwrite).gitignore— appends personal-override entries (deduped)
The install is re-runnable. Running it again refreshes files in place; personal
tweaks live in .claude/settings.local.json and are not touched.
MCP servers (user scope)
Registers MCP servers globally (user scope) so every Claude Code project
sees them. Reads structure from mcp/servers.json (placeholders ${VAR}),
decrypts secrets from mcp/secrets.env.gpg via gpg-agent, expands the
placeholders, then registers anything not already present in
claude mcp list. Idempotent — re-running is safe.
make install-mcp # decrypt + register everything in servers.json
make uninstall-mcp # remove every server listed in servers.json
make check-mcp # dry-run drift report (no decryption, no writes)check-mcp classifies each server as ok (in both), MISSING (configured
but not registered — run install-mcp), or EXTRA (registered but not
configured — usually intentional manual additions like the claude.ai web
servers). Exit code is non-zero only on MISSING, since EXTRA entries
are often deliberate.
What lands on disk during install-mcp:
mcp/gcp-oauth.keys.json(mode 600) — extracted for google-calendar-mcp~/.config/google-docs-mcp/{personal,work}/token.json(mode 600) — per-profile OAuth tokens for@a-bonus/google-docs-mcp
Secrets never touch disk in plain form outside the OAuth artifacts above.
The .gpg file is the source of truth; rotate via gpg --edit-key and
re-encrypt. See mcp/README.org for the full pipeline.
Available languages
| Language | Path | Notes |
|---|---|---|
| elisp | languages/elisp/ |
Emacs Lisp — ERT, check-parens, byte-compile |
Add more by creating languages/<name>/ with the same structure.
Bundle structure
Each language bundle under languages/<lang>/ follows:
languages/<lang>/
├── CLAUDE.md # project instructions template (seed only)
├── claude/ # copied into <project>/.claude/
│ ├── rules/*.md
│ ├── hooks/*.sh
│ └── settings.json
├── githooks/ # copied into <project>/githooks/
│ └── pre-commit
└── gitignore-add.txt # lines appended to <project>/.gitignore
Design principles
- Authoritative source:
.claude/andgithooks/overwrite on every install. If you edit them in-project, your changes will be lost on next install. Put per-project customizations in.claude/settings.local.json(gitignored) or project-specific files outside.claude/. - CLAUDE.md is precious: it's the one file with project-specific prose, so
install never overwrites it unless
FORCE=1. - Portable paths: hooks use
$CLAUDE_PROJECT_DIR(Claude Code sets it) with a script-relative fallback. No hardcoded usernames or paths. - Idempotent: re-running install is always safe. No state beyond file contents.
