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

## Unreleased

### chore(compat): bump tested_up_to to 2.1.150 + ship eight schema-validated opt-ins after SchemaStore PR #5706 merge

[SchemaStore PR #5706](https://github.com/SchemaStore/schemastore/pull/5706) merged 2026-05-23, syncing `claude-code-settings.json` to Claude Code v2.1.143 and unblocking nine settings keys (+ five env vars) that had been held in the configurator's backlog through three prior CHANGELOG resurveys. This PR ships all of them as commented-out opt-ins so users can uncomment to activate, matching the established pattern from PRs #17 (`prUrlTemplate`) and #18 (`sandbox.network.deniedDomains`). Bumps `tested_up_to` 2.1.132 → 2.1.150 (covers the 18 CC releases since the last bump, including the 2.1.147–2.1.150 resurvey that found only one new configurator-adjacent key — `allowAllClaudeAiMcps`, 2.1.149 — Enterprise managed setting, outside configurator territory). Closes tracking issue #53.

**Latent bug fix:** discovered while wiring the new opt-ins that `configure.py`'s `settingsPatch` merger was stripping ALL top-level `//`-prefixed keys, including the opt-in stubs (`// sandbox`, `// prUrlTemplate`) that PRs #17 and #18 promised would surface in users' generated `.claude/settings.json`. The filter intended to drop documentation labels (`//`, `//2`, `//9`) but was too aggressive. New `_is_doc_label(k)` helper distinguishes label keys (pure-digit suffix or empty) from stub keys (`// foo`). The existing `// sandbox` + `// prUrlTemplate` opt-ins now actually appear in scaffolded settings.json for the first time — users who `cc-configure --retrofit` will see them on the next run. No persona snapshot drift (snapshots compare file trees, not contents); all 50+ shell fixtures still pass. Two source patch files also corrected (`safety/settings-patch.slop-scan.json`, `commands/microbit-enforcer/settings-patch.json`) — their top-level `"// settings-patch.slop-scan.json": "..."` / `"// microbit-enforcer.json": "..."` keys were maintainer-facing docs that would otherwise leak into user settings under the new filter; rewritten as plain `"//"` labels.

**Settings keys shipped as opt-ins:**

- **`skillOverrides`** (CC 2.1.129+) → `templates/token-efficiency/settings-patch.tier-pro.json`, behind the existing `tier=pro` flag. Default value in the commented stub is `"name-only"` (most conservative). Values: `off` (hides from model AND `/`-menu), `user-invocable-only` (hides from model only), `name-only` (collapses description to just the skill name). Directly reduces the context metric `/check-context` flags.
- **`worktree.baseRef` + `worktree.bgIsolation`** (CC 2.1.133+ / 2.1.143+) → new `templates/multi-agent/settings-patch.json` (added `settingsPatch` reference to `multi-agent` module — module previously shipped no settings). Pair naturally with `/merge-worktrees`. `baseRef=head` preserves unpushed local commits in new worktrees; `bgIsolation=none` lets background sessions edit the live working copy directly when a worktree is impractical.
- **`autoMode.hard_deny`** (CC 2.1.136+) → `templates/safety/settings-patch.json`. Auto-mode classifier rules that block unconditionally regardless of user intent or allow exceptions. Example values seeded: `"Running executable files"`, `"Writing to system directories"`. Only meaningful under `claude --auto-mode`.
- **`sandbox.failIfUnavailable`** (CC 2.1.143+) → nested inside the existing `// sandbox` block in `templates/safety/settings-patch.json`. Set to `true` for fail-closed sandbox posture (hard failure when required deps missing, instead of falling back to non-sandboxed execution).
- **`subagentStatusLine` + `statusLine.hideVimModeIndicator`** (CC 2.1.143+) → `extraSettings` in `ui` module (`config_schema.py`). `subagentStatusLine` lets subagent runs render a distinct status line for visual separation from the parent session; `hideVimModeIndicator` suppresses CC's built-in vim mode display when the user's statusline script renders its own.
- **Hook `args: string[]` exec form + `continueOnBlock: boolean`** (CC 2.1.139+) → doc comment in `templates/safety/settings-patch.json` and `templates/git-workflow/settings-patch.json` annotating that the new syntax is now schema-valid for custom hooks users add. No active hook configs use them yet — pure forward-looking enablement.

**Env vars (mention-only, in `safety/settings-patch.json` comment block):** `CLAUDE_CODE_STOP_HOOK_BLOCK_CAP` (override 8-block consecutive-Stop cap; seeded value `"16"` inside the commented `// env` block). The other four (`ANTHROPIC_WORKSPACE_ID`, `CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE`, `CLAUDE_CODE_PLUGIN_PREFER_HTTPS`, `CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY`) are platform-/workspace-specific and don't warrant configurator-shipped defaults; captured in the `CLAUDE_CODE_COMPAT` rationale comment for future-self.

**Still held for a future schemastore sync PR:** hook output `terminalSequence` field (CC 2.1.147); Stop/SubagentStop hook input `background_tasks` + `session_crons` fields (CC 2.1.149). Both were verified absent from #5706's head-branch schema and remain in `docs/07-backlog.md`.

`CLAUDE_CODE_COMPAT.tested_up_to` bumped 2.1.132 → 2.1.150; rationale comment rewritten to a clean summary. Local SessionStart watcher (`.claude/hooks/check-schemastore-pr.sh`, gitignored) retired after PR #5706 merged.

## [2.5.0] — 2026-05-21

Bundle release: the drift-monitor family — PR #51 introduced the pattern (`.claude/.cc-manifest.json` baseline + SessionStart hook + `/verify-setup` narrative for MCP servers), and PR #54 completed it with two more dimensions (stack manifests + check-command alignment). Plus PR #49 cleaning up legacy `/brainstorm` references after the superpowers v5.1.0 churn, and PR #52 tracking SchemaStore PR #5706 (no template changes; `tested_up_to` bump deferred to the unblock batch). `CC_VERSION` bumped to 2.5.0.
Expand Down
57 changes: 34 additions & 23 deletions config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
"commands/merge-worktrees/SKILL.md",
"commands/infinite/SKILL.md",
],
"settingsPatch": "multi-agent/settings-patch.json",
},
{
"id": "github-actions",
Expand Down Expand Up @@ -242,7 +243,14 @@
"statusLine": {
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/statusline.sh",
}
"//": "Optional: hideVimModeIndicator (CC 2.1.143+, schemastore-validated 2026-05-23). When the statusline script renders its own vim mode display, set to true to suppress Claude Code's built-in one. Uncomment the next key by removing the leading '// ' (and drop this '//' explainer).",
"// hideVimModeIndicator": True,
},
"//": "Optional: subagentStatusLine (CC 2.1.143+, schemastore-validated 2026-05-23). Distinct statusline for subagent runs so they're visually separable from the parent session. Uncomment the next block by removing the leading '// ' from the key.",
"// subagentStatusLine": {
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/statusline.sh --subagent",
},
},
},
]
Expand Down Expand Up @@ -347,28 +355,31 @@
# configurator against. Newer is likely fine but unverified.
CLAUDE_CODE_COMPAT = {
"min_version": "2.1.116", # agent mcpServers http (2.1.116/117)
"tested_up_to": "2.1.132", # alwaysLoad MCP, updatedToolOutput PostToolUse,
# ultrareview non-interactive, prUrlTemplate +
# sandbox.network.deniedDomains schema-validated.
# 2.1.122-128: bug fixes + MCP "workspace" reserved
# + managed-settings channelsEnabled (enterprise).
# 2.1.129-132: skillOverrides settings.json key now
# works (held — not yet in schemastore 2026-05-06);
# plugin manifests gain experimental: wrapper for
# themes/monitors; CLAUDE_CODE_SESSION_ID exposed in
# Bash subprocess env; no other configurator-
# territory schema additions.
# 2026-05-21 resurvey of 2.1.133-2.1.146: eleven
# configurator-territory keys + five env vars held
# in SchemaStore PR #5706 (sync to v2.1.143;
# supersedes the closed #5665). Bump deferred until
# #5706 merges and the unblock batch ships per the
# "no lone tracking bumps" rule. Two further items
# (terminalSequence hook output from 2.1.141;
# background_tasks/session_crons hook input from
# 2.1.145) need a future sync PR. No live breakage:
# /simplify → /code-review rename in 2.1.146 does
# not collide with the configurator's /review.
"tested_up_to": "2.1.150", # SchemaStore PR #5706 merged 2026-05-23 (sync to
# v2.1.143), unblocking nine settings.json keys for
# opt-in templating: skillOverrides (token-
# efficiency-pro tier-pro patch), worktree.baseRef
# + worktree.bgIsolation (multi-agent patch),
# autoMode.hard_deny + sandbox.failIfUnavailable
# (safety patch), subagentStatusLine +
# statusLine.hideVimModeIndicator (ui extraSettings),
# and the hook `args: string[]` + `continueOnBlock`
# forms (doc-only in safety/git-workflow patches).
# Five new env vars also schema-validated and
# mention-only in module docs: ANTHROPIC_WORKSPACE_ID,
# CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE,
# CLAUDE_CODE_PLUGIN_PREFER_HTTPS,
# CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY,
# CLAUDE_CODE_STOP_HOOK_BLOCK_CAP (safety patch).
# 2.1.147-150 resurvey (2026-05-23): only one new
# configurator-adjacent key (allowAllClaudeAiMcps,
# 2.1.149) — Enterprise managed setting, outside
# configurator territory. /simplify → /code-review
# rename (2.1.146) does not collide with /review.
# Still held for a future schemastore sync PR:
# hook output `terminalSequence` (2.1.147); Stop /
# SubagentStop hook input `background_tasks` +
# `session_crons` fields (2.1.149).
}


Expand Down
14 changes: 12 additions & 2 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,16 @@ def repl(m):
return re.sub(r"\{\{(\w+)\}\}", repl, text)


def _is_doc_label(k: str) -> bool:
# Source patch files use two `//` conventions: numbered doc labels
# ("//", "//2", "//9") that explain the patch to humans reading the
# source and must NOT propagate to the user's generated settings.json,
# and stub keys ("// sandbox", "// prUrlTemplate") that DO propagate so
# the user can uncomment them. Distinguish by the bit after `//`: pure
# digits (or empty) = doc label.
return k == "//" or (k.startswith("//") and k[2:].isdigit())


def deep_merge(a, b):
if isinstance(a, list) and isinstance(b, list):
return a + b
Expand All @@ -460,7 +470,7 @@ def compute_merged_settings(form_values: dict, selected: set, module_flags: dict
if m.get("settingsPatch"):
patch_path = TEMPLATE_DIR / m["settingsPatch"]
patch = json.loads(patch_path.read_text(encoding="utf-8"))
patch = {k: v for k, v in patch.items() if not k.startswith("//")}
patch = {k: v for k, v in patch.items() if not _is_doc_label(k)}
settings = deep_merge(settings, patch)
if m.get("extraSettingsHook"):
settings["hooks"] = deep_merge(settings.get("hooks", {}), m["extraSettingsHook"])
Expand All @@ -475,7 +485,7 @@ def compute_merged_settings(form_values: dict, selected: set, module_flags: dict
extra = extra.get(selected_value)
if extra:
extra_patch = json.loads((TEMPLATE_DIR / extra).read_text(encoding="utf-8"))
extra_patch = {k: v for k, v in extra_patch.items() if not k.startswith("//")}
extra_patch = {k: v for k, v in extra_patch.items() if not _is_doc_label(k)}
settings = deep_merge(settings, extra_patch)
# extraSettingsEnv: merge env vars driven by the flag's value.
# Boolean false ⇒ skip. Otherwise emit each {key: value} pair into
Expand Down
2 changes: 1 addition & 1 deletion templates/commands/microbit-enforcer/settings-patch.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"// microbit-enforcer.json": "Auto-installed alongside the freeze/unfreeze/guard/careful microbits when commands.subset is 'full' or 'rigorous'. PreToolUse rejects Write/Edit/NotebookEdit when a marker is present; SessionStart clears markers (session-scoped lifecycle).",
"//": "Auto-installed alongside the freeze/unfreeze/guard/careful microbits when commands.subset is 'full' or 'rigorous'. PreToolUse rejects Write/Edit/NotebookEdit when a marker is present; SessionStart clears markers (session-scoped lifecycle).",
"hooks": {
"PreToolUse": [
{
Expand Down
3 changes: 2 additions & 1 deletion templates/git-workflow/settings-patch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"//5": "GitLab: https://gitlab.com/{owner}/{repo}/-/merge_requests/{number}",
"//6": "Bitbucket: https://bitbucket.org/{owner}/{repo}/pull-requests/{number}",
"//7": "GHE: https://gh.example.com/{owner}/{repo}/pull/{number}",
"//8": "Uncomment by removing the leading '// ' on the next line, then set the template, then drop these //N keys.",
"//8": "Hook authoring note (CC 2.1.139+, schemastore-validated 2026-05-23): hookCommand entries now accept 'args: string[]' for direct-exec form (no shell wrapping, no quote-escaping pain) and 'continueOnBlock: boolean' for prompt hooks (default false; when true, ok:false feeds reason back to Claude and continues the turn instead of stopping). Useable on the hooks below if you customize them.",
"//9": "Uncomment prUrlTemplate by removing the leading '// ' on the next line, then set the template, then drop these //N keys.",
"// prUrlTemplate": "https://gitlab.com/{owner}/{repo}/-/merge_requests/{number}",
"hooks": {
"PostToolUse": [
Expand Down
10 changes: 10 additions & 0 deletions templates/multi-agent/settings-patch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"//": "Merged into .claude/settings.json. Multi-agent module ships no active settings by default — the commented opt-ins below are for users running parallel sessions or worktrees and pair naturally with /merge-worktrees.",
"//2": "Optional: worktree.baseRef (CC 2.1.133+, schemastore-validated 2026-05-23). Values: 'fresh' (default; creates new worktrees from origin/HEAD) or 'head' (preserves unpushed local commits in the new worktree). Pick 'head' if you frequently spin up worktrees from in-progress work.",
"//3": "Optional: worktree.bgIsolation (CC 2.1.143+, schemastore-validated 2026-05-23). Values: 'worktree' (default; background sessions get their own worktree) or 'none' (background sessions edit the live working copy directly, skipping EnterWorktree). 'none' is useful for repos where worktrees are impractical (build artifacts outside the tree, hardcoded paths).",
"//4": "Uncomment by removing the leading '// ' on the next key + tuning the values, then drop these //N keys.",
"// worktree": {
"baseRef": "head",
"bgIsolation": "worktree"
}
}
18 changes: 16 additions & 2 deletions templates/safety/settings-patch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
"//3": "Optional opt-in: sandbox.network.deniedDomains (CC 2.1.113+, schemastore-validated 2026-04-28).",
"//4": "Only takes effect when the sandbox is otherwise active for the command (see sandboxing docs).",
"//5": "Supports wildcards (*.example.com). Below is a small data-exfiltration-resistant baseline; tune for your threat model.",
"//6": "Uncomment by removing the leading '// ' on the next key, then drop these //N keys.",
"//6": "Inside the // sandbox block: failIfUnavailable (CC 2.1.143+, schemastore-validated 2026-05-23) makes sandbox startup a hard failure when required dependencies are missing, instead of falling back to non-sandboxed execution. Fail-closed posture for safety-sensitive projects — uncomment the inner '// failIfUnavailable: true' line after uncommenting the outer block.",
"//7": "Optional: autoMode.hard_deny (CC 2.1.136+, schemastore-validated 2026-05-23). Classifier rules that block unconditionally regardless of user intent or allow exceptions — final guardrail when running with auto mode. Edit the strings to match the action categories you want to hard-block. Only meaningful if you run `claude --auto-mode`.",
"//8": "Optional: env CLAUDE_CODE_STOP_HOOK_BLOCK_CAP (CC 2.1.143+) overrides the default 8-block cap for consecutive Stop hook blocks. Raise this only if a safety Stop hook intentionally blocks repeatedly and you want to tolerate it without the cap kicking in.",
"//9": "Hook authoring note (CC 2.1.139+, schemastore-validated 2026-05-23): hookCommand entries now accept 'args: string[]' for direct-exec form (no shell, no quote-escaping pain) and 'continueOnBlock: boolean' for prompt hooks (default false; when true, ok:false feeds the reason back to Claude and the turn continues instead of stopping). Use these on custom hooks you add below.",
"//10": "Uncomment any opt-in by removing the leading '// ' on its key, then drop the explainer //N keys.",
"// sandbox": {
"network": {
"deniedDomains": [
Expand All @@ -19,7 +23,17 @@
"anonfiles.com",
"uguu.se"
]
}
},
"// failIfUnavailable": true
},
"// autoMode": {
"hard_deny": [
"Running executable files",
"Writing to system directories"
]
},
"// env": {
"CLAUDE_CODE_STOP_HOOK_BLOCK_CAP": "16"
},
"hooks": {
"PreToolUse": [
Expand Down
2 changes: 1 addition & 1 deletion templates/safety/settings-patch.slop-scan.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"// settings-patch.slop-scan.json": "Registers the slop-scan PostToolUse hook. Applied via safety.flags.slop_scan when set to true. Only the hook registration lives here; the action mode + opt-in flags are exported via extraSettingsEnv (see config_schema.py).",
"//": "Registers the slop-scan PostToolUse hook. Applied via safety.flags.slop_scan when set to true. Only the hook registration lives here; the action mode + opt-in flags are exported via extraSettingsEnv (see config_schema.py).",
"hooks": {
"PostToolUse": [
{
Expand Down
2 changes: 2 additions & 0 deletions templates/token-efficiency/settings-patch.tier-pro.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"//": "Optional: skillOverrides (CC 2.1.129+, schemastore-validated 2026-05-23). Suppresses skill visibility/descriptions to reduce context overhead — the metric /check-context flags. Values: 'off' (hides from model AND /-menu), 'user-invocable-only' (hides from model, /-menu still works), 'name-only' (collapses description to just the skill name). 'name-only' is the conservative default; pick 'user-invocable-only' if you only ever invoke skills explicitly. Uncomment the next line by removing the leading '// '.",
"// skillOverrides": "name-only",
"env": {
"CLAUDE_BASH_MAX_LINES": "80"
},
Expand Down
Loading