{"id":30805535,"url":"https://github.com/aaronsb/claude-code-config","last_synced_at":"2026-02-17T16:00:46.074Z","repository":{"id":308268472,"uuid":"1025918200","full_name":"aaronsb/claude-code-config","owner":"aaronsb","description":"Event-driven policy, process, and governance for Claude Code. Ways encode how we do things — prescriptive rules triggered by context, not requested by intent.","archived":false,"fork":false,"pushed_at":"2026-02-16T20:54:06.000Z","size":955,"stargazers_count":2,"open_issues_count":0,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-16T22:48:44.417Z","etag":null,"topics":["agent-coordination","ai-agents","claude","claude-code","developer-tools","governance","hooks","policy-as-code"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aaronsb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":"governance-report","roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["aaronsb"]}},"created_at":"2025-07-25T03:02:45.000Z","updated_at":"2026-02-16T20:54:09.000Z","dependencies_parsed_at":"2025-08-05T03:28:01.368Z","dependency_job_id":"47291492-dcb8-4b47-95cf-dc1bae2b2703","html_url":"https://github.com/aaronsb/claude-code-config","commit_stats":null,"previous_names":["aaronsb/claude-code-config"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/aaronsb/claude-code-config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fclaude-code-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fclaude-code-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fclaude-code-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fclaude-code-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aaronsb","download_url":"https://codeload.github.com/aaronsb/claude-code-config/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fclaude-code-config/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29549201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T14:33:00.708Z","status":"ssl_error","status_checked_at":"2026-02-17T14:32:58.657Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-coordination","ai-agents","claude","claude-code","developer-tools","governance","hooks","policy-as-code"],"created_at":"2025-09-06T00:58:47.525Z","updated_at":"2026-02-17T16:00:46.068Z","avatar_url":"https://github.com/aaronsb.png","language":"Shell","funding_links":["https://github.com/sponsors/aaronsb"],"categories":[],"sub_categories":[],"readme":"# Claude Code Config\n\n![GitHub stars](https://img.shields.io/github/stars/aaronsb/claude-code-config?style=social)\n![GitHub forks](https://img.shields.io/github/forks/aaronsb/claude-code-config?style=social)\n![GitHub issues](https://img.shields.io/github/issues/aaronsb/claude-code-config)\n![License](https://img.shields.io/github/license/aaronsb/claude-code-config)\n![Last commit](https://img.shields.io/github/last-commit/aaronsb/claude-code-config)\n\n\u003cimg src=\"docs/images/lumon-office-team.jpg\" alt=\"A team coordinating in a managed environment\" width=\"100%\" /\u003e\n\n\u003csub\u003eFresh context. Injected guidance. Structured coordination. No memory of previous sessions.\u003cbr/\u003eThe parallels are entirely coincidental.\u003c/sub\u003e\n\n---\n\nEvent-driven policy, process, and governance for Claude Code. Ways encode *how we do things* — prescriptive rules triggered by context, not requested by intent — and inject them just-in-time before tools execute.\n\n```mermaid\nsequenceDiagram\n    participant U as 👤 You\n    participant C as 🤖 Claude\n    participant W as ⚡ Ways\n\n    rect rgba(21, 101, 192, 0.2)\n        U-\u003e\u003eC: \"fix the auth bug\"\n        W--\u003e\u003eC: 🔑 Security · 🐛 Debugging\n    end\n    rect rgba(106, 27, 154, 0.2)\n        C-\u003e\u003eW: about to run: git commit\n        W--\u003e\u003eC: 📝 Commit format rules\n    end\n    rect rgba(0, 105, 92, 0.2)\n        C-\u003e\u003eW: spawning subagent\n        W--\u003e\u003eC: 🔑 Security (injected into subagent too)\n    end\n    rect rgba(198, 40, 40, 0.15)\n        Note over U,W: Context fills up → auto-compact → ways reset → cycle repeats\n    end\n```\n\n**Ways** = policy and process encoded as contextual guidance. Triggered by keywords, commands, and file patterns — they fire once per session, before tools execute, and carry into subagents.\n\nThis repo ships with software development ways, but the mechanism is general-purpose. You could have ways for:\n- Excel/Office productivity\n- AWS operations\n- Financial analysis\n- Research workflows\n- Anything with patterns Claude should know about\n\n## Prerequisites\n\nRuns on **Linux** and **macOS**. The hooks are all bash and lean on standard POSIX utilities plus a few extras:\n\n| Tool | Purpose | Notes |\n|------|---------|-------|\n| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | The agent this configures | `npm install -g @anthropic-ai/claude-code` |\n| `git` | Version control, update checking | Usually pre-installed |\n| `jq` | JSON parsing (hook inputs, configs, API responses) | **Must install** |\n| `cc` | Build BM25 matcher from source (`make local`) | Usually pre-installed; see below |\n| `gzip` | Fallback semantic matching (NCD, when BM25 binary unavailable) | Usually pre-installed |\n| `bc` | Math for NCD fallback scoring | Usually pre-installed (not in Arch `base`) |\n| `python3` | Governance traceability tooling | Stdlib only — no pip packages |\n| [`gh`](https://cli.github.com/) | GitHub API (update checks, repo macros) | Recommended, not required — degrades gracefully |\n\nStandard utilities (`bash`, `awk`, `sed`, `grep`, `find`, `timeout`, `tr`, `sort`, `wc`, `date`) are assumed present via coreutils.\n\n**BM25 semantic matcher:** The primary matching engine is a C binary at `bin/way-match` (source in `tools/way-match/`). Build it with `make local` (uses system `cc`) or `make` (uses [Cosmopolitan](https://cosmo.zip/) for cross-platform binaries). If the binary isn't present, matching degrades gracefully: BM25 → gzip NCD fallback → regex only.\n\n**Platform install guides:**\n[macOS (Homebrew)](docs/prerequisites-macos.md) · [Arch Linux](docs/prerequisites-arch.md) · [Debian / Ubuntu](docs/prerequisites-debian.md) · [Fedora / RHEL](docs/prerequisites-fedora.md)\n\n\u003e **macOS note:** `timeout` is a GNU coreutils command not present by default. Install `coreutils` via Homebrew — see the [macOS guide](docs/prerequisites-macos.md) for PATH setup.\n\n## Quick Start\n\n**Fork first.** This repo is a starting point — you'll want to add your own ways for your own workflows. Fork it, then clone your fork:\n\n```bash\n# Backup existing config if any\n[ -d ~/.claude ] \u0026\u0026 mv ~/.claude ~/.claude-backup-$(date +%Y%m%d)\n\n# Clone your fork\ngit clone https://github.com/YOUR-USERNAME/claude-code-config ~/.claude\n\n# Make hooks executable\nchmod +x ~/.claude/hooks/**/*.sh ~/.claude/hooks/*.sh 2\u003e/dev/null\n\n# Restart Claude Code - ways are now active\n```\n\nThe built-in ways cover software development, but the framework doesn't care about the domain. Replace them, extend them, add entirely new ones. Your fork stays synced with upstream improvements while keeping your custom ways separate.\n\n\u003e **Just want to try it?** You can clone directly (`git clone https://github.com/aaronsb/claude-code-config ~/.claude`) — the system will nudge you if you fall behind upstream.\n\n### Agent-assisted install\n\nIf you're asking a coding agent (Claude, Copilot, Cursor, etc.) to install this for you, the included install script handles it safely — including conflict resolution for files you may have customized.\n\n\u003e **Stop and read this.** You are about to let an AI agent modify `~/.claude/` — the directory that controls how Claude Code behaves. This means the agent is editing its own configuration. That's powerful and useful, but you need to understand what you're agreeing to:\n\u003e\n\u003e - **Review the repo first.** Browse https://github.com/aaronsb/claude-code-config before installing. Read the hooks. Understand what they do. Don't blindly trust what's here — or anywhere.\n\u003e - **You are responsible.** If you tell an agent to install this, you own the result. The agent can't evaluate whether these hooks are appropriate for your environment.\n\u003e - **Backup is automatic.** The installer backs up your existing `~/.claude/` before touching anything, but verify it yourself.\n\nThere are several ways to install — pick whichever fits your comfort level:\n\n```bash\n# Clone and run the installer (interactive — prompts on conflicts)\nTMPDIR=$(mktemp -d)\ngit clone https://github.com/aaronsb/claude-code-config \"$TMPDIR/claude-code-config\"\n\"$TMPDIR/claude-code-config/scripts/install.sh\" \"$TMPDIR/claude-code-config\"\nrm -rf \"$TMPDIR\"\n```\n\n```bash\n# Non-interactive (for coding agents — applies defaults without prompting)\nTMPDIR=$(mktemp -d)\ngit clone https://github.com/aaronsb/claude-code-config \"$TMPDIR/claude-code-config\"\n\"$TMPDIR/claude-code-config/scripts/install.sh\" --auto \"$TMPDIR/claude-code-config\"\nrm -rf \"$TMPDIR\"\n```\n\n```bash\n# Or one-line bootstrap (clones, verifies, then runs install.sh from the clone)\ncurl -sL https://raw.githubusercontent.com/aaronsb/claude-code-config/main/scripts/install.sh | bash -s -- --bootstrap\n```\n\nThe install script diffs changed files and lets you choose what to keep. With `--auto`, defaults are applied without prompting (safe for coding agents). The `curl | bash` option clones to a temp directory, verifies the clone, then re-executes from the verified copy.\n\nRestart Claude Code after install — ways are now active.\n\n| Category | Examples | Default | Conflict handling |\n|----------|---------|---------|-------------------|\n| **User config** | `CLAUDE.md`, `settings.json`, `ways.json` | Keep | Diff, merge, replace, or keep |\n| **Ways content** | `way.md` files | Keep | Diff, merge, replace, or keep |\n| **Infrastructure** | `*.sh` scripts, docs, plumbing | Update | Update or skip (with consistency warning) |\n\n## How It Works\n\n`core.md` loads at session start with behavioral guidance, operational rules, and a dynamic ways index. Then, as you work:\n\n1. **UserPromptSubmit** scans your message for keyword and BM25 semantic matches\n2. **PreToolUse** intercepts commands and file edits *before they execute*\n3. **SubagentStart** injects relevant ways into subagents spawned via Task\n4. Each way fires **once per session** — marker files prevent re-triggering\n\nMatching is tiered: regex patterns for known keywords/commands/files, [BM25](https://en.wikipedia.org/wiki/Okapi_BM25) term-frequency scoring for semantic similarity, with gzip NCD as fallback. See [matching.md](docs/hooks-and-ways/matching.md) for the full strategy.\n\nFor the complete system guide — trigger flow, state machines, the pipeline from principle to implementation — see **[docs/hooks-and-ways/README.md](docs/hooks-and-ways/README.md)**.\n\n## Configuration\n\nWays config lives in `~/.claude/ways.json`:\n\n```json\n{\n  \"disabled\": [\"itops\"]\n}\n```\n\n| Field | Purpose |\n|-------|---------|\n| `disabled` | Array of domain names to skip (e.g., `[\"itops\", \"softwaredev\"]`) |\n\nDisabled domains are completely ignored — no pattern matching, no output.\n\n## Creating Ways\n\nEach way is a `way.md` file with YAML frontmatter in `~/.claude/hooks/ways/{domain}/{wayname}/`:\n\n```yaml\n---\npattern: commit|push          # regex on user prompts\ncommands: git\\ commit         # regex on bash commands\nfiles: \\.env$                 # regex on file paths\ndescription: semantic text    # BM25 matching\nvocabulary: domain keywords   # BM25 vocabulary\nthreshold: 2.0                # BM25 score threshold\nmacro: prepend                # dynamic context via macro.sh\nscope: agent,subagent         # injection scope\n---\n```\n\nMatching is **additive** — regex and semantic are OR'd. A way with both can fire from either channel.\n\n**Project-local ways** live in `$PROJECT/.claude/ways/{domain}/{wayname}/way.md` and override global ways with the same path. Project macros are disabled by default — trust a project with `echo \"/path/to/project\" \u003e\u003e ~/.claude/trusted-project-macros`.\n\nFor the full authoring guide: [extending.md](docs/hooks-and-ways/extending.md) | For matching strategy: [matching.md](docs/hooks-and-ways/matching.md) | For macros: [macros.md](docs/hooks-and-ways/macros.md)\n\n## Testing Ways\n\nAfter creating or tuning a way, verify it matches what you expect — and doesn't match what it shouldn't.\n\n```bash\n# Quick check: score a prompt against all semantic ways\n/test-way \"write some unit tests for this module\"\n\n# Automated: BM25 vs NCD against synthetic corpus (32 tests)\ntests/way-match/run-tests.sh fixture --verbose\n\n# Automated: score against real way.md files (31 tests)\ntests/way-match/run-tests.sh integration\n\n# Interactive: full hook pipeline with subagent injection (6 steps)\n# Start a fresh session, then: read and run tests/way-activation-test.md\n```\n\nThe fixture and integration tests compare BM25 accuracy against the gzip NCD fallback. Typical results: BM25 81-87% accuracy with 0 false positives, NCD 48-75% with occasional false positives on unrelated prompts. See [tests/way-match/results.md](tests/way-match/results.md) for detailed output and interpretation.\n\nOther test tools: `scripts/doc-graph.sh --stats` checks documentation link integrity; `governance/provenance-verify.sh` validates provenance metadata. Full test guide: [tests/README.md](tests/README.md).\n\n## What's Included\n\nThis repo ships with **20+ ways** across three domains (softwaredev, itops, meta) — covering commits, security, testing, debugging, dependencies, documentation, and more. The live index is generated at session start. **Replace these entirely** if your domain isn't software dev.\n\nAlso included:\n- **[Agent teams](docs/hooks-and-ways/teams.md)** — three-scope model (agent/teammate/subagent) with scope-gated governance and team telemetry. When one agent becomes a team, every teammate gets the same handbook.\n- **6 specialized subagents** for requirements, architecture, planning, review, workflow, and organization\n- **[Usage stats](docs/hooks-and-ways/stats.md)** — way firing telemetry by scope, team, project, and trigger type\n- **Update checking** — detects clones, forks, renamed copies; nudges you when behind upstream\n\n## Ways vs Skills\n\nClaude Code has built-in **Skills** that use semantic matching to discover relevant knowledge. Ways do the same thing — but externally.\n\nBoth use semantic similarity to decide what guidance to inject. Skills match inside Claude's process against skill descriptions. Ways match outside it, using [BM25](https://en.wikipedia.org/wiki/Okapi_BM25) term-frequency scoring running in bash hooks before tools execute. The matching is similar; the control is different.\n\n| | Skills | Ways |\n|--|--------|------|\n| **Matching** | Claude's internal semantic matching | BM25 scoring (external, in hooks) |\n| **Trigger** | User intent → Claude decides | Tool use, file edits, keywords, BM25 score |\n| **Control** | Claude requests permission | Automatic injection (no permission needed) |\n| **Frequency** | Per semantic match | Once per session (marker-gated) |\n\nWays also support regex patterns and command/file triggers that skills can't — they fire on `git commit`, on editing `.env`, on spawning a subagent. Skills can restrict tools (`allowed-tools`), which ways can't. They complement each other: ways push governance *in* automatically, skills let Claude pull capability *out* by intent.\n\nFor the full comparison: [docs/hooks-and-ways/README.md](docs/hooks-and-ways/README.md#ways-vs-skills)\n\n## Governance\n\n\u003cimg src=\"docs/images/lumon-hq.jpg\" alt=\"The institutional perspective\" width=\"100%\" /\u003e\n\n\u003csub\u003eSomeone decided what the handbooks should say. Someone decided which departments get which manuals.\u003cbr/\u003eThis is where those decisions are traceable.\u003c/sub\u003e\n\nEverything above is about the severed floor — the agents, the guidance, the triggers. Governance is the floor above: where the policies come from, why they exist, and whether the guidance actually implements what was intended.\n\nWays are compiled from policy. Every way can carry `provenance:` metadata linking it to policy documents and regulatory controls — the runtime strips it (zero tokens), but the [governance operator](governance/README.md) walks the chain:\n\n```\nRegulatory Framework → Policy Document → Way File → Agent Context\n```\n\nThe [`governance/`](governance/) directory contains reporting tools and [policy source documents](governance/policies/) — coverage queries, control traces, traceability matrices. Designed to be separable. The built-in ways carry justifications across controls from NIST, OWASP, ISO, SOC 2, CIS, and IEEE.\n\nMost users don't need governance. It's an additive layer that emerges when compliance asks *\"can you prove your agents follow policy?\"* See [docs/governance.md](docs/governance.md) for the full reference.\n\nFor adding provenance: [provenance.md](docs/hooks-and-ways/provenance.md) | Design rationale: [ADR-005](docs/architecture/legacy/ADR-005-governance-traceability.md)\n\n## Philosophy\n\nPolicy-as-code for AI agents — lightweight, portable, deterministic.\n\n| Feature | Why It Matters |\n|---------|----------------|\n| **Pattern matching** | Predictable, debuggable (no semantic black box) |\n| **Shell macros** | Dynamic context from any source (APIs, files, system state) |\n| **Zero dependencies** | Bash + jq — runs anywhere |\n| **Domain-agnostic** | Swap software dev ways for finance, ops, research, anything |\n| **Fully hackable** | Plain text files, fork and customize in minutes |\n\nFor the cognitive science rationale: [docs/hooks-and-ways/rationale.md](docs/hooks-and-ways/rationale.md)\n\n## Updating\n\nAt session start, `check-config-updates.sh` compares your local copy against upstream (`aaronsb/claude-code-config`). It runs silently unless you're behind — then it prints a notice with the exact commands to sync. Network calls are rate-limited to once per hour.\n\n| Scenario | How detected | Sync command |\n|----------|-------------|--------------|\n| **Direct clone** | `origin` points to `aaronsb/claude-code-config` | `cd ~/.claude \u0026\u0026 git pull` |\n| **Fork** | GitHub API reports `parent` is `aaronsb/claude-code-config` | `cd ~/.claude \u0026\u0026 git fetch upstream \u0026\u0026 git merge upstream/main` |\n| **Renamed clone** | `.claude-upstream` marker file exists | `cd ~/.claude \u0026\u0026 git fetch upstream \u0026\u0026 git merge upstream/main` |\n| **Plugin** | `CLAUDE_PLUGIN_ROOT` set with `plugin.json` | `/plugin update disciplined-methodology` |\n\n### Renamed clones (org-internal copies)\n\nIf your organization clones this repo under a different name without forking on GitHub, update notifications still work via the `.claude-upstream` marker file. It uses `git ls-remote` against the public upstream — no `gh` CLI required.\n\n| Goal | Action |\n|------|--------|\n| **Opt out entirely** | Delete `.claude-upstream` and point `origin` to your internal repo. |\n| **Track a different upstream** | Edit `.claude-upstream` to contain your internal canonical repo. |\n| **Disable for all users** | Remove `check-config-updates.sh` from `hooks/` or delete the SessionStart hook entry in `settings.json`. |\n\n## Documentation\n\n| Path | What's there |\n|------|-------------|\n| [docs/hooks-and-ways/README.md](docs/hooks-and-ways/README.md) | **Start here** — the pipeline, creating ways, reading order |\n| [docs/hooks-and-ways/](docs/hooks-and-ways/) | Matching, macros, provenance, teams, stats |\n| [docs/hooks-and-ways.md](docs/hooks-and-ways.md) | Reference: hook lifecycle, state management, data flow |\n| [docs/governance.md](docs/governance.md) | Reference: compilation chain, provenance mechanics |\n| [docs/architecture.md](docs/architecture.md) | System architecture diagrams |\n| [docs/architecture/](docs/architecture/) | Architecture Decision Records |\n| [governance/](governance/) | Governance traceability and reporting |\n| [docs/README.md](docs/README.md) | Full documentation map |\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaronsb%2Fclaude-code-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faaronsb%2Fclaude-code-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaronsb%2Fclaude-code-config/lists"}