| name | setup-refresh |
| description | Refresh generated setup artifacts (principles, conventions, detected tools, AGENTS.md, configs, indexes) against codebase drift — proposes diffs for engineer-edited files instead of overwriting. |
| type | skill |
| user-invocable | false |
MTK Setup Refresh — Detect Drift, Regenerate Scoped, Propose Diffs
MTK File Resolution
MTK skills and shared references live either in the project (local install) or the plugin cache (marketplace install). Resolve once:
- If
$CLAUDE_PLUGIN_ROOT is set, prefix .claude/skills/ and .claude/references/ reads with it.
- Otherwise, if
.claude/skills/context-engineering/SKILL.md exists locally → project-relative paths work as-is.
- Otherwise, fall back to
find ~/.claude/plugins -maxdepth 8 -name "SKILL.md" -path "*/mtk/*/context-engineering/*" -type f 2>/dev/null | sort -V | tail -1 | sed 's|/.claude/skills/context-engineering/SKILL.md||'. If empty, MTK skills are unavailable — warn the engineer and proceed with CLAUDE.md only.
Always project-relative (never prefixed): CLAUDE.md, .claude/tech-stack, .claude/rules/, tasks/, docs/, .claude/references/architecture-principles.md, .claude/references/pre-commit-review-list.md, .mtk/ (workflow state). Resolve skills and scripts from the same root: a split (skills from a local dev checkout, scripts from the plugin cache) risks version drift — anchor both the same way.
This skill re-runs setup's generators on an already-bootstrapped repo. It never re-audits blind: it consults scripts/setup-refresh-plan.sh for a per-artifact staleness verdict, regenerates only what drifted, and — critically — never silently overwrites a file an engineer has hand-edited. Engineer-edited files go through the diff-proposal contract in .claude/references/regen-diff-contract.md, the same contract setup-audit and setup-bootstrap use for their own re-run merges. This is the inverse of .claude/skills/setup-converge/SKILL.md: refresh brings the docs back in line with the code, while converge treats the docs as normative and reports where the code has drifted from them.
File Preservation Policy
This skill inherits the File Preservation Policy defined in .claude/skills/setup-bootstrap/SKILL.md (## File Preservation Policy) wholesale — read it before writing anything. In short: only MTK-owned files may be overwritten in place, everything else (nested CLAUDE.md, custom rules, custom references, lockfiles, source) is preserved untouched, and superseding a prior MTK-owned file must be reported loudly, never silent. Refresh must not weaken this contract in any way — it has strictly more ways to go wrong than bootstrap (drift scoping, cached ancestors, diff proposals), and every one of them defaults to preserving what's on disk.
STEP 0: Preconditions
Require a prior bootstrap:
test -f .claude/tech-stack || MISSING_TECH_STACK=1
test -f .claude/mtk-version.json || MISSING_VERSION=1
If either file is missing, STOP immediately and tell the engineer:
"This repo has not been bootstrapped yet (.claude/tech-stack and/or .claude/mtk-version.json missing). Run /mtk-setup (full bootstrap) first, then /mtk-setup --refresh on future re-runs."
Do not attempt a partial refresh, and do not fall back to generating these files yourself — that is bootstrap's job, not refresh's.
Otherwise, resolve the active stack as usual: read .claude/tech-stack, then load .claude/skills/tech-stack-{stack}/SKILL.md. Its ## Scan Recipes section is the input STEP 3 uses when a full re-audit is required.
STEP 1: Staleness Plan
Run the plan script and read its structured output — this is the sole source of truth for what has drifted:
bash scripts/setup-refresh-plan.sh --json
Parse each artifact row (the script emits full paths: .claude/references/architecture-principles.md, .claude/references/conventions.md, CLAUDE.md, .claude/detected-tools.json, AGENTS.md, path-references, and the informational .claude/setup-answers.json row) for its status (fresh / stale / missing / unstamped / unknown / present / absent) and reason. STEP 3 scopes its regeneration entirely from this plan — do not re-derive staleness by re-reading the codebase from scratch. If the plan script itself fails or is not found, STOP and report the failure; do not silently degrade to a full re-audit as a workaround.
STEP 2: Dry-Run Gate
If --dry-run was passed:
- Re-run
bash scripts/setup-refresh-plan.sh without --json and print the resulting plan table verbatim — every row, no reformatting or summarizing away entries (the table format exists only in the default output mode).
- Follow it with one paragraph describing what a full refresh would do, per stale/missing row (e.g., "
architecture-principles.md is stale — 4 claims touch changed files under src/Api/; a refresh would re-read those files plus their containing modules, regenerate the affected sections, and propose any resulting diff against your on-disk copy per the regen-diff-contract before writing anything").
- STOP. Write nothing — no docs, no cache entries, no stamps, no
.claude/detected-tools.json updates.
STEP 3: Scoped Regeneration
For each artifact the plan marked stale, missing, or unstamped, apply the matching procedure below (unstamped docs route to the full-re-audit path — there is no stamp to scope by). Skip rows marked fresh or unknown — leave those files exactly as they are. The informational setup-answers.json row never drives regeneration; STEP 5 handles it.
Temp-path mandate: STEP 3 never writes a regenerated doc to its on-disk path. Every regenerated doc goes to a temp path (e.g. /tmp/mtk-refresh/<file>); only STEP 4 — the diff-proposal contract — may touch the on-disk copy. The two exceptions are the deterministic artifacts explicitly listed below (AGENTS.md/tool configs/indexes), whose generators carry their own marker-refusal guards.
architecture-principles.md / conventions.md
- Get the stale-claim scoping input from the same drift source the plan consulted:
bash scripts/audit-drift-check.sh <doc> --json — its drift array pairs each changed path with the claim anchor it touches.
- Compute the full changed-file set yourself (the drift check reports only the changed ∩ cited intersection, which systematically undercounts churn): read the doc's
audited-against: stamp, then git diff --name-only <stamp>..HEAD. Count tracked source files for the active stack (git ls-files filtered to stack extensions) as the denominator.
- Full re-audit (re-run
setup-audit's STEP 0.5 through STEP 3.7 for this doc, in full) only when: the doc's stamp is missing or unreadable, or the full git diff changed set from item 2 exceeds ~30% of tracked source files. In that case, treat this as equivalent to a fresh /mtk-setup --audit for this one document.
- Scoped regeneration (the default path): re-read only the changed files reported by the drift check, plus the directories/modules that contain them. Re-derive only the principle/convention lines whose evidence anchors point into that changed set. Every other section is carried over verbatim, byte-for-byte from the current on-disk doc — do not reword, re-flow, or "improve" untouched sections. This keeps prompt-cache prefixes stable and keeps the diff STEP 4 has to reason about small and honest.
- Either way, the regenerated doc is written to the temp path, never in place. Run
setup-audit STEP 3.5 (Provenance section) against the temp copy so fresh is complete before classification. Stamping and verify-claims happen in STEP 5, against the on-disk doc after STEP 4 has resolved the proposals — the engineer-approved state is what gets stamped and verified, not the unreviewed template.
.claude/detected-tools.json
Re-run setup-audit STEP 2.6 (tool detection) only — do not re-run the full scan recipes. Write the result to a temp path first; STEP 4 diffs it against the on-disk copy before deciding whether to overwrite (this file is machine-generated and deterministic, but a manual edit is still possible and must not be clobbered silently).
Reference pruning
Re-run setup-bootstrap STEP 3.6 (prune stack reference files against detected tools) against the freshly regenerated detected-tools.json. This may newly ship a reference file that was previously pruned (a tool got detected). Refresh-time pruning affects only which files would be newly shipped — it never deletes or proposes deleting an on-disk reference file. "Prune" is a ship-time filter, not an operation on existing files (File Preservation Policy).
AGENTS.md + tool configs + indexes
When AGENTS.md or path-references is stale/missing, regenerate deterministically:
bash scripts/generate-agents-md.sh
bash scripts/generate-tool-configs.sh --all
bash scripts/refresh-derived.sh references triggers
These generators carry their own preservation guards, which is why they may write in place: generate-agents-md.sh refuses to overwrite an AGENTS.md that lacks its auto-generated marker and preserves ## Custom: sections when regenerating its own output; generate-tool-configs.sh applies the same marker-refusal rule per output file. A marker-less config (AGENTS.md, GEMINI.md, .windsurfrules, …) is hand-curated — leave it alone, list it under "Preserved hand-authored files", and note it as a Needs review item if the plan flagged it. Never pass --force to reconcile a staleness row; a row that cannot be reconciled without --force means the file is not MTK's to regenerate. refresh-derived.sh is idempotent and silent on no-op, so running it at the end of this step regardless of the trigger is safe and keeps .claude/references.index / .claude/triggers.index in sync with whatever STEP 3 just touched.
CLAUDE.md and .claude/rules/*
Never rewritten in place, regardless of staleness reason (version-drift footer or stale dependency mentions). Compute the fresh template content as setup-bootstrap would, then hand it to STEP 4 — CLAUDE.md and every .claude/rules/*.md file always go through the diff-proposal contract, never a direct Write.
STEP 4: Engineer-Edited Files
For every file STEP 3 regenerated or would regenerate (architecture-principles.md, conventions.md, CLAUDE.md, each .claude/rules/*.md, .claude/detected-tools.json), resolve ancestor / current / fresh and apply .claude/references/regen-diff-contract.md exactly as written there — do not re-derive or restate its classification, diff-proposal, or cache-update rules here. In short: files unchanged since the last generation overwrite cleanly; files an engineer edited get their MTK delta proposed hunk-by-hunk via AskUserQuestion, never force-merged; hunks that no longer apply cleanly land under Needs review with the conflicting region quoted; protected files (manifest.protected) that this run has no business touching are reported SKIP.
Run this step for every candidate file even if STEP 3 judged the underlying content unchanged — the contract's own current == ancestor check is what decides "safe to overwrite," and that decision belongs to the contract, not to this step.
When applying resolved content to .claude/references/architecture-principles.md, write via a temp file promoted through the shrink guard (S3.16), same as setup-audit:
. hooks/lib/shrink-guard.sh
mtk_guarded_write .claude/references/architecture-principles.md "$tmp"
STEP 5: Grounding
For every doc whose on-disk copy STEP 4 actually changed (wholesale stock overwrite or applied hunks):
- Sync Impact stamp. Refresh the
<!-- mtk-stamp --> block with the three re-run fields, computed by diffing the regenerated doc against its previous on-disk version before writing:
<!-- mtk-stamp
audited-against: <sha>
audited-at: <ISO8601>
mtk-version: <version>
previous-stamp: <previous audited-against sha, or "none">
sections-changed: <comma-separated H2 titles, or "none">
claims-delta: +<added> ~<modified> -<removed>
-->
- Verify-claims retry loop. Run
bash scripts/verify-claims.sh <doc>. Read .claude/.mtk-cache/weak-claims-<doc>.json. For each downgraded claim, make exactly one re-derivation attempt: re-locate correct evidence (fix the anchor — right path, right glob, right symbol), or, if it truly cannot be evidenced, delete the claim line — but only if the line is byte-identical to the fresh template's version (i.e., this run generated it). A line the engineer authored or modified is never deleted by the retry loop: leave the downgraded tag in place and let the engineer decide. Every deleted line must be itemized in the STEP 6 report. Rewrite the doc and run verify-claims.sh once more. Downgrades that survive the second pass are accepted and reported in STEP 6 — never loop a third time, and never re-upgrade a tag without a resolving anchor.
- Load
.claude/setup-answers.json. If present, treat its contents as authoritative human input. Any rule or claim sourced from it must keep the evidence-anchor convention (Evidence: engineer interview — .claude/setup-answers.json (hard_nevers)), which always resolves for verify-claims.sh (it checks the path exists before content-grep) — engineer-stated rules are therefore never auto-downgraded by the verify pass. Regeneration must not drop or reword a rule sourced from this file. If a fresh scan finding contradicts an interview answer, do not silently pick a side — emit a Needs review item citing both the answer and the contradicting finding.
STEP 6: Report
Print a summary with four counts — Updated, Created, Preserved (untouched), Needs review — followed by an itemized list of every needs-review item. Apply the same preservation reporting rules as setup-bootstrap STEP 5: list every preserved hand-authored file (or "none found"), and if any MTK-owned file was retired this run, list it explicitly under a "Retired prior MTK files" heading — never let a retirement pass silently.
✅ MTK SETUP REFRESH COMPLETE
Plan: [N] fresh, [N] stale, [N] missing, [N] unstamped/unknown
Updated: [N]
[file — RESULT from regen-diff-contract, e.g. "architecture-principles.md — scoped regen, 3 sections re-derived"]
Created: [N]
[file — e.g. "conventions.md — was missing"]
Preserved (untouched): [N]
[file — reason, e.g. "CLAUDE.md — PROPOSED (2 hunks: 2 applied, 0 skipped)" or "conventions.md — fresh, no drift"]
Needs review: [N]
[file — hunk description and quoted conflicting region, per regen-diff-contract]
Preserved hand-authored files (untouched):
[nested CLAUDE.md, custom rules/references outside the standard set — or "none found"]
Retired prior MTK files (explicitly removed this run):
[MTK-owned files this run superseded — or "none"]
Next steps:
1. Resolve each Needs review item — the conflicting region is quoted above
2. Re-run `/mtk-setup --check` to confirm the plan is now clean
Verification
bash scripts/setup-refresh-plan.sh --json ran and its output drove every scoping decision in STEP 3 (no ad-hoc staleness judgment).
- No file outside the plan's
stale/missing artifacts (or the derived AGENTS.md/tool-config/index set) was modified; no non-MTK file was modified or deleted.
- Every doc rewritten in STEP 3/4 carries a refreshed
<!-- mtk-stamp --> with previous-stamp / sections-changed / claims-delta populated.
scripts/verify-claims.sh ran per refreshed doc, including the one-retry loop where downgrades occurred.
- Every engineer-edited file went through
.claude/references/regen-diff-contract.md — no direct Write to CLAUDE.md or any .claude/rules/*.md, and no git merge-file --union anywhere in this run.
- The STEP 6 report was printed with all four counts and an itemized needs-review list (or explicit "none").