Purpose
Verify and manage the consuming repo's tracked audit-dimension config at .claude/codebase-health.md
so /codebase-health:audit runs deterministically instead of re-inferring targets every run.
The config is optional: with none, the audit re-infers its targets each run, so its absence is a
reported INFO, never a FAIL. check inspects the effective merged config read-only; apply interviews
and writes it, then re-runs check. No argument or check runs the check; apply runs the check
first, then the interview-and-write flow. Idempotent: re-running reads the existing config and offers
updates rather than overwriting blind.
The config merge model
The audit config resolves as an additive merge of the documented layers. User-global
(~/.claude/codebase-health.md) → team (.claude/codebase-health.md) → local overlay
(.claude/codebase-health.local.md), where a later layer's globs union with (not replace) the
earlier layer's and example-claims concatenate, except that a later layer declaring a dimension
with empty source lists is an explicit opt-out that removes that inherited dimension. This skill
writes only the team file; changes to a higher overlay are the user's to make.
check (read-only)
Inspect the effective merged config and report a PASS/FAIL/INFO table with one remediation line per
FAIL. Modify nothing, and do NOT run an audit. That is /codebase-health:audit.
- Config presence (effective, across layers). Load every layer you can access and report the
effective merged result honoring opt-outs (dimensions present, glob counts, example-claim counts),
and which layer contributes what. No layer readable and no team file → INFO: the audit re-infers
targets each run;
apply writes .claude/codebase-health.md to make the run deterministic. When a
higher layer (a user-global base outside the repo) cannot be read, WARN it was not considered rather
than presenting the team file alone as the effective config.
- Dimension source lists. For each dimension present in the team file, its declared source lists
parse and name real paths/globs. A dimension whose source list is malformed or fails to parse is
FAIL, naming it. A dimension deliberately zeroed (empty source lists) by an overlay is INFO (an opt-out),
reported as removed, not broken.
- Tracked, not ignored, a present team file must be committed to be team-shared: run
git check-ignore -v .claude/codebase-health.md; a non-empty result is FAIL with the matching
pattern. The .local.md overlay is expected to be ignored. INFO, not FAIL.
- Overlay divergence. INFO: when a local or user-global overlay changes the team file's effect
(adds globs, or opts a dimension out with empty source lists), say so explicitly, since
apply
writes only the team file.
apply (idempotent)
Run check, then interview and write the config. Proceed non-interactively where the invocation and
the repo make the values unambiguous; ask only where a dimension's targets genuinely need the user.
- Start from the effective config
check just reported. This step writes only the team file,
so name what a higher overlay contributes. When a local or user-global opt-out zeroes a dimension,
a team-scope re-enable will not restore it on this machine, because the overlay keeps removing it;
prompt the user to remove or update the opt-out in that overlay too. The interview proposes
changes against that baseline, and nothing is dropped without the user confirming.
- Explore the repo to draft defaults. Before asking anything, infer candidates:
- documentation primary-sources: doc directories (
docs/, README.md), agent-instruction
files (AGENTS.md, CLAUDE.md), ADR directories, convention docs.
- configuration primary-sources: build config, lint config, CI workflows, git-hook config, detected from what actually exists (e.g.
Directory.Build.props, pyproject.toml,
package.json, .github/workflows/, lefthook.yml, .editorconfig).
- code-quality primary-sources: source roots; verification-sources: test roots plus the
same source roots, a cross-file DRY/SOLID claim is validated by reading peer source files,
which a discovery agent can only read when they are in
verification-sources (the fence forbids
the other primary-source files). Omitting them makes cross-file findings unreachable.
- architecture primary-sources: dependency manifests + architecture docs;
verification-sources: analyzers / architecture tests where present plus the dependency
manifests and source roots. Dependency-direction and boundary claims need peer manifests
readable, for the same fence reason.
- Interview, one decision at a time. Present each dimension's drafted globs with a
recommendation; let the user accept, edit, or remove the dimension. Offer custom dimensions
last ("anything else this repo should audit as its own lane?").
- Draft example-claims. For each accepted dimension, read one or two representative
primary-source files and propose 2–4 concrete
{ claim, verify-via } rows drawn from real
sentences in them. Concrete rows teach the discovery pass what drift looks like in THIS repo, the highest-value part of the config. The user approves or edits each row.
- Write the config. Materialize
.claude/codebase-health.md following the structure in
${CLAUDE_PLUGIN_ROOT}/skills/setup/templates/config-template.md (replace every placeholder comment
with real values; drop unused placeholder rows).
- Verify after remediation. Re-run the
check probes on the written file. Dimension source lists
parse and name real paths, and both halves of the tracked-file pair hold:
git check-ignore -v .claude/codebase-health.md reports no match (a match is FAIL; surface the
pattern and offer to fix .gitignore before reporting success) AND
git ls-files --error-unmatch .claude/codebase-health.md exits 0 (non-zero means un-ignored but
still untracked, the guaranteed state right after a fresh write, so report "written but
untracked: commit it to share with the team", never success). Then offer the overlay convention: personal overrides go in
.claude/codebase-health.local.md; recommend the consumer add the recursive .claude/**/*.local.*
line to .gitignore if not already covered. A user-global base at ~/.claude/codebase-health.md is also honored. Layers
resolve user-global → team → local overlay, additively.
Re-running apply after everything passes changes nothing and reports "already configured".
Output
A tracked .claude/codebase-health.md in the consuming repo, plus a one-paragraph summary of what
was written and how to re-run this setup to reconfigure.
What this skill does NOT do
- Run an audit. That is
/codebase-health:audit. check only inspects config.
- Write machine-local state. Configuration lives in the consumer's tracked file, never in the
plugin directory or the plugin data directory.
1---2name: setup-473description: Verify and configure the codebase-health plugin for this repository. check inspects the tracked .claude/codebase-health.md config read-only across its merge layers (presence, dimension source lists, tracked-not-ignored); apply interviews the user, infers audit targets from the repo layout, and writes the config. Use when: 'set up codebase-health', 'is codebase-health configured', 'configure the audit', 'codebase-health setup', the audit skill reports missing or thin config, or audit dimensions need tuning. Re-runnable. Safe to invoke again to reconfigure.4---56## Purpose78Verify and manage the consuming repo's tracked audit-dimension config at `.claude/codebase-health.md`9so `/codebase-health:audit` runs deterministically instead of re-inferring targets every run.1011The config is optional: with none, the audit re-infers its targets each run, so its absence is a12reported INFO, never a FAIL. `check` inspects the effective merged config read-only; `apply` interviews13and writes it, then re-runs `check`. No argument or `check` runs the check; `apply` runs the check14first, then the interview-and-write flow. Idempotent: re-running reads the existing config and offers15updates rather than overwriting blind.1617## The config merge model1819The audit config resolves as an additive merge of the documented layers. User-global20(`~/.claude/codebase-health.md`) → team (`.claude/codebase-health.md`) → local overlay21(`.claude/codebase-health.local.md`), where a later layer's globs union with (not replace) the22earlier layer's and example-claims concatenate, **except** that a later layer declaring a dimension23with empty source lists is an explicit opt-out that *removes* that inherited dimension. This skill24writes only the **team** file; changes to a higher overlay are the user's to make.2526## `check` (read-only)2728Inspect the effective merged config and report a PASS/FAIL/INFO table with one remediation line per29FAIL. Modify nothing, and do NOT run an audit. That is `/codebase-health:audit`.30311. **Config presence (effective, across layers)**. Load every layer you can access and report the32 *effective merged* result honoring opt-outs (dimensions present, glob counts, example-claim counts),33 and which layer contributes what. No layer readable and no team file → INFO: the audit re-infers34 targets each run; `apply` writes `.claude/codebase-health.md` to make the run deterministic. When a35 higher layer (a user-global base outside the repo) cannot be read, WARN it was not considered rather36 than presenting the team file alone as the effective config.372. **Dimension source lists**. For each dimension present in the team file, its declared source lists38 parse and name real paths/globs. A dimension whose source list is malformed or fails to parse is39 FAIL, naming it. A dimension deliberately zeroed (empty source lists) by an overlay is INFO (an opt-out),40 reported as removed, not broken.413. **Tracked, not ignored**, a present team file must be committed to be team-shared: run42 `git check-ignore -v .claude/codebase-health.md`; a non-empty result is FAIL with the matching43 pattern. The `.local.md` overlay is expected to be ignored. INFO, not FAIL.444. **Overlay divergence**. INFO: when a local or user-global overlay changes the team file's effect45 (adds globs, or opts a dimension out with empty source lists), say so explicitly, since `apply`46 writes only the team file.4748## `apply` (idempotent)4950Run `check`, then interview and write the config. Proceed non-interactively where the invocation and51the repo make the values unambiguous; ask only where a dimension's targets genuinely need the user.52531. **Start from the effective config `check` just reported.** This step writes only the *team* file,54 so name what a higher overlay contributes. When a local or user-global opt-out zeroes a dimension,55 a team-scope re-enable will not restore it on this machine, because the overlay keeps removing it;56 prompt the user to remove or update the opt-out in that overlay too. The interview proposes57 changes against that baseline, and nothing is dropped without the user confirming.582. **Explore the repo to draft defaults.** Before asking anything, infer candidates:59 - **documentation** primary-sources: doc directories (`docs/`, `README.md`), agent-instruction60 files (`AGENTS.md`, `CLAUDE.md`), ADR directories, convention docs.61 - **configuration** primary-sources: build config, lint config, CI workflows, git-hook config, detected from what actually exists (e.g. `Directory.Build.props`, `pyproject.toml`,62 `package.json`, `.github/workflows/`, `lefthook.yml`, `.editorconfig`).63 - **code-quality** primary-sources: source roots; verification-sources: test roots **plus the64 same source roots**, a cross-file DRY/SOLID claim is validated by reading peer source files,65 which a discovery agent can only read when they are in `verification-sources` (the fence forbids66 the other primary-source files). Omitting them makes cross-file findings unreachable.67 - **architecture** primary-sources: dependency manifests + architecture docs;68 verification-sources: analyzers / architecture tests where present **plus the dependency69 manifests and source roots**. Dependency-direction and boundary claims need peer manifests70 readable, for the same fence reason.713. **Interview, one decision at a time.** Present each dimension's drafted globs with a72 recommendation; let the user accept, edit, or remove the dimension. Offer custom dimensions73 last ("anything else this repo should audit as its own lane?").744. **Draft example-claims.** For each accepted dimension, read one or two representative75 primary-source files and propose 2–4 concrete `{ claim, verify-via }` rows drawn from real76 sentences in them. Concrete rows teach the discovery pass what drift looks like in THIS repo, the highest-value part of the config. The user approves or edits each row.775. **Write the config.** Materialize `.claude/codebase-health.md` following the structure in78 [`${CLAUDE_PLUGIN_ROOT}/skills/setup/templates/config-template.md`](templates/config-template.md) (replace every placeholder comment79 with real values; drop unused placeholder rows).806. **Verify after remediation.** Re-run the `check` probes on the written file. Dimension source lists81 parse and name real paths, and both halves of the tracked-file pair hold:82 `git check-ignore -v .claude/codebase-health.md` reports no match (a match is FAIL; surface the83 pattern and offer to fix `.gitignore` before reporting success) AND84 `git ls-files --error-unmatch .claude/codebase-health.md` exits 0 (non-zero means un-ignored but85 still untracked, the guaranteed state right after a fresh write, so report "written but86 untracked: commit it to share with the team", never success). Then **offer the overlay convention**: personal overrides go in87 `.claude/codebase-health.local.md`; recommend the consumer add the recursive `.claude/**/*.local.*`88 line to `.gitignore` if not already covered. A user-global base at `~/.claude/codebase-health.md` is also honored. Layers89 resolve user-global → team → local overlay, additively.9091Re-running `apply` after everything passes changes nothing and reports "already configured".9293## Output9495A tracked `.claude/codebase-health.md` in the consuming repo, plus a one-paragraph summary of what96was written and how to re-run this setup to reconfigure.9798## What this skill does NOT do99100- Run an audit. That is `/codebase-health:audit`. `check` only inspects config.101- Write machine-local state. Configuration lives in the consumer's tracked file, never in the102 plugin directory or the plugin data directory.