Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to this project. Format: [Keep a Changelog](https://keepacha

- **feat: generate `templates/INDEX.md`, scaffold `.claude/workflows/`, and document teams / channels / routines.** Three gaps the currency audit left open. **(1)** `templates/INDEX.md` was hand-maintained and had gone stale enough to mislead — it still referenced a `configurator.html` that no longer exists and was missing half the modules. It is now **generated** from `MODULES` by `python3 configure.py --write-index`, and `--check` fails when the committed copy and the generator disagree, so it cannot drift again. **(2)** Dynamic workflows have been a first-class Claude Code surface since 2.1.154 and the configurator scaffolded nothing for them. The `multi-agent` module now ships `.claude/workflows/spec-fanout.js` (runs as `/spec-fanout`), which generates N variants of one spec into disjoint slots and then **screens each variant against the spec** before reporting. It is the workflow-native successor to the `/infinite` skill in the same module — same job, but the runtime holds the loop and the intermediate results, the run is resumable, and the screening pass is a real gate rather than a suggestion. Project workflows under `.claude/workflows/` are shared with everyone who clones the repo. `--check` gained a rule validating that every shipped workflow declares a usable `meta` block and uses no `import()` (the runtime rejects both). `workflowSizeGuideline` is stubbed in `settings.local.json.example`. **(3)** `docs/04` gains a table comparing the five ways to run work in parallel (subagent / skill / agent team / workflow / worktree session) by *who holds the plan*, and states plainly why the configurator ships no templates for agent teams, channels or routines: teams are spawned in conversation and live for a session (only `teammateMode` is worth setting, and it's a per-machine terminal preference — stubbed in settings.local); the channel gate keys `channelsEnabled` and `allowedChannelPlugins` are **managed-settings only**, so a project cannot enable them; and routines are scheduled cloud agents that run against a repo rather than from your checkout, where a `Stop` or `SessionStart` hook is the project-scoped equivalent.

- **feat(hooks): PowerShell hook variants behind `--hook-shell powershell`.** The `shell: "bash"` fix covers Windows *with* Git Bash; this covers the machines without it, where `"bash"` has nothing to resolve to. Six hooks now ship a `.ps1` sibling — `block-dangerous-bash`, `scan-secrets`, `format-on-write`, `stop-run-checks`, `pre-compact-snapshot`, `microbit-enforcer` — and `--hook-shell powershell` swaps a `.sh` for its sibling **by name, per entry**, setting `"shell": "powershell"` on just those hooks. Everything without a sibling stays bash, which is correct rather than lazy: `check-package-availability` probes apt/brew and `sessionstart-drift-check` is jq-driven, so both are Linux/macOS-shaped by nature. The answer persists to `.claude-config.json` like the rest of the intake; the default is unchanged. **Three Windows-specific traps, each found by running the hooks rather than reading about them:** **(a)** Windows PowerShell 5.1 — still the default — reads `.ps1` as the system ANSI code page unless the file has a BOM. A UTF-8 em-dash decodes to a cp1252 smart quote, which PowerShell accepts as a *string delimiter*: the string terminated mid-line and `microbit-enforcer.ps1` failed to parse. All shipped `.ps1` are ASCII and BOM-free, and `--check` enforces that (plus the `.sh` pairing, since an orphan `.ps1` would never be installed). **(b)** Windows ships execution policy `Restricted`, so naming a `.ps1` directly fails with *"running scripts is disabled on this system"* — a silent, machine-dependent break of exactly the kind this work exists to prevent. The generated command spawns PowerShell with `-ExecutionPolicy Bypass`, which applies only to that child process running a script the user installed deliberately, and never changes machine policy. **(c)** A wrapping `powershell -Command` collapses any non-zero child exit to `1`, which would have turned a `PreToolUse` **block** (exit 2) into a mere non-blocking error — the safety hooks would have appeared to work while silently permitting everything. The command ends with `; exit $LASTEXITCODE`; exit 2 was then verified to survive both a direct `-File` invocation and a `-Command` wrapper. The SessionStart marker-clear is not a script but an inline `rm -f … || true`, which is not valid PowerShell, so it gets an explicit translation. A `target_path_for` routing rule keyed to `.sh` was widened, or `microbit-enforcer.ps1` would have been routed to `.claude/skills/` and silently never installed — caught by asserting that every settings entry resolves to a file on disk. New `test/portability/test-powershell-hooks.sh` checks the wiring on any platform and executes the hooks wherever PowerShell is present (`pwsh` ships on all three GitHub runner images); README and `docs/03` document the flag, the policy tradeoff, and which hooks stay bash.

- **fix(commands): rename `/review` → `/review-branch` so it stops shadowing the bundled `/code-review`.** CC 2.1.223 made `/review` the alias of the bundled `/code-review` — Claude Code's multi-agent reviewer, including the cloud `ultra` mode. A project skill of that name wins it (verified headlessly on 2.1.241: a project skill named `review` ran for `/review`, and the same held for `plan` against the built-in `/plan`), so **every scaffolded project was silently hiding the better built-in behind this simpler single-pass skill** — overlap that turned into a real capability loss the day the alias shipped. The skill moves to `templates/commands/review-branch/` with `name: review-branch`, and its description now positions it honestly ("a quick single-pass review; Claude Code's bundled `/code-review` is the deeper multi-agent one"). Both are reachable again. Updated across `config_schema.py`, `configure.py`'s pattern-integration map, `templates/INDEX.md`, the `/investigate` and `/plan-eng-review` cross-references, docs 02/03/05/09/10/11, README, and the example project. **Migration:** the configurator has no mechanism to delete a file it previously wrote, so an upgraded project keeps the old `.claude/skills/review/` alongside the new one — and the stale copy still shadows the alias. New `/verify-setup` **check 13** detects exactly that pair and tells the user to `rm -rf .claude/skills/review`. `/plan` is left alone deliberately: it shadows a built-in *command* rather than a bundled skill, and plan mode stays reachable via Shift+Tab, so it's a name clash rather than a lost capability — README now says so and points at the rename if you'd rather keep the shortcut.

- **docs: re-baseline the MCP context claims against tool search, and scope `/infinite` against dynamic workflows.** Two of the project's headline claims had been overtaken by Claude Code and were overstating what the modules buy. **MCP.** README claimed per-task profiles "drop a bloated 4-MCP baseline from ~49% context to under 5%", and `docs/04` asserted "every MCP tool is a chunk of JSON schema loaded at session start". Tool search defers MCP schemas by default (`alwaysLoad: true` is the opt-*out*), so the premise no longer holds. Measured rather than re-guessed — four local stdio servers advertising twelve tools each (48 total) against an otherwise identical one-turn session on CC 2.1.245: **26,665 tokens with no MCP servers, 27,361 deferred (+696, ~14/tool), 40,993 with `alwaysLoad: true` (+14,328, ~298/tool)** — deferral removes ~95% of the schema cost, and the numbers reproduced exactly across runs. The claim was also embedded in four *shipped* templates, which is worse than in the docs because it lands in every user's project: `check-context/SKILL.md` (its budget guardrails and the "MCP > 10%" flag), `claude-ctx.sh`'s rationale comment, `servers-cookbook.md` (which already explained deferral correctly a few sections earlier, so it contradicted itself), and the `mcp.minimal.json` profile comment. All corrected. Profiles are now documented for what they still genuinely buy — which servers *connect*: startup time, auth prompts, cold start, and the blast radius `--strict-mcp-config` enforces — and `docs/06` picks up the same correction. The dated `experiments-memory` example keeps its original result with a superseding **addendum** rather than a rewrite, because an experiment log records what was true when it ran. **`/infinite`.** Dynamic workflows now do staged, resumable, budgeted fan-out with structured output between stages; hand-rolled wave batching is the weaker instrument for that job. The skill opens with a decision table sending staged / merge-heavy / resumable work to a workflow, and keeps the one case it is genuinely good at — N variants of a single spec into disjoint slots with no cross-iteration coordination. README's module row and a new `docs/04` section say the same.
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Headless CLI that generates Claude Code project scaffolding — `CLAUDE.md`, `.c
| --- | --- |
| **Linux** (Debian/Ubuntu/Arch/Fedora/…) | Primary target. Everything works out of the box. |
| **macOS** (12+) | Works, and exercised in CI (`portability (macos-latest)`). Bash 3.2 from the system is sufficient — no shipped script uses a bash 4+ construct. GNU `timeout` isn't present by default, so the `safety` package-availability gate runs its probes unbounded unless you have coreutils (`brew install coreutils` gives `gtimeout`, which the hook also accepts). |
| **Windows** | Claude Code 2.1.120+ runs natively on Windows — when Git Bash is absent, Claude Code falls back to PowerShell as its shell tool. The `.sh` hook scripts this project ships still need a bash interpreter, so every shipped hook entry declares `"shell": "bash"` (honored by Claude Code 2.1.81+): with Git for Windows installed the hooks run under Git Bash even when Claude Code's own shell tool fell back to PowerShell, and without it Claude Code prompts to install Git Bash instead of failing silently. Alternatives: use WSL, or translate a hook to PowerShell and set `"shell": "powershell"` on its entry. The template directory uses `dot-claude/` (rewritten to `.claude/` at install) so the templates browse and sync cleanly on filesystems and tools that special-case dotfiles. Scaffolding from Windows is exercised in CI (`portability (windows-latest)`): generated files are written with LF on every platform and the scaffold appends a `.gitattributes` block pinning it, so a Windows-authored `.claude/` still runs on a teammate's Linux/macOS checkout. Git can't carry the executable bit the same way — after your first `git add`, run `git update-index --chmod=+x claude-ctx` (the generated `CLAUDE.md` says so too). |
| **Windows** | Claude Code 2.1.120+ runs natively on Windows — when Git Bash is absent, Claude Code falls back to PowerShell as its shell tool. The `.sh` hook scripts this project ships still need a bash interpreter, so every shipped hook entry declares `"shell": "bash"` (honored by Claude Code 2.1.81+): with Git for Windows installed the hooks run under Git Bash even when Claude Code's own shell tool fell back to PowerShell, and without it Claude Code prompts to install Git Bash instead of failing silently. For a Windows machine with no Git Bash at all, `--hook-shell powershell` installs PowerShell variants of the six core hooks (`block-dangerous-bash`, `scan-secrets`, `format-on-write`, `stop-run-checks`, `pre-compact-snapshot`, `microbit-enforcer`) and sets `"shell": "powershell"` on just those entries — the rest stay bash, since they're Linux/macOS-shaped anyway (apt/brew probing, jq-driven drift diffing). WSL remains the option that gets you everything. The template directory uses `dot-claude/` (rewritten to `.claude/` at install) so the templates browse and sync cleanly on filesystems and tools that special-case dotfiles. Scaffolding from Windows is exercised in CI (`portability (windows-latest)`): generated files are written with LF on every platform and the scaffold appends a `.gitattributes` block pinning it, so a Windows-authored `.claude/` still runs on a teammate's Linux/macOS checkout. Git can't carry the executable bit the same way — after your first `git add`, run `git update-index --chmod=+x claude-ctx` (the generated `CLAUDE.md` says so too). |

## Install

Expand Down Expand Up @@ -202,6 +202,11 @@ All five preflight checks are silent on a clean default scaffold; informational
--force Kill-switch: skip the deep-merge AND the collision
strategy. Every existing file is overwritten with .bak-<ts>
(the pre-Tier-2 behavior). Implies --on-collision=overwrite.
--hook-shell SHELL bash (default) or powershell. powershell installs the
.ps1 variants of the hooks that have one and sets
"shell": "powershell" on those entries; hooks without a
.ps1 sibling stay bash. For Windows machines with no
Git Bash. Persists to .claude-config.json.
--write-index Regenerate templates/INDEX.md from MODULES (maintainer
tool; --check fails when the committed index is stale).
--save-config FILE Save answers to FILE (plus scaffolding)
Expand Down
Loading