# Stack Update

> Apply a pending claude-code-setup update — fetches upstream, shows what changed, three-way-diffs CLAUDE.md against your local edits, and re-runs install.sh. Invoke on "update the stack", "upgrade the kit", "update claude-code-setup", "is there an update", or the SessionStart hook's update notice.

- **Type:** Skill
- **Install:** `agentstack add skill-turbokach-claude-code-setup-stack-update`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [TurboKach](https://agentstack.voostack.com/s/turbokach)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [TurboKach](https://github.com/TurboKach)
- **Source:** https://github.com/TurboKach/claude-code-setup/tree/master/skills/stack-update

## Install

```sh
agentstack add skill-turbokach-claude-code-setup-stack-update
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Stack update

This kit installs by **copying** files into `~/.claude` — once copied, an installed file has
no link back to the repo. This skill is the manual apply step for the update the SessionStart
hook noticed: fetch upstream, show what changed, gate on approval, and (critically) reconcile
`CLAUDE.md`, which `install.sh` never overwrites once it exists.

State dir: `${CLAUDE_HOME:-$HOME/.claude}/.claude-code-setup/` — `installed` (SHA that
skills, agents, and settings are at), `claude-md-installed` (SHA whose `global/CLAUDE.md` the
user actually accepted — written only when they applied the upstream hunks or confirmed a
completed hand-merge, never on a plain skip; if absent, there is no known base — `install.sh`
only writes it when it copied `CLAUDE.md` for a user who had none, so anyone with a pre-existing
personal `CLAUDE.md` has no stamp at all; never fall back to `installed`, see step 5),
`claude-md-skipped` (SHA of upstream's `global/CLAUDE.md` at the point the user last declined to
reconcile it — suppresses re-showing an identical comparison in step 5; never used as a diff
base and never implies acceptance), `last-check` (epoch of last poll), `disabled` (presence
silences the SessionStart check entirely; `touch` it to opt out).

Repo: `https://github.com/TurboKach/claude-code-setup.git`, default branch **`master`** (not
`main`).

## Procedure

Steps 1–3 are read-only reconnaissance — nothing outside the scratchpad clone is touched, and
no state-dir file is written, until the approval gate in step 4 passes.

1. **Read state.** Read `installed` from the state dir — this is the SHA to diff against. Do
   not modify any state file yet.

2. **Clone.** Full `git clone` (not `--depth`) of the repo into the session scratchpad. Full
   history, because step 3 needs `` reachable to diff against; the repo is ~20
   files, so a shallow clone buys nothing here. The clone is read-only reconnaissance — nothing
   is copied out of it until approval.

3. **Summarize what's new, grouped by surface.** First check history shape with
   `git merge-base --is-ancestor  HEAD`:
   - **Ancestor (normal case)** — derive the summary from `git log --oneline ..HEAD`
     and `git diff --stat ..HEAD`; raw commit subjects are not the deliverable, a
     "what changes for me" bullet list is.
   - **Reachable but not an ancestor** — upstream rewrote history (force-push). Label the
     summary as **divergent history**, not "what changed since you installed": `..HEAD`
     is a set difference, not a lineage, and would misrepresent it. Base the bullets on
     `git diff ..HEAD` instead (endpoint comparison — stays correct regardless of
     rewritten history).
   - **`` empty, unknown, or unreachable at all** — say plainly that a change summary
     is unavailable because there's no base to diff against. Show only the current HEAD SHA and
     short subject, and the last ~10 commit subjects (`git log --oneline -10`) as context — and
     label that list explicitly as *not* a diff against what the user has installed.

   Group bullets by the surfaces the user actually has installed, each stated in user-facing
   terms (not a hash dump):
   - `global/CLAUDE.md` → their always-on rules — what changed, in a sentence.
   - `skills/*` → which skills are new or changed.
   - `agents/*` → which role agents changed.
   - `install.sh` / `settings.example.json` → what the installer will now do differently.
   Omit a group with no changes.

4. **Approval gate #1 — apply the update at all?** `AskUserQuestion`: "Apply this update?" with
   options *Apply* / *Show the full diff first* / *Cancel*.
   - *Show the full diff first* → show it, then re-ask this same question; it is not itself an
     answer.
   - *Cancel* → stop here. **Nothing is written and the state dir is left exactly as it was** —
     do not touch `installed` or `last-check`, so the update notice correctly reappears next
     session.
   - Silence, or the question going unanswered, is not approval — never infer Apply from a
     default or from the user being away.
   - Only *Apply* proceeds past this point.

5. **The `CLAUDE.md` three-way diff and approval gate #2 — this is the step that justifies the
   skill.** `install.sh` deliberately never overwrites an existing `~/.claude/CLAUDE.md` (see
   `install.sh:35-39`) — it just prints a reminder to merge by hand. So step 6's install
   refreshes skills and agents but silently skips the single most important file, and a
   two-way diff can't tell an upstream improvement apart from the user's own customization. Do
   it properly. Use `claude-md-installed` as the base for this diff, not `installed` — it's the
   SHA the user actually accepted `CLAUDE.md` at, which may lag `installed` if a prior run was
   skipped or handed off for manual merge.
   - **`claude-md-installed` exists (normal case)** — three-way diff:
     - `git show :global/CLAUDE.md` — what the user last accepted.
     - the clone's `global/CLAUDE.md` — what upstream has now.
     - the live `~/.claude/CLAUDE.md` — the user's file, possibly hand-edited.
     Diff the first two to isolate what actually changed upstream, then show that upstream
     change against the live file.
   - **`claude-md-installed` is absent — unknown base, do not fall back to `installed`.** This
     is the common case: `install.sh` only writes `claude-md-installed` when it copies
     `CLAUDE.md` for a user who had none, so anyone who already had a personal `CLAUDE.md`
     (i.e. every existing user) ends up with an `installed` SHA but no `claude-md-installed`.
     Falling back to `installed` would silently claim they accepted that revision's
     `global/CLAUDE.md`, which they never did, and would permanently hide every upstream change
     made before it. Check `claude-md-skipped` first:
     - **Absent, or upstream's `global/CLAUDE.md` has changed since the SHA it records** — say
       plainly there's no record of which `global/CLAUDE.md` revision they've accepted (either
       their `CLAUDE.md` predates the marker, or they've always kept their own), and show a
       **two-way** diff instead — the clone's current `global/CLAUDE.md` against the live
       `~/.claude/CLAUDE.md` — labeled explicitly as "upstream's current version vs yours", not
       as "what changed upstream since you installed". This diff will be noisy if they carry
       heavy local edits — expected and honest. Proceed to the gate #2 question below.
     - **Present, and upstream's `global/CLAUDE.md` is unchanged since that SHA** — nothing new
       to show. Note in one line that the `CLAUDE.md` reconciliation the user previously declined
       is still outstanding, skip re-rendering the diff, and skip gate #2 for this run.
   Then a **separate** `AskUserQuestion` — approving the bundle
   in gate #1 is not approval to rewrite `CLAUDE.md`, it's a distinct decision because the
   live file may carry local edits — with three choices: apply the upstream hunks (back up the
   live file first, preserve any local edits that don't conflict) / show the full diff and let
   the user decide by hand / skip `CLAUDE.md` entirely. **Never** rewrite
   `~/.claude/CLAUDE.md` without an explicit answer to this question — silence is not approval.

6. **Install.** Run `./install.sh` from the clone. It already backs up skills and agents to
   `~/.claude/.backup-` and merges settings.json keys — reuse it, don't reimplement its
   logic here.
   - **If it exits non-zero:** stop — do not write `installed` or `claude-md-installed`, the run
     is not complete. Report exactly what was and wasn't applied (skills/agents may be partially
     updated; `CLAUDE.md` may already have been changed by gate #2 above, before this step ran).
     Point the user at the restore path: `~/.claude/.backup-` (skills/agents backup
     `install.sh` already took) and, if gate #2 applied hunks, the `CLAUDE.md` backup it took.
     Don't invent a rollback — just leave the state files untouched and tell the user where the
     backups are.

7. **Update state.** Only now write to the state dir, and only on a zero-exit install:
   - `installed` — the clone's new HEAD SHA. After `install.sh` succeeds, skills, agents, and
     settings genuinely are at this revision.
   - `claude-md-installed` and `claude-md-skipped` — one rule, unconditional, no per-path
     exception, applies whether this was the three-way or unknown-base case in step 5:
     - Gate #2 answered *apply the upstream hunks* — write `claude-md-installed` at the clone's
       new HEAD SHA, and delete `claude-md-skipped` if present. This is the only answer that
       stamps acceptance, because it's the only one where `CLAUDE.md` was actually rewritten.
     - Gate #2 answered *skip* or *show the full diff and decide by hand*, or gate #2 wasn't
       asked this run (step 5's suppressed case) — leave `claude-md-installed` untouched (do not
       write it, even if absent), and write `claude-md-skipped` at the clone's new HEAD SHA. The
       declined or unconfirmed `CLAUDE.md` change stays pending and resurfaces in the next run's
       step 5 instead of being silently dropped or falsely marked accepted.
   - Delete `last-check` so the next session re-polls fresh instead of trusting the 24h cache.

8. **Tell the user to restart Claude Code.** Skills, agents, hooks, and settings `env` are all
   read at session start — nothing applied by this run is live in the current session until
   it's restarted.

## Opt-out

`touch ~/.claude/.claude-code-setup/disabled` silences the SessionStart update check
permanently (delete the file to re-enable).

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [TurboKach](https://github.com/TurboKach)
- **Source:** [TurboKach/claude-code-setup](https://github.com/TurboKach/claude-code-setup)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-turbokach-claude-code-setup-stack-update
- Seller: https://agentstack.voostack.com/s/turbokach
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
