Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e43df62
fix(hooks): strip heredoc bodies before classifying, so a file body t…
roadhero Sep 6, 2026
28ce2c9
fix(hooks): one quote model for the data strip, carried across lines
roadhero Sep 6, 2026
3eb4d53
fix(hooks): the walker never treats bash code as data: arithmetic, co…
roadhero Sep 6, 2026
843f28a
fix(hooks): unquoted heredoc bodies still expand substitutions; join …
roadhero Sep 6, 2026
2e607ae
fix(hooks): comments start only at a word start; frames for ${ } and …
roadhero Sep 6, 2026
51ea0c5
fix(hooks): bodies start and end on parser state, not the physical li…
roadhero Sep 6, 2026
2fa95cc
fix(hooks): case counted only in command position; a ) unwinds to the…
roadhero Sep 6, 2026
0d94b8e
fix(hooks): separators are text inside expansion and arithmetic frame…
roadhero Sep 6, 2026
1c26efb
fix(hooks): glue short quoted fragments back into their word; fast pa…
roadhero Sep 6, 2026
02845b7
fix(hooks): quoted separators are data; ANSI-C numeric escapes fail c…
roadhero Sep 6, 2026
fb4540a
test(hooks): the unicode-escape case actually uses a unicode escape
roadhero Sep 6, 2026
b36ad83
fix(hooks): the fast-path retry runs for any unmatched payload; every…
roadhero Sep 6, 2026
3617ab9
fix(hooks): a newline separates commands only at the top level; conti…
roadhero Sep 6, 2026
7a2f4cd
fix(hooks): separators inside $( ) never split the enclosing command;…
roadhero Sep 6, 2026
1bd0577
fix(hooks): a newline ends the enclosing command only outside every e…
roadhero Sep 6, 2026
50bbd77
fix(hooks): stdin-fed shells, trap, and -c clusters are wrappers; pro…
roadhero Sep 6, 2026
31273da
fix(hooks): the wrapper rule is stated, not enumerated; same-call git…
roadhero Sep 6, 2026
17b47e6
fix(hooks): real command boundaries are a sentinel byte; redirection …
roadhero Sep 6, 2026
d60b5d9
fix(hooks): keep a dropped quoted span as one argument; refuse a raw …
roadhero Sep 6, 2026
b6c7680
fix(hooks): subscripts are text, expansions leave a mark, run-time pa…
roadhero Sep 6, 2026
192a225
docs: say the guard strips data before checking and refuses what it c…
roadhero Sep 6, 2026
1832493
fix(hooks): a ${...} word is its `$`; `)` inside it is text; `[` outs…
roadhero Sep 6, 2026
90d648a
fix(hooks): `[` inside ${...} is text; a `}` over an open inner frame…
roadhero Sep 6, 2026
7642359
fix(hooks): a ${...} spanning lines emits nothing; case patterns end …
roadhero Sep 6, 2026
b5c5f02
fix(hooks): a heredoc pending inside an open ${...} is refused; backt…
roadhero Sep 6, 2026
b6e7509
fix(hooks): a heredoc before a substitution is refused; whole-arg-quo…
roadhero Sep 6, 2026
0f7b305
fix(hooks): an empty quote is an argument only when it is a whole wor…
roadhero Sep 6, 2026
a24c28a
fix(hooks): a bare $name expansion leaves a mark, like ${...}, so an …
roadhero Sep 6, 2026
e986453
fix(hooks): a possibly-empty expansion inside double quotes cannot gl…
roadhero Sep 6, 2026
991fc08
fix(hooks): refuse a ${parameter:-default} whose default value is a flag
roadhero Sep 6, 2026
e1a97c4
fix(hooks): the flag-default refuse also covers alternate operators a…
roadhero Sep 6, 2026
1ae042e
fix(hooks): a brace-default value that is a flag, a +refspec, or a co…
roadhero Sep 6, 2026
ff4bf18
fix(hooks): a config or identity value built from an expansion is cau…
roadhero Sep 6, 2026
1126b90
fix(hooks): a same-call `git config user.name/email` to a bot is refu…
roadhero Sep 6, 2026
8d9c372
fix(hooks): the config-identity check reads the stripped text and ref…
roadhero Sep 6, 2026
d398035
fix(hooks): the config-identity refuse skips short option flags too (…
roadhero Sep 6, 2026
38ccdba
fix(hooks): the config-identity refuse also skips an equals-glued opt…
roadhero Sep 6, 2026
9794db5
fix(hooks): the config-identity expansion refuse is case-insensitive,…
roadhero Sep 6, 2026
b0d8a8e
docs: set §19.4 live version to v1.0.7
roadhero Sep 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Requires `shellcheck`, `jq`, and `git` (the hooks need `jq` at runtime too) —

### 19.4 Current release pointers

- **Live version:** v1.0.6 (annotated tag, latest on `main`).
- **Live version:** v1.0.7 (annotated tag, latest on `main`).
- **In flight:** none (set per session).
- **CHANGELOG:** none — release notes are the GitHub Release body, generated from `git log` between tags.
- **Spec / PRD:** `README.md` + `STRUCTURE.md` are canonical.
Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ Most people publish a single `CLAUDE.md` and call it a setup. The thing that act

## What's inside

| Path | What it is |
| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLAUDE.md` | The universal spine — a lean (~220-line) always-loaded core: workflow, git rules, coding guidelines, secrets, anti-patterns. Stack-agnostic. Longer reference material lives in `docs/` and loads on demand. |
| `rules/{web,android,ios,compute}.md` | Platform rule packs. Each carries a `paths:` frontmatter glob; Claude Code loads a pack when it reads a file matching that glob (`*.kt` → android, `*.swift` → ios, `*.ts`/`*.py` → web, `*.cpp`/`*.cu` → compute). Path-triggered, so packs whose files you never touch stay out of context. |
| `agents/` (15) | The default subagent roster: the four-hat chain (architect → senior-swe → code-reviewer → qa), plus specialists (security, performance, db-migration, debugger, devops, docs, design), release-engineer + tech-writer, and a delivery layer (TPM, scrum-master). |
| `agents-android/` (7), `agents-ios/` (7), `agents-compute/` (13) | Per-stack overrides. Drop them into a repo's `.claude/agents/` and they override the generic ones of the same name with platform-brained versions. |
| `hooks/guard-commit.sh` | A Claude Code Bash hook (PreToolUse) that blocks the _agent_ from force-pushing, skipping git hooks with `--no-verify`, committing as a non-human, writing AI attribution into a commit message, or staging obvious secrets. Every segment of a chained command is checked on its own. It guards Claude's git commands — not a human typing `git` directly in their own terminal. |
| `hooks/format.sh` | Auto-formats edited files by extension across every stack. Missing formatter is a silent no-op, never an error. |
| `tests/hooks/` | Behavioral tests for both hooks: a JSON payload on stdin, an exit code out, one case per rule and per past regression. Plain bash 3.2 + `jq`. CI (`.github/workflows/gate.yml`) runs them with the rest of the quality gate on every PR. |
| `skills/new-repo/` | A scaffolder skill: spins up a new repo with the right `CLAUDE.md`, `.gitignore`, quality gate, and release workflow. Scaffolds **web + Android**; iOS and compute ship as rule + agent packs (no scaffolder for them yet). |
| `docs/` | On-demand reference the spine points to (full roster tables, the Phase-3 review checklist, the error-recovery table, PR template, scaling notes). Installed to `~/.claude/docs/`; loaded only when a stub references it. |
| `templates/` | Blank project `CLAUDE.md` templates (generic + compute) to copy into a new repo and fill in. |
| `examples/CLAUDE.example-web.md` | A filled-in example so you can see what "done" looks like before you write your own. |
| `STRUCTURE.md` | The full layout, install steps, and how the two-settings-file swap works. **Read this first.** |
| Path | What it is |
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLAUDE.md` | The universal spine — a lean (~220-line) always-loaded core: workflow, git rules, coding guidelines, secrets, anti-patterns. Stack-agnostic. Longer reference material lives in `docs/` and loads on demand. |
| `rules/{web,android,ios,compute}.md` | Platform rule packs. Each carries a `paths:` frontmatter glob; Claude Code loads a pack when it reads a file matching that glob (`*.kt` → android, `*.swift` → ios, `*.ts`/`*.py` → web, `*.cpp`/`*.cu` → compute). Path-triggered, so packs whose files you never touch stay out of context. |
| `agents/` (15) | The default subagent roster: the four-hat chain (architect → senior-swe → code-reviewer → qa), plus specialists (security, performance, db-migration, debugger, devops, docs, design), release-engineer + tech-writer, and a delivery layer (TPM, scrum-master). |
| `agents-android/` (7), `agents-ios/` (7), `agents-compute/` (13) | Per-stack overrides. Drop them into a repo's `.claude/agents/` and they override the generic ones of the same name with platform-brained versions. |
| `hooks/guard-commit.sh` | A Claude Code Bash hook (PreToolUse) that blocks the _agent_ from force-pushing, skipping git hooks with `--no-verify`, committing as a non-human, writing AI attribution into a commit message, or staging obvious secrets. Every segment of a chained command is checked on its own. Quoted text, heredoc bodies, substitutions, and arithmetic are stripped as data first, so a commit message or a file body that merely mentions a blocked flag never trips it; a shape the check cannot classify (a shell wrapper of any form, a substitution inside `${...}`, an unquoted pattern in a commit or push, git config passed through the environment) is refused rather than guessed. It guards Claude's git commands — not a human typing `git` directly in their own terminal. |
| `hooks/format.sh` | Auto-formats edited files by extension across every stack. Missing formatter is a silent no-op, never an error. |
| `tests/hooks/` | Behavioral tests for both hooks: a JSON payload on stdin, an exit code out, one case per rule and per past regression. Plain bash 3.2 + `jq`. CI (`.github/workflows/gate.yml`) runs them with the rest of the quality gate on every PR. |
| `skills/new-repo/` | A scaffolder skill: spins up a new repo with the right `CLAUDE.md`, `.gitignore`, quality gate, and release workflow. Scaffolds **web + Android**; iOS and compute ship as rule + agent packs (no scaffolder for them yet). |
| `docs/` | On-demand reference the spine points to (full roster tables, the Phase-3 review checklist, the error-recovery table, PR template, scaling notes). Installed to `~/.claude/docs/`; loaded only when a stub references it. |
| `templates/` | Blank project `CLAUDE.md` templates (generic + compute) to copy into a new repo and fill in. |
| `examples/CLAUDE.example-web.md` | A filled-in example so you can see what "done" looks like before you write your own. |
| `STRUCTURE.md` | The full layout, install steps, and how the two-settings-file swap works. **Read this first.** |

## The idea in one paragraph

Two tiers. The **global** tier (`~/.claude/CLAUDE.md` + `rules/` + `agents/` + `hooks/`) is everything that's true regardless of what you're building. The **project** tier is a short `CLAUDE.md` at the repo root that holds only what's specific to that project (§19: stack, quality gate, release pointers, compliance scope). The spine gets prompt-cached and never changes; the project file is the only thing you edit per repo. Rules specialize by path-trigger (a pack loads when Claude reads a file its `paths:` glob matches); agents specialize by name-override (a repo's `.claude/agents/<name>.md` shadows the global agent of the same name). Neither scans the repo up front. You configure once, then mostly leave it alone.

## Install

Mac/Linux, with Claude Code already installed. Full steps and the per-repo install are in [`STRUCTURE.md`](./STRUCTURE.md). First install the hook prerequisite `jq` (`guard-commit.sh` fails closed without it): `brew install jq` (macOS) / `sudo apt-get install jq` (Debian/Ubuntu). Then:
Mac/Linux, with Claude Code already installed. Full steps and the per-repo install are in [`STRUCTURE.md`](./STRUCTURE.md). First install the hook prerequisite `jq` (`guard-commit.sh` fails closed without it): `brew install jq` (macOS) / `sudo apt-get install jq` (Debian/Ubuntu); the guard also needs git 2.28 or newer. Then:

```bash
git clone https://github.com/roadhero/claude-code-setup.git && cd claude-code-setup
Expand Down
Loading