@whitehatd/crag 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,855 +2,372 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/%40whitehatd%2Fcrag?color=%23e8bb3a&label=npm&logo=npm)](https://www.npmjs.com/package/@whitehatd/crag)
4
4
  [![Test](https://github.com/WhitehatD/crag/actions/workflows/test.yml/badge.svg)](https://github.com/WhitehatD/crag/actions/workflows/test.yml)
5
+ [![Release](https://github.com/WhitehatD/crag/actions/workflows/release.yml/badge.svg)](https://github.com/WhitehatD/crag/actions/workflows/release.yml)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
6
7
  [![Node](https://img.shields.io/node/v/%40whitehatd%2Fcrag)](https://nodejs.org)
7
8
  [![Zero dependencies](https://img.shields.io/badge/dependencies-0-brightgreen)](./package.json)
8
- [![228 tests](https://img.shields.io/badge/tests-228%20passing-brightgreen)](./test)
9
- [![Security hardened](https://img.shields.io/badge/security-hardened-brightgreen)](./SECURITY.md)
9
+ [![323 tests](https://img.shields.io/badge/tests-323%20passing-brightgreen)](./test)
10
10
 
11
- **The bedrock layer for AI coding agents. One `governance.md`. Any project. Never stale.**
12
-
13
- Write your AI agent rules once. Enforce them in **Claude Code, Cursor, Copilot, Codex, Gemini, Aider, Cline, Continue, Windsurf, Zed, and Sourcegraph Cody** — plus your CI pipeline and git hooks. From a single 20-line file.
11
+ > **One `governance.md`. Any project. Generated in 250 ms.**
12
+ >
13
+ > Point crag at an existing codebase. It reads the filesystem, detects your
14
+ > stack, parses your CI, and writes a 30-line governance file that compiles
15
+ > to GitHub Actions, git hooks, and config for nine AI coding agents.
14
16
 
15
17
  ```bash
16
- npx @whitehatd/crag init # Interview generate governance
17
- npx @whitehatd/crag analyze # Or skip the interview: infer from existing project
18
- npx @whitehatd/crag compile --target all # Output for 12 downstream tools
18
+ npx @whitehatd/crag analyze # Generate governance.md from an existing project
19
+ npx @whitehatd/crag compile --target all # Turn it into CI + 12 downstream configs
19
20
  ```
20
21
 
21
- > **The one-sentence pitch:** Every other AI coding tool ships static config files that hardcode your project's current shape. They rot. crag ships a runtime discovery engine plus a single governance file — the engine reads the filesystem every session so it never goes stale, and the governance is your rules, not your paths.
22
+ Zero dependencies. Node 18+. Validated across [20 OSS projects](#validation-on-real-repos).
22
23
 
23
24
  ---
24
25
 
25
- ## The 12-target pitch, visually
26
-
27
- ```
28
- ┌──────────────────┐
29
- │ governance.md │ ← you maintain this (20-30 lines)
30
- │ one file │
31
- └────────┬─────────┘
32
-
33
- crag compile
34
-
35
- ┌─────────────────────┼─────────────────────┐
36
- │ │ │
37
- ┌─────┴──────┐ ┌─────┴──────┐ ┌─────┴──────┐
38
- │ CI / hooks │ │ AI native │ │ AI extras │
39
- ├────────────┤ ├────────────┤ ├────────────┤
40
- │ GitHub CI │ │ AGENTS.md │ │ Copilot │
41
- │ husky │ │ Cursor │ │ Cline │
42
- │ pre-commit │ │ Gemini │ │ Continue │
43
- └────────────┘ └────────────┘ │ Windsurf │
44
- │ Zed │
45
- │ Cody │
46
- └────────────┘
47
- ```
48
-
49
- Change one line in `governance.md`, re-run `crag compile --target all`, and 12 downstream configs regenerate. Your rules, your CI, your git hooks, and 9 different AI coding agents all stay in lock-step from a single source.
26
+ ## What it does
50
27
 
51
- ---
28
+ crag turns project-specific configuration work into a single file.
52
29
 
53
- ## Why "crag"?
30
+ - **You write**: a 20–30 line `governance.md` describing your quality gates, branch strategy, and security rules.
31
+ - **crag generates**: GitHub Actions workflow, husky hooks, pre-commit config, and configuration for **AGENTS.md** (Codex/Aider/Factory), **Cursor**, **Gemini**, **Copilot**, **Cline**, **Continue**, **Windsurf**, **Zed**, and **Sourcegraph Cody** — from that one file.
32
+ - **crag discovers**: runtimes, frameworks, linters, test runners, CI systems, and monorepo layouts — at session time, from the filesystem. Nothing to hardcode.
54
33
 
55
- A crag is a rocky outcrop an unmoving landmark that stands while seasons, paths, and generations change around it. That's exactly what this tool is. Your skills discover. Your gates run. Your CI regenerates. But `governance.md` the crag — doesn't move until you say so. Your AI agents anchor to it.
34
+ The result is a single source of truth for your rules that stays in lock-step with your CI pipeline, your pre-commit hooks, and every AI tool your team uses.
56
35
 
57
36
  ---
58
37
 
59
- ## Proven in Production
38
+ ## Validation on real repos
60
39
 
61
- Not on demos. On real systems, in production, shipping to real infrastructure.
40
+ Unlike most tools in this space, crag ships with a reproducible cross-repo benchmark. `crag analyze --dry-run` was run against 20 diverse open-source projects:
62
41
 
63
- | Project | Stack | Services | Deployment | Result |
64
- |---|---|---|---|---|
65
- | **Leyoda** | Spring Boot + Next.js 16 + Python | Monolith + signal engine | Docker blue-green, NGINX | Discovered entire stack, 215-line governance, zero skill modification |
66
- | **MetricHost** | Spring Boot + Next.js 16 | 11 microservices | Kubernetes (k3s), Kafka, Redis | 3-level governance hierarchy (root + backend + frontend), dual-repo |
67
- | **StructuAI** | Node + Rust + Python + Java + React | 9 Docker Compose services | Docker Compose | 5 languages detected, all gates generated from interview |
68
- | **crag** | Node.js CLI | Single module | npm | Scaffolds itself — full dogfooding, 159 tests, zero deps |
42
+ | Grade | Count | Meaning |
43
+ |---|---:|---|
44
+ | **A** ship-ready governance | **17 / 20 (85%)** | Stack + test + lint + build gates captured. Minimal noise. Ready to commit with light review. |
45
+ | **B** usable after cleanup | 3 / 20 (15%) | Stack correct, some gates need pruning or adding. Still faster than writing from scratch. |
46
+ | **C** rework needed | **0 / 20 (0%)** | |
69
47
 
70
- The same universal skills written once, never modified per project discovered a full-stack monolith with OAuth and blue-green deploys, an 11-microservice K8s platform with Stripe billing and Kafka event buses, a 5-language polyglot with Rust decoders and Puppeteer rendering, and a Node.js CLI. Zero project-specific instructions in the skills. They discovered everything.
48
+ Repos tested: `expressjs/express`, `chalk/chalk`, `fastify/fastify`, `axios/axios`, `prettier/prettier`, `vitejs/vite`, `psf/requests`, `pallets/flask`, `pallets/click`, `tiangolo/fastapi`, `BurntSushi/ripgrep`, `clap-rs/clap`, `rust-lang/mdBook`, `tokio-rs/axum`, `spf13/cobra`, `gin-gonic/gin`, `charmbracelet/bubbletea`, `spring-projects/spring-petclinic`, `sinatra/sinatra` (Ruby), `slimphp/Slim` (PHP).
71
49
 
72
- ---
73
-
74
- ## The Architecture
75
-
76
- ```
77
- ┌──────────────────────────────────────────────────────────────┐
78
- │ Ships with crag (universal — same for every project) │
79
- │ │
80
- │ ┌──────────────────────┐ ┌──────────────────────┐ │
81
- │ │ pre-start skill │ │ post-start skill │ │
82
- │ │ discovers ANY │ │ validates using │ │
83
- │ │ project │ │ YOUR gates │ │
84
- │ └──────────┬───────────┘ └──────────┬───────────┘ │
85
- └─────────────┼───────────────────────────────┼───────────────┘
86
- │ │
87
- │ reads at runtime │ reads at runtime
88
- ▼ ▼
89
- ┌──────────────────────────────────────────────────────────────┐
90
- │ Generated from interview or analyze (project-specific) │
91
- │ │
92
- │ ┌────────────────────────────────────────────┐ │
93
- │ │ governance.md — 20-30 lines of YOUR rules │ │
94
- │ └────────────────────────────────────────────┘ │
95
- │ │
96
- │ Also generated: hooks/ agents/ settings │
97
- └──────────────────────────────────────────────────────────────┘
98
- ```
50
+ | Metric | Value |
51
+ |---|---|
52
+ | Mean `crag analyze` time | **238 ms** per repo |
53
+ | Success rate | **20 / 20 exit 0** |
54
+ | Language families covered | Node, Python, Rust, Go, Java, Ruby, PHP |
55
+ | Zero-gate failures | **0** |
99
56
 
100
- The skills ship once and work forever. They don't know your stack — they discover it. They don't know your gates — they read them from governance.md. Add a service, change your CI, switch frameworks — the skills adapt. Nothing to update.
101
-
102
- ### The Core Insight: Discovery vs Governance
103
-
104
- Every other tool in this space mixes "how to find things" with "what to enforce." crag separates them cleanly:
105
-
106
- - **Discovery** (universal skills) — reads the filesystem, detects runtimes, maps architecture, finds configs. Works on any project without modification.
107
- - **Governance** (your `governance.md`) — defines YOUR rules: quality gates, security requirements, branch strategy, deployment pipeline. Changes only when YOU change it.
108
-
109
- The skills handle discovery. `governance.md` handles governance. The skills never go stale because they re-discover every session. The governance never goes stale because it's your standards, not your file paths.
57
+ Full methodology, grading rubric, per-repo results, and raw outputs: [`benchmarks/results.md`](./benchmarks/results.md).
110
58
 
111
59
  ---
112
60
 
113
- ## Quick Start
114
-
115
- ```bash
116
- # Install once globally (the package is scoped; the binary name is `crag`)
117
- npm install -g @whitehatd/crag
61
+ ## Quick start
118
62
 
119
- # Or use via npx (no install)
120
- npx @whitehatd/crag init
121
-
122
- # After install, all commands use the plain `crag` binary
123
- crag init # Interview → generate governance + hooks + agents
124
- crag analyze # Zero-interview: infer governance from existing project
125
- crag check # Verify infrastructure
126
- crag diff # Compare governance against codebase reality
127
- crag upgrade # Update universal skills (with hash-based conflict detection)
128
- crag workspace # Inspect detected workspace
129
- crag compile --target all # Compile governance → CI, hooks, and 9 AI agent configs
130
- crag install # Install interview agent globally for /crag-project
131
- ```
132
-
133
- After setup, in any Claude Code session:
134
63
  ```bash
135
- /pre-start-context # Discovers project, loads governance, ready to work
136
- # ... do your task ...
137
- /post-start-validation # Validates, captures knowledge, commits, deploys
138
- ```
64
+ # Use via npx (no install)
65
+ npx @whitehatd/crag analyze
66
+ npx @whitehatd/crag compile --target all
139
67
 
140
- ---
141
-
142
- ## User Guide
143
-
144
- ### Installation
145
-
146
- crag is a zero-dependency Node.js CLI. You don't need to install it — run it via `npx`:
147
-
148
- ```bash
149
- npx crag <command>
150
- ```
151
-
152
- Or install globally:
153
- ```bash
68
+ # Or install globally
154
69
  npm install -g @whitehatd/crag
155
- crag <command>
156
- ```
157
-
158
- The package is published under a scope (`@whitehatd/crag`) but the binary name remains `crag`, so after installation all commands work as `crag init`, `crag analyze`, etc.
159
-
160
- **Requirements:**
161
- - Node.js 18+ (uses built-in `https`, `crypto`, `fs`, `child_process`)
162
- - Git (for branch strategy inference and discovery cache)
163
- - Claude Code CLI (`claude --version`) — only needed for `crag init`
164
-
165
- ### Choosing Your Entry Point
166
-
167
- crag has two ways to generate governance for a project:
168
-
169
- | Situation | Command | What happens |
170
- |-----------|---------|--------------|
171
- | New project, unsure of standards | `crag init` | Interactive interview — agent asks about your stack, quality bar, security, deployment |
172
- | Existing project with CI/linters already configured | `crag analyze` | Zero-interview mode — reads your CI workflows, package.json scripts, linter configs, git history |
173
- | Want to see what would be generated | `crag analyze --dry-run` | Prints inferred governance without writing |
174
- | Already have governance, want to add inferred gates | `crag analyze --merge` | Preserves existing governance, appends inferred additions |
175
- | Monorepo with sub-projects | `crag analyze --workspace` | Analyzes root + every workspace member |
176
-
177
- ### Command Reference
178
-
179
- #### `crag init` — Interactive Setup
180
-
181
- Runs an interview agent that asks about your project, then generates all infrastructure:
182
-
183
- ```bash
184
- cd your-project
185
- npx crag init
70
+ crag analyze
71
+ crag compile --target all
186
72
  ```
187
73
 
188
- **What gets generated:**
189
- - `.claude/skills/pre-start-context/SKILL.md` — universal discovery skill
190
- - `.claude/skills/post-start-validation/SKILL.md` — universal validation skill
191
- - `.claude/governance.md` — your rules (from interview answers)
192
- - `.claude/hooks/` — sandbox-guard, drift-detector, circuit-breaker, auto-post-start
193
- - `.claude/agents/` — test-runner, security-reviewer, skill-auditor
194
- - `.claude/settings.local.json` — permissions + hook wiring
195
- - `.claude/ci-playbook.md` — empty template for known CI failures
74
+ **Requirements:** Node.js 18+. Git. (Claude Code CLI is only needed for the interactive `crag init` flow.)
196
75
 
197
- After init, the skills are ready to use in any Claude Code session via `/pre-start-context`.
198
-
199
- #### `crag analyze` — Zero-Interview Governance
200
-
201
- Generates `governance.md` from your existing project without asking questions:
202
-
203
- ```bash
204
- crag analyze # Generate .claude/governance.md
205
- crag analyze --dry-run # Preview without writing
206
- crag analyze --workspace # Analyze all workspace members
207
- crag analyze --merge # Merge with existing governance
208
- ```
209
-
210
- **What it detects:**
211
- - **Stack:** Node, Rust, Python, Java, Go, Docker (from manifests)
212
- - **Gates from CI:** parses `.github/workflows/*.yml` (recursively) for `run:` steps including multiline `run: |` blocks
213
- - **Gates from scripts:** `package.json` `test`, `lint`, `build`, `format`, `typecheck`
214
- - **Linters:** ESLint, Biome, Prettier, Ruff, Clippy, Rustfmt, Mypy, TypeScript
215
- - **Branch strategy:** feature branches vs trunk-based (from git history)
216
- - **Commit convention:** conventional vs free-form (from git log)
217
- - **Deployment:** Docker, Kubernetes, Vercel, Fly.io, Netlify, Render, Terraform
218
-
219
- Output sections marked `# Inferred` should be reviewed.
76
+ ---
220
77
 
221
- #### `crag check` — Verify Infrastructure
78
+ ## How it works
222
79
 
223
- Lists all core and optional files, shows which are present:
80
+ crag separates two things that every other tool in this space conflates:
224
81
 
225
- ```bash
226
- crag check
227
82
  ```
228
-
229
- Run this after `crag init` to verify everything was generated, or any time you're unsure if the setup is complete.
230
-
231
- #### `crag compile` Export Governance (12 targets)
232
-
233
- Compiles your `governance.md` to multiple formats:
234
-
235
- ```bash
236
- # CI / git hooks
237
- crag compile --target github # .github/workflows/gates.yml
238
- crag compile --target husky # .husky/pre-commit
239
- crag compile --target pre-commit # .pre-commit-config.yaml
240
-
241
- # AI coding agents — native formats
242
- crag compile --target agents-md # AGENTS.md (Codex, Aider, Factory)
243
- crag compile --target cursor # .cursor/rules/governance.mdc
244
- crag compile --target gemini # GEMINI.md
245
-
246
- # AI coding agents — additional formats
247
- crag compile --target copilot # .github/copilot-instructions.md
248
- crag compile --target cline # .clinerules
249
- crag compile --target continue # .continuerules
250
- crag compile --target windsurf # .windsurfrules
251
- crag compile --target zed # .zed/rules.md
252
- crag compile --target cody # .sourcegraph/cody-instructions.md
253
-
254
- crag compile --target all # All 12 targets at once
255
- crag compile # List available targets
83
+ ┌────────────────────────────────────────────────────────────────┐
84
+ │ DISCOVERY (ships with crag universal, same for any repo) │
85
+ │ │
86
+ │ Reads the filesystem at runtime. Detects languages, frame- │
87
+ │ works, CI systems, workspace layout, linters, test runners. │
88
+ │ │
89
+ │ Never hardcoded. Never goes stale. Add a service, switch │
90
+ │ frameworks, change CI — discovery adapts automatically. │
91
+ └───────────────────────────┬────────────────────────────────────┘
92
+
93
+
94
+ ┌────────────────────────────────────────────────────────────────┐
95
+ │ GOVERNANCE (your governance.md — project-specific) │
96
+ │ │
97
+ │ 20-30 lines of YOUR rules: quality gates, branch strategy,
98
+ │ security requirements, deployment policy.
99
+ │ │
100
+ │ Human-controlled. Version-pinned. Changes only when you do. │
101
+ └───────────────────────────┬────────────────────────────────────┘
102
+
103
+
104
+ ┌────────────────────────────────────────────────────────────────┐
105
+ │ COMPILE (crag compile --target all) │
106
+ │ │
107
+ │ One governance.md 12 outputs │
108
+ │ │
109
+ │ CI / hooks: GitHub Actions · husky · pre-commit │
110
+ │ AI (native): AGENTS.md · Cursor · Gemini │
111
+ │ AI (extras): Copilot · Cline · Continue · Windsurf · │
112
+ │ Zed · Sourcegraph Cody │
113
+ └────────────────────────────────────────────────────────────────┘
256
114
  ```
257
115
 
258
- **Why this matters:** one `governance.md` becomes your CI workflow, your git hooks, and configuration for **9 different AI coding agents**. Change a gate once, recompile, and every downstream tool sees the update. The generator detects Node/Python/Java/Go versions from your project files (`package.json engines.node`, `pyproject.toml requires-python`, `build.gradle.kts` toolchain, `go.mod` directive) instead of hardcoding defaults.
259
-
260
- Gate classifications control behavior per target:
261
- - `# [MANDATORY]` (default) — stop on failure
262
- - `# [OPTIONAL]` — warn via `continue-on-error: true` (GitHub) or wrapper (husky/pre-commit)
263
- - `# [ADVISORY]` — log result, never block
264
-
265
- #### `crag diff` — Governance Drift Detection
116
+ Change one line in `governance.md`, re-run `crag compile --target all`, and 12 downstream configs regenerate. Every AI tool on your team plus your CI pipeline and pre-commit hooks stays in sync from a single source.
266
117
 
267
- Compares `governance.md` against codebase reality:
268
-
269
- ```bash
270
- crag diff
271
- ```
272
-
273
- ```
274
- MATCH node --check bin/crag.js
275
- DRIFT ESLint referenced but biome.json found
276
- MISSING CI gate: cargo test (in governance, not in CI)
277
- EXTRA docker build (in CI, not in governance)
118
+ ---
278
119
 
279
- 3 match, 1 drift, 1 missing, 1 extra
280
- ```
120
+ ## What crag detects
281
121
 
282
- Command alias normalization means `npm test` and `npm run test` are treated as equivalent, as are `./gradlew` and `gradlew`.
122
+ ### Languages and runtimes
283
123
 
284
- #### `crag upgrade` Update Skills
124
+ | Family | Detected | Gates emitted |
125
+ |---|---|---|
126
+ | **Node / Deno / Bun** | `package.json`, `deno.json`, `bun.lockb`, `bunfig.toml` | `npm run test/lint/build`, `tsc --noEmit`, `eslint`, `biome check`, `xo`, `deno test/lint/fmt`, `bun test` |
127
+ | **Python** | `pyproject.toml`, `setup.py`, `requirements.txt` | `uv run pytest`, `poetry run pytest`, `pdm run pytest`, `hatch run pytest`, `tox run`, `nox`, `ruff check/format`, `mypy`, `black` — detected per runner |
128
+ | **Rust** | `Cargo.toml`, `Cargo.toml [workspace]` | `cargo test`, `cargo clippy -- -D warnings`, `cargo fmt --check` |
129
+ | **Go** | `go.mod`, `.golangci.yml` | `go test ./...`, `go vet ./...`, `golangci-lint run` |
130
+ | **Java / Kotlin** | `pom.xml`, `build.gradle(.kts)`, Kotlin plugin detection | `./mvnw test verify`, `./gradlew test build`, `checkstyle`, `detekt` |
131
+ | **Ruby** | `Gemfile`, `*.gemspec`, `Rakefile` | `bundle exec rspec`, `bundle exec rake test`, `rubocop`, `standardrb`, `brakeman`, `bundle-audit` |
132
+ | **PHP** | `composer.json`, `phpunit.xml(.dist)` | `composer test`, `vendor/bin/phpunit`, `vendor/bin/pest`, `vendor/bin/phpstan analyse`, `vendor/bin/psalm`, `vendor/bin/phpcs`, `composer validate --strict` |
133
+ | **.NET** | `*.csproj`, `*.fsproj`, `*.sln` | `dotnet test`, `dotnet build`, `dotnet format --verify-no-changes` |
134
+ | **Swift** | `Package.swift` | `swift test`, `swift build`, `swiftlint` |
135
+ | **Elixir** | `mix.exs` | `mix test`, `mix format --check-formatted`, `mix credo --strict`, `mix dialyzer` |
136
+ | **Infrastructure** | `*.tf`, `Chart.yaml`, `Dockerfile`, `openapi.yaml`, `*.proto` | `terraform fmt/validate/plan`, `tflint`, `helm lint`, `hadolint`, `spectral lint`, `buf lint` |
285
137
 
286
- Updates universal skills in the current project to the latest version:
138
+ ### CI systems
287
139
 
288
- ```bash
289
- crag upgrade # Update skills in current project
290
- crag upgrade --check # Dry run — show what would change
291
- crag upgrade --workspace # Update all workspace members
292
- crag upgrade --force # Overwrite locally modified skills (creates backup)
293
- ```
140
+ `crag analyze` parses `run:` / `script:` / `command:` steps from nine CI systems and feeds them through a normalizer that dedupes matrix expansions, filters background processes, and strips shell plumbing:
294
141
 
295
- **How it works:**
296
- - Skills track their version in YAML frontmatter (`version: 0.2.1`)
297
- - A `source_hash` (SHA-256, CRLF-normalized) detects local modifications
298
- - If you modified a skill locally, upgrade won't overwrite it without `--force`
299
- - When force-overwriting, a timestamped backup is created (`SKILL.md.bak.1712252400`)
300
- - Global 24-hour cache at `~/.claude/crag/update-check.json`
301
- - Opt-out: `CRAG_NO_UPDATE_CHECK=1`
142
+ GitHub Actions · GitLab CI · CircleCI · Travis CI · Azure Pipelines · Buildkite · Drone · Woodpecker · Bitbucket Pipelines
302
143
 
303
- #### `crag workspace` — Inspect Workspace
144
+ ### Task runners
304
145
 
305
- Shows the detected workspace, all members, their tech stacks, and governance hierarchy:
146
+ Real target mining not placeholders. Canonical test/lint/build targets extracted from:
306
147
 
307
- ```bash
308
- crag workspace # Human-readable
309
- crag workspace --json # Machine-readable JSON (for CI/scripting)
310
- ```
148
+ - **Makefile** (`.PHONY` directives + column-0 targets)
149
+ - **Taskfile.yml** (`tasks:` sub-keys)
150
+ - **justfile** (recipe names)
311
151
 
312
- Example output:
313
- ```
314
- Workspace: npm
315
- Root: /path/to/monorepo
316
- Config: package.json
317
- Members: 3
318
- Root governance: 2 gate section(s), runtimes: node
319
-
320
- Members:
321
- ✓ backend [node]
322
- packages/backend
323
- ✓ frontend [node] (inherits)
324
- packages/frontend
325
- ○ shared [node]
326
- packages/shared
327
- ```
152
+ ### Workspaces
328
153
 
329
- Use this to debug workspace detection or understand governance inheritance in monorepos.
154
+ Eleven workspace types, enumerated at discovery time:
330
155
 
331
- #### `crag install` Install Global Agent
156
+ pnpm · npm/yarn · Cargo · Go · Gradle · Maven · Nx · Turborepo · Bazel · git submodules · independent nested repos
332
157
 
333
- Installs the `crag-project` interview agent to `~/.claude/agents/` so you can invoke it with `/crag-project` from any Claude Code session:
158
+ ### Frameworks
334
159
 
335
- ```bash
336
- crag install
337
- ```
160
+ Detected from manifest dependencies (runtime deps only — no false positives from dev fixtures):
338
161
 
339
- #### `crag version` / `crag help`
162
+ **Web:** Next.js · React · Vue · Svelte · SvelteKit · Nuxt · Astro · Solid · Qwik · Remix · Express · Fastify · Koa · Hono · NestJS · Phoenix
163
+ **Backend:** Rails · Sinatra · Hanami · Laravel · Symfony · Slim · Yii · CakePHP
340
164
 
341
- ```bash
342
- crag version # Print version
343
- crag help # Print usage
344
- ```
165
+ ### Documentation mining
345
166
 
346
- ### The Session Loop
167
+ `CONTRIBUTING.md` and `.github/PULL_REQUEST_TEMPLATE.md` are scanned for gate candidates in code fences and inline backticks — advisory-only, capped at 5, gated by canonical-verb filter.
347
168
 
348
- Once crag is set up, your workflow in any Claude Code session becomes:
169
+ ---
349
170
 
350
- ```
351
- 1. /pre-start-context → Discovers project, loads governance, checks skill currency
352
- 2. ... your task ... → Write code, fix bugs, add features
353
- 3. /post-start-validation → Runs gates, security review, captures knowledge, commits
354
- ```
171
+ ## Commands
355
172
 
356
- **Pre-start does:**
357
- - Detects workspace type (pnpm, Cargo, Go, Gradle, Maven, Nx, Turbo, Bazel, submodules, nested repos)
358
- - Enumerates members and checks for multi-level governance
359
- - Detects runtime versions (Node, Java, Python, Go, Rust, Docker)
360
- - Reads `governance.md` and applies rules for the session
361
- - Loads cross-session memory (if MemStack enabled)
362
- - Checks skill currency — notifies if `crag upgrade` available
363
-
364
- **Post-start does:**
365
- - Runs governance gates in order (stops on MANDATORY failure; logs OPTIONAL/ADVISORY)
366
- - Auto-fixes mechanical errors (lint, format) with bounded retry
367
- - Runs security review (grep for secrets, check new endpoints)
368
- - Captures knowledge (insights, sessions) if MemStack enabled
369
- - Commits with conventional commit format
370
- - Writes `.session-state.json` for next session's warm start
371
-
372
- ### Common Workflows
373
-
374
- **Workflow 1: Add crag to an existing project**
375
173
  ```bash
376
- cd my-existing-project
377
- npx crag analyze --dry-run # Preview what it would generate
378
- npx crag analyze # Write .claude/governance.md
379
- # Review the generated file, adjust as needed
380
- npx crag check # Verify infrastructure
381
- # Use /pre-start-context in Claude Code
382
- ```
174
+ crag analyze # Generate .claude/governance.md from filesystem
175
+ crag analyze --dry-run # Print what would be generated, don't write
176
+ crag analyze --workspace # Analyze root + every workspace member
177
+ crag analyze --merge # Preserve existing governance, append inferred sections
383
178
 
384
- **Workflow 2: Start a brand new project**
385
- ```bash
386
- mkdir my-new-project && cd my-new-project
387
- git init
388
- npx crag init # Interactive interview
389
- # Follow the prompts — agent asks ~20 questions
390
- # Skills + hooks + agents are all generated
391
- npx crag check
392
- ```
179
+ crag init # Interactive interview (needs Claude Code CLI)
393
180
 
394
- **Workflow 3: Monorepo with per-service governance**
395
- ```bash
396
- cd my-monorepo
397
- npx crag workspace # See detected type + members
398
- npx crag init # Root-level governance
399
- cd packages/backend
400
- npx crag analyze --merge # Add backend-specific gates
401
- cd ../../packages/frontend
402
- npx crag analyze --merge # Add frontend-specific gates
403
- # Now each package has its own governance.md, and root has cross-cutting rules
404
- ```
181
+ crag compile --target <name> # Compile governance to a single target
182
+ crag compile --target all # Compile to all 12 targets at once
183
+ crag compile # List available targets
405
184
 
406
- **Workflow 4: Keep everything current**
407
- ```bash
408
- npx crag upgrade --check # See what would update
409
- npx crag upgrade # Apply updates (preserves local changes)
410
- npx crag diff # Check governance hasn't drifted
411
- npx crag compile --target all # Regenerate CI workflows, hooks, cross-agent files
412
- ```
185
+ crag diff # Compare governance against codebase reality
186
+ crag upgrade # Update universal skills to latest version
187
+ crag upgrade --check # Dry-run: show what would change
188
+ crag check # Verify Claude Code infrastructure is in place
189
+ crag workspace # Inspect detected workspace
190
+ crag workspace --json # Machine-readable workspace report
413
191
 
414
- **Workflow 5: Switch AI tools (Claude → Cursor → Gemini)**
415
- ```bash
416
- npx crag compile --target agents-md # Generate AGENTS.md
417
- npx crag compile --target cursor # Generate .cursor/rules/
418
- npx crag compile --target gemini # Generate GEMINI.md
419
- # Same governance rules now work in Codex, Cursor, Gemini CLI, Aider, Factory
192
+ crag version / crag help
420
193
  ```
421
194
 
422
- ### Troubleshooting
423
-
424
- **Q: `crag init` says "Claude Code CLI not found"**
425
- A: Install Claude Code from https://claude.com/claude-code. Only `init` needs it; other commands don't.
426
-
427
- **Q: `crag upgrade` shows "locally modified" and won't update**
428
- A: You edited a skill file. Either (1) accept that your edits are preserved and stay on the old version, or (2) run `crag upgrade --force` to overwrite (backup is created).
429
-
430
- **Q: `crag analyze` generates nothing useful**
431
- A: It needs signals — CI configs, `package.json` scripts, linter configs. For greenfield projects, use `crag init` for the interview flow instead.
432
-
433
- **Q: `crag diff` reports drift but my CI is working**
434
- A: Drift means `governance.md` says one thing and the codebase uses another. Either update `governance.md` to match reality, or update the codebase to match governance. Both are valid.
435
-
436
- **Q: Skills don't auto-update when I run `/pre-start-context`**
437
- A: Auto-update runs via the CLI commands, not the skill itself. Run `crag upgrade` from your terminal. The skill reports skill version on pre-start so you know when to run upgrade.
438
-
439
- **Q: Multi-level governance not merging correctly**
440
- A: Check that member governance files use `## Gates (inherit: root)` to opt in to inheritance. Without this marker, member governance replaces root.
441
-
442
195
  ---
443
196
 
444
- ## governance.md
197
+ ## The governance file
445
198
 
446
- The only file you maintain. 20-30 lines. Everything else is universal.
199
+ The only file you maintain. 2030 lines. Everything else is universal or generated.
447
200
 
448
201
  ```markdown
449
- # Governance — StructuAI
202
+ # Governance — example-app
450
203
 
451
204
  ## Identity
452
- - Project: StructuAI
453
- - Description: AI-powered Minecraft schematic describer
205
+ - Project: example-app
206
+ - Description: Example project using crag
454
207
 
455
208
  ## Gates (run in order, stop on failure)
456
- ### Frontend
457
- - npx eslint frontend/ --max-warnings 0
458
- - cd frontend && npx vite build
209
+ ### Frontend (path: web/)
210
+ - npx eslint web/ --max-warnings 0
211
+ - cd web && npx vite build
459
212
 
460
213
  ### Backend
461
- - node --check scripts/api-server.js scripts/worker.js scripts/queue.js
462
- - cargo clippy --manifest-path source/decode/Cargo.toml
463
- - cargo test --manifest-path source/decode/Cargo.toml
214
+ - cargo clippy --all-targets -- -D warnings
215
+ - cargo test
464
216
 
465
217
  ### Infrastructure
466
218
  - docker compose config --quiet
467
219
 
468
220
  ## Branch Strategy
469
221
  - Trunk-based, conventional commits
470
- - Auto-commit after all gates pass
222
+ - Auto-commit after gates pass
471
223
 
472
224
  ## Security
473
- - Schematic file uploads only (validate file type server-side)
474
- - No hardcoded secrets or API keys in source
475
- ```
476
-
477
- Change a gate → takes effect next session. Add a security rule → enforced immediately. The skills read this file every time — they never cache stale instructions.
478
-
479
- ### Governance v2 annotations (optional)
480
-
481
- Gate sections support optional annotations for workspace-aware execution:
482
-
483
- ```markdown
484
- ## Gates (run in order, stop on failure)
485
- ### Frontend (path: frontend/) # cd to frontend/ before running
486
- - npx biome check . # [MANDATORY] (default)
487
- - npx tsc --noEmit # [OPTIONAL] — warn but don't fail
488
-
489
- ### TypeScript (if: tsconfig.json) # skip section if file doesn't exist
490
- - npx tsc --noEmit
491
-
492
- ### Audit
493
- - npm audit # [ADVISORY] — informational only
494
-
495
- ## Gates (inherit: root) # merge with root governance
225
+ - No hardcoded secrets or API keys
496
226
  ```
497
227
 
498
- All annotations are optional. Existing governance files work unchanged. Classifications are honored by all compile targets (GitHub Actions `continue-on-error`, husky/pre-commit wrapper scripts).
499
-
500
- ### Multi-level governance (monorepos)
501
-
502
- For projects with multiple sub-repos or services, governance can be hierarchical:
503
-
504
- ```
505
- project-root/
506
- ├── .claude/governance.md # Cross-stack: branch strategy, deployment, security
507
- ├── backend/.claude/governance.md # Backend-specific: Gradle gates, service tests
508
- └── frontend/.claude/governance.md # Frontend-specific: Biome, Vitest, responsive audit
509
- ```
228
+ **Annotations** (all optional):
510
229
 
511
- Each level gets the same universal skills. Each reads its own `governance.md`. Open Claude Code at the root get the cross-stack view. Open it in `backend/` — get backend-specific gates. The skills adapt to wherever you are.
230
+ - `### Section (path: subdir/)` — run this section's gates from `subdir/`
231
+ - `### Section (if: config.json)` — skip if file doesn't exist
232
+ - `- command # [OPTIONAL]` — warn but don't fail
233
+ - `- command # [ADVISORY]` — log only, never block
234
+ - `## Gates (inherit: root)` — merge with root governance (monorepo)
512
235
 
513
236
  ---
514
237
 
515
- ## Workspace Detection
516
-
517
- crag auto-detects 11+ workspace types:
518
-
519
- | Marker | Workspace Type |
520
- |--------|----------------|
521
- | `pnpm-workspace.yaml` | pnpm |
522
- | `package.json` with `"workspaces"` | npm/yarn |
523
- | `Cargo.toml` with `[workspace]` | Cargo |
524
- | `go.work` | Go |
525
- | `settings.gradle.kts` with `include(` | Gradle |
526
- | `pom.xml` with `<modules>` | Maven |
527
- | `nx.json` | Nx |
528
- | `turbo.json` | Turborepo |
529
- | `WORKSPACE` / `MODULE.bazel` | Bazel |
530
- | `.gitmodules` | Git submodules |
531
- | Multiple child `.git` dirs | Independent repos |
238
+ ## Compile targets (12 outputs)
532
239
 
533
- Workspace members are enumerated, checked for their own `.claude/governance.md`, and their tech stacks detected. Multi-level governance merges root gates (mandatory) with member gates (additive).
240
+ | Target | Output | Consumer |
241
+ |---|---|---|
242
+ | `github` | `.github/workflows/gates.yml` | GitHub Actions |
243
+ | `husky` | `.husky/pre-commit` | husky framework |
244
+ | `pre-commit` | `.pre-commit-config.yaml` | pre-commit.com |
245
+ | `agents-md` | `AGENTS.md` | Codex, Aider, Factory, Crush |
246
+ | `cursor` | `.cursor/rules/governance.mdc` | Cursor |
247
+ | `gemini` | `GEMINI.md` | Gemini CLI |
248
+ | `copilot` | `.github/copilot-instructions.md` | GitHub Copilot |
249
+ | `cline` | `.clinerules` | Cline (VS Code) |
250
+ | `continue` | `.continuerules` | Continue.dev |
251
+ | `windsurf` | `.windsurfrules` | Windsurf IDE |
252
+ | `zed` | `.zed/rules.md` | Zed Editor |
253
+ | `cody` | `.sourcegraph/cody-instructions.md` | Sourcegraph Cody |
254
+
255
+ The compiler detects runtime versions from your project (`package.json engines.node`, `pyproject.toml requires-python`, `go.mod` directive, Gradle toolchain). All writes are atomic — partial failures leave the old state intact.
534
256
 
535
257
  ---
536
258
 
537
- ## Governance Compiler — 12 Targets
538
-
539
- `governance.md` is agent-readable. But the gates in it are just shell commands — they can also drive your CI pipeline, git hooks, and configuration for **9 different AI coding agents**. One source of truth, twelve outputs:
540
-
541
- ### Full target list
542
-
543
- | Group | Target | Output path | Consumed by |
544
- |---|---|---|---|
545
- | **CI** | `github` | `.github/workflows/gates.yml` | GitHub Actions |
546
- | **CI** | `husky` | `.husky/pre-commit` | husky pre-commit framework |
547
- | **CI** | `pre-commit` | `.pre-commit-config.yaml` | pre-commit.com framework |
548
- | **AI native** | `agents-md` | `AGENTS.md` | Codex, Aider, Factory, and any tool reading `AGENTS.md` |
549
- | **AI native** | `cursor` | `.cursor/rules/governance.mdc` | Cursor |
550
- | **AI native** | `gemini` | `GEMINI.md` | Google Gemini CLI |
551
- | **AI extras** | `copilot` | `.github/copilot-instructions.md` | GitHub Copilot (VS Code, JetBrains, Visual Studio, Copilot Workspace) |
552
- | **AI extras** | `cline` | `.clinerules` | Cline (VS Code extension) |
553
- | **AI extras** | `continue` | `.continuerules` | Continue.dev |
554
- | **AI extras** | `windsurf` | `.windsurfrules` | Windsurf IDE (Codeium) |
555
- | **AI extras** | `zed` | `.zed/rules.md` | Zed Editor AI assistant |
556
- | **AI extras** | `cody` | `.sourcegraph/cody-instructions.md` | Sourcegraph Cody |
259
+ ## Workspaces
557
260
 
558
261
  ```bash
559
- crag compile --target all # Generate all 12 at once
560
- crag compile --target github # Or pick one
561
- crag compile # Or list targets interactively
562
- ```
563
-
564
- The compiler parses your gates, auto-detects runtimes from the commands (Node, Rust, Python, Java, Go, Docker), and generates the right setup steps with proper version inference from your project files (not hardcoded defaults). Human-readable `Verify X contains Y` gates are compiled to `grep` commands automatically (with shell-injection-safe escaping). All 12 targets write atomically (temp file + rename) so partial failures leave the old state intact.
262
+ crag workspace # Human-readable
263
+ crag workspace --json # Machine-readable
565
264
 
265
+ crag analyze --workspace # Analyze every member and emit per-member gates
566
266
  ```
567
- ┌────────────────────┐
568
- │ governance.md │
569
- │ (one file) │
570
- └──────────┬─────────┘
571
-
572
- crag compile --target all
573
-
574
- ┌─────────────────────────┼─────────────────────────┐
575
- │ │ │
576
- ▼ ▼ ▼
577
- ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
578
- │ CI / hooks │ │ AI native │ │ AI extras │
579
- ├─────────────┤ ├─────────────┤ ├─────────────┤
580
- │ gates.yml │ │ AGENTS.md │ │ Copilot │
581
- │ husky │ │ Cursor MDC │ │ Cline │
582
- │ pre-commit │ │ GEMINI.md │ │ Continue │
583
- └─────────────┘ └─────────────┘ │ Windsurf │
584
- │ Zed │
585
- │ Cody │
586
- └─────────────┘
587
-
588
- + read at runtime by
589
- universal skills
590
- (pre-start / post-start)
591
- ```
592
-
593
- Governance-as-config that compiles to agent behavior, CI/CD pipelines, and **9 different AI coding tool configs** from a single 20-line file.
594
-
595
- ---
596
-
597
- ## Zero-Interview Mode
598
267
 
599
- Don't want an interview? `crag analyze` generates governance from your existing project:
268
+ Detected types: `pnpm` · `npm/yarn` · `cargo` · `go` · `gradle` · `maven` · `nx` · `turbo` · `bazel` · `git-submodules` · `independent-repos`.
600
269
 
601
- ```bash
602
- crag analyze # Infer governance from codebase + CI
603
- crag analyze --dry-run # Preview without writing
604
- crag analyze --workspace # Analyze all workspace members
605
- crag analyze --merge # Merge with existing governance
606
- ```
270
+ Test-fixture directories (`playground/`, `fixtures/`, `examples/`, `demos/`, `__fixtures__/`) are excluded from per-member enumeration so monorepos like Vite don't generate 79 sections for their playground directories.
607
271
 
608
- It reads your CI workflows (recursively, handling `run: |` multiline blocks), `package.json` scripts, linter configs, git history, and deployment configs. Outputs `governance.md` with `# Inferred` markers so you know what to verify.
272
+ Multi-level governance is supported: root governance sets cross-cutting rules (branch strategy, security), member governance adds stack-specific gates via `## Gates (inherit: root)`.
609
273
 
610
274
  ---
611
275
 
612
- ## Governance Drift Detection
276
+ ## The session loop (Claude Code)
613
277
 
614
- `crag diff` compares your `governance.md` against codebase reality:
278
+ Once crag is set up in a Claude Code project, each session is:
615
279
 
616
- ```bash
617
- crag diff
618
280
  ```
619
-
281
+ /pre-start-context → Discovers project, loads governance, caches runtimes
282
+
283
+ your task
284
+
285
+ /post-start-validation → Runs gates, auto-fixes lint/format, commits
620
286
  ```
621
- MATCH node --check bin/crag.js (tool exists)
622
- DRIFT ESLint referenced but biome.json found
623
- MISSING CI gate: cargo test (in governance, not in CI)
624
- EXTRA CI step: docker build (in CI, not in governance)
625
287
 
626
- 3 match, 1 drift, 1 missing, 1 extra
627
- ```
288
+ `/pre-start-context` classifies task intent, uses a content-hashed discovery cache to skip ~80% of redundant scans on unchanged code, and reads `governance.md` fresh every session so the rules are always current.
628
289
 
629
- ---
290
+ `/post-start-validation` runs gates in the order declared in `governance.md`, stops on `[MANDATORY]` failure, retries mechanical errors (lint, format) up to twice with auto-fix, runs a security review, and creates a conventional-commit commit when everything passes.
630
291
 
631
- ## Auto-Update
292
+ ---
632
293
 
633
- Skills track their version in YAML frontmatter. When you run any crag command, it checks for updates:
294
+ ## Installation and requirements
634
295
 
635
296
  ```bash
636
- crag upgrade # Update skills in current project
637
- crag upgrade --workspace # Update all workspace members
638
- crag upgrade --check # Dry run — show what would change
639
- crag upgrade --force # Overwrite locally modified skills (with backup)
297
+ npm install -g @whitehatd/crag
298
+ # or
299
+ npx @whitehatd/crag <command>
640
300
  ```
641
301
 
642
- The update checker queries the npm registry (cached for 24 hours, 3s timeout, graceful failure offline). Skills are only overwritten if the user hasn't modified them local modifications are detected via SHA-256 content hash (CRLF-normalized for cross-platform consistency) and preserved unless `--force` is used.
643
-
644
- ---
302
+ - **Node.js 18+**uses built-in `https`, `crypto`, `fs`, `child_process`. No runtime dependencies.
303
+ - **Git** — for branch strategy inference and the discovery cache.
304
+ - **Claude Code CLI** — only needed for the interactive `crag init` flow. `analyze`, `compile`, `diff`, `upgrade`, `workspace`, `check` all run standalone.
645
305
 
646
- ## What Ships vs What's Generated
647
-
648
- | Component | Source | Maintains itself? |
649
- |-----------|--------|-------------------|
650
- | Pre-start skill | **Ships universal** | Yes — discovers at runtime, caches results, auto-updates |
651
- | Post-start skill | **Ships universal** | Yes — reads governance for gates, auto-fixes, auto-updates |
652
- | `governance.md` | **Generated from interview or analyze** | No — you maintain it (20-30 lines) |
653
- | Hooks | **Generated for your tools** | Yes — sandbox guard + drift detector + gate enforcement |
654
- | Agents | **Generated for your stack** | Yes — read governance for commands |
655
- | Settings | **Generated** | Yes — RTK wildcards cover new tools |
656
- | CI playbook | **Generated template** | You add entries as failures are found |
657
- | Compile targets | **Generated on demand** | `crag compile` regenerates from governance (12 targets) |
658
- | Workspace detection | **Ships universal** | Yes — detects 11+ workspace types at runtime |
659
- | Governance diff | **Ships universal** | Yes — compares governance vs codebase reality |
306
+ The package is published under `@whitehatd/crag` but the binary name is plain `crag` after install.
660
307
 
661
308
  ---
662
309
 
663
- ## Why Everything Else Is Static
310
+ ## Release pipeline
664
311
 
665
- | Current ecosystem | Why it rots | crag's approach |
666
- |-------------------------------------------|--------------------------------------|------------------------------------------------|
667
- | **CLAUDE.md / AGENTS.md** static files | Hardcode project facts; manual edits | **Universal skills** read filesystem every session — always current |
668
- | **Skill collections** (1,234+ skills) | Pick-per-project; stack mismatch | **One engine** that works for any stack |
669
- | **Per-framework templates** | One stack per template; rot on change | **`governance.md`** — 20–30 lines of YOUR rules only, human-controlled |
312
+ Every push to `master` runs the full CI matrix (Ubuntu / macOS / Windows × Node 18 / 20 / 22) and, if tests pass, auto-bumps the patch version and publishes to npm with SLSA provenance attestation. Tags are created automatically. GitHub releases are generated from `CHANGELOG.md`.
670
313
 
671
- **The difference:** everything else tries to pack facts INTO config files. crag reads facts FROM the filesystem at runtime. The skills don't know your stack — they discover it. The governance doesn't know your paths — it holds your rules.
314
+ To skip a release on a specific push, put `crag:skip-release` on its own line in the commit body.
672
315
 
673
316
  ---
674
317
 
675
- ## The Session Loop
318
+ ## Design principles
676
319
 
677
- ```
678
- ┌────────────────────────────────────────────────────────────────┐
679
- │ PRE-START (universal skill — runs before every task) │
680
- │ │
681
- │ Warm start? Intent? Cache valid? │
682
- │ .session-state.json → classify → .discovery-cache.json │
683
- │ │ │ │ │
684
- │ │ │ ┌───────┴───────┐ │
685
- │ │ │ ▼ ▼ │
686
- │ │ │ Fast path Full discovery │
687
- │ │ │ (skip 80%) (detect stack, │
688
- │ │ │ │ load memory) │
689
- │ └────────────────┴──────────┴───────────────┘ │
690
- │ │ │
691
- │ ▼ │
692
- │ Read governance.md │
693
- └───────────────────────────────┬────────────────────────────────┘
694
-
695
-
696
- ┌──────────────────┐
697
- │ YOUR TASK │
698
- │ (code changes) │
699
- └────────┬─────────┘
700
-
701
-
702
- ┌────────────────────────────────────────────────────────────────┐
703
- │ POST-START (universal skill — runs after every task) │
704
- │ │
705
- │ Detect changes → Run gates → (fail?) → Auto-fix → retry │
706
- │ │ │
707
- │ pass │
708
- │ ▼ │
709
- │ Security review → Capture knowledge │
710
- │ │ │
711
- │ ▼ │
712
- │ Write session state · Commit │
713
- └────────────────────────────────┬───────────────────────────────┘
714
-
715
- │ cache + state + knowledge
716
- └─────► feeds next session
717
- ```
718
-
719
- ### What makes this loop tight
320
+ 1. **Discover, don't hardcode.** Every fact about the codebase is read at runtime. Skills never say "22 controllers" — they say "read the controller directory." They never go stale because there is nothing to go stale.
720
321
 
721
- | Feature | What it does | Savings |
722
- |---|---|---|
723
- | **Discovery cache** | Hashes build files, skips unchanged domains | ~80% of pre-start tool calls on unchanged projects |
724
- | **Intent-scoped discovery** | Classifies task, skips irrelevant domains | Skip frontend discovery for backend bugs, and vice versa |
725
- | **Session continuity** | Reads `.session-state.json` for warm starts | Near-zero-latency startup when continuing work |
726
- | **Gate auto-fix** | Fixes lint/format errors, retries gate (max 2x) | Eliminates human round-trip for mechanical failures |
727
- | **Auto-post-start** | Hook warns before commit if gates haven't run | Removes "forgot to validate" failure mode |
728
- | **Sandbox guard** | Hard-blocks destructive commands at hook level | Security at system level, not instruction level |
729
- | **Workspace detection** | Detects 11+ workspace types, enumerates members | Automatic monorepo/polyrepo awareness |
730
- | **Auto-update** | Version-tracked skills with hash-based conflict detection | Skills stay current across all projects |
731
- | **Governance diff** | Compares `governance.md` against actual codebase | Catches drift before it causes failures |
732
-
733
- No agent framework does all of these. Most re-discover cold every session, require manual validation, and trust instructions for safety.
734
-
735
- ---
322
+ 2. **Govern, don't hope.** Your quality bar lives in `governance.md`. Skills enforce it but never modify it. It changes only when you change it.
736
323
 
737
- ## Generated Infrastructure
324
+ 3. **Ship the engine, generate the config.** Universal skills ship once and work for every project. `governance.md` is generated per project. The engine works forever. The config is 20 lines.
738
325
 
739
- ```
740
- .claude/
741
- ├── governance.md # YOUR rules (only custom file)
742
- ├── skills/
743
- │ ├── pre-start-context/SKILL.md # Universal discoverer
744
- │ └── post-start-validation/SKILL.md # Universal validator
745
- ├── hooks/
746
- │ ├── sandbox-guard.sh # Hard-blocks destructive commands
747
- │ ├── auto-post-start.sh # Gate enforcement before commits
748
- │ ├── drift-detector.sh # Checks key files exist
749
- │ ├── circuit-breaker.sh # Failure loop detection
750
- │ ├── pre-compact-snapshot.sh # Memory before compaction
751
- │ └── post-compact-recovery.sh # Memory after compaction
752
- ├── agents/
753
- │ ├── test-runner.md # Parallel tests (Sonnet)
754
- │ ├── security-reviewer.md # Security audit (Opus)
755
- │ ├── dependency-scanner.md # Vulnerability scan
756
- │ └── skill-auditor.md # Infrastructure audit
757
- ├── rules/ # Cross-session memory
758
- ├── ci-playbook.md # Known CI failures
759
- ├── .session-name # Notification routing
760
- ├── .discovery-cache.json # Cached discovery (auto-generated)
761
- ├── .session-state.json # Session continuity (auto-generated)
762
- ├── .gates-passed # Gate sentinel (auto-generated)
763
- └── settings.local.json # Hooks + permissions
764
- ```
326
+ 4. **Enforce, don't instruct.** Hooks are 100% reliable at zero token cost. Prose rules in context files are ~80% compliant. Critical behavior (destructive-command blocks, gate enforcement) goes in hooks.
765
327
 
766
328
  ---
767
329
 
768
- ## Principles
769
-
770
- 1. **Discover, don't hardcode.** Every fact about the codebase is read at runtime. The skills never say "22 controllers" — they say "read the controller directory."
330
+ ## Honest status
771
331
 
772
- 2. **Govern, don't hope.** Your quality bar lives in `governance.md`. The skills enforce it but never modify it. It changes only when you change it.
332
+ - **Published:** 2026-04-04 as `@whitehatd/crag` on npm. Scoped public package.
333
+ - **Tests:** 323 unit tests, passing on Ubuntu/macOS/Windows × Node 18/20/22.
334
+ - **Benchmark:** 17/20 grade A, 0/20 grade C across the 20 reference repos. Reproducible via `benchmarks/results.md`.
335
+ - **Languages fully supported:** Node, Deno, Bun, Python, Rust, Go, Java, Kotlin, Ruby, PHP, .NET, Swift, Elixir (+ Terraform/Helm/K8s infra gates).
336
+ - **CI systems parsed:** 9 (GitHub Actions, GitLab CI, CircleCI, Travis, Azure Pipelines, Buildkite, Drone, Woodpecker, Bitbucket).
337
+ - **Compile targets:** 12 (GitHub Actions, husky, pre-commit, AGENTS.md, Cursor, Gemini, Copilot, Cline, Continue, Windsurf, Zed, Cody).
773
338
 
774
- 3. **Ship the engine, generate the config.** Universal skills ship once. `governance.md` is generated per-project. The engine works forever. The config is 20 lines.
339
+ ### Known limitations
775
340
 
776
- 4. **Enforce, don't instruct.** Hooks are 100% reliable at zero token cost. CLAUDE.md rules are ~80% compliance. Critical behavior goes in hooks.
341
+ - **FastAPI and similar repos** where CI runs via `uv run ./scripts/*.py` data-pipeline scripts: crag captures the script invocations as gates. A user reviewing the output should prune the ones that aren't quality checks.
342
+ - **Complex CI matrix template expansions** (clap's `make test-${{matrix.features}}` pattern): line-based extraction captures one variant per template; multi-line YAML join is not implemented yet.
343
+ - **Jenkinsfile** (Groovy): CI system is detected but step extraction is not attempted.
344
+ - **No telemetry, no network calls** beyond the optional `crag upgrade --check` npm registry ping (24h cached, 3s timeout, graceful offline).
777
345
 
778
- 5. **Compound, don't restart.** Cross-session memory means each session knows what the last one learned. Knowledge self-verifies against source files.
346
+ ### What crag does not do
779
347
 
780
- 6. **Guard, don't trust.** Security hooks hard-block destructive commands at the system level `rm -rf /`, `DROP TABLE`, `curl|bash`, force-push to main. Even if instructions are misread, the sandbox catches it. Defense in depth: hooks enforce what skills instruct.
781
-
782
- 7. **Cache, don't re-discover.** Every discovery result is cached with content hashes. If nothing changed, the next session starts in seconds, not minutes. The cache is advisory — if it's wrong, full discovery runs as normal.
348
+ - It does not write or modify code in your repo.
349
+ - It does not call any LLM. Discovery, analysis, and compilation are pure filesystem operations.
350
+ - It does not replace your CI provider, your linters, or your test runners. It generates config for them.
351
+ - It does not gate-keep. You can add, remove, or edit any gate in `governance.md` at any time.
783
352
 
784
353
  ---
785
354
 
786
- ## Prior Art
787
-
788
- An independent review assessed every major AI coding tool, open-source project, academic paper, and patent filing as of April 2026. The closest candidates and why they differ:
355
+ ## Why "crag"
789
356
 
790
- | Candidate | What it does | Why it's not this |
791
- |---|---|---|
792
- | **AGENTS.md** (60K+ repos) | Static config file AI agents read | Human-maintained, multiple files by scope, no runtime discovery |
793
- | **Claude Code** `/init` + CLAUDE.md | Scans repo, generates static instructions | Generates static output that rots. Multiple files. No governance separation |
794
- | **Cursor** `.cursor/rules/` | Per-directory rule files | Static context, multiple artifacts, no universal engine |
795
- | **Gemini CLI** GEMINI.md hierarchy | JIT instruction file scanning | Discovers *instruction files*, not the project itself |
796
- | **Kiro** steering docs | Generates product/tech/structure docs | Multiple steering files, not single governance, not universal |
797
- | **Codex** AGENTS.md + hooks + skills | Layered static instructions + extensibility | Instruction chain by directory. Could host this engine but doesn't ship one |
798
- | **claude-code-kit** | Framework detection + generated .claude/ | Kit/framework-specific (Next.js, React, Express). Not universal polyglot |
799
- | **OpenDev** (arxiv paper) | CLI agent with lazy tool discovery | Research prototype. No governance file. Not productized |
800
- | **Repo2Run** (arxiv paper) | Repo → runnable Dockerfile synthesis | Build/CI domain only. No agent governance architecture |
801
-
802
- **Adjacent patents identified:**
803
- - **US20250291583A1** (Microsoft) — YAML-configured agent rules/actions. Covers "config file drives AI agents" broadly but not universal repo discovery.
804
- - **US9898393B2** (Solano Labs) — Repo pattern analysis → inferred CI config. Strong historic prior art for build-system discovery, but not AI agent governance.
805
-
806
- Neither patent blocks this architecture. Both are adjacent, not overlapping.
807
-
808
- **Three novelty hypotheses validated by the review:**
809
- 1. **Compositional:** Many systems have pieces (hooks, skills, context files). None compose them into universal discovery engine + single governance file + continuously regenerated artifacts.
810
- 2. **Scope:** Closest implementations (claude-code-kit) are framework-specific, not polyglot-universal.
811
- 3. **Governance-as-contract:** Existing tools treat instruction files as context (often non-enforced). This treats governance as an executable contract that deterministically shapes gates and commit behavior.
357
+ A crag is a rocky outcrop — an unmoving landmark that stands while seasons, paths, and generations change around it. Your skills discover, your gates run, your CI regenerates — but `governance.md`, the crag, doesn't move until you say so. Your AI agents anchor to it.
812
358
 
813
359
  ---
814
360
 
815
- ## Roadmap
816
-
817
- - [x] Universal pre-start and post-start skills
818
- - [x] Interview-driven governance generation
819
- - [x] CLI (`crag init`, `crag check`, `crag install`)
820
- - [x] Proven on 5-language multi-service project (StructuAI)
821
- - [x] Proven on full-stack monolith with blue-green deploys (Leyoda)
822
- - [x] Proven on 11-microservice K8s platform with dual-repo governance (MetricHost)
823
- - [x] Multi-level governance hierarchy (root + backend + frontend)
824
- - [x] `crag compile` — governance.md → GitHub Actions, husky, pre-commit, AGENTS.md, Cursor, Gemini
825
- - [x] Incremental discovery cache — content-addressed, skips 80% of pre-start on unchanged projects
826
- - [x] Intent-scoped discovery — classifies task, skips irrelevant domains
827
- - [x] Session continuity — warm starts via `.session-state.json`
828
- - [x] Gate auto-fix loop — fixes lint/format errors automatically, bounded retry (max 2x)
829
- - [x] Auto-post-start hook — gate enforcement before commits
830
- - [x] Sandbox guard — hard-blocks destructive commands (rm -rf /, DROP TABLE, curl|bash, force-push main)
831
- - [x] `crag analyze` — generate governance from existing project without interview
832
- - [x] `crag diff` — compare governance against codebase reality
833
- - [x] `crag upgrade` — update universal skills when new version ships
834
- - [x] `crag workspace` — inspect detected workspace type and members
835
- - [x] Workspace detection — 11+ types (pnpm, npm, Cargo, Go, Gradle, Maven, Nx, Turbo, Bazel, submodules, nested repos)
836
- - [x] Governance v2 format — path-scoped gates, conditional sections, mandatory/optional/advisory classification
837
- - [x] Auto-update — version tracking, npm registry check, content-hash conflict detection
838
- - [x] Cross-agent compilation — **12 targets** (GitHub Actions, husky, pre-commit, AGENTS.md, Cursor, Gemini, Copilot, Cline, Continue, Windsurf, Zed, Sourcegraph Cody)
839
- - [x] Modular architecture — 24 modules across 6 directories (zero dependencies)
840
- - [x] Test suite — 159 tests covering parse, integrity, detect, enumerate, merge, compile, version, shell, CLI, 6 new compile targets, analyze internals, diff internals
841
- - [x] Published on npm as `@whitehatd/crag`
842
- - [x] GitHub Actions CI/CD — multi-OS (Ubuntu/macOS/Windows) × multi-Node (18/20/22) test matrix, automated npm publish with SLSA provenance, stale issue cleanup
843
- - [ ] Cross-repo benchmark — 20-30 repos, measure coverage %, false positives, failure modes
844
- - [ ] Drift resilience test — add services, change linters, rename directories. Does the engine re-discover?
845
- - [ ] Baseline comparison — same governance in AGENTS.md, CLAUDE.md, .cursor/rules, GEMINI.md
846
- - [ ] crag Cloud (paid tier) — hosted governance registry, cross-repo dashboard, team library, compliance templates, drift alerts
361
+ ## Contributing
362
+
363
+ Issues and PRs welcome at [github.com/WhitehatD/crag](https://github.com/WhitehatD/crag). See [CONTRIBUTING.md](./CONTRIBUTING.md) for the workflow.
364
+
365
+ If you run crag on a repo and it misses something — a language, a CI system, a gate pattern — that's the bug report I want most. Include the URL of the repo and a paste of `crag analyze --dry-run` output.
847
366
 
848
367
  ---
849
368
 
850
369
  ## License
851
370
 
852
- MIT
853
-
854
- ---
371
+ MIT — see [LICENSE](./LICENSE).
855
372
 
856
- *Built by [Alexandru Cioc (WhitehatD)](https://github.com/WhitehatD)*
373
+ Built by [Alexandru Cioc (WhitehatD)](https://github.com/WhitehatD).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whitehatd/crag",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "The bedrock layer for AI coding agents. One governance.md. Any project. Never stale.",
5
5
  "bin": {
6
6
  "crag": "bin/crag.js"
@@ -21,7 +21,7 @@
21
21
 
22
22
  const fs = require('fs');
23
23
  const path = require('path');
24
- const { extractRunCommands } = require('../governance/yaml-run');
24
+ const { extractRunCommands, stripYamlQuotes } = require('../governance/yaml-run');
25
25
  const { safeRead } = require('./stacks');
26
26
 
27
27
  /**
@@ -165,7 +165,7 @@ function extractCircleCommands(content) {
165
165
  const rest = inline[1].trim();
166
166
  if (rest && !rest.startsWith('#') && !rest.startsWith('|') && !rest.startsWith('>') &&
167
167
  !rest.startsWith('{') && !rest.startsWith('name:') && !rest.startsWith('command:')) {
168
- commands.push(rest.replace(/^["']|["']$/g, ''));
168
+ commands.push(stripYamlQuotes(rest));
169
169
  }
170
170
  }
171
171
  // Nested: command: ...
@@ -173,7 +173,7 @@ function extractCircleCommands(content) {
173
173
  if (cmdMatch) {
174
174
  const rest = cmdMatch[1].trim();
175
175
  if (rest && !rest.startsWith('|') && !rest.startsWith('>') && !rest.startsWith('#')) {
176
- commands.push(rest.replace(/^["']|["']$/g, ''));
176
+ commands.push(stripYamlQuotes(rest));
177
177
  } else if (rest === '|' || rest === '>-' || rest.startsWith('|') || rest.startsWith('>')) {
178
178
  // Block scalar — collect following lines with greater indent
179
179
  const baseIndent = (line.match(/^(\s*)/) || ['', ''])[1].length;
@@ -220,7 +220,7 @@ function extractAzureCommands(content) {
220
220
  commands.push(inner.trim());
221
221
  }
222
222
  } else if (rest && !rest.startsWith('#')) {
223
- commands.push(rest.replace(/^["']|["']$/g, ''));
223
+ commands.push(stripYamlQuotes(rest));
224
224
  }
225
225
  }
226
226
  return commands;
@@ -287,7 +287,7 @@ function extractYamlListField(content, fields) {
287
287
  if (innerIndent <= baseIndent) break;
288
288
  const listItem = inner.match(/^\s*-\s*(.+)$/);
289
289
  if (listItem) {
290
- commands.push(listItem[1].trim().replace(/^["']|["']$/g, ''));
290
+ commands.push(stripYamlQuotes(listItem[1].trim()));
291
291
  }
292
292
  }
293
293
  } else if (/^[|>][+-]?\s*$/.test(rest)) {
@@ -303,11 +303,11 @@ function extractYamlListField(content, fields) {
303
303
  // Inline list: script: [cmd1, cmd2]
304
304
  const inner = rest.slice(1, rest.indexOf(']') === -1 ? rest.length : rest.indexOf(']'));
305
305
  for (const item of inner.split(',')) {
306
- const trimmed = item.trim().replace(/^["']|["']$/g, '');
306
+ const trimmed = stripYamlQuotes(item.trim());
307
307
  if (trimmed) commands.push(trimmed);
308
308
  }
309
309
  } else if (!rest.startsWith('#')) {
310
- commands.push(rest.replace(/^["']|["']$/g, ''));
310
+ commands.push(stripYamlQuotes(rest));
311
311
  }
312
312
  }
313
313
 
@@ -94,6 +94,22 @@ function isNoise(cmd) {
94
94
  // License checkers are typically gates, but their exact invocation is
95
95
  // long and project-specific. Keep them.
96
96
 
97
+ // Dev/maintenance scripts under a `scripts/` directory are one-off tasks,
98
+ // not gates. FastAPI runs its doc, sponsor, people, translation pipelines
99
+ // this way via `uv run ./scripts/*.py`. These are publishing automations,
100
+ // not quality checks.
101
+ if (/^(uv|poetry|pdm|hatch|rye|pipenv)\s+run\s+(\.\/)?scripts\//.test(trimmed)) return true;
102
+ if (/^python3?\s+(\.\/)?scripts\//.test(trimmed)) return true;
103
+ if (/^node\s+(\.\/)?scripts\//.test(trimmed)) return true;
104
+ if (/^(bash|sh)\s+(\.\/)?scripts\//.test(trimmed)) return true;
105
+ if (/^npx\s+(tsx?|ts-node)\s+(\.\/)?scripts\//.test(trimmed)) return true;
106
+
107
+ // Shell control-flow fragments leaked from block scalars. When a `run: |`
108
+ // wraps a multi-line if/for/while/case, our line-based extractor pulls out
109
+ // the control keyword line as a pseudo-command.
110
+ if (/^(if|then|else|elif|fi|for|do|done|while|until|case|esac)\s/.test(trimmed)) return true;
111
+ if (/^(then|else|fi|do|done|esac)$/.test(trimmed)) return true;
112
+
97
113
  return false;
98
114
  }
99
115
 
@@ -1,5 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ /**
4
+ * Strip surrounding matching quotes from a YAML scalar value.
5
+ *
6
+ * Only strips when the ENTIRE string is wrapped in matching single or double
7
+ * quotes. Previously we used `replace(/^["']|["']$/g, '')` which stripped a
8
+ * trailing quote even when no leading quote existed — that truncated commands
9
+ * like `make test-X ARGS='--workspace --benches'` to `make test-X ARGS='--workspace --benches`.
10
+ */
11
+ function stripYamlQuotes(str) {
12
+ const m = str.match(/^(['"])(.*)\1$/);
13
+ return m ? m[2] : str;
14
+ }
15
+
3
16
  /**
4
17
  * Shared YAML `run:` command extraction for GitHub Actions workflows.
5
18
  *
@@ -42,8 +55,7 @@ function extractRunCommands(content) {
42
55
  if (trimmed && !trimmed.startsWith('#')) commands.push(trimmed);
43
56
  }
44
57
  } else if (rest && !rest.startsWith('#')) {
45
- // Inline: strip surrounding single/double quotes if present
46
- commands.push(rest.replace(/^["']|["']$/g, ''));
58
+ commands.push(stripYamlQuotes(rest));
47
59
  }
48
60
  }
49
61
 
@@ -142,4 +154,4 @@ function isGateCommand(cmd) {
142
154
  return patterns.some((p) => p.test(cmd));
143
155
  }
144
156
 
145
- module.exports = { extractRunCommands, isGateCommand };
157
+ module.exports = { extractRunCommands, isGateCommand, stripYamlQuotes };