Update Agent OS
Synchronizes your local ~/.claude/skills/ and ~/.claude/agents/ installations against the canonical Agent OS library. Reads the canonical manifest from GitHub, diffs your installed skills and agents against the canonical set, surfaces the current release version, and presents a per-row action table for you to approve before anything is changed. Nothing is written, renamed, or removed without your explicit confirmation.
Trigger
When the user runs /update-agent-os, execute the following phases in order.
Phase 1: Resolve Canonical Source
Pre-flight: active session detection (runs before any fetch).
- Check whether
~/.claude/.session-versionexists.- If absent: no active session is stamped — proceed normally to step 1 below.
- If present: read its contents as the stamped version (e.g.
v2.10.0).
- Fetch the canonical version from the remote manifest (or read from local
skills-manifest.jsonif already resolved in a prior step) as the canonical version.- If the canonical version cannot be determined yet at this point, continue to step 1 below and re-run this comparison after step 1 once the canonical version is known.
- Compare stamped version to canonical version:
If they are identical: proceed normally — the update would not change the running version.
If they differ: surface the following message and halt at Phase 5 Apply pending user confirmation:
"Active session detected at . Applying canonical will update the skills for the next session. Proceed with update now, or cancel to update at next session start?"
- If the user replies to proceed: continue through all phases normally.
- If the user replies to cancel: stop after Phase 4 (do not apply any changes). Print:
Update deferred — skills unchanged. Re-run /update-agent-os at next session start.
This gate is informational, not a hard block. The user decides.
Attempt to fetch the canonical manifest directly from GitHub:
- Default URL:
https://raw.githubusercontent.com/designgrappler/agent-os/main/skills-manifest.json - If a
skills-manifest.jsonexists in the project root with acanonical-registryURL, that URL overrides the default above.
- Default URL:
Stale registry detection (runs before fetch). If a
skills-manifest.jsonexists in the project root, run:grep "canonical-registry" skills-manifest.jsonIf the output contains
gastownhall(the retired org):- Print:
Stale registry detected: gastownhall/agent-os is retired. Updating skills-manifest.json to designgrappler/agent-os. - Rewrite
skills-manifest.jsonin the project root, replacing thecanonical-registryvalue withhttps://raw.githubusercontent.com/designgrappler/agent-os/main/skills-manifest.json. Preserve all other fields. - Also update
release-versionto use the key namerelease-versionif the file uses the old keyinstalled-version. - Continue using the corrected URL for the rest of this run.
- Print:
If the fetch fails (network unavailable, 404, or any HTTP error): stop immediately and surface a clear error:
"Cannot reach the canonical source at
<URL>. Check your network connection and try again." Do not proceed to Phase 2.
Phase 2: Inventory
Skills:
- Check whether
~/.claude/skills/exists.- If absent: silently create the directory (
mkdir -p ~/.claude/skills/). The installed skill set is empty. - If present: continue.
- If absent: silently create the directory (
- List all
<name>/subdirectories in~/.claude/skills/that contain aSKILL.mdfile. This is the installed skill set. - Read the
skillsarray from the resolved manifest. This is the canonical skill set.
Agents:
4. Check whether ~/.claude/agents/ exists.
- If absent: silently create the directory (
mkdir -p ~/.claude/agents/). The installed agent set is empty. - If present: continue.
- List all
<name>.mdfiles in~/.claude/agents/. This is the installed agent set. - Read the
agentsarray from the resolved manifest. This is the canonical agent set.
Hooks:
H1. Read the hooks[] array from the resolved skills-manifest.json. This is the canonical hook set (a list of .sh filenames). For each entry, read the canonical hook file contents from <canonical-source>/claude/hooks/<E>.
- Absent-path: if the canonical source has no
claude/hooks/directory ORskills-manifest.jsonhas nohooks[]key, treat the canonical hook set as empty and skip the Hooks phase entirely without error. H2. Check whether.claude/hooks/exists in the working directory. - If absent: silently create the directory (
mkdir -p .claude/hooks/). The installed hook set is empty. - If present: list all
.shfiles in.claude/hooks/. The installed hook set is these filenames.
Note: Hooks are project-scoped (.claude/hooks/). Do NOT inventory or modify ~/.claude/hooks/.
Release info:
- Read
release-versionfrom the manifest. This is the canonical release version.
Display neither list yet — hold all data for Phase 3.
Phase 3: Diff
For skills — produce three lists by comparing canonical against installed:
a. New — present in canonical skills array but absent from ~/.claude/skills/.
b. Removed — present in ~/.claude/skills/ but absent from the canonical skills array.
- Cross-array invariant guard: if the candidate IS in canonical
skills, treat as current (no rename, no removal). Surface diagnostic:Manifest invariant warning: <name> appears in both skills[] and renames[].from. Treating as canonical (no action). - Check the manifest
renamesarray first (confirmed rename). For unmatched names, apply name-similarity heuristic as suggestion only requiring explicit user confirmation.
c. Outdated — present in both but file contents differ.
For agents — produce three parallel lists with the same logic.
For hooks — skip entirely if the canonical hook set is empty.
a. New — filenames in canonical hooks[] but absent from .claude/hooks/.
b. Outdated — filenames in both, but contents differ.
c. Removed-from-canonical — filenames in .claude/hooks/ but absent from canonical. Default: Keep local hook (no canonical match). Never auto-removed.
Three-way merge detection (applies to all Outdated rows):
For every file classified as Outdated (skills, agents, or hooks), apply the following sub-classification before recording the row in the diff table.
Read the hash manifest for the appropriate install tier:
- Skills and agents:
~/.claude/agent-os-manifest.json - Hooks:
.claude/agent-os-manifest.json
If the manifest file is absent, or it contains no files entry for this file's path, classify the row as Clean update and proceed as today — no base was recorded yet (first-install context). No error.
If a manifest entry exists for this file:
- Read the
base-hashvalue from the entry. - Compute the SHA-256 hash of the local installed file:
shasum -a 256 "<local-file-path>" | cut -d' ' -f1 - Sub-classify:
- If local-hash == base-hash: Clean update — canonical has changed but the local file is unmodified from the last recorded install. Safe to overwrite as today.
- If local-hash != base-hash: Three-way conflict — the local file has been modified since the last recorded install AND canonical has also changed. Requires explicit per-file resolution. Never blind-overwrite.
Record each Outdated row's sub-classification (Clean update or Three-way conflict) and carry it into Phase 4 and Phase 5.
Absent manifest is not an error. The skill's existing tolerance posture applies: a missing manifest means first-install context for all Outdated rows on this run — no conflict detection; manifest is written at end of Phase 5.
Retired-artifacts detection (fires every run):
Using the canonical agents[] and skills[] arrays already resolved in Phase 2, perform a canonical diff against local agent and skill directories. Do not use a hardcoded filename list.
Agent canonical diff — global (~/.claude/agents/):
For each .md file in ~/.claude/agents/: extract the basename without .md. If that name is NOT in the canonical agents[] array, emit: RETIRED:global:~/.claude/agents/<filename>.md
Agent canonical diff — project-local (.claude/agents/):
For each .md file in .claude/agents/: extract the basename without .md. If that name is NOT in the canonical agents[] array, emit: RETIRED:project:.claude/agents/<filename>.md
Project-local skill canonical diff (.claude/skills/):
For each subdirectory in .claude/skills/ that contains a SKILL.md file: if the subdirectory name is NOT in the canonical skills[] array AND NOT in any renames[].from entry, emit: RETIRED:project:.claude/skills/<name>/
Note: ~/.claude/skills/ stale entries are already covered by the Removed list in the main Phase 3 diff above. This step is scoped to .claude/skills/ (project-local) only.
Path-structure artifacts (explicit path checks — unchanged):
[ -f "AGENTIC.md" ] && echo "RETIRED:path:AGENTIC.md"
[ -d "claude/skills/report-track-status" ] && echo "RETIRED:path:claude/skills/report-track-status/"
For every RETIRED: line produced above, add a [retired] row to the diff table (Phase 4). The row shows the exact rm or rm -rf command and requires the user to type yes before deletion executes.
If the above produces no RETIRED: lines, print: Retired artifacts: None found.
CLAUDE.md legacy format check (always runs): If a CLAUDE.md exists in the working directory, check whether it contains ## Initialization Loop or references to AGENTIC.md. If either marker is present, add an [outdated] row to the diff table:
| CLAUDE.md | [claude.md] | Outdated — manual only | Legacy format detected. Back up customizations, then replace with the lean bootstrap template at ~/.claude/skills/install-agent-scaffold/SKILL.md (section 4a). |
CRITICAL: this row is manual-migration only. It must NOT appear in the approval tiers as an overwrite candidate. In Phase 4, explicitly exclude [claude.md] rows from all approval tiers (New, Outdated, Hook). In Phase 5 Apply, [claude.md] rows are informational only — never write, overwrite, or modify CLAUDE.md. The block-orchestrator-execution hook already prevents this, but the skill must encode it explicitly so no future implementor creates an auto-overwrite path.
CLAUDE.md bridge-doc convention check (always runs): If a CLAUDE.md exists in the working directory, scan it for the deprecated disk-write bridge-doc convention — markers: any of handoff-t, docs/context/handoff, or Handoff Bridge co-located with a write or docs/context instruction. If any marker is present, add an informational [claude.md] row to the diff table:
| CLAUDE.md | [claude.md] | Outdated — manual only | Deprecated bridge-doc convention detected. Migrate to the dynamic agent-spawn bridge convention — bridge docs are now created at agent-spawn time, not written to disk. |
CRITICAL: this row is manual-migration only. It must NOT appear in any approval tier and must never trigger a CLAUDE.md write, overwrite, or edit. In Phase 4, explicitly exclude this row from all approval tiers (New, Outdated, Hook). In Phase 5 Apply, this row is informational only — no action. Same hard constraint as the legacy-format row.
CLAUDE.md reference scan (fires on rename or removal only):
If the diff contains at least one rename or removal: scan CLAUDE.md for references to renamed/removed skill names (auto-trigger rows, inline /skill-name mentions, path literals). Collect hits as CLAUDE.md reference list. Hold for Phase 4.
CLAUDE.md Team table reconciliation (runs unconditionally when CLAUDE.md exists):
If CLAUDE.md is present in the working directory, scan it for a Team Architecture table — any markdown table containing columns named Role, Function, or Agent with agent name rows. For each agent name found in the table body rows:
- Check whether that name is present in the canonical
agents[]array. - If the name is not in
agents[], add a[claude.md]row to the diff table:
| CLAUDE.md — Team table | [claude.md] | Stale agent reference | Remove or replace with canonical agent name |
Each such row requires explicit user approval before any edit is made to CLAUDE.md. Same hard constraint as all [claude.md] rows: never auto-applied, never included in any approval tier. Display in the table for visibility only; the user must explicitly instruct the edit.
Phase 4: Present Report
Surface release information first — display release version before the action table.
Enumerated table (always shown in full): Display one row for every skill, agent, and hook — not just affected items. This gives a complete picture of installation health before any action is taken. Prefix rows with [skill], [agent], or [hook]. CLAUDE.md reference rows ([claude.md]) are appended after the main table when present.
Status values:
New— present in canonical, not installed locallyOutdated— installed locally, differs from canonicalCurrent— installed locally, matches canonicalLocal-only— installed locally, not in canonical manifest (kept, no action)
Example table:
Skills
| Name | Type | Status | Proposed action |
|-----------------------------------|-----------|--------------|-------------------------------------------------------|
| check-agent-os | skill | Current | |
| onboard-existing-project | skill | Outdated | Update → overwrite with canonical SKILL.md |
| update-agent-os | skill | New | Install → ~/.claude/skills/update-agent-os/ |
| old-skill | skill | Local-only | (no action — not in canonical) |
Agents
| Name | Type | Status | Proposed action |
|-----------------------------------|-----------|--------------|-------------------------------------------------------|
| backend | agent | Current | |
| technical-architect | agent | New | Install → ~/.claude/agents/technical-architect.md |
Hooks
| Name | Type | Status | Proposed action |
|-----------------------------------|-----------|--------------|-------------------------------------------------------|
| block-orchestrator-execution.sh | hook | Outdated | Update → overwrite .claude/hooks/ |
| stop-reminder.sh | hook | Current | |
If the canonical hook set is empty: print Hooks: none in canonical manifest and omit the Hooks table entirely.
If there are no New, Outdated, or Removed rows across all three groups, state: "Your installation is up to date — no changes needed." and stop (the enumerated table still appears above this message).
Safety-control gate for hook rows: Before presenting any [hook] row with Status Outdated or New, display verbatim:
This is a safety-control hook. Review the diff carefully before approving.
Safety-control gate for Outdated rows: Before presenting any [skill] or [agent] row with Status Outdated, display one of the following messages based on the Phase 3 sub-classification:
Clean update (local-hash == base-hash, or no manifest entry): display verbatim:
This file exists locally and will be overwritten. Canonical has changed; your local copy is unmodified from the last recorded install.Three-way conflict (local-hash != base-hash): display verbatim:
THREE-WAY CONFLICT — Your local copy has been modified since the last recorded install, AND the canonical version has also changed. You must choose: keep local (skip) or accept canonical (overwrite). Never auto-overwritten.
For Three-way conflict rows: show the two-way diff (local vs canonical) so the user can see what the canonical change contains. Also display: Note: base-hash recorded at last install = <base-hash>; local-hash now = <local-hash> — confirms local was modified after install. Present the resolution prompt: Type "accept" to overwrite with canonical or "keep" to skip this file.
For Clean update rows: show the standard two-way diff (local vs canonical) and the standard per-file confirmation prompt, as today.
In both cases, per-file confirmation is required — Outdated rows (Clean update or Three-way conflict) cannot be included in "Approve all".
CLAUDE.md reference rows — appended after the main table when the diff produced rename or removal rows. These are informational only; see Phase 3 CLAUDE.md reference scan.
Approval tiers:
- New rows (no local file exists) — eligible for "Approve all". No overwrite risk.
- Outdated rows (local file differs from canonical) — require individual per-file confirmation. Cannot be included in "Approve all".
- Hook rows — require individual per-hook confirmation (unchanged).
[claude.md]rows — explicitly excluded from all approval tiers. These are informational only. Never include[claude.md]rows in New, Outdated, or Hook tier prompts. Display them in the table for visibility, but do not ask for approval — no action will be taken on them.
Ask: "Approve all NEW actions (no overwrite risk), a subset, or decline? Outdated rows each require individual confirmation — they will be listed separately."
Wait for the user's response before proceeding to Phase 5.
Phase 5: Apply
For each action the user approved, execute one at a time:
Skills:
- Install: create
~/.claude/skills/<name>/and copy the canonicalSKILL.md. Print:installed ~/.claude/skills/<name>/SKILL.md - Rename (confirmed from manifest): rename directory; overwrite with canonical version. Print:
renamed ~/.claude/skills/<old-name>/ → ~/.claude/skills/<new-name>/ - Update: overwrite
~/.claude/skills/<name>/SKILL.mdwith canonical. Print:updated ~/.claude/skills/<name>/SKILL.md - Remove: delete
~/.claude/skills/<name>/. Print:removed ~/.claude/skills/<name>/ - Skip: print:
skipped <name>
Agents:
- Install: create
~/.claude/agents/<name>.mdwith canonical content. Print:installed ~/.claude/agents/<name>.md - Rename (confirmed from manifest): rename file; overwrite if new name in canonical. Print:
renamed ~/.claude/agents/<old-name>.md → ~/.claude/agents/<new-name>.md - Update: overwrite
~/.claude/agents/<name>.mdwith canonical. Print:updated ~/.claude/agents/<name>.md - Remove: delete
~/.claude/agents/<name>.md. Print:removed ~/.claude/agents/<name>.md - Skip: print:
skipped <name>
CLAUDE.md references (applied after all skill and agent changes):
- For each approved
[claude.md]row from the rename reference scan (Phase 3 CLAUDE.md reference scan), apply the edit toCLAUDE.md. Print:updated CLAUDE.md line <N>: <old-ref> → <new-ref> [claude.md]rows from the CLAUDE.md legacy format check are NEVER acted on here. These rows are informational only — never write, overwrite, or modifyCLAUDE.mdbased on a legacy format detection row. No action, no prompt, no write.
Hooks:
- Install (confirmed): copy canonical hook to
.claude/hooks/<E>. Print:installed .claude/hooks/<E> - Update (confirmed per-hook): overwrite
.claude/hooks/<E>. Print:updated .claude/hooks/<E> - Remove (confirmed per-hook opt-in only): delete
.claude/hooks/<E>. Print:removed .claude/hooks/<E> - Keep (default for Removed-from-canonical): print:
skipped .claude/hooks/<E> (kept local) - Do NOT edit user-owned
.claude/settings.jsonfields (permissions, allow/deny lists,mcpServers, custom hooks). Canonical fields are patched if-absent by Phase 7 only. If a new hook was installed, print advisory:note: verify .claude/settings.json PreToolUse wiring references .claude/hooks/<E>
Never apply an action the user did not explicitly approve.
Hash manifest update (runs after all writes complete):
After all Install, Update, and Rename writes for this run complete, record the SHA-256 hash of each written file in the appropriate hash manifest. This establishes the new base for three-way conflict detection on future runs.
For each file written during this Phase 5 run (Install, Update, Rename — not Skip or Remove):
- Compute the SHA-256 hash of the written file:
shasum -a 256 "<installed-file-path>" | cut -d' ' -f1 - Upsert the entry in the appropriate manifest:
- Skills and agents written to
~/.claude/→~/.claude/agent-os-manifest.json - Hooks written to
.claude/hooks/→.claude/agent-os-manifest.json
- Skills and agents written to
Manifest format (JSON; matches skills-manifest.json tooling discipline — no new parser):
{
"schema-version": "1",
"last-updated": "<ISO-8601>",
"files": {
"<installed-file-path>": {
"base-hash": "<sha256-hex>",
"updated": "<ISO-8601>"
}
}
}
Write rules:
- If the manifest file does not exist: create it with the new entries.
- If the manifest file exists: read, merge new/updated entries (upsert by path key), write back. Never remove existing entries for files not touched this run.
- If the manifest file exists but is not valid JSON: skip silently and print:
Hash manifest update skipped — <path> is not valid JSON; not modified.Do not fail Phase 5. - Do not write the manifest if Phase 5 produced no writes (all rows were skipped or removed).
- Write the manifest only after all Phase 5 writes complete — mirrors the
skill-receipts.jsonlappend-at-success pattern. Per-file writes are not recorded individually mid-pass.
Print on manifest update: hash manifest updated — <N> entries recorded in <manifest-path>
Execution receipt: On successful completion of Phase 5 Apply, append one line to docs/context/skill-receipts.jsonl (create the file if absent):
{"skill":"update-agent-os","timestamp":"<ISO-8601 timestamp>","sprint":"<sprint-id>","version":"<release-version>","flags":[]}
timestamp: current ISO-8601 datetime (e.g.2026-09-02T14:30:00Z)sprint: read fromdocs/context/plan.md— match## Current Sprint: <ID>(e.g.S81); if not found use"unknown"version: the canonicalrelease-versionresolved in Phase 1 (not the local installed version); if not available use"unknown"- Append only — never overwrite. Create the file and any missing parent directories silently if absent.
Phase 6: Connectors symlink
Condition: Runs automatically on every update run (unconditional — not gated on actions applied).
Ensures the project has a local pointer to the global connectors registry.
- Check whether
~/.claude/connectors.mdexists.- If absent: skip this phase silently. Print:
Phase 6 skipped — ~/.claude/connectors.md not found.
- If absent: skip this phase silently. Print:
- Check whether
docs/context/connectors.mdalready exists (as a symlink or file).- If present: skip silently. Print:
connectors symlink already present
- If present: skip silently. Print:
- If
~/.claude/connectors.mdexists anddocs/context/connectors.mdis absent:- Create
docs/context/if it does not exist. - Run:
ln -sf ~/.claude/connectors.md docs/context/connectors.md - Add
docs/context/connectors.mdto.gitignoreif not already present (only when a.gitignorefile exists — do not create one). - Print:
connectors symlink created → docs/context/connectors.md
- Create
Phase 7: Canonical settings.json patch-if-absent
Condition: Runs automatically after Phase 5 whenever at least one action was applied.
Reads .claude/settings.json and adds canonical fields only when they are absent. This never overwrites an existing value and never touches a user-owned field.
- If
.claude/settings.jsondoes not exist, skip this phase entirely (the install path owns first creation). Do not create the file here. - Read and parse
.claude/settings.json. If it is malformed JSON, skip with advisory:Phase 7 skipped — .claude/settings.json is not valid JSON; not modified.Never rewrite a file you could not parse. - For each canonical field below, patch only if the field is absent. If the field is present with any value, leave it untouched (no overwrite):
worktree.baseRef— canonical value:"head". If theworktreeobject is absent, create it with{ "baseRef": "head" }. Ifworktreeexists butbaseRefis absent, addbaseRef: "head". Ifworktree.baseRefalready has a value, do nothing.- Standard
Stophook — canonical value: the hygiene-reminder Stop hook block thatinstall-agent-scaffoldwrites (section 4g ofinstall-agent-scaffold/SKILL.md). Ifhooks.Stopis absent, add the standard block. Ifhooks.Stopalready exists (any entry), do nothing — never append to or rewrite an existing Stop hook array.
- Never read, write, add, remove, or reorder
permissions, allow/deny lists,mcpServers, or any hook other than an absent standardStop. These are user-owned. - Preserve all existing fields, key order where practical, and formatting. Write back only if at least one canonical field was added.
- Print a status block:
Status tokens:Canonical settings.json patch-if-absent: worktree.baseRef added ("head") | already present (unchanged) hooks.Stop added | already present (unchanged)added/already present (unchanged)/skipped — no settings.json/skipped — invalid JSON.
Phase 8: Global scaffold-check hook
Condition: Runs unconditionally on every update run.
Installs the Agent OS new-project detection hook globally so it fires in every project session.
Note:
agent-os-scaffold-check.shis intentionally not listed inskills-manifest.jsonhooks[]. That array enumerates project-scoped hooks installed to.claude/hooks/; scaffold-check is a global hook installed to~/.claude/hooks/by this phase alone. Its absence fromhooks[]is correct — do not add it there.
- Check whether
~/.claude/hooks/exists. If not, create it silently. - Copy
claude/hooks/agent-os-scaffold-check.shfrom the canonical source to~/.claude/hooks/agent-os-scaffold-check.sh. - Make the installed copy executable:
chmod +x ~/.claude/hooks/agent-os-scaffold-check.sh. - Patch
~/.claude/settings.jsonpatch-if-absent: add theUserPromptSubmithook entry only ifhooks.UserPromptSubmitis absent.- Read
~/.claude/settings.json. If it does not exist or is not valid JSON, skip the settings patch and print:Phase 8 settings patch skipped — ~/.claude/settings.json absent or invalid JSON; not modified. - If
hooks.UserPromptSubmitalready exists (any value), do not touch it. - If absent, add:
under the existing"UserPromptSubmit": [ { "matcher": "", "hooks": [ { "type": "command", "command": "~/.claude/hooks/agent-os-scaffold-check.sh" } ] } ]hooksobject (or createhooksif absent). Never overwrite any other hooks key. - Security constraint:
~/.claude/settings.jsonmay contain live secrets (ANTHROPIC_AUTH_TOKEN, API keys). Read, parse, patch one absent field, write back. Never log or surface secret values.
- Read
- Print a status block:
Phase 8: Global scaffold-check hook hook installed ~/.claude/hooks/agent-os-scaffold-check.sh UserPromptSubmit added | already present (unchanged) | skipped — settings.json absent or invalid
Decision (T78.1b, S78):
~/.claude/hooks/is an authorized write target for this skill. The scaffold-check hook is the only file this skill writes there. The "Do NOT modify~/.claude/hooks/" constraint below carries an explicit exception for this file.
Phase 9: Summary
Refresh complete: N installed, N renamed, N removed, N updated, N skipped.
Skills: <counts>. Agents: <counts>. Hooks: <counts>. CLAUDE.md: <N> reference(s) updated.
Agent OS updated. These changes apply globally — all projects on this machine now use the latest agents and skills.
Post-apply commit advisory (fires when at least one file was changed):
If any file was written, overwritten, renamed, or removed during Phase 5, surface:
Post-apply: N file(s) changed. Commit these changes now?
git add -A
git commit -m "chore: update-agent-os — sync to v<canonical-version>"
Reply `yes` to run this automatically, or run it manually.
If the user replies yes: run both git commands and print the resulting commit SHA.
If no files were changed during Phase 5: skip this block silently.
Phase 10: Post-Update Health Check
Runs automatically after Phase 5 whenever at least one action was applied.
- Confirm
skills-manifest.jsonrelease-versionmatches the canonical version surfaced in Phase 4. - Confirm the orchestrator skill exists at
claude/skills/orchestrator/SKILL.md. - Confirm
CLAUDE.mdcontains## Orchestrator Behavior.
Print result:
Post-update health check: PASS
Or if any check fails:
Post-update health check: FAIL — [specific check that failed]
A FAIL here does not block the summary — it is advisory, prompting the user to run /check-agent-os for full diagnosis.
Phase 11: CLAUDE.md Stale Reference Patch
Condition: Runs unconditionally on every update run (cheap read-only scan — no diff required).
Search CLAUDE.md for every renames[].from name. For each hit, show the line and proposed replacement. Apply only user-approved patches.
If CLAUDE.md is absent: print No CLAUDE.md in working directory — skipping stale-reference scan.
Coupled-file contract
update-agent-os (update path) and install-agent-scaffold (install path) govern the same distributed system from two directions. They are a coupled pair:
- Any change to how this skill treats a canonical field or file MUST be reflected in
install-agent-scaffold/SKILL.md, and vice versa, so install and update stay in sync. - Settings.json note: this skill patches canonical fields into
.claude/settings.jsononly when they are absent (worktree.baseRef, the standardStophook — see the patch-if-absent step) and never overwrites user-owned fields (permissions, allow/deny lists,mcpServers, custom hooks). The canonical tier is supplied once byinstall-agent-scaffold; this skill only adds a missing canonical default. Do not extend this skill to write or overwrite any user-owned field without an approved safety review. - QA directive: when either
update-agent-os/SKILL.mdorinstall-agent-scaffold/SKILL.mdis in a track's scope, the reviewer must open the coupled file and confirm it needs no matching change. Changing one without a recorded decision on the other is a review failure.
Hard Constraints
- Write targets are enumerated. This skill writes only to:
~/.claude/skills/<name>/SKILL.md~/.claude/agents/<name>.mddocs/context/connectors.md— Phase 6 symlink only; never created as a regular file.claude/hooks/<name>.sh(confirm-required per-hook)CLAUDE.md— reference updates only (Phase 5 and Phase 11, user-approved).claude/settings.json— Phase 7 patch-if-absent of canonical fields only (worktree.baseRef, standardStophook); never overwrites an existing value, never touches user-owned fields.~/.claude/hooks/agent-os-scaffold-check.sh— Phase 8 only; exception to the general~/.claude/hooks/prohibition. This is the single authorized global hook write. Decision recorded in T78.1b (S78).~/.claude/settings.jsonhooks.UserPromptSubmit— Phase 8 patch-if-absent only; adds the scaffold-check hook entry when absent; never overwrites if present.~/.claude/agent-os-manifest.json— global hash-manifest for skills and agents; written/updated by Phase 5 after all writes complete; upsert only (never removes entries for files not touched this run); created if absent..claude/agent-os-manifest.json— project hash-manifest for hooks; written/updated by Phase 5 after all writes complete; upsert only; created if absent.
- Never overwrite user-owned
.claude/settings.jsonfields (permissions, allow/deny lists,mcpServers, custom hooks). The only permitted.claude/settings.jsonwrites are Phase 7 patch-if-absent of canonical fields (worktree.baseRef, standardStophook) and Phase 8 patch-if-absent ofhooks.UserPromptSubmit. Never write any path not in the enumerated list above. - Never delete a file the user has not explicitly approved for removal.
CLAUDE.mdis never written by this skill except for approved rename-reference patches (Phase 5 and Phase 11). The legacy-format[claude.md]row is informational only — it never triggers a write, overwrite, or modification ofCLAUDE.md.- CLAUDE.md team table reconciliation rows require explicit user approval before edit. Never auto-update the team table.
- Phase 3 Diff must prefer the manifest's
renamesarray over any name-similarity heuristic. Heuristic is suggestion-only. - Compatibility window: never treat a missing-but-defaultable frontmatter field as a hard error.
- CLAUDE.md scan is conditional: fires only when diff contains at least one rename or removal.
- Phase 11 is unconditional: runs on every update run, regardless of whether the diff produced changes.
- Absent directories are created silently. No user message. No prompt. Error only if creation fails.
- Manifest cross-array invariant: if a name appears in both
renames[].fromand the canonicalskillsoragentsarray, canonical membership is authoritative — never propose rename or removal. Surface a one-line diagnostic.
Verification Checklist (Internal — Run Before Reporting Complete)
- Canonical source (GitHub) resolved before any prompt was shown; clear error surfaced if unreachable
- Stale registry check ran;
gastownhallURL detected and rewritten todesigngrapplerif present -
~/.claude/skills/and~/.claude/agents/existence checked; absent directories created silently - Release version read from manifest and surfaced before action table
- Phase 3 Diff run for skills and agents
- Cross-array invariant guard applied before each
renameslookup - Manifest invariant violations surfaced as diagnostics
- Compatibility-window check applied; missing-but-defaultable fields surfaced as drift, not errors
- CLAUDE.md scanned only when diff contains at least one rename or removal
- CLAUDE.md legacy format check ran (always fires); if
## Initialization LooporAGENTIC.mdreference found,[claude.md]informational row added to table - CLAUDE.md bridge-doc convention check ran (always fires); if
handoff-t,docs/context/handoff, orHandoff Bridgemarkers found,[claude.md]informational row added to table; row NOT included in any approval tier; no action taken in Phase 5 -
[claude.md]legacy format row NOT included in any approval tier; no action taken on it in Phase 5 - Retired-artifacts canonical diff executed: ~/.claude/agents/ and .claude/agents/ diffed against canonical agents[] array; .claude/skills/ diffed against canonical skills[] array (excluding renames[].from); path-structure artifacts checked via explicit bash; all RETIRED: lines surfaced in diff table
- Phase 4 enumerated table shown — all skills, agents, and hooks listed (not just affected rows); status values are New / Outdated / Current / Local-only
- If canonical hook set is empty, "Hooks: none in canonical manifest" printed; Hooks table omitted
- User confirmed before any file was modified
- Outdated rows were NOT covered by "Approve all" — each required individual confirmation
- Diff shown for each Outdated row before the user confirmed
- Phase 9 summary printed with per-type counts
- Phase 11 ran (unconditionally); CLAUDE.md checked against every renames[].from
- Phase 6 ran; connectors symlink created if ~/.claude/connectors.md present and docs/context/connectors.md absent; skipped silently otherwise
- Hooks phase: per-hook explicit confirmation required for each Outdated/New hook; no blanket "approve all" for hooks
- Hooks phase: no hook with Removed-from-canonical status auto-removed; default was Keep
- Hooks phase: no user-owned
.claude/settings.jsonfield (permissions,mcpServers, custom hooks) overwritten; any settings.json write was Phase 7 canonical patch-if-absent only - CLAUDE.md team table reconciliation ran when CLAUDE.md present; stale agent names surfaced as [claude.md] rows; user approval required before edit
- Post-apply commit advisory shown when at least one file was changed; git commands surfaced or executed on user approval
- Phase 3 three-way detection ran for every Outdated row; manifest read from the correct install tier (global
~/.claude/agent-os-manifest.jsonfor skills/agents; project.claude/agent-os-manifest.jsonfor hooks) - Three-way conflict rows surfaced with the conflict message, base-hash/local-hash disclosure, and explicit choose-side resolution prompt ("accept" or "keep"); not blind-overwritten
- Clean update rows (local-hash == base-hash, or no manifest entry) proceeded with standard per-file Outdated confirmation flow
- Absent manifest treated as first-install context; no error raised; all Outdated rows on that run treated as Clean update
- Phase 5 hash manifest written only after all writes complete (not per-file); not written if Phase 5 produced no writes
- Manifest entries use the installed file path as key; hash is SHA-256 computed from the written file immediately after write
- Manifest upsert preserves existing entries for files not touched this run; invalid JSON manifest skipped with advisory message