AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Portable Claude Code global configuration: custom skills, PreToolUse hooks, and a custom statusline. Runs on Linux, macOS, WSL.
Translation pending
Developer toolsPython · ShellGitHub @jcdendriteSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Installable projects can be verified without a deployment domain. Use GitHub sign-in for a personal repository, or the repository verification file above for an organization repository.
Ask about other verification options
Loading the full README. The saved excerpt is shown below.
Status: stable — actively maintained.
Portable Claude Code global configuration: custom skills, PreToolUse hooks that gate git commit and PR-comment flows, and a custom statusline. Runs on any Unix-like system (Linux, macOS, WSL). Managed with GNU Stow.Read the full README ↗Status: stable — actively maintained.
Portable Claude Code global configuration: custom skills, PreToolUse hooks that gate git commit and PR-comment flows, and a custom statusline. Runs on any Unix-like system (Linux, macOS, WSL). Managed with GNU Stow.
Install it to wire in a set of pre-built hooks that gate commits, pushes, and PR comments until explicit review steps are satisfied; a full contribution pipeline from /plan-it through /respond-pr; a roster of specialist reviewer agents auto-triggered from code review; and a three-tier private-project redaction system that blocks sensitive identifiers before they land in public commits. See Philosophy for the design rationale.
Maintained by Cordova Strategy.
Working across a variety of projects from very early stage to enterprise-level, I wanted to use a flexible but predictable setup for Claude Code to help me get through large chunks of work efficiently and cost-effectively: from security audits of vibe-coded codebases to building out standard features, adding testing infrastructure, and enforcing quality against industry-standard, best-practice checklists. I wanted to stop fixing the same errors that AI agents kept encountering and really focus my time on the nuanced technical challenges that need human judgment.
AI agents are powerful but probabilistic. They will frequently gaslight you, or more fairly put, they will confidently draw incorrect conclusions from prose (even top-class models). Simply stated, unsupervised AI is reliable for summarization but not synthesis. I wanted to add a layer of determinism on top of agents' inherently probabilistic judgment to enforce quality and prevent repetitive errors where I could. To achieve these goals, I added safeguards in this repo with hooks and markers.
I also wanted to encode industry-standard best practices in this repo. LLMs are trained on the corpus of the internet and are biased by the loudest and most common viewpoints. While the wisdom of the masses can often be directionally correct, it's best to defer to primary sources and scientific thinking, applying the rigor of research and adhering to evidence-based approaches. You'll see those perspectives represented in the content of the skills and instructions in this repo, with references to primary sources that converge on tried-and-true guidelines on how to design and write good software.
Claude Code without enforcement will claim code is done before tests pass, skip the review step when it judges a change "too small," write to the main worktree when a concurrent session is already staged there, and paste project codenames directly into commit messages and PR bodies. claude-config makes these mistakes structurally impossible rather than relying on prompt instructions.
A CLAUDE.md instruction says "you should run code-review before committing." A PreToolUse hook says "the commit is denied until code-review ran against this exact diff." This distinction is the core design choice: enforce at the tool-call boundary, not at the prompt layer, because prompt-layer instructions are advisory — the model can disregard them on any change it judges simple enough not to need review.
claude-config is a workflow-enforcement layer — hooks that gate what Claude can do until explicit review steps are satisfied. It ships a set of bundled Claude Code skills that overlap with its review pipeline disabled by default, so contributors opt in deliberately (see the "Bundled skills disabled by default" section of docs/skills.md). claude-config ships the enforcement harness; hand-rolled ~/.claude/ configs improvise the patterns claude-config systematizes: content-addressed review markers, specialist reviewer routing, and three-tier redaction.
docs/design-decisions/ — one file per non-obvious design decision in this repo (hook-enforced gates, content-addressed review markers, no shared skill partials, project-layer composition via prose-pointer + glob, reviewer persona roster operations, etc.) and the reasoning behind each.docs/case-studies.md — index of longer-form case studies: individual design decisions examined in depth with primary-source citations.docs/walkthrough.md — one full contribution cycle: plan → plan-review → code → code-review → commit → ready-for-review → push → respond-pr, showing each hook firing in sequence.CLAUDE.md files, plus path-scoped rules. The repo-root CLAUDE.md is contributor workflow for this repo (what GitHub renders by default). The stowed claude/.claude/CLAUDE.md is the global engineering instructions applied to every Claude Code session on the machine after ./install.sh. Contributor-workflow instructions that only apply to specific file types live in .claude/rules/ instead, Claude Code's native path-scoped rules directory — loaded automatically only when a matching file is opened, rather than every session. The stowed claude/.claude/rules/ is the same mechanism applied to the global surface — it installs to ~/.claude/rules/ and applies in every repo the user opens, not just this one.The README below is organized by feature surface (hooks, skills, plugins, scripts). If you came looking for transferable ideas, these are the load-bearing ones:
<repo-hash>.<session-id> filename is a write-side key only, so parallel sessions can't clobber each other's markers. See docs/hooks.md (require-code-review.sh) and docs/design-decisions/content-addressed-review-markers.md.session-marker-dashboard.sh matches startup|clear|compact, restoring active-bypass marker visibility after auto-compact fires. See Context management.restore-authorization-boundary-on-compact.sh matches compact only, re-injecting the irreversible-action confirmation boundary the harness-generated compact summary's "Optional Next Step" section carries no trace of. See Context management.require-routing-read.sh blocks subagent spawn during /plan-review until ROUTING.md is read; a PostToolUse companion records the read per session. See docs/hooks.md./handoff//brief write to a durable ~/.claude/ directory, not /tmp, so they survive a reboot. Three paths consume the file: a PostToolUse Read hook mechanically consumes it the moment it's read directly (the backstop for a plain Read after ), consumes it on the fresh-process path, and consumes it through before reading it in the current session. Every consume also lands in a per-uid index a different session can query via , rather than grepping every moved file by content. Owner-only permissions come from 's one-time hardening, not a per-skill chmod. See (), , and .git clone [email protected]:jcdendrite/claude-config.git ~/claude-config
cd ~/claude-config
./install.sh
This links the entries of claude/.claude/ one by one into a real $HOME/.claude/ directory. See "Updating after git pull" for what a later pull needs.
Edits to existing files, and new files nested under a directory ~/.claude already links into this checkout, are on disk after git pull. A running session may need a restart to read them.
A new entry directly under claude/.claude/ and any new wrapper under claude/.local/bin/ need ./install.sh, because ~/.claude and ~/.local/bin are real directories.
What only the installer produces needs it too: the ~/.local/bin copy of relocate-claude-config, plugin registrations, migrations, the stow package list in claude/.claude/scripts/stow-packages.sh, and any change to install.sh itself.
To check a new file, run ls "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/<path under claude/.claude/>", which assumes no same-named local file of yours sits there. "No such file or directory" means re-run the installer once the change is in the checkout.
install.sh uses GNU stow with symlinks. If you're on Windows, install inside WSL instead.install.sh uses #!/usr/bin/env bash. On macOS, /bin/bash is 3.2, so run brew install bash and put Homebrew's bin directory before /bin on PATH. Elsewhere, install bash 5.2 or newer by any means that puts it first on PATH: a distro package, Homebrew on Linux, or a source build. Below the floor, install.sh exits naming the bash it found, and every gate denies with "could not source _lib.sh"; docs/hooks.md § "Bash version" describes the rest. CI runs bash 5.2.stow, git, gh, jq, sha256sum, python3, and the claude CLI. install.sh verifies they exist and exits early if any are missing.git version: git 2.43 or newer, first on the PATH Claude Code starts with. 2.43 is the git Ubuntu 24.04 ships, and the floor follows that release, not the oldest git the code runs on. Debian 12 (git 2.39.5) and Ubuntu 22.04 (git 2.34.1) ship an older git; brew install git (Homebrew on macOS or Linux) or any other package that puts git 2.43 or newer first on PATH meets the floor. install.sh exits before changing anything when git --version reports a lower version or none it can read. Nothing checks the version at runtime, so a git pull does not re-check it; re-run ./install.sh from the shell that launches Claude Code to check.jq version: review-pr-checkout.sh's stacked-base audit needs a jq whose jq -R -s keeps NUL bytes in raw input. That behavior was verified on jq 1.8.2 only. A jq that truncates raw input at NUL makes every stacked PR with a non-empty delta exit 2 there.timeout version: timeout (or gtimeout) must accept -k (GNU coreutils, or BusyBox 1.35.0 or newer; other implementations are unverified), because a timeout that rejects makes every gate hook deny its tool calls, as § "Gate deadlock recovery" describes.macOS: bash 5.2 or newer and sha256sum come from Homebrew. sha256sum ships in GNU coreutils. Install with brew install bash coreutils, put Homebrew's bin directory before /bin on PATH (export PATH="$(brew --prefix)/bin:$PATH"), then add the gnubin directory to PATH so the unprefixed sha256sum resolves: export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH".
PATH setup for script wrappers: The user-facing scripts are installed as wrappers under ~/.local/bin/. That directory needs to be on your PATH:
install.sh adds export PATH="$HOME/.local/bin:$PATH" to ~/.bashrc and ~/.zshrc itself, idempotently, on every run. If either file is a symlink (e.g. into another dotfiles-management repo), install.sh won't write through it — it either finds a .local-suffixed companion file that rc file already sources and manages the PATH block there instead, or prints a warning telling you the exact line to add and where. Restart your shell (or source ~/.zshrc / source ~/.bashrc) after the first run.fish_add_path ~/.local/binVerify: command -v cleanup-merged-branches should print the wrapper path.
Existing users: git pull does not apply the owner-only permissions on ~/.claude and ~/.claude.json; only ./install.sh does. "Updating after git pull" above says when new wrappers need it too. Re-run it once to apply the permissions. After re-stowing, run git status in the repo: if any file under claude/.local/bin/ shows as modified, stow's --adopt flag adopted a same-named local file. Revert with git checkout claude/.local/bin/<name> and rename the conflicting local script.
Before pulling a change that raises the bash or Claude Code floor, update both from a terminal, restart any running Claude Code session, and pull from a separate terminal. docs/hooks.md § "Gate deadlock recovery" gives the full procedure, including what to do if gates deny after a pull.
claude/ # stow package — claude/.claude/ → ~/.claude/
claude-skills/ # stow package — claude-skills/skills/ → ~/.claude/skills/
plugins/ # marketplace plugins (see Plugins section below)
docs/ # design-decisions, walkthrough, hooks, skills, scripts, auto-mode, redaction
.github/ # workflows, dependabot
.claude/ # repo-local plans, settings, worktrees (gitignored)
The skills form a sequential pipeline that covers the full contribution lifecycle. Hooks enforce the transitions so steps cannot be skipped.
Linear pipeline: plan-it → plan-review → code → code-review → commit → ready-for-review → push → respond-pr; each transition gated by a require-* hook.
flowchart LR
A[/plan-it/] --> B[/plan-review/]
B -->|"require-plan-review.sh\ngates ExitPlanMode + Write/Edit while plan exists\n(exempt: writes to the plan file itself)"| EPM([ExitPlanMode / present to user])
EPM --> C([Write code])
C --> D[/code-review/]
D -->|"require-code-review.sh\ngates git commit"| E([git commit])
E --> F[/ready-for-review/]
F -->|"require-ready-for-review.sh\ngates git push"| G([git push / PR open])
G --> H([Review comments arrive])
H --> I[/respond-pr/]
I -->|"require-respond-pr.sh\ngates gh api comment reads/posts"| J([PR replies posted])
K([Session start]) -->|"capture-session-id.sh\nwrites session-id for marker lookup"| D
K --> F
Skills in the pipeline:
/plan-it — produce the implementation plan./plan-review — review the plan against domain checklists./code-review — principal-engineer review with ripple-effect triage./skill-review — behavioral-equivalence audit when a SKILL.md changes. Hook-enforced. See docs/skills.md./agent-review — same audit for agent files (claude/.claude/agents/*.md or plugins/*/agents/*.md). Dispatcher-invoked by /code-review; not hook-enforced. See docs/skills.md — Skill architecture notes./ready-for-review — final tests + cumulative-diff review before push./pr-description — author a PR body to standard, or verify an existing one against branch state./respond-pr — fetch and reply to all PR comments with [Claude Code] attribution.Hook transitions:
| Hook | Gates | Cleared by |
|---|---|---|
require-plan-review.sh | Write/Edit/ExitPlanMode while an uncommitted or modified plan file exists in .claude/plans/, except a Write/Edit/MultiEdit targeting one of those plan files itself | /plan-review marker covering the current plan set |
require-code-review.sh | git commit — see docs/hooks.md's require-code-review.sh bullet for the exact trigger | /code-review run against current staged state |
require-skill-review.sh | git commit — see docs/hooks.md's require-skill-review.sh bullet for the exact (base-relative) trigger | structural validation + /skill-review behavioral-equivalence audit |
require-plugin-version-bump.sh | git commit under a plugin dir without a version bump on the branch (see Plugins) | bump the plugin's version field |
deny-private-project-refs.sh | git commit, gh pr create, gh pr edit, gh issue create, gh issue comment, gh issue edit, mutating gh api — see docs/hooks.md's deny-private-project-refs.sh bullet for the exact git commit trigger | Clean the flagged tracker ID or private-project name from the diff/PR/issue body |
deny-pii-in-commits.sh | git commit when PII/PHI is in the staged diff or commit message (opt-in), or a credential-shaped value is (always on) — see 's bullet for the exact trigger |
See docs/walkthrough.md for a concrete example of one full contribution cycle with hooks firing. For full descriptions of all hooks, skills, scripts, and project-scoped plugins, see docs/hooks.md, docs/skills.md, and docs/scripts.md.
Opus 4.7 [###-------] 32% • 5h:7% • 7d:24% • $1.24 • ~/MyCode/proj • (main)
statusline-command.sh renders model, context usage percentage, 5-hour and 7-day capacity used percentages (for subscription plans), session cost (for API-based plans), working directory, git branch, and a clickable link to the current branch's open PR (colored by review state) in the status bar. Configured in settings.json via the statusline key.
The account segment (email / plan) reads ${CLAUDE_CONFIG_DIR:-$HOME}/.claude.json, so it follows whichever account the running session authenticated as. CLAUDE_CONFIG_DIR is a first-party Claude Code env var that relocates ~/.claude paths (see the .claude directory reference) — any account-switching setup that sets it before launching Claude Code gets a matching statusline for free.
Skills that apply to one or a few private projects — not broadly to all sessions — live as marketplace plugins under plugins/<name>/ rather than in claude-skills/skills/. This keeps them out of the global skill catalog and lets them be installed only in the repos that need them.
This repo exposes a marketplace via .claude-plugin/marketplace.json. Each plugin lives under plugins/<name>/ with a .claude-plugin/plugin.json manifest and skills under plugins/<name>/skills/<name>/SKILL.md.
Current plugins:
./install.sh registers the claude-config marketplace automatically, and — when run from within claude-config's own checkout — also installs, at project scope, whichever of this repo's own plugins its committed .claude/settings.json declares enabled. To register the marketplace manually (without running install.sh), run claude plugin marketplace add <path-to-claude-config>. Then install any of the plugins below at project scope in a consumer repo:
Marketplace registration and user-scope enabledPlugins install are also available standalone via register-marketplace — install.sh calls it once for its own profile, but a machine running multiple Claude Code config profiles (each pointed at its own config directory via CLAUDE_CONFIG_DIR) can re-run it per profile: CLAUDE_CONFIG_DIR=<profile-dir> register-marketplace. See docs/scripts.md for the full description.
skill-management, plugin-semver, npm-semver and lovable-cloud ship gates that need the bash and Claude Code versions in Requirements. Each plugin takes a raised floor on claude plugin install or claude plugin update, so raise bash and Claude Code before installing or updating it. Below the bash floor, each gate denies every call its registration covers, not only the guarded action: every Bash call for skill-management, every Write call for lovable-cloud, and only git commit calls for plugin-semver and npm-semver. Below the Claude Code minimum, how that version treats the onFailure field is unverified, so a gate that crashes or times out may not block.
lovable-cloud — Skills for Lovable Cloud projects: Project/Workspace Knowledge fields, edge-function auth model (ES256 gateway constraint, two-tier auth), and migration-sync workflow. claude plugin install lovable-cloud@claude-config --scope project
skill-management — Authoring guardrails for SKILL.md files: a commit-time structural validator (catches frontmatter that would silently truncate from the harness's skill listing or fail strict-YAML parsing) plus a behavioral-equivalence audit via /skill-review. claude plugin install skill-management@claude-config --scope project
Plugin dependency: the structural validator imports pyyaml. On first session in a consumer repo, the plugin's SessionStart hook provisions a persistent venv at ${CLAUDE_PLUGIN_DATA}/venv and installs pyyaml into it; the commit-time hook prefers that venv's python and falls back to system python3. ./install.sh does not install anything into the host Python — contributors who run the test suite set up a repo-local .venv per Tests.
claude-hook-review — Review playbook for .claude/hooks/*.sh and settings.json hook entries: event/matcher selection, path resolution, script skeleton, fail-open/fail-closed posture, dispatch drift, and the review checklist. claude plugin install claude-hook-review@claude-config --scope project
plugin-semver — Semver and version-field discipline for Claude Code plugin changes: when to bump major/minor/patch, which fields must be kept in sync, and a commit-time hook (require-plugin-version-bump.sh) that blocks a plugin-directory change unless the plugin's version was raised on the branch. claude plugin install plugin-semver@claude-config --scope project
npm-semver — Semver and version-field discipline for published npm packages: when to bump major/minor/patch against the package's declared public API, a reminder to propagate a bump to consuming repos, and a commit-time hook (require-npm-version-bump.sh) that blocks a non-private package's source change unless package.json's version was raised on the branch. claude plugin install npm-semver@claude-config --scope project
Two agent types ship in claude/.claude/agents/:
Reviewer subagents — eight stack-agnostic personas spawned by /plan-review and /code-review based on the Item ownership tables in those skills. Each runs in its own context with tools Read, Grep, Glob, Bash, Write; all write structured findings to agent-reviews/<agent-name>-<epoch>-<slug>.md when dispatched with findings_path: and return only a pointer line inline.
ciso-reviewer — threat modeling, auth boundaries, privilege escalation, data exposure, defense in depth.staff-backend-engineer — API contracts, error handling, idempotency, retry semantics, service boundaries; AND application data-store schema design (relational + NoSQL): partition keys, GSI/LSI, document shape, single-table vs multi-table, index coverage for app queries.staff-frontend-engineer — components, state, data fetching, cache consistency, routing, forms, accessibility, Web Vitals, i18n, client-side analytics emission.staff-data-engineer — operational data infrastructure across all stores: migration pipeline impact, DDL execution shape, CDC / change-stream config, ETL/ELT pipelines, warehouse ingestion transport, schema-drift detection, catalog / lineage tracking.staff-analytics-engineer — warehouse-side modeling (fact/dim, SCD, partitioning, materialization), transformation correctness, source-schema review for ELT-readiness from a data-contract consumer perspective.staff-platform-engineer — CI/CD, IaC, shell, deployment ordering, secret provisioning; observability coverage, alerting, SLO impact, runbook linkage, load, cost; deploy-window ordering and lock-budget on migrations.staff-product-engineer — spec-to-user-problem fidelity, critical spec reading, telemetry semantics, adjacent-regression, backward compat, accessibility-as-spec-fidelity.staff-sdet — testability of the design, pyramid shape, edge cases, mock design, fixture realism, security-invariant coverage, production code that lacks tests.Schema-change diffs nominally route three ways — staff-backend-engineer (designs), staff-data-engineer (operational / pipeline impact, DDL shape), staff-analytics-engineer (ELT-readiness). Trigger discipline in the skill bodies prevents three-persona fire on trivial additive changes. The decision criteria for adding, splitting, or excluding a persona — including why DBRE, data platform engineer, and data steward are deliberately not in the roster — are in docs/design-decisions/specialist-reviewer-roster.md.
For guidance on extending, splitting, or spawning personas, see design-decisions/reviewer-persona-roster-operations.md.
skill-fidelity-reviewer — a reviewer spawned by /ready-for-review (not by the two dispatchers, so it is outside the specialist-roster count above). It checks whether the skills a branch's work invoked were actually executed or silently abbreviated: it reads each invoked skill's body fresh and compares it to the delivered diff, so the observer never shares the deviating session's reasoning. Tools Read, Grep, Glob, Write — no Bash, because its task is closed-form (it is handed the skill-invocation list, not raw transcripts). Like the specialist reviewers, it writes findings to agent-reviews/<agent-name>-<epoch>-<slug>.md under findings_path: and returns only a pointer line.
comment-discipline-reviewer — a reviewer spawned by /code-review's Ripple-effect-triage Change-type table (also outside the specialist-roster count above), for diffs that add or modify a comment or durable in-repo doc prose beyond a hygiene tweak. It checks the diff against the CLAUDE.md prose rules its agent file names from a context the authoring session never touched, enumerating every violating site rather than the one a human happened to point at. Tools Read, Grep, Glob, Write — no Bash, same closed-form rationale as skill-fidelity-reviewer: the task is reading a diff against a fixed rule set, not shelling out. Like the specialist reviewers, it writes findings to agent-reviews/<agent-name>-<epoch>-<slug>.md under findings_path: and returns only a pointer line.
code-writer — a non-reviewer Sonnet agent that implements delegated code changes and self-reviews its own diff before returning, verifying it against the relevant staff-* reviewer angles so review-finding-class defects are caught in its own context rather than as a parent round-trip. Dispatched by the parent in place of general-purpose for code-writing; see claude/.claude/CLAUDE.md "Model Routing" and docs/design-decisions.md §11.
CLAUDE.md — baseline engineering instructions (judgment heuristics, working style, safety rules)..claude/rules/ — path-scoped instructions, loaded automatically only when a matching file is opened; used here for skill/agent self-review discipline, per-file-type review-pipeline dispatch, test-tree packaging, this repo's bash unit-test-seam mechanics, and the shell floor.claude/.claude/rules/ — the stowed, user-scope sibling (installs to ~/.claude/rules/); holds CI/infra, SQL/DDL, Python environment, settings.json conventions, and CLAUDE.md/AGENTS.md loading conventions that apply across every repo the user opens, not just this one.settings.json — global settings wiring up the hooks, statusline, and a permissions.deny hard floor for sudo, secret-file reads, and tool-availability entries (see Auto mode). Configured with sonnet as the default model. The escalation path for Opus judgment is plan-architect, dispatched automatically by /plan-it Step 5 or on the user's explicit ask for an ad hoc consult (Model & Effort Routing section of CLAUDE.md). Session-only overrides (model, effortLevel) are intentionally not tracked — use the ANTHROPIC_MODEL and CLAUDE_CODE_EFFORT_LEVEL env vars, or /effort max mid-session.Utility scripts in claude/.claude/scripts/ (stowed to ~/.claude/scripts/); user-facing ones are installed as wrappers under ~/.local/bin/. For full descriptions of every script, see docs/scripts.md.
Configuration options spanning machine-local, project-local, and user-local settings. See SECURITY.md for the threat model — what the hook system protects against and what it doesn't.
require-worktree-for-git-writes.sh denies non-read-only git operations (commit, push, rebase, reset, merge, checkout, etc.) unless the session runs inside a linked git worktree. Read-only commands (status, log, diff, fetch, show, blame, etc.) are always allowed. The hook is opt-in per repo (via a committed .claude/worktree-required sentinel) or per machine (via the worktree_required config key, checked as a union with the legacy ~/.claude/worktree-required location so a value armed before CLAUDE_CONFIG_DIR adoption still activates — see docs/config-file.md).
The race it prevents: concurrent Claude Code sessions sharing a working tree can step on each other — one session's git reset --hard, git stash, or git checkout silently wipes another session's uncommitted edits. See Claude Code issue #34327 for examples of this failure mode in the wild.
Worktrees only isolate each session's state if each session gets its own — two sessions that independently anchor into the same linked worktree are back to that same race. Both hooks close that gap too: a write into a worktree a live session already holds (tracked via an atomic O_EXCL create against the worktree's own <git-dir>/locked file, not git worktree lock — see _lib_worktree_collision_guard in _lib.sh) is denied for a second session, naming the holder's pid. A worktree whose holder has since exited has its lock automatically reclaimed and re-acquired for the current caller within the same hook invocation — no manual git worktree unlock step, no retry. This lets a background subagent dispatch clear it itself with no human in the loop. Reclaim is a once-only right per lock identity; see docs/design-decisions.md §36 for the eviction-claim mechanism and its failure-mode fallback.
The sentinel coexists with any existing .claude/ content — mkdir -p is a no-op if the directory is already there, and the sentinel is an inert marker file alongside whatever project-level plans, settings.local.json, or untracked worktree dirs the repo already holds.
cd path/to/your/repo
mkdir -p .claude
cat > .claude/worktree-required <<'EOF'
# Claude Code worktree enforcement marker.
# Presence of this file activates ~/.claude/hooks/require-worktree-for-git-writes.sh.
# See https://github.com/jcdendrite/claude-config for details.
EOF
grep -qxF '.claude/worktrees/' .gitignore 2>/dev/null || echo '.claude/worktrees/' >> .gitignore
git add .claude/worktree-required .gitignore
git commit -m "Activate Claude Code worktree enforcement"
A git worktree is a linked working directory on a separate branch that shares the repo's .git object storage with the main clone. git worktree add <path> -b <branch> creates one; multiple worktrees of the same repo can have different branches checked out simultaneously, which is what lets concurrent Claude Code sessions stay isolated.
With enforcement active, start sessions for non-trivial work in a worktree instead of the main tree:
git worktree add .claude/worktrees/my-feature -b my-feature
cd .claude/worktrees/my-feature
# work happens here; git commit/push/etc. pass through the hook cleanly
The contributor .venv is gitignored and lives only in the main worktree root — linked worktrees never inherit it. See Tests for cross-worktree invocation.
Agent dispatches with isolation: worktree follow a separate rule, scoped to whether the agent's input or output touches the parent's working tree. See claude/.claude/CLAUDE.md's Agent Briefing section for that rule. For PR-bound work that needs a meaningful branch name, create the worktree yourself first per the branch-management skill, then dispatch the agent into the new worktree.
To opt out, delete .claude/worktree-required.
./install.sh now offers this interactively on every run — the snippet below is the non-interactive/scripted alternative, not the only path.
If you work across many repos and want enforcement everywhere without adding a marker to each, set the worktree_required config key:
printf 'worktree_required = true\n' >> "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/claude-config.toml"
See docs/config-file.md for the file's hand-edit contract. This activates enforcement for every git repo on your machine. Any repo that already has a committed .claude/worktree-required is unaffected (it was already enforcing). To exempt a specific repo from machine-level enforcement:
mkdir -p .claude && touch .claude/worktree-optout
The opt-out only modulates the machine-level default — it cannot exempt a repo whose committed .claude/worktree-required travels with the source.
Machine-level enforcement produces an untracked .claude/worktrees/ directory in every repo you open, not just ones you've configured — so pair it with a global git-excludes entry rather than relying on each repo's own (possibly absent) .gitignore. This is a permanent, machine-wide change (it applies to every repo you ever open, not just this one); to reverse it later, remove the appended line from the same file:
f=$(git config --path --get core.excludesFile || echo "${XDG_CONFIG_HOME:-$HOME/.config}/git/ignore")
mkdir -p "$(dirname "$f")"
grep -qxF '**/.claude/worktrees/' "$f" 2>/dev/null || echo '**/.claude/worktrees/' >> "$f"
Without this, a git add -A in a repo that never got the per-repo .gitignore line (see above) can sweep live worktrees into a commit.
If the agent ends its turn asking whether you want to review the diff before it commits — even after finishing the work you asked for — this is the setting that removes that pause. advance-past-commit-stall.sh (a Stop hook) force-continues the turn through /code-review → commit → /ready-for-review → PR-open, stopping only before merge, whenever the machine-level autonomous_shipping config key resolves true and the current repo carries no .claude/autonomous-shipping-optout. A repo cannot grant this by committing anything — only this machine-level key can; see claude/.claude/hooks/_lib.sh's _lib_autonomous_shipping_active.
./install.sh now offers this interactively on every run — the snippet below is the non-interactive/scripted alternative, not the only path.
printf 'autonomous_shipping = true\n' >> "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/claude-config.toml"
See docs/config-file.md for the file's hand-edit contract.
To exempt a specific repo:
mkdir -p .claude && touch .claude/autonomous-shipping-optout
See docs/commit-stall-block.md for the fire predicate, in-session recovery, log format, and known limitations.
pr-description can embed the PR body's cost block — branch-scoped session count, token volume, and list-price dollars from transcript-analysis.py cost --summary. Off by default; gated by the pr_cost_disclosure config key, scoped to the Claude account, not to the repo.
printf 'pr_cost_disclosure = "dollars"\n' >> "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/claude-config.toml"
The key resolves to exactly one config dir ($CLAUDE_CONFIG_DIR if set and absolute, else $HOME/.claude) and its value (dollars vs. anything else) toggles the mode account-wide, so one account's opt-in never activates disclosure under another — see docs/config-file.md for the file format and resolution precedence.
The disclosed fields are not a safe-by-default aggregate — see the "The disclosed fields are not neutral" paragraph in docs/transcript-analysis.md's cost section and docs/hooks.md's "Non-hook opt-in/opt-out sentinels" for the full mechanics. ./install.sh's sentinel inventory (report_sentinel_inventory) reports this key's state alongside every other opt-in.
pr-description runs a tighten-prose pass over the drafted body before its checks. On by default, unlike PR cost disclosure above — opt out per account by touching a sentinel scoped the same way.
touch "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/pr-description-tighten-prose-optout"
See docs/hooks.md's "Prose tightening opt-out" for the full mechanics.
If you're running in auto permission mode and want to know which commands still trigger an interactive approval dialog — and how often — this opt-in hook captures it. track-permission-prompts.sh (a Notification hook, matcher permission_prompt) appends the redacted payload to a local, gitignored log whenever the sentinel below exists on this machine.
touch "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/track-permission-prompts"
See docs/permission-prompt-tracking.md for the log location/format, redaction coverage, and known limitations.
nudge-error-mode-analysis.sh (a UserPromptSubmit hook) watches the current session's transcript for a repeated-failure pattern — hook denials, failed test runs, and user-correction phrases — and, once that composite crosses a threshold, suggests offering to run /error-mode-analysis if the current work looks close to delivered. It's off by default for every contributor.
./install.sh now offers this interactively on every run — the snippet below is the non-interactive/scripted alternative, not the only path.
touch "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/.error-mode-nudge-enabled"
See docs/error-mode-nudge.md for the fire predicate, log location, and known limitations.
transcript-analysis.py cost-ledger --record appends the current ISO week's cost and efficiency figures to a local ledger file outside this repo. The row aggregates every project's transcripts in scope, which by default includes every account declared in ~/.claude/transcript-config-dirs. --this-repo narrows the project set. The row outlives Claude Code's rolling transcript cleanup. Off by default; a week not recorded while its transcripts are still on disk can't be recovered later.
./install.sh now offers this interactively on every run — the snippet below is the non-interactive/scripted alternative, not the only path.
printf '\ncost_ledger_recording = true\n' >> "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/claude-config.toml"
See docs/cost-ledger.md for the ledger's default location, schema, and recording mechanics, and docs/config-file.md for the file's hand-edit contract.
Moving or renaming this checkout (mv ~/current-location/claude-config ~/somewhere-else) breaks every stow symlink under ~/.claude/ and ~/.local/bin/ at once — the symlinks stow created encode the checkout's location, and since ~/.claude/hooks/, ~/.claude/skills/, and the ~/.local/bin/* wrappers are themselves part of what breaks, nothing is left running inside the checkout that could detect or explain the failure. Two guardrails address this:
deny-repo-relocation.sh (always on, no opt-in) stops Claude Code itself from performing an unsupported mv/rsync --remove-source-files of this checkout's root (or an ancestor of it) and points at relocate-claude-config instead. It's a best-effort guard against the common literal-path case, not a hard security boundary: a source argument reached only through a shell variable, command substitution, or a preceding cd fails open (allow) rather than deny. In that case the command never invokes relocate-claude-config, so its destination-side validation never runs either — the repo, and every hook symlink under ~/.claude/hooks/, can land anywhere, unchecked, not merely broken stow symlinks. See docs/hooks.md for the full documented known gaps.
relocate-claude-config is the single supported command for both deliberate relocation and after-the-fact repair:
relocate-claude-config <new-path> # repo hasn't moved yet: unstows, mv's, re-stows
relocate-claude-config --repair <new-path> # repo already moved outside a Claude Code session
The primary form unstows the current checkout, moves it, and re-stows at the new location — do not run it while other Claude Code sessions are active, since every hook under ~/.claude/hooks/ is briefly absent between the unstow and re-stow steps, and a concurrent session's tool call in that window gets a hard deny. --repair is for when the checkout was already moved outside any Claude Code session (a manual mv, a Finder drag, a sync-tool restore, or a crash mid-relocation) — it quarantines (never deletes) any ~/.claude or ~/.local/bin entry left as a dangling symlink into the old location, then re-stows at the location you give it. Both modes canonicalize the destination and refuse one outside $HOME unless you pass --allow-outside-home.
A one-line manifest, ~/.claude-config-source, records the checkout's current absolute path — install.sh writes it, and relocate-claude-config reads and rewrites it — so the command can find the checkout even when the ~/.claude symlinks it depends on for everything else are the very thing it's asked to fix. relocate-claude-config is installed as a real file copy (install -m 755), not a stow symlink, since a stow-managed wrapper would inherit the exact failure it exists to repair.
Optional, manual, macOS-only hardening: chflags uchg <repo-root> (clear with chflags nouchg <repo-root>) makes macOS refuse to rename or delete the checkout's top-level directory entry, even for the owner, without an explicit nouchg first. It is not wired into install.sh and never will be by default: Linux's equivalent (chattr +i) needs root, so the mechanism would silently cover macOS only; and even on macOS, the flag also blocks creating, removing, or renaming any entry directly inside the flagged directory — a git pull or git checkout that adds or removes a top-level file in this repo would fail outright. If you want the extra defense-in-depth and accept that tradeoff, set it yourself; it is not something any script here toggles automatically.
This repo is public — any project codename, organization name, or tracker-ID that lands in a commit or PR description ships to the world. claude-config defends against that in three tiers:
deny-private-project-refs.sh blocks git commit, gh pr create, gh pr edit, gh issue create, gh issue comment, gh issue edit, and mutating gh api calls whose content carries [A-Z]{2,}-\d+ tracker tokens outside an OSS-prefix allowlist, or one of six structural shapes (see The six structural detectors).<config-dir>/private-projects.md and blocks any commit or PR whose content matches a listed project name (case-insensitive, whole-word). install-dev.sh requires this file to exist before setting up a contributor's .venv, so the opt-in isn't silently skippable at first setup.The repo-root CLAUDE.md "Redact private-project-identifying content" rule defines what to keep out; the hook is the mechanical enforcement of tiers 1–2. The hook runs in claude-config and its forks (origin URL contains claude-config), and in any other repo that commits .claude/private-projects-optin; see docs/private-project-redaction.md. For blocklist setup, file format, match semantics, the deny-message contract, and the fork-contributor path, see docs/private-project-redaction.md.
Auto mode replaces per-action permission prompts with a background classifier that evaluates each tool call before it runs, blocking anything irreversible, destructive, or targeted outside your environment. This repo adds two things on top of the stock feature:
claude-auto wrapper — resolves a model mismatch, not a plan restriction, for whoever's session model resolves to opusplan (Opus in plan mode, Sonnet during execution) — this repo's own default, sonnet, is already a valid auto-mode session model. Auto mode anchors a session to one concrete model for its entire lifetime, so opusplan itself isn't a valid session model for it. The wrapper starts a session directly in auto mode, taking the same --model flag as claude and falling back to Sonnet when you don't name one (full precedence).permissions.deny rules — settings.json ships deny rules that run before the classifier and cannot be overridden by any autoMode.allow entry, hard-blocking sudo, well-known secret-file reads, and select tool-availability entries (full list in docs/auto-mode.md). These apply in every permission mode, not just auto mode.For plan and model requirements, activation, the full hard-floor deny table, the settings.local.json autoMode.environment schema, and tuning commands, see docs/auto-mode.md.
To customize response tone, formatting, and communication style, create <config-dir>/output-preferences.md. This file is user-local and never committed to this repo. It is loaded via an instruction in claude/.claude/CLAUDE.md's Main session group (under Working Style), which applies to the main session and forks. The "Prose and Output Format" section, in the Agent Core group, also carries the non-personal prose rules — response shape, concision, sentence craft — and those apply to every session and subagent whether or not this file exists.
Cap: keep it under 50 lines — content beyond that competes with project context for the 200-line CLAUDE.md budget. Keep it to personal tone and style — rules already in the global CLAUDE.md apply regardless, and a second copy here costs context budget and drifts from the original.
Template:
# Output preferences
- Tone: direct and calibrated — state things plainly; match certainty to evidence (no overclaiming, no hedging filler).
- Avoid emoji unless explicitly asked.
Personal permission overrides belong in a repository's own .claude/settings.local.json (untracked, gitignored automatically) — Claude Code scopes this file to the repository root, not the user's home directory, so there is no single file that covers every repo on the machine at once. For a preference that should apply everywhere, use an environment variable exported from your shell profile instead — see the ANTHROPIC_MODEL/CLAUDE_CODE_EFFORT_LEVEL example in Configuration files above. This does not apply to disableArtifact/disableWorkflows, which are a shared repo-wide default rather than a personal preference — see the next section for how to override those two specifically.
The built-in Artifact and Workflow tools are the two largest eagerly-loaded tool schemas in every session's system prompt, so settings.json sets disableArtifact/disableWorkflows to true by default; see docs/design-decisions.md §31 for the measurement. Two commands re-enable one tool for a single session, taking CLI-scope precedence over the shared default:
claude-workflow — starts a session with the Workflow tool enabled (Artifact stays off). Takes the same flags and positional prompt as claude.claude-artifact — same, for the Artifact tool.To flip the default itself rather than opting back in per session, set disableWorkflows: false (or disableArtifact: false) in a repository's own .claude/settings.json or .claude/settings.local.json — both outrank the User-scope default this repo ships.
Claude Code compresses conversation history when the context window fills up. This config adds two layers to keep that process reliable.
Marker re-injection (automatic). session-marker-dashboard.sh is registered with matcher startup|clear|compact, so it fires on session start, after /clear, and after compaction. It emits hookSpecificOutput.additionalContext with the current state of all active review-skill gate markers, restoring marker knowledge in the resumed context automatically. You don't need to do anything for this to work.
/handoff slash command (user-invoked). When the task will continue in a fresh session, run /handoff to write a structured resume file at <config-dir>/handoffs/<slug>-handoff.md — durable, so it survives a reboot. The §1–§7 shape is defined inline in claude-skills/skills/handoff/SKILL.md. Claude recommends /handoff or /compact (which one: docs/handoff-nudge.md "Compaction as an alternative to /handoff") once context crosses nudge-handoff-near-context-cap.sh's computed threshold — 40% of the model's context window, capped at 150000 tokens (HANDOFF_NUDGE_ABS_CAP overrides it) — because cleaner context produces a higher-quality /handoff resume file, and every turn spent past a 150000-token prefix on the largest context window is waste. Resume with resume-context --cwd <worktree-path> <config-dir>/handoffs/<slug>-handoff.md when the handoff named a worktree, or resume-context <config-dir>/handoffs/<slug>-handoff.md alone from the main checkout — either form moves the file to a temp path and launches a new session with it loaded, consumption mechanical rather than dependent on the resuming session remembering to read or delete the file. --cwd launches the session in that directory outright, rather than depending on the invoker separately cd-ing there first. To resume inside the current process instead, after /clear or in a new session started in the same worktree, run /resume-context; it prints the shell command in place of loading when it cannot confirm the file belongs to this worktree. See docs/skills.md for when each path applies.
Post-compaction authorization boundary restatement (automatic). restore-authorization-boundary-on-compact.sh fires only on , re-injecting that restates the irreversible-action confirmation boundary — advisory, not a gate. Opt out via .
| Situation | Right action |
|---|---|
| Switching to an unrelated task | /clear (intent-driven, no percentage threshold) |
| Ending a session, will resume later | /handoff (produces resume file; the announce message after the write names the resume route) |
| Continuing the same task in the same session | /compact [instructions] (manual; the handoff nudge recommends it only when the criteria in docs/handoff-nudge.md "Compaction as an alternative to /handoff" all hold, otherwise /handoff into a fresh session) |
| Context >83.5%: auto-compact fires | Happens automatically; marker state is restored by the hook |
/handoff's suggested threshold — this repo's own chosen ceiling, not a vendor-specified figure, overridable via HANDOFF_NUDGE_ABS_CAP. nudge-handoff-near-context-cap.sh computes the actual per-session threshold as the lesser of 40% of the resolved model's context window (200k or 1M, model-dependent) and this cap; see docs/handoff-nudge.md for the per-model table and known limitations.HANDOFF_NUDGE_BLOCK_AT, the absolute token position past which a further re-arm hard-blocks (stderr + exit 2) instead of staying advisory, independent of how many re-arms preceded it. Overridable via HANDOFF_NUDGE_BLOCK_AT; see docs/handoff-nudge.md for why this point and the surviving exits from a block.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE).analyze-context to inspect token usage for the current session.Pytest suite covering hooks (allow, deny, and ask paths) and skill description contracts. Pins live in requirements-dev.txt (single source for CI + contributors):
./install-dev.sh # from the main checkout's root: creates .venv, installs requirements-dev.txt, offers the pyright-lsp plugin (contributor only)
scripts/venv-run.sh pytest claude/.claude/ claude-skills/ plugins/ evals/
scripts/venv-run.sh ruff check claude/.claude/ claude-skills/ plugins/ evals/ # Python
scripts/list-shell-files.sh | xargs -0 scripts/venv-run.sh shellcheck # shell
ShellCheck takes no flags on the command line — they live in the repo-root
.shellcheckrc, so CI, the command above, and any editor integration agree.
The .venv lives only in the main checkout's root, and linked worktrees never inherit it. scripts/venv-run.sh <tool> [args...] finds that .venv through git and runs <tool> from its bin/ directory, so the scripts/venv-run.sh commands above work unchanged at any depth. Run them from the root of the main checkout or of a linked worktree, since they are cwd-relative.
./install-dev.sh also offers to install pyright-lsp@claude-plugins-official at local scope, giving Claude Code sessions in this checkout Python diagnostics and navigation. Local scope records the plugin only in this checkout's gitignored .claude/settings.local.json. The install runs only when claude-plugins-official is already registered and you answer y at the prompt. If the marketplace is not registered, the script prints the claude plugin marketplace add anthropics/claude-plugins-official command instead. That registration applies to every project on your profile. A non-interactive run prints the claude plugin install command to run from this checkout instead of prompting. A local-scope install made from the main checkout root is active in Claude Code sessions anchored in a linked worktree under .claude/worktrees/ too. See docs/design-decisions/pyright-lsp-installed-per-contributor.md for why the plugin reaches contributors only, and only from an interactive terminal. The pyright-langserver binary needs to be on the PATH of the shell that launches Claude Code, and ./install-dev.sh checks for it but does not install it:
pipx install pyright. Without pipx, python3 -m pip install --user pyright works only on an interpreter that is not externally managed (PEP 668).npm install -g pyright where the global npm prefix is root-owned (common on stock Linux/WSL2); that fails with EACCES..venv. A .venv-scoped binary is not on PATH for the process that launches Claude Code.which pyright-langserver resolves to the Linux-side binary, not a Windows-side one on an inherited PATH.The suite runs under pytest-xdist (-n auto) by default; pass -n0 to run serially for -s / --pdb / -x debugging.
Test trees under claude/.claude/ that carry their own conftest.py are Python packages, so each tree's conftest resolves to a distinct module name. .claude/rules/test-tree-packaging.md states what a new tree must add; claude/.claude/tests/test_pytest_collection_config.py enforces it.
-n auto resolves to the machine's logical CPU count. select-tests.py sizes PYTEST_XDIST_AUTO_NUM_WORKERS itself from the current 1-minute load average, never exceeding what -n auto would have picked. A run starting on an already-busy machine takes only the idle headroom instead of a full machine's worth. Check its stderr line for the count it picked. Running scripts/venv-run.sh pytest claude/.claude/ claude-skills/ plugins/ evals/ directly has no such sizing; cap it manually:
PYTEST_XDIST_AUTO_NUM_WORKERS=<N> in the environment.
scripts/venv-run.sh pytest run and select-tests.py.select-tests.py's own sizing, which defers whenever the variable is already set.-n <N> on the command line for a single run. It wins over both. select-tests.py forwards it through to pytest.-n 4). Check xdist's startup banner to confirm a run picked up the value.claude had at launch rather than reading the shell live, so export it before starting that session — setting it afterward in a running session's terminal won't reach that session's test runs.CI runs the same pin set on every PR and main push via .github/workflows/tests.yml. It runs pytest in two passes: a parallel pass for everything not marked timing, then a serial pass for the timing tests, which flake under sibling-worker load. To reproduce the serial pass locally, add -m timing -n0 to the pytest command above.
For a faster local dev loop, select-tests.py runs pytest against just the test domains implicated by what you changed, instead of the whole suite. It computes the changed-file set as the merge-base diff against origin/main unioned with your dirty working tree. It then maps each changed path to its test domain. Any change it can't map with confidence fails open to running the full suite:
scripts/venv-run.sh python3 claude/.claude/scripts/select-tests.py
This is the required local command for agents, including in /ready-for-review. CI still runs the whole suite on every PR and main push — a deliberate choice, see docs/design-decisions/ci-stays-an-unconditional-full-suite-backstop.md.
Set test_selection_tracking = true in <config-dir>/claude-config.toml (off by default) to log every select-tests.py invocation's selection outcome to <config-dir>/.test-selection-log.jsonl, one JSON line per invocation. Each line always records the selection reason. For a full-suite fallback, it also records which changed path triggered it. When that invocation computed a load-aware worker count, it also records the worker count and the 1-minute load average. This makes fallback-to-full-suite frequency measurable instead of a stderr line that scrolls away. Like .permission-prompt-log.jsonl, the log is append-only with no automatic rotation; trim it manually if disk space or data age is a concern. Its invocation frequency is structurally higher than that log's, since it appends on every select-tests.py run rather than only on an interactive permission dialog.
Heavy reliance on official Anthropic documentation throughout: Claude Code docs, permission modes reference, auto-mode engineering deep dive, skill best practices, and Claude Code best practices. Stow distribution pattern inspired by the GNU Stow community.
Bug reports and feature requests: GitHub Issues. Security disclosures: see SECURITY.md.
Released under the MIT License — see LICENSE.
/clearresume-context.sh/resume-contextresume-context.sh --consume-only/tmpfind-consumed-continuity-file.sh./install.shconsume-durable-continuity-file-on-read.shpost-crash-sessions cross-references five session-liveness sources, including a never-swept lookup corpus that survives a same-day crash with no reboot, to find and resume crash-orphaned sessions, with a versioned --json mode for programmatic consumers. See docs/scripts.md./plan-it, /plan-review, /code-review, and /test-conventions glob for .claude/skills/<parent>-<project>/SKILL.md at runtime; consuming repos extend the base skill without forking. Description-based auto-trigger was empirically tested and rejected (it doesn't fire from inside a running skill). Add-on skills on the project side should set disable-model-invocation: true — the parent invokes them via the Skill tool, so their description doesn't need to be in the always-loaded skill-listing budget. See docs/skills.md and docs/design-decisions/project-layer-composition.md.transcript-analysis.py, post-crash-sessions, analyze-context.py, and token-analyzer.py default to the union of every root in ~/.claude/transcript-config-dirs, except a few subcommands that read the active account only, among them cost --summary (this repository on the active account only) and period-cost (the active account's whole projects directory). A subcommand that prints a resolved-scope header states the root count there. See docs/transcript-analysis.md for the per-subcommand mechanics.docs/transcript-analysis-architecture.md.require-architect-consult.sh denies a reviewer-persona spawn once a branch's distinct (HEAD sha, staged-diff sha256) states hit a cap of two, interrupting a non-converging review loop before the round-3 fan-out it exists to prevent gets paid for. Unlike this repo's content-addressed markers described above (decision 2), the release latch is presence-only and does not re-arm on state change, since the diff changing is exactly what rounds 3+ look like. See docs/hooks.md (require-architect-consult.sh, log-reviewer-round.sh) and docs/design-decisions.md §45.-kdocs/hooks.mdpython3 >= 3.11. Stock macOS /usr/bin/python3 is 3.9.6, Ubuntu 22.04 LTS ships 3.10, and Debian 11 ships 3.9 — all below this floor. Install a newer interpreter (e.g. via Homebrew or pyenv on macOS; your distro's python3.11+ package or pyenv on Linux) so it resolves first on PATH. install.sh checks this and exits early if it isn't met.pytest for running the test suite (see the Tests section below for the command; add -n0 to run serially for -s / --pdb / -x debugging).onFailure: "block", which older versions may ignore or reject (unverified). install.sh warns when the claude on its PATH reports an older version, or when it cannot read a version from claude --version. It does not run on git pull, so update Claude Code before pulling. If you pulled first, update Claude Code, restart it, and confirm /hooks lists the gates and /permissions shows the deny rules.deny-pii-in-commits.shRemove the flagged content; see docs/hooks.md |
deny-data-file-reads.sh | Read of a data-shaped file (opt-in) | No clear — inspect data files outside Claude |
deny-credential-bash-reads.sh | Bash command referencing a credential-shaped path (SSH key, .netrc, cloud credential store, and similar) | No clear — no bypass valve; inspect/run the specific command outside Claude |
deny-credential-file-reads.sh | Read of a credential-shaped path, including through a symlink | No clear — no bypass valve; inspect the file outside Claude |
deny-network-installs.sh | Bash command that installs a named package (including uv add), uses npx/bunx/uvx/pipx run/npm exec with an explicit -y/--yes, uses pnpm/yarn dlx unconditionally, or hands fetched content to a shell/interpreter | No clear — no bypass valve; ask the user to run the specific command in a separate terminal |
ask-new-dependency-disclosure.sh | — (PreToolUse Edit/Write/MultiEdit to package.json, informational) | Asks, naming each name@constraint pair, when the edit adds a dependency not already declared; see docs/security-hardening.md |
redact-credential-values.sh | — (PostToolUse Bash/Read/WebFetch/Grep/Task, informational) | Redacts a credential-shaped value in the tool result via updatedToolOutput; see docs/hooks.md |
deny-reviewer-tree-mutation.sh | Bash/Write/Edit/MultiEdit from a review-only agent (ciso-reviewer, staff-*, Explore, Plan) that would mutate the tree under review | No clear — confirm by reading and tracing; a persona's scratch work follows its ## Scratch execution section |
deny-plan-writer-off-plan-writes.sh | Write/MultiEdit, or an Edit to anything but an existing .claude/plans/ file, from a plan-writer agent (plan-architect) | No clear — the agent returns its sections as text |
require-architect-consult.sh | Reviewer-persona Agent/Task spawn when a branch is entering its third distinct reviewed state | A plan-architect MODE=consult dispatch (self-initiated or gate-prescribed), which log-reviewer-round.sh records as a per-branch latch; or <config-dir>/.round-consult-gate-disabled |
deny-no-op-dispatch.sh | Agent/Task spawn whose prompt is under 600 characters and matches a closed no-work idiom list | No clear — state the dispatch's actual work in the prompt, or end the turn without a tool call |
require-ready-for-review.sh | git push, gh pr ready, gh pr create | /ready-for-review run since last commit |
require-respond-pr.sh | gh api PR comment reads/posts | /respond-pr active bypass marker |
advance-past-commit-stall.sh | — (Stop, turn-gate, opt-in) | Forces the turn to continue past a commit/push/PR-open permission question when autonomous shipping is active; see Autonomous shipping |
capture-session-id.sh | — (SessionStart, no gate) | Writes session-id so marker filenames are per-session |
nudge-handoff-near-context-cap.sh | — (PostToolBatch + Stop, advisory) | Injects a one-shot reminder near the context cap; see docs/handoff-nudge.md |
nudge-error-mode-analysis.sh | — (UserPromptSubmit, advisory, opt-in) | Injects a one-shot suggestion to run /error-mode-analysis; see docs/error-mode-nudge.md |
nudge-memory-store-audit.sh | — (SessionStart, advisory) | Nudges an audit of the machine's auto-memory stores once their total size passes a count-scaled threshold; see docs/memory-audit-nudge.md |
nudge-worktree-anchor.sh | — (UserPromptSubmit, advisory) | Reports when the session is working from the main tree of a worktree-enforcing repo while a linked worktree other than a review-pr checkout exists |
check-branch-divergence.sh | — (SessionStart, advisory) | Surfaces feature-branch divergence from origin/<default>; see docs/hooks.md |
set-session-title-from-branch.sh | — (SessionStart, advisory) | Sets the terminal tab title to <repo>/<branch> on feature branches; see docs/hooks.md |
bootstrap-project-plugins.sh | — (SessionStart, informational, on by default) | Installs a trusted repo's missing enabledPlugins into the plugin registry at -s local in the background; plugin_bootstrap = false turns it off; see docs/hooks.md |
track-permission-prompts.sh | — (Notification, informational, opt-in) | Appends a redacted permission-prompt event to a local log; see Permission-prompt tracking |
linear-formatting — Linear issue-comment and issue-link formatting conventions for tracker writes: issue-ID auto-linking and comment markdown support. Names each MCP tool by role across both observed server prefixes rather than picking one. Distinct from the unrelated linear@claude-plugins-official plugin, which only registers the Linear MCP server and carries no skills. claude plugin install linear-formatting@claude-config --scope project
issue-triage — Stateless, report-only triage of a repo's open GitHub issues via /issue-triage: batched parallel evidence-gathering, cross-batch synthesis, and an independent claim-verification pass, delivered as a disposition report written outside the repository. All three dispatch stages run general-purpose under the operator's own ambient gh credentials and unrestricted Bash, with no command-level enforcement. The same prompt-level standing rules (never invoke a gh write subcommand, never target a repo other than the run's resolved target) are the only control, applied identically to all three. Install only where the credential's actual reach, the untrusted issue/comment input, and the unredacted artifact retention are all acceptable. claude plugin install issue-triage@claude-config --scope project
compacthookSpecificOutput.additionalContext~/.claude/.authorization-boundary-disabled