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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ All notable changes to this project. Format: [Keep a Changelog](https://keepacha

## Unreleased

- **fix(portability): scaffolding from Windows emitted CRLF into every generated file; `--check` crashed; two hooks assumed tools that aren't there.** Four bugs, all invisible to a Linux-only CI. **(1) CRLF output.** `Path.write_text()` opens in text mode with `newline=None`, which translates `\n` to `os.linesep` — so a Windows scaffold wrote CRLF into all 13 hooks, `claude-ctx`, `CLAUDE.md` and `settings.json` (measured: 100% CRLF, zero bare LF). Harmless *on* Windows, where Git Bash strips the CR, but the shebang carried one, and `.claude/` is meant to be committed and shared (the generated CLAUDE.md says so, and `small-team` is a shipped persona) — so a teammate's Linux/macOS clone got `bad interpreter: /usr/bin/env bash^M` on every hook. All six write sites now route through a `write_text_lf()` helper using `open(..., newline="\n")` (`Path.write_text` only gained a `newline` parameter in 3.10; the project floor is 3.8). **(2) `--check` crashed on Windows** with `UnicodeEncodeError` on the `✓` under cp1252 — the exact command CONTRIBUTING gives new contributors. Python uses UTF-8 for a real Windows console, so this bit hardest when output was piped or redirected (CI logs, `cc-configure > setup.log`, an editor terminal). Both streams are now retagged UTF-8 with `errors="replace"` where the runtime allows it. **(3) The Stop hook's report depended on an unguarded `jq -n`.** jq isn't preinstalled on macOS, Windows, or most Linux distros; without it the checks ran, the hook exited 0, and Claude never learned anything had failed — the hook's entire purpose, lost silently. It now prefers jq, falls back to python3, and as a last resort prints the report to stderr with an explicit "NOT reaching Claude" warning. **(4) The package-availability gate disabled itself on stock macOS.** It bounded each probe with GNU `timeout`, absent there; the resulting rc=127 took the "probe inconclusive" branch, so the gate stood down on the first package for every macOS user — fail-open, so no false denials, but the advertised `safety` feature simply did not work, and said nothing. It now falls back to `gtimeout`, then to an unbounded probe. **(5) `--check`'s shell-syntax gate mis-fired on Windows CI.** `shutil.which("bash")` resolves to `System32ash.exe` — the WSL launcher — on the GitHub `windows-latest` image, ahead of Git Bash. With no distro installed it exits non-zero writing *nothing* to stderr, so all 16 shipped `.sh` files were reported as `bash syntax error:` with a blank message, while the same command passed on a dev box where Git Bash wins PATH. Found only once the new matrix job ran the gate on a real Windows runner — the job earning its keep on its first run. Candidates are now validated by *executing* one (`bash -c 'exit 0'`), with Git Bash's own binary as fallback and `CC_BASH` as an override; when none works the check emits a single WARN and still passes, because a validation that could not run is not the same as one that failed. Reported paths are `as_posix()`-normalized and bash's echo of its own absolute path is stripped, so `--check` output is now byte-identical on all three platforms. **Mitigation for what the configurator can't control:** the scaffold appends a `.gitattributes` block (`*.sh text eol=lf`, `claude-ctx`, `.claude/skills/**/scripts/*`) through the same managed-block append the `.gitignore` block uses — written when absent, line-level-unioned into a stale block, never touching the user's own rules. Git cannot record the *executable* bit that way, and `core.filemode=false` (the Windows default) drops it, so the generated `CLAUDE.md` § Repo bootstrap now tells Windows committers to run `git update-index --chmod=+x claude-ctx`. New `test/portability/` fixtures cover all of it by behavior, not by grepping source: every generated file is CRLF-free and every hook shebang is clean; the `.gitattributes` block is written, idempotent and union-safe; and the two hooks are run under a PATH that hides jq, python3 and timeout. README's runtime-dependency list now names jq and the timeout fallback; the platform table reflects what CI actually exercises. The `python-uv-fastapi` example and all five persona snapshots are regenerated (`.gitattributes` is new output).
- **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.

- **fix(portability): scaffolding from Windows emitted CRLF into every generated file; `--check` crashed; two hooks assumed tools that aren't there.** Four bugs, all invisible to a Linux-only CI. **(1) CRLF output.** `Path.write_text()` opens in text mode with `newline=None`, which translates `\n` to `os.linesep` — so a Windows scaffold wrote CRLF into all 13 hooks, `claude-ctx`, `CLAUDE.md` and `settings.json` (measured: 100% CRLF, zero bare LF). Harmless *on* Windows, where Git Bash strips the CR, but the shebang carried one, and `.claude/` is meant to be committed and shared (the generated CLAUDE.md says so, and `small-team` is a shipped persona) — so a teammate's Linux/macOS clone got `bad interpreter: /usr/bin/env bash^M` on every hook. All six write sites now route through a `write_text_lf()` helper using `open(..., newline="\n")` (`Path.write_text` only gained a `newline` parameter in 3.10; the project floor is 3.8). **(2) `--check` crashed on Windows** with `UnicodeEncodeError` on the `✓` under cp1252 — the exact command CONTRIBUTING gives new contributors. Python uses UTF-8 for a real Windows console, so this bit hardest when output was piped or redirected (CI logs, `cc-configure > setup.log`, an editor terminal). Both streams are now retagged UTF-8 with `errors="replace"` where the runtime allows it. **(3) The Stop hook's report depended on an unguarded `jq -n`.** jq isn't preinstalled on macOS, Windows, or most Linux distros; without it the checks ran, the hook exited 0, and Claude never learned anything had failed — the hook's entire purpose, lost silently. It now prefers jq, falls back to python3, and as a last resort prints the report to stderr with an explicit "NOT reaching Claude" warning. **(4) The package-availability gate disabled itself on stock macOS.** It bounded each probe with GNU `timeout`, absent there; the resulting rc=127 took the "probe inconclusive" branch, so the gate stood down on the first package for every macOS user — fail-open, so no false denials, but the advertised `safety` feature simply did not work, and said nothing. It now falls back to `gtimeout`, then to an unbounded probe. **Mitigation for what the configurator can't control:** the scaffold appends a `.gitattributes` block (`*.sh text eol=lf`, `claude-ctx`, `.claude/skills/**/scripts/*`) through the same managed-block append the `.gitignore` block uses — written when absent, line-level-unioned into a stale block, never touching the user's own rules. Git cannot record the *executable* bit that way, and `core.filemode=false` (the Windows default) drops it, so the generated `CLAUDE.md` § Repo bootstrap now tells Windows committers to run `git update-index --chmod=+x claude-ctx`. New `test/portability/` fixtures cover all of it by behavior, not by grepping source: every generated file is CRLF-free and every hook shebang is clean; the `.gitattributes` block is written, idempotent and union-safe; and the two hooks are run under a PATH that hides jq, python3 and timeout. README's runtime-dependency list now names jq and the timeout fallback; the platform table reflects what CI actually exercises. The `python-uv-fastapi` example and all five persona snapshots are regenerated (`.gitattributes` is new output).

- **fix(install): the `ln -sf` shortcut silently froze on Windows; PATH-independent shim, honest prerequisites.** Under Git Bash/MSYS, `ln -s` **copies** unless `MSYS=winsymlinks:nativestrict` is set *and* the user has Developer Mode or admin — so `~/.local/bin/cc-configure` became a snapshot of configure.py taken on install day. `git -C ~/.cc-configurator pull` updated the clone while the command kept running the old copy, with nothing to indicate it. The installer now verifies the link actually resolved (`[ -L ]`) and otherwise writes a two-line `exec python3 <clone>/configure.py "$@"` shim, which tracks the clone on every platform; both checks live in the `if` condition, because under `set -e` a trailing `[ -L … ] && link_ok=1` in a then-block would abort the installer on precisely the platform the fallback exists for. Also: `git` is now checked up front (it was used before the first guard), the missing-python3 hint is OS-aware instead of always saying `apt install python3`, and the closing usage banner no longer advertises `--preset aggressive` and the legacy `commands-core` / `token-efficiency-pro` module IDs — both deprecated and slated for removal in v3.0.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ There are 11 modules; legacy IDs (`commands-core`, `agents`, `token-efficiency-p
| **safety** | PreToolUse hooks (block dangerous bash + scan Write/Edit for secrets + gate `apt\|brew\|dnf\|yum\|pacman\|apk install` for packages not in any configured repo, with structured denial listing available siblings + detected installed version); `permissions.disableBypassPermissionsMode: "disable"` hard-blocks `--dangerously-skip-permissions`. Sub-flags: `lockdown` (sets `DISABLE_UPDATES=1` — blocks autoupdates AND manual `claude update`; for air-gapped / enterprise environments); `slop_scan` (PostToolUse hook on Write/Edit/NotebookEdit flagging filler / marketing-voice / hedging / em-dash patterns; `slop_scan_action=warn\|block`, `slop_scan_density` and `slop_scan_imports` opt-in). All non-`custom` personas pre-set `slop_scan=true` action=warn. |
| **git-workflow** | PostToolUse formatter on Write/Edit, Stop hook running typecheck / lint / tests. |
| **token-efficiency** | Path-scoped `.claude/rules/` starters + PreCompact snapshot hook. `tier` flag: `basic` (default) ships discipline rules + snapshot only; `pro` adds bash-output truncation hook + always-loaded discipline rules. |
| **commands** | Slash commands + agents + microbits. `subset` flag (linear ordering: `curated ⊂ full ⊂ rigorous`): **`curated`** = 3 essential skills (`/plan`, `/commit`, `/verify-setup`) + the `code-reviewer` agent. **`full`** (default) = 9 workflow skills (adds `/review`, `/ship`, `/sync-docs`, `/check-context`, `/session-retro`, `/retrofit`) + 4 agents (`code-reviewer`, `test-runner`, `doc-writer`, `security-auditor`) + 4 discipline microbits (`/freeze`, `/unfreeze`, `/guard`, `/careful`) + the `microbit-enforcer.sh` PreToolUse hook. **`rigorous`** = `full` + `/investigate` + `/plan-eng-review`, the rigor skills that embed `templates/commands/_patterns/` cross-cutting blocks (confidence gate, independent verification, no-fix-without-investigation, AI-slop detection). `/review` and `/plan` share their names with Claude Code built-ins (the `/review` alias of the bundled `/code-review` since CC 2.1.223, and the `/plan` plan-mode shortcut); a project skill wins by name (verified on CC 2.1.241), so reach the built-in multi-agent review with `/code-review` and plan mode with Shift+Tab. The `security-auditor` frontmatter wires Sonatype's dependency-management MCP (`https://mcp.guide.sonatype.com/mcp`) scoped to that agent — active only when it runs, so ~0 baseline context cost. Set `SONATYPE_TOKEN` env var to enable ([generate a token](https://guide.sonatype.com/settings/tokens)). |
| **commands** | Slash commands + agents + microbits. `subset` flag (linear ordering: `curated ⊂ full ⊂ rigorous`): **`curated`** = 3 essential skills (`/plan`, `/commit`, `/verify-setup`) + the `code-reviewer` agent. **`full`** (default) = 9 workflow skills (adds `/review-branch`, `/ship`, `/sync-docs`, `/check-context`, `/session-retro`, `/retrofit`) + 4 agents (`code-reviewer`, `test-runner`, `doc-writer`, `security-auditor`) + 4 discipline microbits (`/freeze`, `/unfreeze`, `/guard`, `/careful`) + the `microbit-enforcer.sh` PreToolUse hook. **`rigorous`** = `full` + `/investigate` + `/plan-eng-review`, the rigor skills that embed `templates/commands/_patterns/` cross-cutting blocks (confidence gate, independent verification, no-fix-without-investigation, AI-slop detection). **Naming note:** a project skill wins its name against Claude Code's built-ins (verified on CC 2.1.241). `/review-branch` is deliberately *not* called `review`, because CC 2.1.223 made `/review` the alias of the bundled `/code-review` and taking that name would hide Claude Code's multi-agent reviewer. `/plan` does still shadow the built-in plan-mode shortcut — plan mode remains reachable with Shift+Tab, so this is a name clash rather than a lost capability; rename the skill if you'd rather keep the shortcut. The `security-auditor` frontmatter wires Sonatype's dependency-management MCP (`https://mcp.guide.sonatype.com/mcp`) scoped to that agent — active only when it runs, so ~0 baseline context cost. Set `SONATYPE_TOKEN` env var to enable ([generate a token](https://guide.sonatype.com/settings/tokens)). |
| **mcp** | `.mcp.json` generated from selected servers, plus **per-task profiles** (`.mcp.research.json`, `.mcp.frontend.json`, `.mcp.minimal.json`) and an executable `./claude-ctx` wrapper that launches Claude with `--mcp-config <profile> --strict-mcp-config` — drops a bloated 4-MCP baseline from ~49% context to under 5%. |
| **multi-agent** | Path-scoped `multi-agent-guardrails.md` (5-scenario "when not to parallel" list), `/merge-worktrees` skill, `/infinite` skill, `parallel-generator` subagent. |
| **github-actions** | `.github/workflows/claude.yml` pinned to `anthropics/claude-code-action@v1`. Triggers on `@claude` mentions in issues, PR comments, and PR reviews. |
Expand Down
4 changes: 2 additions & 2 deletions config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@
{
"id": "commands",
"title": "Slash commands + subagents",
"description": "Bundled commands (plan/review/commit/ship/sync-docs/check-context/session-retro/verify-setup/retrofit) + 4 subagents (code-reviewer/test-runner/doc-writer/security-auditor).",
"description": "Bundled commands (plan/review-branch/commit/ship/sync-docs/check-context/session-retro/verify-setup/retrofit) + 4 subagents (code-reviewer/test-runner/doc-writer/security-auditor).",
"paths": [
"commands/plan/SKILL.md",
"commands/review/SKILL.md",
"commands/review-branch/SKILL.md",
"commands/commit/SKILL.md",
"commands/ship/SKILL.md",
"commands/sync-docs/SKILL.md",
Expand Down
2 changes: 1 addition & 1 deletion configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ def warn(source, msg):
"_patterns/confidence-gate.md",
"_patterns/independent-verification.md",
],
"commands/review/SKILL.md": [
"commands/review-branch/SKILL.md": [
"_patterns/confidence-gate.md",
"_patterns/independent-verification.md",
"_patterns/ai-slop-detection.md",
Expand Down
4 changes: 2 additions & 2 deletions docs/02-git-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Every change follows this shape:
2. **Branch** — `git checkout -b feat/<short-name>` off main.
3. **Small diff** — one logical change at a time. If the diff grows past ~200 LOC, split.
4. **Tests** — every new behavior gets a test in the same branch.
5. **Review** — `/review` or let `code-reviewer` subagent run. Address critical issues.
5. **Review** — `/review-branch` or let `code-reviewer` subagent run. Address critical issues.
6. **Ship** — `/ship` runs format → lint → typecheck → test → commit → push.

## Branch naming
Expand Down Expand Up @@ -133,7 +133,7 @@ Rewind (`Esc Esc` in Claude Code) and `git reflog` are your safety net. You don'
1. `claude` from the repo root.
2. Describe the task. Claude drafts a plan (via `/plan` or plan mode).
3. Confirm or adjust, then let it edit.
4. `/review` → fix what matters.
4. `/review-branch` → fix what matters.
5. `/ship` → commits and pushes.
6. Open PR manually or with `gh pr create`. Merge.

Expand Down
4 changes: 2 additions & 2 deletions docs/03-commands-and-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ Frontmatter fields worth knowing:

Inline: `` !`git diff --staged` `` — runs at skill-expansion time, output replaces the placeholder before Claude sees the prompt. Multi-line: fenced block ```` ```! ````.

Great for injecting live repo state into the prompt. The `/review` and `/commit` skills in the template library use this.
Great for injecting live repo state into the prompt. The `/review-branch` and `/commit` skills in the template library use this.

### Starter kit

- `/plan` — forces a structured plan before edits. Shadows Claude Code's built-in `/plan` (the plan-mode shortcut) — a project skill wins by name; Shift+Tab still enters plan mode.
- `/review` — code review against main via the `code-reviewer` agent. Shadows the bundled `/review` alias that CC 2.1.223 added for `/code-review` (verified on 2.1.241) — type `/code-review` for the built-in multi-agent review.
- `/review-branch` — code review against main via the `code-reviewer` agent. Named `review-branch`, not `review`, on purpose: CC 2.1.223 made `/review` the alias of the bundled `/code-review`, and a project skill of that name wins it (verified on 2.1.241), which would hide Claude Code's multi-agent reviewer behind this simpler one. Both are available now — `/code-review` for the deep pass, `/review-branch` for the quick one.
- `/commit` — Conventional Commits from staged diff.
- `/ship` — full pre-push gauntlet.
- `/sync-docs` — update `CLAUDE.md` / rules from recent work.
Expand Down
2 changes: 1 addition & 1 deletion docs/05-safety-permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Writes a summary of the session to `.claude/logs/` before compression happens. R
Automated review is the last line.

### At turn-end
The `code-reviewer` subagent runs against `git diff` or `git diff --merge-base main`. Called explicitly via `/review` or auto-invoked when Claude writes code with "use proactively" description matching.
The `code-reviewer` subagent runs against `git diff` or `git diff --merge-base main`. Called explicitly via `/review-branch` or auto-invoked when Claude writes code with "use proactively" description matching.

### At commit-time
The `/commit` skill forces a Conventional Commit message summarizing the change, which forces the model to think about whether the diff actually does what it thinks.
Expand Down
2 changes: 1 addition & 1 deletion docs/09-retrofit-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Two paths:
**Manual.** Diff each pair from the report and decide:

```bash
diff -u .claude/skills/review/SKILL.md .claude-retrofit/incoming/.claude/skills/review/SKILL.md
diff -u .claude/skills/review-branch/SKILL.md .claude-retrofit/incoming/.claude/skills/review-branch/SKILL.md
```

For each, decide: keep yours (delete the staged), replace yours with ours (`mv`), merge sections (edit by hand), or install ours alongside (move to `<name>-cc/SKILL.md`).
Expand Down
Loading