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. B...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add mik2win/foureyes --skill update-kit --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Update Kit?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/mik2win-update-kit)More formats (shields.io, HTML) on the badges page.
---
name: update-kit
disable-model-invocation: true
description: |
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).
allowed-tools: Read, Grep, Glob, Bash, Write, Edit, AskUserQuestion
effort: high
---
# /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** — `sha256` per 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 placeholder
`guard-bash.sh` come 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
1. Confirm this project is **already bootstrapped**: `.claude/PROJECT.md` exists with
`profile_status: ACTIVE`. If it's missing or still `TEMPLATE`, STOP — tell the user to run
`/bootstrap` first (this skill updates an existing install; it is not the first install).
2. Stage **THEIRS**:
- If `$ARGUMENTS` is a path to a new kit checkout, copy it into the staging dir, excluding the
kit's own dev dirs:
```bash
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.
3. Sanity-check the staged source looks like the kit (`.kit-incoming/_kit/KIT.md` and
`.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:
```bash
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 rollback
```
Back 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:
```bash
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).
- **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`**). 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 | re-add? ask |
| present | present | absent (gone upstream) | removed upstream | offer **delete** (confirm) |
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.json` from 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…end` block in `CLAUDE.md` and 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)
Hash the **final** class-A files in `.claude/` and write `.claude/.kit-manifest.json`:
```json
{
"kit_version": "<from .kit-incoming/_kit/KIT.md version or the date>",
"installed_at": "<ISO-8601>",
"files": { "skills/analyst/SKILL.md": "<sha256>", "agents/code-reviewer.md": "<sha256>", "...": "..." }
}
```
This becomes the BASE for the next `/update-kit`, so subsequent updates stay quiet.
## Phase 7 — Report & next step
Output:
- **File merge:** a table per class-A path — `unchanged · updated · merged · added · deleted ·
kept-yours · skipped(project-owned)`.
- **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's `test` command; if anything looks off, you can still roll back (Phase 8).
- **Re-check hook registration.** This run may have rewritten `settings.json` hook 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 `/hooks` is unavailable (TUI-only), provoke
a hook into output and look for an `attachment` / `hook_success` record carrying `command` in
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 any `feature-flow-kit` block 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-kit` run does load-new + merge-old + re-adapt. Never make the
user run `/bootstrap` separately 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.
- **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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!