update-kit
Skill2 starsChanged 3 months agoMITView on GitHub
Update or re-adapt the feature-flow kit in a project that was ALREADY bootstrapped, without clobbering your local adaptations — the safe path for both a newer kit version and a plain re-adapt after structural changes. Does a 3-way merge (manifest baseline vs your files vs the staged version), asks only on real conflicts, never touches project-owned files (PROJECT.md, CONTEXT.md, docs/adr/, backlog), then re-runs the bootstrap re-adapt inline so settings/hooks/rules refresh in the same pass. Backs up first and asks keep-or-rollback. Trigger when the user says "update the kit", "pull a newer kit version", "sync the kit", "re-adapt the kit", "/update-kit", "/sync-kit", drops a new kit version into .claude/.kit-incoming/, or runs /bootstrap on a project that's already adapted (bootstrap hands off here). DO NOT TRIGGER for the FIRST install of the kit (use /bootstrap), or to remove it (/teardown).
- Deletes or force-pushes
In this repository48 other files it gives its agents.
- analystSkill
- api-designSkill
- arch-healthSkill
- audit-qualitySkill
- audit-securitySkill
- bootstrapSkill
- clean-mvpSkill
- close-epicSkill
- codebase-designSkill
- code-reviewSkill
- decomposeSkill
- deploySkill
- depsSkill
- diagnoseSkill
- discoverSkill
- distillSkill
- domain-modelSkill
- epic-statusSkill
- grillSkill
- grill-with-docsSkill
- handoffSkill
- ideaSkill
- implementSkill
- incidentSkill
- onboardSkill
- perfSkill
- preflightSkill
- prepareSkill
- prompt-masterSkill
- prototypeSkill
- refactorSkill
- retroSkill
- revisitSkill
- rolloutSkill
- scaffoldSkill
- select-techSkill
- spikeSkill
- sweepSkill
- tddSkill
- teardownSkill
- testSkill
- test-specSkill
- threat-modelSkill
- to-issuesSkill
- to-prdSkill
- triageSkill
- which-skillSkill
- writing-skillsSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 50
Only the persistent, pristine-by-default kit files: skills/ (kit skills), agents/, hooks/ except guard-bash.sh, rules/_generic/, …
- Very specific: line 84
If $ARGUMENTS is a path to a new kit checkout, copy it into the staging dir, excluding the kit's own dev dirs:
- Very specific: line 112
Read .claude/.kit-manifest.json.
- Very specific: line 190
Do not re-interview the domain or re-touch PROJECT.md content beyond what reconcile records.
- Very specific: line 236
Ask via AskUserQuestion: Keep or Roll back (identical to /bootstrap Phase 8).
- Very specific: line 244
After the user keeps the result, remove the build-time material this run staged (same as /bootstrap Phase 9): rm -rf .claude/_kit, delete …
- Distinctive: line 256
3-way, not 2-way: Use the manifest BASE; only a genuine BASE≠MINE≠THEIRS divergence is a conflict worth a question.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/update-kit — pull a newer kit version into an already-bootstrapped project
The kit is a copy-in bundle, so a newer version can't auto-update itself, and re-copying it
over .claude/ would clobber any skill you adapted. This skill is the safe path for any
post-install adaptation — a version bump or a plain re-adapt after structural changes. It
brings in the staged kit, 3-way merges it against your local copy, resolves conflicts with
you, then re-adapts — all in one run. (/bootstrap is the front door: on an already-adapted
project it hands off here; you can also run /update-kit directly.) A same-version re-adapt is
just the degenerate case where everything merges quietly and only the re-adapt step does work.
Work top-to-bottom, naming each phase as you enter it — the phase headings below are the
checklist, and none is optional. A merge run that loses its place re-litigates a conflict the
user already resolved. New kit source: $ARGUMENTS (a path), or
the pre-staged .claude/.kit-incoming/ if no path is given.
The model: 3-way, not 2-way
A plain "copy and compare" is a 2-way diff (mine vs theirs) — it can't tell "I adapted this"
from "the kit changed this upstream"; both just look different. To merge safely you need a third
reference, the BASE: what the kit file was when it was last installed. The kit records that in
a content-hash manifest, so this works even when .claude/ is gitignored (git is not used).
- BASE —
sha256per file from.claude/.kit-manifest.json(last install/update). - MINE — the file currently in
.claude/. - THEIRS — the same file in the new kit source (staged).
Which files this merges (class A)
Only the persistent, pristine-by-default kit files:
skills/** (kit skills), agents/**, hooks/** except guard-bash.sh, rules/_generic/**,
output-styles/**, schemas/**, docs/** (kit docs — docs/adr/ is project-owned, see below).
Carve-out inside class A: a rule's paths: frontmatter is project-owned. /bootstrap
narrows each installed rule's globs to the project's real layout (Phase 5.2), so THEIRS carries
the kit's "**/*" template default while MINE carries the deliberate project scope. Merge the
rule body normally and keep MINE's paths: block — taking THEIRS silently re-widens the
rule to every file touch and quietly inflates the standing context budget, which is the kind of
regression nobody notices until a session is paying for rules it never needed. Surface it instead:
when THEIRS changes a paths: block, report it as a suggested re-scope with both globs shown,
and let the user apply it. Same treatment for a rule that gains or loses paths: entirely — moving
a rule into or out of the always-on set is a context-budget decision, not a file sync.
Everything else falls out naturally and is not file-merged:
- Project-owned (never touched):
.claude/PROJECT.md,CONTEXT.md,docs/adr/, the backlog, and any project-specific skill/agent the user created — these aren't in the kit source at all, so the sync physically can't reach them. A path under.claude/that is absent from the manifest is project-owned by definition — leave it. - Mixed (kit template + project inserts) → regenerated by re-adapt, not merged:
.claude/settings.json,.claude/hooks/guard-bash.sh,CLAUDE.md,.gitignore. The kit's templates for these (settings.template.json,CLAUDE.snippet.md) and the placeholderguard-bash.shcome in THEIRS only to feed the re-adapt phase. - Build-time (staged for re-adapt, then cleaned):
_kit/**,*.template.*,CLAUDE.snippet.md,settings.stop-gate.example.json.
Phase 0 — Preconditions & staging the new version
- Confirm this project is already bootstrapped:
.claude/PROJECT.mdexists withprofile_status: ACTIVE. If it's missing or stillTEMPLATE, STOP — tell the user to run/bootstrapfirst (this skill updates an existing install; it is not the first install). - Stage THEIRS:
- If
$ARGUMENTSis a path to a new kit checkout, copy it into the staging dir, excluding the kit's own dev dirs:mkdir -p .claude/.kit-incoming rsync -a --delete --exclude='.git' --exclude='.claude' --exclude='.claude copy' \ --exclude='_backlog' --exclude='guide' "$ARGUMENTS"/ .claude/.kit-incoming/ - Else if
.claude/.kit-incoming/already exists (the user dropped it there manually), use it. - Else STOP and tell the user: drop the new kit version into
.claude/.kit-incoming/(or pass its path), then re-run.
- If
- Sanity-check the staged source looks like the kit (
.kit-incoming/_kit/KIT.mdand.kit-incoming/skills/present). If not, stop and report.
Phase 0.5 — Back up before any writes
Same mechanism as /bootstrap Phase 0.5 — reuse it so backup/rollback behave identically:
TS=$(date +%Y%m%d-%H%M%S); BK=".claude/.bootstrap-backup/$TS"; mkdir -p "$BK"
: > "$BK/created.txt" # paths this run newly creates — for a clean rollbackBack up every class-A file before you overwrite it (mkdir its parent under $BK, cp -p).
Append each newly created path to $BK/created.txt. On re-run, add a new snapshot — never
delete earlier ones.
Phase 1 — Load the baseline (BASE)
Read .claude/.kit-manifest.json. Define a hash helper:
hashof() { shasum -a 256 "$1" 2>/dev/null | cut -d' ' -f1 || sha256sum "$1" | cut -d' ' -f1; }- Manifest present → full 3-way (the normal, quiet path). Also read its optional
excludedarray — kit paths this project removed on purpose (e.g. an agent replaced by a project-owned one). Phase 2 skips them entirely. - Manifest absent (a legacy project bootstrapped before manifests existed) → degraded 2-way mode: there is no BASE, so any class-A file that differs from THEIRS becomes a conflict to ask about (can't auto-tell adapted from upstream-changed). Warn the user it'll be noisier this once, and that Phase 6 writes a manifest so future updates are quiet.
Phase 2 — Classify
Enumerate the class-A paths present in .kit-incoming/ (the list above; exclude
hooks/guard-bash.sh and every path in the manifest's excluded). For each, compute BASE (from manifest), MINE (hashof the local file if
present), THEIRS (hashof the staged file). Bucket by this matrix:
| BASE | MINE | THEIRS | Verdict | Action |
| present | == BASE | any | untouched locally | take-new (quiet) |
| present | != BASE | == BASE | you edited, kit didn't | keep-mine (quiet) |
| present | != BASE | == MINE | converged | take-new (quiet) |
| present | != BASE | != BASE, != MINE | real conflict | → Phase 3 |
| — (absent) | absent | present | new kit file | add (quiet) |
| present | absent | present | you deleted a kit file | ask: re-add, or exclude for good (move the path from files to excluded) |
| present | present | absent (gone upstream) | removed upstream | offer delete (confirm) |
A path in excluded never reaches this matrix: without the list, a removed kit file whose entry
is dropped from files reads as new kit file and is silently re-added on the next run, and one
whose entry is kept is asked about on every run.
In degraded 2-way mode collapse to: MINE == THEIRS → nothing; MINE absent → add;
THEIRS absent → offer delete; otherwise → conflict (Phase 3).
Produce two lists: quiet actions and conflicts.
Phase 3 — Resolve conflicts (one batch of focused questions)
For each conflict show a short diff (MINE vs THEIRS; mention if THEIRS also moved from BASE) and
ask via AskUserQuestion: take-new / keep-mine / merge (hand-combine — you do the
edit, preserving the user's intent and the new upstream improvement).
For an adapted skill specifically, add the kit's guidance so the conflict stops recurring:
- General improvement (useful in any project) → upstream it: keep your version now, and open a change in the kit repo so the next release carries it.
- Genuinely project-specific → rename it to a project-owned skill (a name not in the manifest);
then kit updates will never collide with it again, per the kit's design (skills stay invariant;
project specifics live in
PROJECT.md/rules or in project-owned skills).
Group related conflicts; don't ask twenty separate questions when a few grouped ones cover it.
Phase 4 — Apply the file merge
Apply the resolved class-A actions: take-new (copy THEIRS over MINE), merge (write the
combined file), add (copy new file), delete (remove, confirmed). Back up each overwritten
file into $BK first; log each newly created path to $BK/created.txt. Do not touch class-B
(project-owned) or class-C (mixed) files here — class C is the next phase's job.
Stage the build-time inputs the re-adapt needs, logging them as created:
cp -R .claude/.kit-incoming/_kit .claude/_kit and copy the contracts
(PROJECT.template.md, settings.template.json, CLAUDE.snippet.md,
settings.stop-gate.example.json) into .claude/.
Phase 5 — Re-adapt (inline, automatic — no separate command)
Within this same run, perform the bootstrap re-adapt so settings/hooks/rules refresh against the
new version. Follow skills/bootstrap/SKILL.md Phases 3–6 against the freshly staged .claude/_kit
and contracts (it sees profile_status: ACTIVE, so it updates in place):
- re-select & reconcile stack rule packs, reusing the decisions already recorded in
PROJECT.md→ "Rules notes" (don't re-ask what's already answered); - regenerate
.claude/settings.jsonfrom the new template + the profile's permissions; - regenerate
.claude/hooks/guard-bash.sh(kit regions from the new version + the project's__BOOTSTRAP_PROJECT_BLOCKS__from the deny decisions; keep__VCS_PUBLISH_BLOCKS__per policy); - replace the
feature-flow-kit:begin…endblock inCLAUDE.mdand in.gitignore.
Do not re-interview the domain or re-touch PROJECT.md content beyond what reconcile records;
leave CONTEXT.md, docs/adr/, and the backlog alone (bootstrap already treats them as project-owned).
Phase 6 — Write the new manifest (new BASE)
Record, for every class-A path this run kept in sync, the hash of THEIRS — the staged kit file
as the kit shipped it, not the local copy, and write .claude/.kit-manifest.json:
{
"kit_version": "<from .kit-incoming/_kit/KIT.md version or the date>",
"installed_at": "<ISO-8601>",
"files": { "skills/analyst/SKILL.md": "<sha256 of .kit-incoming/skills/analyst/SKILL.md>", "...": "..." },
"excluded": ["agents/<removed-on-purpose>.md"]
}BASE means the kit version this project last merged. For a pristine file THEIRS and the local
copy hash the same, so nothing changes; the difference is every adapted file — a merge, a
keep-mine, a narrowed paths: block. Hash the local copy there and the next run reads it as
MINE == BASE → untouched locally → take-new, and silently overwrites the adaptation this run just
preserved. Hashing THEIRS keeps it reading as MINE != BASE, so it stays keep-mine until the kit
changes it, and then it is a conflict you are asked about. Carry excluded forward, plus any path
the user chose to exclude in Phase 2. Check before writing: every adapted file must still differ
from its recorded hash — if one does not, you hashed the wrong copy.
Phase 7 — Report & next step
Output:
- File merge: a table per class-A path —
unchanged · updated · merged · added · deleted · kept-yours · excluded · skipped(project-owned). - New paths-scoped rules: any rule that arrived new with template
paths:(sql.mdis the first) needs the narrowing/bootstrapdoes — name it and this project's DB directories. - Re-adapt: what bootstrap regenerated (settings/hooks/CLAUDE.md/.gitignore) and the reconciliation summary.
- To upstream: the adapted skills you chose to keep that are worth contributing back to the kit repo.
- Next step: smoke-test — run
/analyst(it should read the refreshed profile) and the profile'stestcommand; if anything looks off, you can still roll back (Phase 8). - Re-check hook registration. This run may have rewritten
settings.jsonhook entries, and a hook that failed to register is indistinguishable from a silent one./hooks→ non-zero count per event + source label = your settings file; when/hooksis unavailable (TUI-only), provoke a hook into output and look for anattachment/hook_successrecord carryingcommandin the session transcript. Procedure:_kit/KIT.md§ Hook & permission configuration.
Phase 8 — Keep or roll back (ask)
Ask via AskUserQuestion: Keep or Roll back (identical to /bootstrap Phase 8).
- Keep → Phase 9.
- Roll back → undo this run from
$BK: delete every path in$BK/created.txt, restore every backed-up file, strip anyfeature-flow-kitblock this run added to a file it created. Leave.kit-incoming/so the user can retry. Report exactly what was undone.
Phase 9 — Clean up (ask first)
After the user keeps the result, remove the build-time material this run staged (same as
/bootstrap Phase 9): rm -rf .claude/_kit, delete .claude/*.template.*,
.claude/CLAUDE.snippet.md, .claude/settings.stop-gate.example.json, and .claude/.kit-incoming/.
Offer to prune old .claude/.bootstrap-backup/* snapshots. Leave a clean .claude/ plus the
updated .kit-manifest.json.
Hard rules
- Single command. One
/update-kitrun does load-new + merge-old + re-adapt. Never make the user run/bootstrapseparately afterward. - 3-way, not 2-way. Use the manifest BASE; only a genuine BASE≠MINE≠THEIRS divergence is a conflict worth a question. Quiet on everything else.
- BASE is the kit's file, never yours. The new manifest records THEIRS hashes (Phase 6) — a local hash there turns every adaptation into a silent overwrite on the next run.
- Exclusions are durable. A path in
excludedis never added, re-added, merged, or asked about. - Project-owned is sacred. Anything not in the manifest is the project's — never overwrite
PROJECT.md,CONTEXT.md,docs/adr/, the backlog, or user-created skills/agents. - Idempotent. Re-running with the same source yields zero conflicts and zero changes.
- Reversible. Back up before writing; confirm keep-or-rollback before cleanup; a rolled-back run leaves no trace.
- No git dependency. Detection is hash-based so it works when
.claude/is gitignored.
See also
/bootstrap— first install + the re-adapt phases this skill calls inline./teardown— remove the kit or its leftovers (also cleans.kit-incoming/and the manifest)./writing-skills— when an adapted skill should be upstreamed into the kit.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

