Harness
Control surface for the user-scope Claude Code "harness" — feedforward guides (CLAUDE.md, memory), feedback sensors (hooks), and an optional drift-detection loop (snapshot + monthly audit).
The vocabulary follows OpenAI's Harness engineering (https://openai.com/index/harness-engineering/) and Martin Fowler's writeup (https://martinfowler.com/articles/harness-engineering.html). Day-to-day patterns are convergent picks from Boris Cherny, Simon Willison, Jesse Vincent (Superpowers), Geoffrey Huntley (Ralph loop), Hamel Husain (eval skills), and Steve Yegge (Gas Town). See README.md for citations.
Sub-action dispatch
The user invokes this skill, optionally with an action word. Detect intent and run the matching sub-action. If the user says /harness without context, run status first (it's read-only and informative), then ask which action they want.
| Said by user |
Sub-action |
Script |
| "install", "set up", "bootstrap" |
install |
scripts/install.sh |
| "uninstall", "remove", "undo" |
uninstall |
scripts/uninstall.sh |
| "update", "pull latest templates", "refresh" |
update |
scripts/update.sh |
| "doctor", "diagnose", "is it working" |
doctor |
scripts/doctor.sh |
| "adopt", "add to existing project", "retrofit" |
adopt |
scripts/adopt.sh |
| "snapshot", "backup", "mirror to git" |
snapshot |
scripts/snapshot.sh |
| "status", "what's installed", "audit local" |
status |
scripts/status.sh |
| "audit", "schedule audit", "monthly check" |
audit |
(prep work — see below) |
| "memoize", "consolidate memory", "prune memory" |
memoize |
scripts/memoize.sh |
Substitute the skill's absolute base directory for $SKILL_DIR in every command — it's announced at the top of this invocation.
install
Lays down the harness at the scope where the skill itself lives, derived from $SKILL_DIR:
- Skill at
<X>/.claude/skills/harness/ (or under a plugin cache below <X>/.claude/) → install at <X>/.claude/.
- If
<X> is $HOME, that's user scope; otherwise project scope.
- Override with
--scope=user, --scope=project, or --target=PATH.
- If the skill is being run from a checkout (no
.claude/ ancestor), the script errors with a clear message asking for --scope or --target.
What lands at user scope:
| Surface |
Path |
| Operating contract |
~/.claude/CLAUDE.md |
| Hooks |
~/.claude/hooks/{block-force-push,format-on-edit,post-compact-reinject,verify-before-stop}.sh |
| Slash commands |
~/.claude/commands/{verify,plan,critique}.md |
| Auto-memory |
~/.claude/projects/<slug>/memory/{MEMORY.md, user_role, feedback_concise, feedback_plan_first, feedback_verification} |
| settings.json |
Adds env.CLAUDE_CODE_AUTO_COMPACT_WINDOW=400000 + 4 hook entries (uses ~/.claude/hooks/... form) |
What lands at project scope (<project>/.claude/):
| Surface |
Path |
| Operating contract |
<project>/CLAUDE.md (skipped if it already exists — most projects have one. --force overrides) |
| Hooks |
<project>/.claude/hooks/*.sh |
| Commands |
<project>/.claude/commands/{verify,plan,critique}.md |
| settings.json |
<project>/.claude/settings.json — 4 hook entries with .claude/hooks/... (project-relative) form. No env var, no memory at project scope. |
| Memory |
(skipped — memory is per-user by design and lives under $HOME regardless of project scope) |
bash "$SKILL_DIR/scripts/install.sh"
Common flags:
--dry-run — show the preflight + plan, change nothing.
--force — overwrite existing files (including project CLAUDE.md).
Per-surface skip flags (escape hatch — pick & choose what to install):
--skip-claude-md, --skip-hooks, --skip-commands, --skip-memory, --skip-settings
Or a positive list (everything else is skipped):
--include=hooks,commands — install only those.
--include=claude-md,settings — only the operating contract + settings patch.
- Valid items:
claude-md, hooks, commands, memory, settings.
The script always prints a preflight banner showing scope, target, the per-surface plan (with SKIP markers reflecting the active flags), and a pointer to the uninstaller with --all warnings. Read it before proceeding.
After install, walk the user through the hand-edits printed under "Next steps":
- Fill in
## Stack signals in CLAUDE.md (user scope: ~/.claude/CLAUDE.md; project scope: <project>/CLAUDE.md). At install time the script tries to auto-fill this from manifests it finds — verify it picked up your stack correctly. If you need hints, look at ~/.claude/projects/ slugs and installed_plugins.json; ask if unclear. Don't auto-fill from guesswork.
- (User scope only) Replace placeholders in
~/.claude/projects/<slug>/memory/user_role.md with the user's actual role / projects / stack. Ask, don't invent.
Tell them to restart Claude Code so hooks load.
uninstall
bash "$SKILL_DIR/scripts/uninstall.sh"
Same scope auto-detection as install. Conservative defaults:
- Removes hooks + commands only if their sha256 still matches the installed template. User-modified files are kept and reported as
keep (modified).
- Strips the 4 hook entries from
settings.json; drops empty hook event arrays. Leaves all other settings untouched.
- Keeps by default:
CLAUDE.md, memory files, the CLAUDE_CODE_AUTO_COMPACT_WINDOW env var.
Flags:
--dry-run, --force (skip content-match)
- Broaden the sweep:
--remove-claude-md, --remove-memory, --remove-env, --all
- Escape hatch — keep specific surfaces that default would remove:
--keep-hooks, --keep-commands, --keep-settings
The script prints a preflight banner showing scope, target, what will be removed vs kept, and which --keep-* / --remove-* flags are active. Always run --dry-run first if unsure.
Tell the user to restart Claude Code so hook deregistration takes effect.
adopt
Retrofit the harness into an existing project (project scope only). Use when the user says "I have a project, how do I add this?", "adopt", "retrofit", or any variant that implies this isn't a greenfield install.
bash "$SKILL_DIR/scripts/adopt.sh"
What it does:
- Detects the project root (
$CLAUDE_PROJECT_DIR or $PWD; refuses to write into $HOME).
- Reports what's already there:
CLAUDE.md, .claude/, settings.json, scripts/harness-check.sh, plus stack signals.
- Writes a stack-aware starter file to
scripts/harness-check.sh — the project-side pass/fail gate that verify-before-stop.sh and /verify invoke. The starter runs lint / types / tests for whichever ecosystem files are present (package.json, composer.json, pyproject.toml, go.mod, Cargo.toml, Gemfile). Skipped if harness-check.sh already exists (--force to overwrite). Empty-sensor case is treated as PASS so the script never strands Stop.
- Prints the next-step
install.sh --scope=project command. Does not run install itself — the user reviews the preflight banner there separately.
Walk-through for the agent:
- Run
adopt.sh. Read its preflight to the user.
- If the user is happy, run
install.sh --scope=project (or with --include=hooks,commands for a minimum-viable retrofit that doesn't add a CLAUDE.md).
- Tell the user to edit
scripts/harness-check.sh to match their project's commands (the starter is intentionally generous; comment out or delete blocks that don't apply).
- Tell them to restart Claude Code so hooks load.
- Suggest they run
/verify once to smoke-test the gate end-to-end.
- Mention
datashaman/harness-template for the deeper project-scope layer (policy YAMLs, grades, .skip ledger) when they've outgrown the starter.
Flags:
--target=PATH — explicit project root.
--dry-run — show plan, don't write.
--force — overwrite an existing scripts/harness-check.sh (you'll lose edits).
update
bash "$SKILL_DIR/scripts/update.sh"
Smarter than install --force. For each surface compares installed vs current template via sha256 and:
- identical → re-install (no-op cosmetically)
- missing → install
- modified → print diff and SKIP, unless
--merge or --force
Flags:
--dry-run — show plan only.
--force — overwrite ALL files including modified ones (loses customisations).
--merge — for modified files, write the new template to <file>.new alongside the original. The user can diff/merge interactively.
Default behaviour is non-destructive: you'll see diffs but no customised file is overwritten without consent.
doctor
bash "$SKILL_DIR/scripts/doctor.sh"
End-to-end diagnostic. Combines status with sanity checks:
- sha256 tool present
- target dir writable
settings.json is valid JSON
- all 4 hooks exist, are executable, and are wired in
settings.json
- hook entries don't point at unexpected paths (foreign installs)
- smoke-test: invoke
block-force-push.sh with a known-bad command and verify exit code 2
- memory dir populated (user scope)
CLAUDE.md present and ## Stack signals not still placeholder
- snapshot repo (if
$SNAPSHOT_REPO set) — last commit recency
Exits non-zero if any FAIL, zero on warnings. Run doctor after install and after each Claude Code upgrade.
snapshot
SNAPSHOT_REPO=~/Projects/<them>/<repo> bash "$SKILL_DIR/scripts/snapshot.sh"
Mirrors ~/.claude/ into a target git repo, scrubs caches and secret patterns, commits + pushes only on diff. Idempotent.
If the user doesn't have a snapshot repo yet, prompt them to create one (PRIVATE — the snapshot has personal config):
mkdir -p ~/Projects/<them>/claude-setup
cd ~/Projects/<them>/claude-setup
git init -b main
gh repo create <them>/claude-setup --private --source=. --remote=origin
Then run snapshot.sh against it. The first push lands; subsequent runs are no-ops if nothing changed.
Override sources via env: CLAUDE_DIR=..., USER_PROJECT_KEY=....
status
bash "$SKILL_DIR/scripts/status.sh"
Read-only. Reports:
- For each hook + command + memory file + CLAUDE.md:
installed (matches template), modified (customised), or missing.
- For
settings.json: which of the 4 hook entries are wired, plus the env var.
- For snapshot repo (if
SNAPSHOT_REPO env is set): commits ahead of origin, last snapshot timestamp.
Use status first when the user says /harness without an action word, when they say "what's installed?", when they say "is this still set up?", or before any install to show the diff.
audit
The audit is a monthly remote routine — Claude Code's /schedule skill creates it. This skill prepares the prompt and suggests config; the user runs /schedule themselves.
Steps:
- Read
$SKILL_DIR/scripts/audit-prompt.md — that's the prompt for the remote agent. Confirm with the user that it covers what they want.
- Suggested config:
- cron:
0 6 1 * * (1st of month, 06:00 UTC)
- model:
claude-opus-4-7 (audit quality matters)
- tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, WebSearch, Agent
- sources: the user's snapshot repo URL (must exist — run
snapshot first)
- Tell the user to invoke
/schedule and paste the prompt + config. Or, if they have RemoteTrigger available in their session, build the body and call it directly.
The remote agent clones the snapshot repo, researches the last ~30 days of Anthropic releases and canonical Claude Code voices, and PRs audits/YYYY-MM-DD-setup-audit.md with prioritised deltas. It never modifies tracked files outside audits/.
memoize
bash "$SKILL_DIR/scripts/memoize.sh"
Proactive memory hygiene for ~/.claude/projects/<slug>/memory/. Memory is reactive — entries get written when the agent notices something worth saving, but nothing prunes or consolidates. memoize is the deterministic maintenance pass.
What it checks:
- Index sync — every
memory/*.md is listed in MEMORY.md; every MEMORY.md entry points at a file that exists.
- Frontmatter hygiene — every memory has the required
name, description, type.
- Stale citations — path-shaped tokens (anything starting with
~/, /Users/, ./, etc., or ending in a known source extension) that resolve nowhere across ~/.claude/projects/ and ~/Projects/. Conservative on purpose — false positives cost more than misses.
- Possible duplicates — pairs of memories of the same
type whose name or description are lexically similar (Jaccard ≥ 0.5). Flag, don't merge.
Output: a single file at <memory>/_memoize-report.md. The leading underscore is the contract — MEMORY.md indexing rules and the remote routine both ignore _*.md, so the report itself never gets treated as a memory entry. The report is byte-stable on equal runs (two consecutive invocations produce an identical file).
Flags:
--dry-run — print the plan + report preview, write nothing.
--target=PATH — explicit memory dir.
Env knobs (mirror snapshot.sh):
CLAUDE_DIR — root of the Claude Code config dir. Search-root defaults track this, so a custom CLAUDE_DIR cascades correctly.
USER_PROJECT_KEY — the slug under <CLAUDE_DIR>/projects/.
MEMOIZE_SEARCH_ROOTS — colon-separated (PATH-style, supports paths with spaces) list of roots to resolve stale citations against. Defaults to <CLAUDE_DIR>/projects:$HOME/Projects.
Scheduled routine. For the conceptual drift the lexical script can't see (semantic duplicates, outdated facts, conflicting guidance), wire a weekly /schedule job using scripts/memoize-prompt.md. Suggested config:
- cron:
0 6 * * 0 (Sunday 06:00 UTC)
- model:
claude-opus-4-7
- tools: Bash, Read, Write, Edit, Glob, Grep, Agent
- source: the user's snapshot repo (run
harness snapshot first)
Scope: the snapshot repo doesn't mirror harness scripts or local search roots, so the remote agent does its own in-process structural pass (index sync, frontmatter) and adds the semantic checks. Stale-citation analysis stays local-only — the search roots aren't available remotely. The remote agent PRs audits/memory/YYYY-MM-DD.md with proposed edits and never modifies any memory entry.
PostToolUse critique hook — recommendation
We considered a hook that fires after N consecutive Edit/Write calls and runs an automatic critique pass (diff summary + advisor() check). Recommendation: don't ship it. The boundary critiques we already have (verify-before-stop.sh at Stop, advisor() calls bracketing non-trivial work, /critique available on demand mid-flow) cover the same gap with much better signal-to-noise. An always-on PostToolUse critique would (a) burn tokens and wall-clock on edits that don't need it, (b) train the agent to ignore the noise, and (c) duplicate what /critique already provides on user demand. Revisit if users report that mid-flow drift is escaping all three boundary surfaces — but the right next step there would be tuning when /critique gets suggested, not making it automatic.
Constraints
- Never auto-fill stack signals or user_role. Templates have placeholders; ask the user to fill them.
- Never modify
settings.json outside env and hooks. Don't touch permissions, marketplaces, statusLine, advisorModel, theme.
- Memory is sensitive. If
MEMORY.md already exists with the user's entries, leave it alone unless they explicitly say otherwise.
- Snapshot repos must be private. They contain personal config.
- Hooks load on session start. Tell the user to restart Claude Code after install/uninstall.
Files in this skill
| File |
Role |
SKILL.md |
This file — agent instructions |
README.md |
Human-facing overview (with sources / inspiration) |
assets/CLAUDE.md.tmpl |
Operating-contract template |
assets/hooks/*.sh |
Four hook scripts |
assets/commands/*.md |
/verify, /plan, /critique |
assets/memory/*.tmpl |
MEMORY.md index + 3 feedback memories + user_role template |
scripts/install.sh |
Idempotent installer (--dry-run / --force / --skip-*) |
scripts/uninstall.sh |
Symmetric uninstaller (content-match check; --all for full sweep) |
scripts/update.sh |
Refresh installed files vs current templates (--merge / --force) |
scripts/doctor.sh |
End-to-end diagnostic (perms, hook smoke-test, settings JSON, etc.) |
scripts/adopt.sh |
Retrofit into existing project — writes scripts/harness-check.sh |
scripts/snapshot.sh |
Sanitised mirror of ~/.claude/ → target git repo |
scripts/status.sh |
Read-only — reports installed / modified / missing per surface |
scripts/_detect_stack.py |
Stack-signal detector — auto-fills ## Stack signals at install time |
assets/harness-check.sh.tmpl |
Starter project pass/fail gate written by adopt |
scripts/audit-prompt.md |
Prompt template for the monthly remote-audit routine |
scripts/memoize.sh |
Memory consolidation pass — deterministic; emits _memoize-report.md |
scripts/memoize-prompt.md |
Prompt template for the weekly remote-memoize routine |
1---2name: harness3description: Control surface for a harness-engineering Claude Code setup at user or project scope. Handles install, uninstall, update, doctor, adopt, snapshot, status, audit, and memoize. Installs CLAUDE.md, guardrail hooks, /verify, /plan, /critique, memory seeds, and settings patches; can also retrofit an existing project with scripts/harness-check.sh, report install state, snapshot ~/.claude/, and run deterministic memory hygiene. All sub-actions are idempotent. Use when asked to "set up my Claude Code", "install harness", "uninstall harness", "update harness", "diagnose my setup", "adopt harness", "retrofit", "snapshot my setup", "audit my setup", "harden my Claude", "memoize", "consolidate memory", or "prune memory".4---56# Harness78Control surface for the user-scope Claude Code "harness" — feedforward guides (CLAUDE.md, memory), feedback sensors (hooks), and an optional drift-detection loop (snapshot + monthly audit).910The vocabulary follows OpenAI's *Harness engineering* (https://openai.com/index/harness-engineering/) and Martin Fowler's writeup (https://martinfowler.com/articles/harness-engineering.html). Day-to-day patterns are convergent picks from Boris Cherny, Simon Willison, Jesse Vincent (Superpowers), Geoffrey Huntley (Ralph loop), Hamel Husain (eval skills), and Steve Yegge (Gas Town). See README.md for citations.1112## Sub-action dispatch1314The user invokes this skill, optionally with an action word. Detect intent and run the matching sub-action. If the user says `/harness` without context, run **status** first (it's read-only and informative), then ask which action they want.1516| Said by user | Sub-action | Script |17| --------------------------------------------- | ----------- | ------------------------------- |18| "install", "set up", "bootstrap" | `install` | `scripts/install.sh` |19| "uninstall", "remove", "undo" | `uninstall` | `scripts/uninstall.sh` |20| "update", "pull latest templates", "refresh" | `update` | `scripts/update.sh` |21| "doctor", "diagnose", "is it working" | `doctor` | `scripts/doctor.sh` |22| "adopt", "add to existing project", "retrofit"| `adopt` | `scripts/adopt.sh` |23| "snapshot", "backup", "mirror to git" | `snapshot` | `scripts/snapshot.sh` |24| "status", "what's installed", "audit local" | `status` | `scripts/status.sh` |25| "audit", "schedule audit", "monthly check" | `audit` | (prep work — see below) |26| "memoize", "consolidate memory", "prune memory" | `memoize` | `scripts/memoize.sh` |2728Substitute the skill's absolute base directory for `$SKILL_DIR` in every command — it's announced at the top of this invocation.2930## install3132Lays down the harness at the **scope where the skill itself lives**, derived from `$SKILL_DIR`:3334- Skill at `<X>/.claude/skills/harness/` (or under a plugin cache below `<X>/.claude/`) → install at `<X>/.claude/`.35- If `<X>` is `$HOME`, that's user scope; otherwise project scope.36- Override with `--scope=user`, `--scope=project`, or `--target=PATH`.37- If the skill is being run from a checkout (no `.claude/` ancestor), the script errors with a clear message asking for `--scope` or `--target`.3839What lands at user scope:4041| Surface | Path |42| ------------------------ | --------------------------------------------------------------------------------------------------- |43| Operating contract | `~/.claude/CLAUDE.md` |44| Hooks | `~/.claude/hooks/{block-force-push,format-on-edit,post-compact-reinject,verify-before-stop}.sh` |45| Slash commands | `~/.claude/commands/{verify,plan,critique}.md` |46| Auto-memory | `~/.claude/projects/<slug>/memory/{MEMORY.md, user_role, feedback_concise, feedback_plan_first, feedback_verification}` |47| settings.json | Adds `env.CLAUDE_CODE_AUTO_COMPACT_WINDOW=400000` + 4 hook entries (uses `~/.claude/hooks/...` form) |4849What lands at project scope (`<project>/.claude/`):5051| Surface | Path |52| --------------- | ----------------------------------------------------------------------------------------------- |53| Operating contract | `<project>/CLAUDE.md` (skipped if it already exists — most projects have one. `--force` overrides) |54| Hooks | `<project>/.claude/hooks/*.sh` |55| Commands | `<project>/.claude/commands/{verify,plan,critique}.md` |56| settings.json | `<project>/.claude/settings.json` — 4 hook entries with `.claude/hooks/...` (project-relative) form. **No env var, no memory** at project scope. |57| Memory | (skipped — memory is per-user by design and lives under `$HOME` regardless of project scope) |5859```bash60bash "$SKILL_DIR/scripts/install.sh"61```6263Common flags:64- `--dry-run` — show the preflight + plan, change nothing.65- `--force` — overwrite existing files (including project CLAUDE.md).6667Per-surface skip flags (escape hatch — pick & choose what to install):68- `--skip-claude-md`, `--skip-hooks`, `--skip-commands`, `--skip-memory`, `--skip-settings`6970Or a positive list (everything else is skipped):71- `--include=hooks,commands` — install only those.72- `--include=claude-md,settings` — only the operating contract + settings patch.73- Valid items: `claude-md`, `hooks`, `commands`, `memory`, `settings`.7475The script always prints a **preflight banner** showing scope, target, the per-surface plan (with SKIP markers reflecting the active flags), and a pointer to the uninstaller with `--all` warnings. Read it before proceeding.7677After install, walk the user through the hand-edits printed under "Next steps":78791. Fill in `## Stack signals` in `CLAUDE.md` (user scope: `~/.claude/CLAUDE.md`; project scope: `<project>/CLAUDE.md`). At install time the script tries to auto-fill this from manifests it finds — verify it picked up your stack correctly. If you need hints, look at `~/.claude/projects/` slugs and `installed_plugins.json`; ask if unclear. **Don't auto-fill from guesswork.**802. (User scope only) Replace placeholders in `~/.claude/projects/<slug>/memory/user_role.md` with the user's actual role / projects / stack. **Ask, don't invent.**8182Tell them to **restart Claude Code** so hooks load.8384## uninstall8586```bash87bash "$SKILL_DIR/scripts/uninstall.sh"88```8990Same scope auto-detection as install. Conservative defaults:9192- Removes hooks + commands **only if their sha256 still matches** the installed template. User-modified files are kept and reported as `keep (modified)`.93- Strips the 4 hook entries from `settings.json`; drops empty hook event arrays. Leaves all other settings untouched.94- **Keeps by default:** `CLAUDE.md`, memory files, the `CLAUDE_CODE_AUTO_COMPACT_WINDOW` env var.9596Flags:97- `--dry-run`, `--force` (skip content-match)98- Broaden the sweep: `--remove-claude-md`, `--remove-memory`, `--remove-env`, `--all`99- **Escape hatch — keep specific surfaces that default would remove:** `--keep-hooks`, `--keep-commands`, `--keep-settings`100101The script prints a preflight banner showing scope, target, what will be removed vs kept, and which `--keep-*` / `--remove-*` flags are active. Always run `--dry-run` first if unsure.102103Tell the user to **restart Claude Code** so hook deregistration takes effect.104105## adopt106107Retrofit the harness into an existing project (project scope only). Use when the user says "I have a project, how do I add this?", "adopt", "retrofit", or any variant that implies *this isn't a greenfield install*.108109```bash110bash "$SKILL_DIR/scripts/adopt.sh"111```112113What it does:114115- Detects the project root (`$CLAUDE_PROJECT_DIR` or `$PWD`; refuses to write into `$HOME`).116- Reports what's already there: `CLAUDE.md`, `.claude/`, `settings.json`, `scripts/harness-check.sh`, plus stack signals.117- Writes a stack-aware starter file to `scripts/harness-check.sh` — the project-side pass/fail gate that `verify-before-stop.sh` and `/verify` invoke. The starter runs lint / types / tests for whichever ecosystem files are present (`package.json`, `composer.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `Gemfile`). Skipped if `harness-check.sh` already exists (`--force` to overwrite). Empty-sensor case is treated as PASS so the script never strands `Stop`.118- Prints the next-step `install.sh --scope=project` command. **Does not run install itself** — the user reviews the preflight banner there separately.119120Walk-through for the agent:1211221. Run `adopt.sh`. Read its preflight to the user.1232. If the user is happy, run `install.sh --scope=project` (or with `--include=hooks,commands` for a minimum-viable retrofit that doesn't add a CLAUDE.md).1243. Tell the user to edit `scripts/harness-check.sh` to match their project's commands (the starter is intentionally generous; comment out or delete blocks that don't apply).1254. Tell them to **restart Claude Code** so hooks load.1265. Suggest they run `/verify` once to smoke-test the gate end-to-end.1276. Mention `datashaman/harness-template` for the deeper project-scope layer (policy YAMLs, grades, `.skip` ledger) when they've outgrown the starter.128129Flags:130- `--target=PATH` — explicit project root.131- `--dry-run` — show plan, don't write.132- `--force` — overwrite an existing `scripts/harness-check.sh` (you'll lose edits).133134## update135136```bash137bash "$SKILL_DIR/scripts/update.sh"138```139140Smarter than `install --force`. For each surface compares installed vs current template via sha256 and:141142- identical → re-install (no-op cosmetically)143- missing → install144- modified → print diff and **SKIP**, unless `--merge` or `--force`145146Flags:147- `--dry-run` — show plan only.148- `--force` — overwrite ALL files including modified ones (loses customisations).149- `--merge` — for modified files, write the new template to `<file>.new` alongside the original. The user can diff/merge interactively.150151Default behaviour is non-destructive: you'll see diffs but no customised file is overwritten without consent.152153## doctor154155```bash156bash "$SKILL_DIR/scripts/doctor.sh"157```158159End-to-end diagnostic. Combines `status` with sanity checks:160161- sha256 tool present162- target dir writable163- `settings.json` is valid JSON164- all 4 hooks exist, are executable, and are wired in `settings.json`165- hook entries don't point at unexpected paths (foreign installs)166- smoke-test: invoke `block-force-push.sh` with a known-bad command and verify exit code 2167- memory dir populated (user scope)168- `CLAUDE.md` present and `## Stack signals` not still placeholder169- snapshot repo (if `$SNAPSHOT_REPO` set) — last commit recency170171Exits non-zero if any FAIL, zero on warnings. Run `doctor` after `install` and after each Claude Code upgrade.172173## snapshot174175```bash176SNAPSHOT_REPO=~/Projects/<them>/<repo> bash "$SKILL_DIR/scripts/snapshot.sh"177```178179Mirrors `~/.claude/` into a target git repo, scrubs caches and secret patterns, commits + pushes only on diff. Idempotent.180181If the user doesn't have a snapshot repo yet, prompt them to create one (PRIVATE — the snapshot has personal config):182183```bash184mkdir -p ~/Projects/<them>/claude-setup185cd ~/Projects/<them>/claude-setup186git init -b main187gh repo create <them>/claude-setup --private --source=. --remote=origin188```189190Then run `snapshot.sh` against it. The first push lands; subsequent runs are no-ops if nothing changed.191192Override sources via env: `CLAUDE_DIR=...`, `USER_PROJECT_KEY=...`.193194## status195196```bash197bash "$SKILL_DIR/scripts/status.sh"198```199200Read-only. Reports:201202- For each hook + command + memory file + CLAUDE.md: `installed` (matches template), `modified` (customised), or `missing`.203- For `settings.json`: which of the 4 hook entries are wired, plus the env var.204- For snapshot repo (if `SNAPSHOT_REPO` env is set): commits ahead of origin, last snapshot timestamp.205206Use `status` first when the user says `/harness` without an action word, when they say "what's installed?", when they say "is this still set up?", or before any `install` to show the diff.207208## audit209210The audit is a monthly **remote** routine — Claude Code's `/schedule` skill creates it. This skill prepares the prompt and suggests config; the user runs `/schedule` themselves.211212Steps:2132141. Read `$SKILL_DIR/scripts/audit-prompt.md` — that's the prompt for the remote agent. Confirm with the user that it covers what they want.2152. Suggested config:216 - cron: `0 6 1 * *` (1st of month, 06:00 UTC)217 - model: `claude-opus-4-7` (audit quality matters)218 - tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, WebSearch, Agent219 - sources: the user's snapshot repo URL (must exist — run `snapshot` first)2203. Tell the user to invoke `/schedule` and paste the prompt + config. Or, if they have `RemoteTrigger` available in their session, build the body and call it directly.221222The remote agent clones the snapshot repo, researches the last ~30 days of Anthropic releases and canonical Claude Code voices, and PRs `audits/YYYY-MM-DD-setup-audit.md` with prioritised deltas. It never modifies tracked files outside `audits/`.223224## memoize225226```bash227bash "$SKILL_DIR/scripts/memoize.sh"228```229230Proactive memory hygiene for `~/.claude/projects/<slug>/memory/`. Memory is reactive — entries get written when the agent notices something worth saving, but nothing prunes or consolidates. `memoize` is the deterministic maintenance pass.231232What it checks:2332341. **Index sync** — every `memory/*.md` is listed in `MEMORY.md`; every `MEMORY.md` entry points at a file that exists.2352. **Frontmatter hygiene** — every memory has the required `name`, `description`, `type`.2363. **Stale citations** — path-shaped tokens (anything starting with `~/`, `/Users/`, `./`, etc., or ending in a known source extension) that resolve nowhere across `~/.claude/projects/` and `~/Projects/`. Conservative on purpose — false positives cost more than misses.2374. **Possible duplicates** — pairs of memories of the same `type` whose `name` or `description` are lexically similar (Jaccard ≥ 0.5). Flag, don't merge.238239Output: a single file at `<memory>/_memoize-report.md`. The leading underscore is the contract — `MEMORY.md` indexing rules and the remote routine both ignore `_*.md`, so the report itself never gets treated as a memory entry. The report is byte-stable on equal runs (two consecutive invocations produce an identical file).240241Flags:242- `--dry-run` — print the plan + report preview, write nothing.243- `--target=PATH` — explicit memory dir.244245Env knobs (mirror `snapshot.sh`):246- `CLAUDE_DIR` — root of the Claude Code config dir. Search-root defaults track this, so a custom `CLAUDE_DIR` cascades correctly.247- `USER_PROJECT_KEY` — the slug under `<CLAUDE_DIR>/projects/`.248- `MEMOIZE_SEARCH_ROOTS` — colon-separated (PATH-style, supports paths with spaces) list of roots to resolve stale citations against. Defaults to `<CLAUDE_DIR>/projects:$HOME/Projects`.249250**Scheduled routine.** For the conceptual drift the lexical script can't see (semantic duplicates, outdated facts, conflicting guidance), wire a weekly `/schedule` job using `scripts/memoize-prompt.md`. Suggested config:251- cron: `0 6 * * 0` (Sunday 06:00 UTC)252- model: `claude-opus-4-7`253- tools: Bash, Read, Write, Edit, Glob, Grep, Agent254- source: the user's snapshot repo (run `harness snapshot` first)255256Scope: the snapshot repo doesn't mirror harness scripts or local search roots, so the remote agent does its own in-process structural pass (index sync, frontmatter) and adds the semantic checks. Stale-citation analysis stays local-only — the search roots aren't available remotely. The remote agent PRs `audits/memory/YYYY-MM-DD.md` with proposed edits and never modifies any memory entry.257258## PostToolUse critique hook — recommendation259260We considered a hook that fires after N consecutive `Edit`/`Write` calls and runs an automatic critique pass (diff summary + `advisor()` check). **Recommendation: don't ship it.** The boundary critiques we already have (`verify-before-stop.sh` at Stop, `advisor()` calls bracketing non-trivial work, `/critique` available on demand mid-flow) cover the same gap with much better signal-to-noise. An always-on PostToolUse critique would (a) burn tokens and wall-clock on edits that don't need it, (b) train the agent to ignore the noise, and (c) duplicate what `/critique` already provides on user demand. Revisit if users report that mid-flow drift is escaping all three boundary surfaces — but the right next step there would be tuning when `/critique` gets *suggested*, not making it automatic.261262## Constraints263264- **Never auto-fill stack signals or user_role.** Templates have placeholders; ask the user to fill them.265- **Never modify `settings.json` outside `env` and `hooks`.** Don't touch permissions, marketplaces, statusLine, advisorModel, theme.266- **Memory is sensitive.** If `MEMORY.md` already exists with the user's entries, leave it alone unless they explicitly say otherwise.267- **Snapshot repos must be private.** They contain personal config.268- **Hooks load on session start.** Tell the user to restart Claude Code after install/uninstall.269270## Files in this skill271272| File | Role |273| --------------------------------- | --------------------------------------------------------------------- |274| `SKILL.md` | This file — agent instructions |275| `README.md` | Human-facing overview (with sources / inspiration) |276| `assets/CLAUDE.md.tmpl` | Operating-contract template |277| `assets/hooks/*.sh` | Four hook scripts |278| `assets/commands/*.md` | `/verify`, `/plan`, `/critique` |279| `assets/memory/*.tmpl` | MEMORY.md index + 3 feedback memories + user_role template |280| `scripts/install.sh` | Idempotent installer (`--dry-run` / `--force` / `--skip-*`) |281| `scripts/uninstall.sh` | Symmetric uninstaller (content-match check; `--all` for full sweep) |282| `scripts/update.sh` | Refresh installed files vs current templates (`--merge` / `--force`) |283| `scripts/doctor.sh` | End-to-end diagnostic (perms, hook smoke-test, settings JSON, etc.) |284| `scripts/adopt.sh` | Retrofit into existing project — writes `scripts/harness-check.sh` |285| `scripts/snapshot.sh` | Sanitised mirror of `~/.claude/` → target git repo |286| `scripts/status.sh` | Read-only — reports installed / modified / missing per surface |287| `scripts/_detect_stack.py` | Stack-signal detector — auto-fills `## Stack signals` at install time |288| `assets/harness-check.sh.tmpl` | Starter project pass/fail gate written by `adopt` |289| `scripts/audit-prompt.md` | Prompt template for the monthly remote-audit routine |290| `scripts/memoize.sh` | Memory consolidation pass — deterministic; emits `_memoize-report.md` |291| `scripts/memoize-prompt.md` | Prompt template for the weekly remote-memoize routine |