Agent

Survey claude_skill_owl legacy

Prompt:
Survey the legacy project at C:\Users\decid\Documents\projects\claude_skill_owl — this is the original Claude Code integration ("legacy spt" / owl plugin) that a new clean-room adapter `spt-claude-code` must reach FULL FEATURE PARITY with.

I need a structured inventory of EVERYTHING the Claude Code integration does, so I can scope a parity checklist. Be very thorough — look across multiple locations and naming conventions.

Report back:
1. **Top-level structure** — what kind of project is it (CC plugin? skill? binary? mix?), main dirs, languages.
2. **Claude Code integration surface** — every CC hook used (SessionStart, Stop, PreToolUse, UserPromptSubmit, etc.), slash commands / skills it ships, MCP servers, settings.json wiring, statusline, any CC-specific config.
3. **Feature inventory** — messaging, live-agent lifecycle (psyche/commune/signoff/echo), terminal hosting, networking/pairing, self-update, dormancy/wake, alarms, context injection, digest/history. For each: what it does + where it lives.
4. **The "skill"/command catalog** — list every slash command or skill the plugin exposes to a CC user (e.g. /spt:commune, /spt:live, etc.) with a one-line purpose each.
5. **Installer / packaging** — how it gets installed into Claude Code, marketplace, plugin manifest format, version.
6. **Anything that looks Claude-Code-specific** that an adapter would need to replicate (JSONL transcript parsing, session-id discovery, parent-pid/ancestor detection, env vars like $OWL/$SPT/$LIVE).

Give file paths as evidence. Aim for a complete parity-target inventory, grouped by the categories above. Don't dump whole files — excerpts + paths + conclusions.


<owl_reachability_notice>
You have an active owl perch. Launch this Agent with run_in_background: true so you stay reachable for incoming messages while it works.
</owl_reachability_notice>


Async agent launched successfully.
agentId: a6a631c6984fc0c35 (internal ID - do not mention to user. Use SendMessage with to: 'a6a631c6984fc0c35' to continue this agent.)
The agent is working in the background. You will be notified automatically when it completes.
Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.
output_file: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\a6a631c6984fc0c35.output
Do NOT Read or tail this file via the shell tool — it is the full subagent JSONL transcript and reading it will overflow your context. If the user asks for progress, say the agent is still running; you'll get a completion notification.

Survey claude_skill_owl legacy

Prompt:
Survey the legacy project at C:\Users\decid\Documents\projects\claude_skill_owl — this is the original Claude Code integration ("legacy spt" / owl plugin) that a new clean-room adapter `spt-claude-code` must reach FULL FEATURE PARITY with.

I need a structured inventory of EVERYTHING the Claude Code integration does, so I can scope a parity checklist. Be very thorough — look across multiple locations and naming conventions.

Report back:
1. **Top-level structure** — what kind of project is it (CC plugin? skill? binary? mix?), main dirs, languages.
2. **Claude Code integration surface** — every CC hook used (SessionStart, Stop, PreToolUse, UserPromptSubmit, etc.), slash commands / skills it ships, MCP servers, settings.json wiring, statusline, any CC-specific config.
3. **Feature inventory** — messaging, live-agent lifecycle (psyche/commune/signoff/echo), terminal hosting, networking/pairing, self-update, dormancy/wake, alarms, context injection, digest/history. For each: what it does + where it lives.
4. **The "skill"/command catalog** — list every slash command or skill the plugin exposes to a CC user (e.g. /spt:commune, /spt:live, etc.) with a one-line purpose each.
5. **Installer / packaging** — how it gets installed into Claude Code, marketplace, plugin manifest format, version.
6. **Anything that looks Claude-Code-specific** that an adapter would need to replicate (JSONL transcript parsing, session-id discovery, parent-pid/ancestor detection, env vars like $OWL/$SPT/$LIVE).

Give file paths as evidence. Aim for a complete parity-target inventory, grouped by the categories above. Don't dump whole files — excerpts + paths + conclusions.


it needs to be (C). `spt-claude-code` is, while still an independent project, the acceptance phase of `spt-core` v1. it needs to have full parity to legacy spt, which is in sister project `claude_skil…


Align spt-claude-code with spt-core v1 requirements


CONTEXT.md absorbed. Key reframe locked: spt-claude-code = the **"spt plugin" / `claude-spt` adapter** — first consumer of spt-core AND the v1 acceptance proof. Parity target = `claude_skill_owl` (modern SPT). Delegates core to `spt.exe`, holds all CC conventions (hooks, slash-commands, skill/plugin layout, `claude` invocation). spt-core holds zero CC conventions.

Dispatched a full parity-inventory survey of `claude_skill_owl` (running background) — that feeds the acceptance-bar question. Meanwhile, a question that doesn't depend on it:

---

**Q2 — Workflow carry-over: copy or re-author?**

Your ask #2 = carry the workflow style (traceable-reqs gating, JIT plans, grill-with-docs scaffolding). Two ways to hand it to perri:

| | What perri gets | Pro | Con |
|---|---|---|---|
| **Copy-as-template** | spt-core's `traceable-reqs.toml`, `docs/TRACEABILITY.md`, `DOCS-STRATEGY.md`, `CLAUDE.md`, `KNOWN-HAZARDS.md`, JIT-plan convention — copied into spt-claude-code, stripped to skeletons, re-seeded with CC-adapter REQs | perri starts running day 1; proven scaffolding; identical muscle-memory across projects | risk of dragging spt-core-specific content/assumptions in; needs careful scrub |
| **Re-author from principles** | A `WORKFLOW.md` charter describing the style + pointers; perri writes fresh files | clean fit, no spt-core leakage | slower; perri may drift from the proven shape; loses subtle hard-won rules |

My rec: **copy-as-template, scrubbed**. The whole value you're carrying is the *durable underbelly* — re-authoring throws away the exact thing that works. Copy the four process docs (TRACEABILITY, DOCS-STRATEGY, CLAUDE.md, a KNOWN-HAZARDS skeleton) + an empty-seeded `traceable-reqs.toml`, scrub every spt-core-specific reference, and leave REQ registry empty for perri to seed from the parity bar. JIT plans + grill-with-docs need no copying — they're conventions (CLAUDE.md rule) + an installed skill.

One nuance: this scaffolding is *meta-process*, not spt-core source — so copying it does **not** violate perri's "public-surface-only" constraint (that constraint governs spt-core *product* knowledge, not how-we-work docs). Worth stating explicitly to perri so there's no confusion.

Copy-as-template (scrubbed), re-author, or a split?


<task-notification>
<task-id>a6a631c6984fc0c35</task-id>
<tool-use-id>toolu_01VG2966RR2cyZ2Ni922CSHv</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\a6a631c6984fc0c35.output</output-file>
<status>completed</status>
<summary>Agent "Survey claude_skill_owl legacy" completed</summary>
<result>Perfect. Now I have a comprehensive view. Let me compile the full parity inventory:

---

## COMPREHENSIVE LEGACY SPT PLUGIN PARITY INVENTORY

Based on systematic survey of `/c/Users/decid/Documents/projects/claude_skill_owl` (version 1.11.25, Rust binary + plugin architecture).

---

### 1. TOP-LEVEL STRUCTURE

**Project Type:** Claude Code plugin (`spt`) shipping a single statically-compiled Rust binary + skill manifests + hook definitions.

**Main Directories:**
- `src/` — Rust source (54 .rs files, ~12k LOC)
  - `src/main.rs`, `src/cli.rs` — CLI dispatcher and argument parsing
  - `src/owl/` — messaging substrate (send, poll, setup, registry, lifecycle)
  - `src/live/` — live-agent system (psyche wrapper, communes, pulses, signoff)
  - `src/common/` — shared: owlery management, envelope parsing, spool (SQLite), listener, registry, types, protocol
- `plugin/spt/` — plugin manifest and bundled content
  - `.claude-plugin/plugin.json` — plugin metadata (name, version 1.11.25, description)
  - `hooks/hooks.json` — CC hook registration (7 hooks: SessionStart, SessionEnd, PreToolUse, Stop, UserPromptSubmit, SubagentStart, SubagentStop)
  - `skills/*/` — skill definitions (10 skills: `/spt:live`, `/spt:commune`, `/spt:ready`, `/spt:send`, `/spt:signoff`, `/spt:revive`, `/spt:clear-psyche`, `/spt:force-stop`, `/spt:list-agents`, `/spt:new-alarm`, `/spt:whoami`, `/spt:psyche-sync-setup`)
  - `owl.exe` — compiled binary (deployed here)
- `psyche.md` — embedded prompt (included via `include_str!` at compile time) teaching Psyche agent behavior
- `.planning/` — GSD planning artifacts (architecture docs, CONTEXT, STACK, INTEGRATIONS, CONVENTIONS)
- `tests/` — integration tests (native_owl.rs, handoff_integration.rs, hook_chain.rs, doctor_orphan_fix.rs)
- `Cargo.toml` — Rust manifest with deps: clap, serde, chrono, rusqlite, ctrlc, platform-specific (libc/windows-sys)

**Languages:** Rust (100% runtime), Markdown (docs + skills + psyche.md prompt)

---

### 2. CLAUDE CODE INTEGRATION SURFACE

#### **Hooks** (7 total, registered in `plugin/spt/hooks/hooks.json`):

1. **SessionStart** → `owl.exe plugin-session-start`
   - Injects `$OWL` and `$LIVE` env vars into `CLAUDE_ENV_FILE`
   - Captures session UUID from Claude stdin
   - Runs version trampoline (finds newest owl.exe in plugin cache dirs)
   - Delegates to session-resume logic (identity binding)
   - **Source:** `src/owl/plugin_session_start.rs` (D-03/D-04: auto-pick emission predicate)

2. **SessionEnd** → `owl.exe cleanup-session`
   - Cleans up session state (perch removal, cache clearing)
   - **Source:** `src/owl/stop.rs` and related cleanup logic

3. **PreToolUse** → `owl.exe hook-check`
   - Reads hook stdin JSON (session_id, agent_id, stop_hook_active flag)
   - Finds matching perch by session_id or parent_pid
   - Injects inbound messages into working perch for subagents
   - Returns XML `<owl_messages>` envelope if messages pending
   - **Source:** `src/owl/hook_prompt.rs` + `src/common/hook_output.rs`

4. **Stop** (idle_prompt/Notification) → `owl.exe hook-idle`
   - Fired when user is idle or session ends cleanly
   - Triggers echo-commune cadence (background Haiku synthesis)
   - **Source:** `src/owl/hook_idle.rs`

5. **UserPromptSubmit** → `owl.exe hook-prompt`
   - Fires after user submits prompt (fires-and-forgets async pull for psyche-sync-setup)
   - **Source:** `src/owl/hook_prompt.rs`

6. **SubagentStart** → `owl.exe hook-subagent-start`
   - Reads stdin JSON (agent_id, session_uuid, agent_type)
   - Creates working perch directory under Self's nested/
   - Writes subagent context (parent ID, perch info)
   - **Source:** `src/owl/hook_subagent_start.rs`

7. **SubagentStop** → `owl.exe hook-subagent-stop`
   - Tears down working perch for finished subagent
   - **Source:** `src/owl/hook_subagent_stop.rs`

#### **Env Vars** (auto-injected at SessionStart via CLAUDE_ENV_FILE):

- `$OWL` → `owl.exe` (points to plugin binary)
- `$LIVE` → `owl.exe live` (live-agent subcommand prefix)
- `OWL_SESSION_ID` — Claude session UUID (read from SessionStart hook stdin, written to info.json)
- `OWL_ECHO_COMMUNE` — gate to prevent recursion in echo-commune spawns
- `OWL_SKIP_RESUME` — opt-out for scripted/team sessions
- `OWL_HANDOFF_CHILD` — set during binary handoff (version upgrade mid-session)
- `SPT_TRAMPOLINE_GUARD` — guard against runaway exec loop during handoff
- `SPT_TRACE` — gated debug logging (stderr when `SPT_TRACE=1`)

#### **Settings Integration:**

- Non-plugin mode: `auto_setup()` creates/updates `~/.claude/settings.json` with OWL/LIVE env vars + SessionStart/SessionEnd hooks
- Plugin mode: hooks.json and CLAUDE_ENV_FILE are the authoritative source; settings.json changes are not needed
- **Source:** `src/common/auto_setup.rs`

#### **Status Line / Output Convention:**

- Status messages → **stderr** (ANSI-colored: cyan for owl, orange for live)
- Message bodies → **stdout** (one `<EVENT>` line per message in stream mode)
- Status tags: `READY:{id}`, `SENT:{id}`, `STOPPED:{id}`, `CLEANED:{id}`, `DUPLICATE:{id}`, `STALE:{id}`, etc.
- Sync tags (psyche-sync-setup): `PUSHED:{branch}`, `RECONCILED:{branch}`, `DIVERGED:{branch}`, `PUSH_FAILED:{branch}`
- **Source:** `src/common/output.rs`

---

### 3. FEATURE INVENTORY

#### **A. Core Messaging (owl subsystem)**

**Perch Registration & Identity** (`src/owl/setup.rs`, `src/common/owlery.rs`)
- Perches are agent identity anchors: directories under `$SPT_HOME/owlery/` (or nested under parent's `nested/` since Phase 25)
- Each perch contains:
  - `info.json` — metadata (owl_id, parent_pid, session_id, live flag, mode, project_history, timestamps)
  - `ready` — sentinel file marking perch as alive
  - `spool.db` — SQLite queue for offline messages
  - `inbox/` — legacy fallback message directory
  - `.registry` — global TCP address lookup (symlink under owlery root)

**Message Delivery** (`src/owl/send.rs`, `src/common/protocol.rs`)
- **TCP transport** (primary): fast push-based, requires target listener alive
  - Registry lookup → TCP connect with 2s timeout → send framed message
  - Listener via `PollListener` (platform-aware: libc::poll on Unix, WSAPoll on Windows)
- **SQLite spool** (fallback): durable per-perch queue, pull-based
  - Message table: (id, from_id, body, created_at, ttl_seconds, delivered, deferred)
  - Deferred flag (`--deferred` flag) for async delivery without TCP wake
- **Inbox directory** (legacy compatibility): still written to for backward compat

**Messaging Verbs:**
- **send** — fire-and-forget to target; `--reply-to <sender>` for replies; `--deferred` for spool-only (no TCP)
- **ring** / **ask** — send + blocking wait for reply (creates ephemeral perch if caller has none)
- Incoming messages parsed as `__REPLY_TO__:{sender}\n{body}` when they are replies

**Polling & Liveness** (`src/common/listener.rs`, `src/owl/poll.rs`)
- `poll` subcommand: bind TCP listener, register in registry, accept connections
- Stream mode (default): long-running, emits `<EVENT>` envelope per message
- Once-mode (legacy): exit after one message
- Pulse interval: optional wake-on-timeout to emit `PULSE_TRIGGER` sentinel
- **Source:** `src/common/listener.rs` (poll_ready = OS poll syscall)

**Registry** (`src/common/registry.rs`)
- SQLite db at `~/.spt/owlery/.registry`
- Stores: (id TEXT, address TEXT, pid INTEGER, started TEXT)
- Lookup by agent ID → TCP address for push delivery
- Cleanup: removes stale entries (dead PIDs)

**Presence & Liveness Check** (`src/common/types.rs`)
- `check_alive()` — verifies perch has `ready` file AND PID is alive (or parent_pid is alive = "between polls")
- Fallback: parent_pid check handles cases where poll listener is temporarily not running
- `is_process_alive()` — platform-aware: Windows (ToolHelp32Snapshot) vs Unix (kill -0)

#### **B. Session Binding & Resumption**

**Parent-PID Binding** (`src/owl/resume.rs`, `src/common/hook_output.rs`)
- SessionStart hook calls `session-resume` which:
  1. Scans all perches in owlery
  2. Matches against current process's Claude Code parent PID
  3. Returns matching perch ID as XML `<owl-auto-resume>` block
- Fallback: matches by `session_id` in info.json (populated from OWL_SESSION_ID env var)
- **Session cache** (D-08): file at `~/.spt/owlery/.session-cache` (tabs: session_id\towl_id) avoids O(N) rescans on every PreToolUse

**Context Injection** (`src/owl/resume.rs`)
- SessionStart emits XML blocks teaching user their prior identity
- Prints skill context for active perches (ready agent vs live agent)
- Guards: skips injection for agent-mode sessions, team members, compaction

#### **C. Live-Agent Lifecycle**

**Live Agent** = Self (Claude Code session) + Psyche (wrapper process) pair

**Self** — the user-facing CC session
- Runs a poll listener (`poll --live --psyche`)
- Has a perch with `live: true` in info.json
- Can commune with Psyche (write `.claude/{id}-commune.md`, wrapper detects + delivers)
- Can send messages to other agents via `$OWL send`
- Receives messages via Monitor stream EVENT envelopes or PreToolUse hook XML

**Psyche Wrapper** (`src/live/wrapper/mod.rs`, `src/live/start.rs`)
- Detached supervisor process owned by Self
- Spawned by `$LIVE start <id>`
- Runs loop:
  1. Poll own perch (psyche ID = `{self_id}-psyche`)
  2. On message/pulse/commune: invoke `claude -p --resume {self_id}-psyche` with stdin payload
  3. Parse Psyche output for markers ([REPLY], [NOTIFY], [COMMUNE])
  4. Deliver messages back to Self or other agents
  5. Check for orphan condition (Self perch stale + grace period expired)
- State file: `wrapper-state.json` for binary handoff (gen, self_id, period, etc.)
- **Orphan detection** (Phase 27): if Self perch is stale for `PHASE35_LIST_ORPHAN_GRACE_SECS` (60s), wrapper sends `INIT_SIGNOFF` and exits
- **Source:** `src/live/wrapper/lifecycle.rs`, `src/live/wrapper/orphan.rs`

**Generation Counter** (`src/common/types.rs`)
- Increments every `/spt:live start` or `/spt:revive`
- Passed to Psyche via `--resume` session context so Psyche knows it's a new continuation

**Communes** (`src/live/commune.rs`, `src/owl/echo_commune.rs`)
- **User commune**: Self writes `.claude/{self_id}-commune.md` (manual context update)
  - Wrapper detects file, reads body, packages as `<EVENT type="commune">` envelope
  - Sends to Psyche perch spool
  - Deletes file on success
- **Echo commune**: background Haiku synthesizes delta (automated summary)
  - Triggered by Stop hook (cadence: wraps up session summary) or `/clear` (reorientation)
  - Haiku reads `.claude/` transcript JSONL, synthesizes activity delta
  - Routed to `_echo-commune` hidden subcommand for Psyche delivery
  - **Split variant** (Phase 29): delivers to both Psyche AND Self (post-clear rehydration)
  - **Forward-to-self flag**: controls whether echo-commune brief goes to Self's inbox
- **Source:** `src/live/commune.rs`, `src/owl/echo_commune.rs`

**Pulses** (`src/live/pulse_wait.rs`)
- Wrapper emits `PULSE_TRIGGER ({timestamp})` on cadence (default ~60s)
- Psyche receives trigger, evaluates context, nudges Self if warranted (or silent)
- `$LIVE pulse-wait <seconds>` — user-side blocking wait for next pulse
- **Alarms** (formerly TIMED_PULSE): scheduled one-shot reminders created via `/spt:new-alarm` / `$OWL new-alarm`
  - Stored in wrapper's pulse loop tracking
  - Fired on scheduler tick, delivered as `<EVENT type="alarm">` to Self
  - Requires Psyche wrapper (not available on ready agents)
  - **Source:** `src/owl/new_alarm.rs`, `src/live/pulse_wait.rs`

**Signoff** (`src/live/signoff.rs`, `src/owl/signoff.rs`)
- Graceful live-agent shutdown: `/spt:signoff` or `$LIVE signoff <id>`
- Self writes `.claude/{self_id}-signoff.md` (optional final commune message)
- Wrapper detects, downloads Psyche context (via `psyche-download`), packages as `INIT_SIGNOFF` control message
- Wrapper routes final context slice to tracked/ worktrees (live_context.md, project-context per CONTEXT.md D-11)
- Wrapper exits cleanly
- **AmendSignoff** (Phase 33): post-signoff notation (`live amend-signoff {id} <message>`) for additional context

**Revive** (`src/live/start.rs`, `src/live/fork.rs`)
- `/spt:revive <id>` — restart wrapper + Psyche with new generation (keeps same Psyche context file)
- `/spt:fork <src> <new_id>` — clone one agent's psyche.md to a new ID and start
- Both increment generation counter automatically

#### **D. Psyche Agent System**

**Psyche.md Embedded Prompt** (`psyche.md`, ~600 lines)
- Teaches Psyche agent decision tree: commune handler, echo-commune handler, pulse-trigger, schedule-pulse, init-signoff, messages from other agents
- Passive context blocks: OUTSTANDING_PULSES (scheduled alarms), ambient state snapshots
- Communication markers: [REPLY], [NOTIFY], [COMMUNE] (parsed by wrapper)
- Two-slice envelope tags: `<live-context>`, `<project-context>` (Phase 25: routed to different worktrees)

**Psyche Context Storage** (`src/common/tracked.rs`)
- Layout: `$SPT_HOME/psyches/tracked/`
  - `seed/` — bare git repo (bootstrap commit)
  - `agents/{id}/` — linked worktree, branch `a-{id}`
  - `projects/{name}/` — linked worktree, branch `p-{name}` (lazy per Phase 25 D-16)
- Each agent has `{id}.md` file (Psyche's persistent context) + optional `{id}-memformat.xml` (legacy memory format)
- **Psyche download** (`src/live/start.rs`): fetches current state for display/decision-making at session start
- **Psyche clear** (`src/live/start.rs`): wipes psyche.md (user-facing `/spt:clear-psyche`)
- **Source:** `src/common/tracked.rs` (bootstrap, worktree creation, versioning)

**Version Control** (via system `git`, no bundled git)
- Every write to Psyche context creates a git commit
- Trigger types (D-10): `boot` (start), `pulse` (periodic), `commune` (update), `signoff` (final)
- Fallback: if git unavailable, writes are non-versioned (D-02)

#### **E. Working Perches & Subagent Communication**

**Working Perch** (`src/owl/hook_subagent_start.rs`, `src/common/perch_path.rs`)
- Created by SubagentStart hook for each subagent of a live Self
- Path: nested layout (Phase 25) — `$SPT_HOME/owlery/{self_id}/nested/{subagent_id}/`
- Lifetime: created at subagent start, torn down at SubagentStop
- Purpose: enables Self ↔ Subagent message delivery during subagent turn
- Perch-path resolver (`src/common/perch_path.rs`): handles both flat (legacy) and nested (Phase 25+) layouts

**PreToolUse Hook Message Injection** (`src/owl/hook_check.rs`)
- Hook reads working perch's spool
- Injects pending messages as XML `<owl_messages>` block in subagent's context
- Subagent processes and replies via `$OWL send --reply-to {sender}`

#### **F. Session Cleaning & State Management**

**CleanupSession** (`src/owl/stop.rs`)
- SessionEnd hook cleanup
- Removes session cache entries
- Marks perch as stale if no active listener
- Called by `cleanup-session` subcommand

**Doctor/Health Check** (`src/owl/doctor.rs`)
- `owl doctor [--fix]` — diagnoses stale perches, registry corruption, orphaned state
- Fix mode: cleans up dead perches, registry entries

#### **G. Dormant / Unimplemented Features**

**Spine & Touch** (dormant, implemented but never invoked in standard flow)
- Spine: would be supervisor agent monitoring all live agents + wrappers
- Touch: would monitor one specific live agent
- Implemented in `src/live/boot_spine.rs`, `src/cli.rs`, but not called by any standard command
- **Source:** `src/cli.rs` hidden commands `_spine-wrapper`, `_touch-wrapper`

**Capsule** (planned v1.9, not implemented)
- Would launch Claude Code inside psmux terminal session
- Allows keystroke injection instead of waiting for agent to poll
- Designed for full remote control (networked messaging)

**Networked Messaging** (planned, research phase)
- Current: single-machine only (hardcoded to localhost:127.0.0.1)
- Planned: cross-machine subnet via spt-node daemon (Ed25519 keypair per machine)
- **Source:** CONTEXT.md networking vocabulary section + `docs/research/` (referenced but not fully present)

#### **H. Binary Handoff** (Phase 18.4/18.5)

**Self-Migration at Deploy Time**
- When new owl.exe is installed, running processes detect version mismatch
- Old process spawns new binary as child, relays stdio (parent CC session sees no interruption)
- New process takes over polling/wrapping with rehydrated state
- Psyche wrapper: rehydrates from `wrapper-state.json` (gen, self_id, period, session_name)
- **Trampoline guard** (SPT_TRAMPOLINE_GUARD env var): prevents runaway exec loop
- **Source:** `src/main.rs` (trampoline_exec), `src/common/handoff.rs`, `src/common/wrapper_state.rs`

#### **I. Cross-Machine Sync** (Phase 35, psyche-sync-setup)

**Psyche Sync Setup** (`src/owl/psyche_sync_setup.rs`)
- `/spt:psyche-sync-setup [--disable]` — enables/disables cross-machine Psyche context sync
- Creates private GitHub repo `spt-agent-storage`
- Wires as `origin` remote for `psyches/tracked/` worktrees
- Pushes all branches on setup
- Async pull on UserPromptSubmit (fire-and-forget detached child)
- **Source:** `src/owl/psyche_sync_setup.rs`, `src/owl/sync_prompt.rs` (UserPromptSubmit async pull)

#### **J. Marketplace & Installation**

**CPlugs Marketplace Integration**
- Plugin published to `cplugs` marketplace
- Installed via `claude plugin install spt@cplugs`
- Manual deployment: `docs/DEPLOY.ps1` (Windows) — builds, syncs binary + skills + hooks, runs plugin install
- **Source:** `docs/DEPLOY.md`, `docs/DEPLOY.ps1` (PowerShell script)

---

### 4. SKILL / COMMAND CATALOG

All skills exposed to user as `/spt:<name>`:

| Skill | Purpose | Allowed Tools | Key Args |
|-------|---------|---------------|----------|
| `/spt:live` | Start/manage live agent session | Bash, Read, Monitor, AskUserQuestion | `<id>`, `--period`, `--pulse-psyche` |
| `/spt:commune` | Send context update to Psyche | Bash, Read, Write | `[self_id]` (auto-detected) |
| `/spt:ready` | Start/listen as ready agent (no Psyche) | Bash, Read, Monitor | `<id>`, `--reboot`, `--block`, `--once` |
| `/spt:send` | Fire-and-forget message delivery | Bash, Read | `<target>`, `[--block]` |
| `/spt:signoff` | Graceful live-agent shutdown | Bash, Write | `[id]` (auto-detected) |
| `/spt:revive` | Restart live agent with new gen | Bash, Read, Monitor | `<id>`, `[--period]`, `[--pulse-psyche]` |
| `/spt:clear-psyche` | Wipe Psyche context | Bash | `[self_id]` (auto-detected) |
| `/spt:force-stop` | Kill agent/Psyche immediately | Bash | `[<id>]` / `--all` |
| `/spt:list-agents` | List ready/live agents + Psyches | Bash | `[--all]`, `[--offline]`, `[--here]`, `[--psyches]` |
| `/spt:new-alarm` | Schedule one-shot timed reminder | Bash | `<time_spec>` `--` `<message>` |
| `/spt:whoami` | Identify self from session | Bash | none |
| `/spt:psyche-sync-setup` | Enable cross-machine sync | Bash, AskUserQuestion | `[--disable]` |

**Hidden/System Commands** (not user-facing skills):
- `$OWL setup <id> [mode]` — register perch
- `$OWL poll <id> [--live] [--psyche] [--setup] [--once] [--pulse-interval N] [--session-id UUID]` — listen for messages
- `$OWL send <target> [from] [--reply-to X] [--deferred]` — deliver message
- `$OWL ring <target> [from]` — send + wait for reply
- `$OWL list [--all] [--offline] [--here] [--verbose]` — enumerate perches
- `$OWL whoami` — identify self
- `$OWL stop [id] [--all]` — stop agent
- `$OWL reboot [id]` — restart agent
- `$OWL doctor [--fix]` — health check
- `$LIVE start <id> [--period N] [--pulse-psyche]` — spawn Psyche wrapper
- `$LIVE stop [id] [--all]` — kill wrapper
- `$LIVE list [--all] [--offline] [--here] [--verbose]` — list live agents
- `$LIVE commune [self_id]` — send commune to Psyche (reads stdin)
- `$LIVE psyche-download [self_id]` — fetch Psyche state
- `$LIVE clear-psyche [self_id]` — wipe context
- `$LIVE revive <id> [--period N] [--pulse-psyche]` — restart with new gen
- `$LIVE fork <src> <new_id> [--period N] [--pulse-psyche]` — clone agent
- `$LIVE signoff [id] [--message "text"]` — graceful shutdown
- `$LIVE amend-signoff <self_id> <message>` — post-signoff notes
- `$LIVE pulse-wait <seconds>` — block until next pulse

---

### 5. INSTALLER / PACKAGING

**Plugin Manifest** (`plugin/spt/.claude-plugin/plugin.json`)
```json
{
  "name": "spt",
  "version": "1.11.25",
  "description": "Spacetime agent messaging and live agent system for Claude Code",
  "author": { "name": "todlando" },
  "keywords": ["messaging", "agents", "live", "owl"]
}
```

**Deployment Process:**
1. Build: `cargo build --release` → `target/release/owl.exe`
2. Deploy script: `docs/DEPLOY.ps1` (Windows PowerShell)
   - Compiles binary
   - Syncs `owl.exe` to plugin cache dir
   - Copies `plugin/spt/skills/` and `plugin/spt/hooks/` manifests
   - Updates `plugin.json` version
   - Runs `claude plugin install spt@cplugs`
   - (User must manually run `/reload-plugins`)
3. Installation: delivered via CPlugs marketplace; plugin manager handles placement in `~/.claude/plugins/cache/cplugs/spt/`

**Version Tracking:**
- Single source of truth: `Cargo.toml` (name = "owl", version = "1.11.25")
- Plugin metadata synced to `plugin/spt/.claude-plugin/plugin.json`
- CHANGELOG: extensive commit history in `CHANGELOG.md` (130K+, 1300+ entries)

---

### 6. CLAUDE-CODE-SPECIFIC INTERNALS

#### **Env Var Discovery & Injection**

**CLAUDE_PLUGIN_ROOT** (env var)
- Set by Claude Code when running hooks
- Allows auto_setup() to skip if plugin is installed (hooks.json + CLAUDE_ENV_FILE are authoritative)
- **Source:** `src/main.rs` auto_setup guard

**CLAUDE_ENV_FILE** (Claude-managed file)
- Path: `~/.claude/session-env.json` (managed by Claude Code)
- SessionStart hook writes `$OWL` and `$LIVE` environment variable assignments
- Parsed by Claude Code to inject vars into subprocess environ
- **Source:** `src/owl/plugin_session_start.rs` (writes via helper)

**CLAUDE_CODE_TEAM_NAME** (env var)
- Set when running as team agent
- Guard: session-resume skips output when this is set (D-08-a, team members don't get injected context)
- **Source:** `src/owl/resume.rs`

#### **Session ID Binding**

**Session UUID** (Claude Code generates per-session UUID, ephemeral)
- Read from SessionStart hook stdin JSON: `{"session_id": "...UUID..."}`
- Stored in perch `info.json` under `session_id` field
- Used to match subsequent hook calls to the right perch
- **Lifetime:** changes on `/clear` and after crashes (but parent PID is more stable)
- **Fallback:** parent_pid matching when session_id is missing/stale

**OWL_SESSION_ID** (env var)
- SessionStart hook reads Claude session_id from stdin, exports as env var
- Binary handoff uses this to re-establish session state
- **Source:** `src/owl/plugin_session_start.rs`

#### **Process Tree Detection**

**Parent PID Binding**
- At perch registration: `info.json` records `parent_pid` = current CC process's parent PID
- SessionStart hook: walks perches, matches current process's parent_pid against `parent_pid` fields
- Effect: session-resume can identify "which agent am I?" across `/clear` and crashes (since CC process itself stays alive)
- **Source:** `src/common/types.rs` (get_parent_pid, is_process_alive), `src/owl/resume.rs`

**Ancestor Detection** (for working perches)
- SubagentStart hook: extracts parent CC pid, creates working perch with explicit parent_id hint
- **Source:** `src/owl/hook_subagent_start.rs`, `src/common/perch_path.rs`

#### **JSONL Transcript Parsing** (for echo-commune)

**Echo Commune Processing** (`src/owl/echo_commune.rs`)
- Spawns Haiku agent with JSONL transcript read from `.claude/` session history
- Haiku synthesizes activity delta (what was accomplished since last commune)
- Writes output to stdout; wrapper parses for:
  - Two-slice envelope: `<live-context>` and `<project-context>` tags
  - Markers: `[REPLY]`, `[NOTIFY]`, `[COMMUNE]` (in Psyche.md context, not here)
- Routes slices to tracked/ worktrees (live_context.md per agent, project context per project_name)
- **Source:** `src/owl/echo_commune.rs`, `src/common/envelope.rs` (parse_two_slice)

#### **Message Envelopes** (Claude Code event format)

**EVENT Format** (primary message transport via Monitor stream)
```xml
<EVENT type="msg" from="sender_id">
message body here
</EVENT>
```

**REPLY_TO Format** (special handling)
```
__REPLY_TO__:{sender_id}
message body
```

**Psyche-Specific Envelopes**
```xml
<EVENT type="commune" from="self_id">
<EVENT type="echo_commune" from="self_id-psyche">
<EVENT type="alarm">
```

**owl_messages XML** (PreToolUse hook output for subagents)
```xml
<owl_messages>
<EVENT type="msg" from="sender_id">body</EVENT>
...
</owl_messages>
```

**Auto-Pick Block** (Phase 33: SessionStart conditional emission)
```xml
<spt-live-auto-pick>
...picker spec (AskUserQuestion JSON)...
</spt-live-auto-pick>
```

**Resume Context** (SessionStart SessionResume output)
```xml
<owl-auto-resume id="..." live="true/false">
...context for restoring agent identity...
</owl-auto-resume>
```

**Active Perch Injection** (SessionStart active session warning)
```xml
<owl-active-perch id="..." live="true/false">
...instructions for active agent...
</owl-active-perch>
```

#### **Hook Input JSON Schema**

**SessionStart / PreToolUse / Stop hook stdin:**
```json
{
  "session_id": "uuid-string-or-null",
  "agent_id": "string-or-null",
  "agent_type": "string-or-null",     // for Psyche wrapper detection
  "source": "startup|clear|compact",  // SessionStart context
  "stop_hook_active": false           // Stop hook recursion guard (Phase 34)
}
```

**SubagentStart hook stdin:**
```json
{
  "agent_id": "subagent-id",
  "session_uuid": "parent-session-uuid",
  "agent_type": "string"  // e.g. "psyche-wrapper"
}
```

---

### 7. RUNTIME STATE LOCATIONS

**State Root** (overrideable via `SPT_HOME` env var)
- Windows: `%LOCALAPPDATA%\spt\owlery\` (typically `C:\Users\{user}\AppData\Local\spt\owlery\`)
- Unix: `~/.spt/owlery/`

**Owlery Structure**
```
owlery/
├── {self_id}/
│   ├── info.json           (metadata: owl_id, parent_pid, session_id, live, psyche, mode)
│   ├── ready               (marker file, exists iff agent is registered)
│   ├── spool.db            (SQLite: messages table)
│   ├── status              (current state info, human-readable)
│   ├── nested/
│   │   ├── {psyche_id}/    (Psyche perch, Phase 25 nested layout)
│   │   │   ├── info.json
│   │   │   ├── ready
│   │   │   └── spool.db
│   │   └── {worker_id}/    (subagent working perch, temporary)
│   │       ├── info.json
│   │       └── spool.db
│   └── inbox/              (legacy fallback, still written to)
│       └── {message-files}
├── {another_id}/           (second agent, same structure)
├── .registry               (SQLite: agents table with TCP addresses)
├── .session-cache          (tab-separated session_id -> owl_id mappings)
└── node.key                (Ed25519 public key, planned for networking)
```

**Psyche Context Storage** (tracked worktrees)
```
psyches/tracked/
├── seed/                   (bare git repo, bootstrap commit)
├── agents/
│   └── {agent_id}/         (linked worktree, branch a-{id})
│       └── {agent_id}.md   (Psyche context, persistent)
└── projects/
    └── {project_name}/     (linked worktree, branch p-{name})
        └── {agent_id}.md   (Project-scoped context per agent)
```

**Session Tracking** (`~/.claude/`)
```
.claude/
├── LIVE_AGENT_IDS.json     (version 2 format: { "ids": [{id, last_active}, ...], "last_used": "..." })
├── session-env.json        (CLAUDE_ENV_FILE written by SessionStart hook)
└── worktrees/              (GSD workspace roots, tracked separately)
```

**Alarm/Pulse Files** (in psyche wrapper state)
- Wrapper maintains in-memory scheduler
- Writes persistent state to `wrapper-state.json` at perch root
- On startup: loads from JSON and resumes scheduler

---

### 8. VERSION HISTORY & MIGRATION

**Current Version:** 1.11.25 (as of 2026-06-02)

**Notable Phases (from CHANGELOG.md):**
- **Phase 25** (nested perch layout): migrated from flat `owlery/{id}/` to `owlery/{self_id}/nested/{psyche_id}/` and `{worker_id}/`
- **Phase 24** (tracked worktrees): `psyches/tracked/` git-versioned Psyche context + lazy worktree creation
- **Phase 29** (echo-commune split): dual-dispatch split echo-commune to both Psyche and Self post-clear
- **Phase 33** (auto-pick): SessionStart conditional emission of live-agent picker spec (AskUserQuestion)
- **Phase 34** (Stop-hook recursion): recursion guard (`stop_hook_active` flag) for block-loop prevention
- **Phase 35** (psyche-sync-setup): cross-machine GitHub repo sync for Psyche context

**Backward Compatibility:**
- Flat layout (legacy) still recognized and resolved by perch_path resolver
- Envelope parser (Phase 25 two-slice): falls back to whole-body routing if tags missing (back-compat for old psyche.md)
- Deferred messages flag added post-hoc (ALTER TABLE non-breaking)

---

### 9. INTEGRATION TESTING & VALIDATION

**Test Structure** (`tests/`)
- `native_owl.rs` — native Rust integration tests (setup, poll, send, list)
- `handoff_integration.rs` — binary handoff trampoline (exec replacement)
- `hook_chain.rs` — full hook sequence (SessionStart → PreToolUse → Stop)
- `golden_owl.rs`, `golden_live.rs` — golden-file diff tests (excluded from Windows CI, captured via bash)
- `doctor_orphan_fix.rs` — orphan detection + grace-period handling (Phase 35)

**Test Data:** `tests/golden/` (captured output fixtures for diff testing)

---

## SUMMARY: PARITY CHECKLIST FOR `spt-claude-code` ADAPTER

A clean-room adapter implementing **FULL FEATURE PARITY** must:

**Core Messaging:**
- [x] Perch registration with info.json + ready sentinel
- [x] TCP listener with OS-level poll (libc::poll / WSAPoll) for accept timeout
- [x] SQLite spool with messages table + TTL + delivered + deferred flags
- [x] Registry lookup and delivery (TCP primary, spool fallback)
- [x] Message framing protocol (wire format)
- [x] Parent-PID binding for session resumption

**Live Agent System:**
- [x] Psyche wrapper spawning (detached process)
- [x] Wrapper state rehydration (wrapper-state.json)
- [x] Generation counter tracking
- [x] Commune file detection + delivery (wrapped in EVENT envelope)
- [x] Echo-commune spawning (Haiku synthesis)
- [x] Psyche.md embedding + resume invocation
- [x] Orphan detection (liveness check on Self's perch)
- [x] Graceful signoff (INIT_SIGNOFF protocol)
- [x] Psyche context storage (tracked/ worktrees with git versioning)

**Claude Code Hooks:**
- [x] SessionStart hook: env var injection, session-resume, auto-pick emission
- [x] SessionEnd hook: cleanup-session
- [x] PreToolUse hook: working-perch message injection
- [x] Stop hook: echo-commune cadence trigger
- [x] UserPromptSubmit hook: async psyche-sync pull
- [x] SubagentStart hook: working perch creation
- [x] SubagentStop hook: working perch teardown

**Skills & User Commands:**
- [x] `/spt:live`, `/spt:commune`, `/spt:ready`, `/spt:send`, `/spt:signoff`, `/spt:revive`
- [x] `/spt:clear-psyche`, `/spt:force-stop`, `/spt:list-agents`, `/spt:new-alarm`, `/spt:whoami`
- [x] `/spt:psyche-sync-setup` (GitHub cross-machine sync)

**Env Vars & State:**
- [x] `$OWL` and `$LIVE` auto-injection
- [x] `OWL_SESSION_ID`, `OWL_ECHO_COMMUNE`, `OWL_SKIP_RESUME`, `OWL_HANDOFF_CHILD`, `SPT_TRAMPOLINE_GUARD`
- [x] `SPT_TRACE` gated logging
- [x] Session-to-perch cache (fast hook lookup)
- [x] Session state cleanup + LIVE_AGENT_IDS.json tracking

**Message Envelopes:**
- [x] `<EVENT>` wrapper (msg, commune, echo_commune, alarm types)
- [x] `<owl_messages>` block (PreToolUse injection)
- [x] `<owl-auto-resume>` XML (SessionStart context)
- [x] `<owl-active-perch>` warning block
- [x] `<spt-live-auto-pick>` picker spec (conditional)
- [x] Two-slice envelope parsing (`<live-context>`, `<project-context>`)

**Advanced Features:**
- [x] Binary handoff (version upgrade mid-session)
- [x] Working perches + subagent communication
- [x] Cross-machine Psyche sync (psyche-sync-setup)
- [x] Nested perch layout (Phase 25) + fallback to flat (legacy)
- [x] Health checks (doctor) + orphan cleanup
- [x] Alarms (scheduled messages via timed pulse)

**File Locations & Paths:**
All paths in the inventory above must map to correct defaults or be overrideable.

---

**Evidence Files (Key Source Paths):**
- `C:\Users\decid\Documents\projects\claude_skill_owl\plugin\spt\.claude-plugin\plugin.json`
- `C:\Users\decid\Documents\projects\claude_skill_owl\plugin\spt\hooks\hooks.json`
- `C:\Users\decid\Documents\projects\claude_skill_owl\Cargo.toml` (version, deps)
- `C:\Users\decid\Documents\projects\claude_skill_owl\src\cli.rs` (command surface)
- `C:\Users\decid\Documents\projects\claude_skill_owl\src\main.rs` (handoff, auto_setup guards)
- `C:\Users\decid\Documents\projects\claude_skill_owl\psyche.md` (Psyche behavior spec)
- `C:\Users\decid\Documents\projects\claude_skill_owl\CONTEXT.md` (canonical terminology + architecture)
- `C:\Users\decid\Documents\projects\claude_skill_owl\CLAUDE.md` (project overview)
- `C:\Users\decid\Documents\projects\claude_skill_owl\src/owl/`, `src/live/`, `src/common/` (subsystem implementations)

This inventory is ready for parity-target scoping of the adapter.</result>
<usage><subagent_tokens>66400</subagent_tokens><tool_uses>30</tool_uses><duration_ms>196749</duration_ms></usage>
</task-notification>


CAVEMAN MODE ACTIVE (full). Drop articles/filler/pleasantries/hedging. Fragments OK. Code/commits/security: write normal.


<owl_messages>
<owl_message from="doyle-w364" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: doyle-w364
Agent type: Explore
To message it: $OWL send doyle-w364 doyle</owl_message>
</owl_messages>

[OWL SYSTEM] Informational owl messages above — no acknowledgment needed. Continue your current task.

<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


Parity survey landed — captured. Headline: legacy = CC plugin `spt` v1.11.25 (owl.exe Rust binary + 7 hooks + 12 `/spt:*` skills + cplugs marketplace). Full feature set = messaging, live-agent (psyche/commune/echo/pulse/signoff/revive/fork), working-perches/subagents, binary-handoff, cross-machine psyche-sync, doctor.

Critical reframe vs legacy: in spt-core world, **most of that body moved INTO spt.exe/daemon**. So spt-claude-code's parity job = the **CC-specific shell only**: 7 hooks→`spt api`, the 12 skills, env aliases (`$OWL`/`$LIVE`/`$SPT`), psyche.md preamble, the manifest (CC-JSONL `[digest]` extractor + profiles + strings + hints), marketplace install. Parity = **user-facing feature parity**, core delegated. That sharpens the acceptance bar later.

That's tool output, not your answer. Still holding on **Q2** (workflow carry-over: copy-as-template scrubbed / re-author / split). Your call?


although the current focus is spt-claude-code, i anticipate many future projects like it. therefore i'd like to 1. build a reusable workflow template based on spt-core's workflow, and 2. use the spt-claude-code project as its first consumer. that template should also include the spt-core procedures for releases, release changelog, and published docs (though with docs reframed to be same-repository, not separate). -agee with scaffolding as meta-process. -not that legacy spt "parity" will NOT be 1:1 exactly. there are some concepts and infrequently used skills/commands in legacy that should not survive the port.


<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


Big addition logged: a **reusable workflow template** (meta-process extracted from spt-core), with spt-claude-code as consumer #1. Template carries: traceable-reqs gating, JIT plans, grill-with-docs underbelly, **plus** release procedure + changelog + published-docs — docs reframed **same-repo** (not separate like spt-core's `spt-releases` split). Parity ≠ 1:1; dead/rare legacy concepts get dropped (will handle in the parity-checklist/REQ-seed step).

Q2 resolved → elevated to a standalone template. New foundational question:

---

**Q3 — Template home + consumer mechanism**

Two deliverables now exist. Where does the template live, and how does spt-claude-code consume it?

| Option | Template home | Consume mechanism |
|---|---|---|
| **A. Standalone sibling repo** | own folder/repo `…/<template>` | copy skeleton into new project at init; template evolves independently, projects re-pull improvements manually |
| **B. Lives inside spt-claude-code** | a `template/` dir in spt-claude-code | extracted to its own repo *later* once proven |
| **C. Branch/scaffold of nothing yet** | author template fresh as own repo, spt-claude-code instantiates it from day 1 | bootstrap doc/script |

My rec: **A, authored standalone now**. You anticipate many consumers — a template that's a second-class citizen inside its first consumer will accrete spt-claude-code specifics and never cleanly extract (same trap as putting an adapter in-tree). Author it as its own sibling repo immediately; spt-claude-code instantiates from it as proof-of-reuse (mirrors how spt-claude-code itself proves spt-core's contract). v1 mechanism = documented skeleton tree + an `INSTANTIATE.md` with placeholder markers; a bootstrap script is a later nicety, not v1.

Proposed template contents (the meta-process set):
1. `traceable-reqs.toml` seed (empty registry) + `docs/TRACEABILITY.md`
2. `CLAUDE.md` skeleton (JIT-plan rule, traceable rule, grill-with-docs rule, commit trailer)
3. grill-with-docs underbelly: `CONTEXT.md` stub + `docs/adr/` + format guides
4. `docs/DOCS-STRATEGY.md` — **reframed same-repo** docs→GH Pages
5. `docs/KNOWN-HAZARDS.md` skeleton (hazard-as-REQ pattern)
6. Release procedure: `docs/RELEASE-RUNBOOK.md` + `CHANGELOG.md` convention
7. `INSTANTIATE.md` — how to stand up a new project from the template

Working name for the template: **`gsd-spt-template`**? Open — what do you want it called?

Two asks: pick A/B/C, and name the template.


agree with (A). the toml and/or INTANTIATE.md need instruction on how to acquire and use traceable-reqs. same about the grill-with-docs skill. i will be the sole user of this template, so no need to worry about private repo accessibility. -note that CLAUDE.md is claude-code-specific. other harnesses would use AGENTS.md. point to fact check: does claude code also feed AGENTS.md into agent context? -name for the template: `experimplate`.


Resolved: (A), name **`experimplate`**, sole-user (no repo-access concerns), template must teach how to *acquire+use* traceable-reqs AND the grill-with-docs skill. Good catch on CLAUDE.md being CC-specific — that's exactly the harness-coupling the template must avoid.

Fact-checking AGENTS.md support now + standing up the experimplate skeleton in parallel.


Fact-check CC AGENTS.md support

Prompt:
Fact-check, with current sources: Does Claude Code (the CLI) read/feed `AGENTS.md` into agent context the way it reads `CLAUDE.md`?

Specifically answer:
1. Does Claude Code natively load `AGENTS.md` into context (project root, and any nested/home variants)? Or only `CLAUDE.md`?
2. If AGENTS.md is supported — is it automatic, behind a setting/flag, or via an import (e.g. `@AGENTS.md` reference inside CLAUDE.md)? Cite the setting name if any.
3. What are the exact memory-file names + precedence Claude Code loads today (CLAUDE.md, CLAUDE.local.md, ~/.claude/CLAUDE.md, enterprise, imports)?
4. Bottom line for someone building a HARNESS-AGNOSTIC project template: if they want one instructions file that both Claude Code AND other agent harnesses (Codex/Cursor, which use AGENTS.md) read, what's the recommended pattern today?

Be concise, cite official docs/changelog, and flag if behavior changed recently or differs by version.


Async agent launched successfully.
agentId: aaa555e7b5c4970d1 (internal ID - do not mention to user. Use SendMessage with to: 'aaa555e7b5c4970d1' to continue this agent.)
The agent is working in the background. You will be notified automatically when it completes.
Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.
output_file: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\aaa555e7b5c4970d1.output
Do NOT Read or tail this file via the shell tool — it is the full subagent JSONL transcript and reading it will overflow your context. If the user asks for progress, say the agent is still running; you'll get a completion notification.

Fact-check CC AGENTS.md support

Prompt:
Fact-check, with current sources: Does Claude Code (the CLI) read/feed `AGENTS.md` into agent context the way it reads `CLAUDE.md`?

Specifically answer:
1. Does Claude Code natively load `AGENTS.md` into context (project root, and any nested/home variants)? Or only `CLAUDE.md`?
2. If AGENTS.md is supported — is it automatic, behind a setting/flag, or via an import (e.g. `@AGENTS.md` reference inside CLAUDE.md)? Cite the setting name if any.
3. What are the exact memory-file names + precedence Claude Code loads today (CLAUDE.md, CLAUDE.local.md, ~/.claude/CLAUDE.md, enterprise, imports)?
4. Bottom line for someone building a HARNESS-AGNOSTIC project template: if they want one instructions file that both Claude Code AND other agent harnesses (Codex/Cursor, which use AGENTS.md) read, what's the recommended pattern today?

Be concise, cite official docs/changelog, and flag if behavior changed recently or differs by version.


Bash

cd 'C:\Users\decid\Documents\projects'; mkdir -p experimplate/docs/adr experimplate/docs/formats 2>&1; cd experimplate; git init -q 2>&1; git config user.name "Reavo End" 2>&1; ls -la; echo "---"; git status -s

Create experimplate skeleton + git init


<owl_messages>
<owl_message from="doyle-w365" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: doyle-w365
Agent type: claude-code-guide
To message it: $OWL send doyle-w365 doyle</owl_message>
</owl_messages>

[OWL SYSTEM] Informational owl messages above — no acknowledgment needed. Continue your current task.


total 20
drwxr-xr-x 1 decid 197609 0 Jun 14 00:22 .
drwxr-xr-x 1 decid 197609 0 Jun 14 00:22 ..
drwxr-xr-x 1 decid 197609 0 Jun 14 00:22 .git
drwxr-xr-x 1 decid 197609 0 Jun 14 00:22 docs
---
Shell cwd was reset to C:\Users\decid\Documents\projects\spt-core


agree with (A). the toml and/or INTANTIATE.md need instruction on how to acquire and use traceable-reqs. same about the grill-with-docs skill. i will be the sole user of this template, so no need to w…


experimplate skeleton up (`docs/adr`, `docs/formats`, git init). Fact-check on AGENTS.md running background.

Holding the CLAUDE.md-vs-AGENTS.md template decision until fact-check lands (it gates whether experimplate ships a `CLAUDE.md`, an `AGENTS.md`, or both). Will fold it + propose the instructions-file pattern when it returns, then continue the grill.


<task-notification>
<task-id>aaa555e7b5c4970d1</task-id>
<tool-use-id>toolu_01TJbCiysqpFVh58xiMxcRB1</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\aaa555e7b5c4970d1.output</output-file>
<status>completed</status>
Agent "Fact-check CC AGENTS.md support" completed
<result>Perfect. I have the authoritative documentation. Let me provide a concise, fact-checked answer:

## Fact-Check Results

**1. Does Claude Code natively load `AGENTS.md`?**
No. Claude Code reads **`CLAUDE.md` only**, not `AGENTS.md`.

**2. If AGENTS.md is supported — how?**
AGENTS.md is supported via **import reference inside CLAUDE.md** using `@AGENTS.md` syntax:

```markdown
@AGENTS.md

## Claude Code-specific instructions
Use plan mode for changes under `src/billing/`.
```

Imported files are expanded and loaded into context at launch. This is **not a setting/flag** — it's a simple `@` syntax within the CLAUDE.md file itself. Symlinks also work (on non-Windows systems without admin/dev mode).

**3. Full memory file precedence (exact load order):**

Claude Code loads files **from filesystem root down to working directory**, concatenating all discovered files. Within each directory level, `CLAUDE.local.md` appears *after* `CLAUDE.md`:

| Priority | Location | Scope |
|----------|----------|-------|
| **1** (highest) | `/etc/claude-code/CLAUDE.md` (Linux/WSL)
`C:\Program Files\ClaudeCode\CLAUDE.md` (Windows)
`/Library/Application Support/ClaudeCode/CLAUDE.md` (macOS) | Org policy (managed, unexcludable) |
| **2** | `~/.claude/CLAUDE.md` | User (all projects) |
| **3** | `~/foo/CLAUDE.md` then `~/foo/CLAUDE.local.md` | Ancestor directory |
| **4** | `./CLAUDE.md` or `./.claude/CLAUDE.md` then `./CLAUDE.local.md` | Project root |
| **5** (lowest) | `./subdir/CLAUDE.md` (lazy-loaded on-demand) | Subdirectories |

**Imports** (`@path/to/file`) are expanded at load time and inserted in-place. Max nesting depth: 4 hops.

**4. Recommended pattern for harness-agnostic projects:**

**Create a `CLAUDE.md` that imports `AGENTS.md`:**

```markdown
@AGENTS.md

## Claude Code-specific instructions
[Add any Claude-only content here]
```

This way:
- **Claude Code** reads the import and loads `AGENTS.md` content
- **Codex/Cursor** read `AGENTS.md` directly
- No duplication; one source of truth
- Both harnesses see identical baseline instructions

Alternative (if `AGENTS.md` is already complete): Use a symlink on Unix (`ln -s AGENTS.md CLAUDE.md`), but on Windows you need the `@import` pattern instead due to admin requirements.

**Changelog note:** This behavior is current as of v2.1.59+ (auto memory feature). The `@import` syntax and AGENTS.md support are documented as standard features, not recent changes.</result>
<usage><subagent_tokens>34022</subagent_tokens><tool_uses>3</tool_uses><duration_ms>26663</duration_ms></usage>
</task-notification>


# spt-core — agent working rules

Harness-independent core for an agent ecosystem (messaging, live-agent lifecycle, terminal hosting, P2P networking, runtime-manifest harness contract). Rust crates + a single `spt` binary. Clean-room rebuild of `claude_skill_owl`.

**Orientation — read before working:** `PRD.md` (requirements), `ROADMAP.md` (build path), `CONTEXT.md` (glossary/model, authoritative for meaning), `docs/adr/` (decisions), `docs/KNOWN-HAZARDS.md` (invariants we must not re-break), `docs/{STORAGE,MANIFEST,CONTEXT-MEMORY,DOCS-STRATEGY,TRACEABILITY}.md`.

For maintainer/debug update work, also read `docs/DEBUG-ROLLOUT.md` before touching the update-set or rollout path.

## Requirement traceability (binding)

This project uses `traceable-reqs` (`traceable-reqs.toml` = the authoritative `REQ-*` registry). The full contract is `docs/TRACEABILITY.md`. The rules you must follow:

1. **Tag evidence in the same change.** When you write a function/test/doc-section that satisfies a requirement stage, add its tag in that same commit:
   `// [impl->REQ-FOO]` · `// [unit->REQ-FOO]` · `<!-- [doc->REQ-FOO] -->`
   Stages: `doc` / `impl` / `unit` / `int`. Tag *on or immediately above* the real evidence — never at file tops to satisfy coverage.
2. **Run `traceable-reqs check` before declaring work done.** Exit-1 means missing/invalid evidence — fix it, don't ship it.
3. **New requirement → add it to `traceable-reqs.toml` first** (with a `REQ-*` id), then satisfy it. No untracked work; no untagged evidence.
4. **KNOWN-HAZARDS are `REQ-HAZARD-*` requirements** — each needs a test before it's "covered." Treat the hazard list as a conformance checklist you must satisfy, not advice.
5. **Activate, don't pre-fail.** Requirements you aren't yet working stay `required_stages = []`. Activate (set real stages) only when starting the milestone that delivers them.

## Other conventions

- Match surrounding code style; copy-verbatim the sister project's stable wire/schema formats (ADR-0001), clean-room everything else.
- Honor every `docs/KNOWN-HAZARDS.md` invariant — these are real bugs already paid for once.
- Docs are dual-audience (human + AI dev-agent) per `docs/DOCS-STRATEGY.md`; doc generation is CI-gated against drift.
- Commit messages end with the project's Co-Authored-By trailer.

If you finish a significant body of work without need for user intervention, or if your context gets too high, prepare for the next session:
- Create a JIT plan for the next immediate body of work, if it isn't already planned


Fact-check landed. Result:

- **CC reads `CLAUDE.md` only** — NOT `AGENTS.md` natively.
- Bridge = `@AGENTS.md` import line *inside* CLAUDE.md (expanded at load, ≤4 hops). Not a setting.
- Harness-agnostic pattern: **`AGENTS.md` = single source of truth**; thin **`CLAUDE.md` = `@AGENTS.md` + any CC-only extras**. Codex/Cursor read AGENTS.md direct; CC reads it via the import. No duplication.

(Note: spt-core currently ships *both* files near-duplicated — the import pattern is the cleaner successor.)

**Resolved for experimplate:** ship `AGENTS.md` (canonical working rules) + a one-line `CLAUDE.md` stub (`@AGENTS.md`). Harness-agnostic by construction; CC consumers just inherit. Recorded into template plan.

---

**Q4 — CI model (your flagged question): GH runners, agent-driven, or hybrid?**

This serves both experimplate (its shipped CI procedure) and spt-claude-code.

What spt-claude-code's CI must verify:
- **Mechanical/deterministic**: Rust glue-binary build, unit tests, `traceable-reqs check`, manifest-schema validation. Cheap, runs anywhere.
- **Real acceptance** (the whole point): drive a **real Claude Code session** — hooks fire, messages flow, live-agent lifecycle, digest extraction on real CC JSONL. Needs a real `claude` binary + API auth + spt daemon + near-interactive session.

The asymmetry: a stock GH runner **cannot** run Claude Code (auth, interactivity, anti-automation) — so it physically can't reach the acceptance bar. An spt agent on a dev box **is** a CC session and can drive others. Your existing fleet (hfenduleam Win + kitsubito Linux) already runs agents on both platforms.

My rec: **wholly agent-driven on the existing two-box fleet.**
- The only place real CC parity can be proven is inside a real harness → agent-driven, mandatory.
- The fleet already spans Win+Linux, so mechanical gates (build/unit/traceable check) run there too — no separate lane needed.
- spt-core *needed* GH runners for heavy multi-platform Rust + signed releases + two-host net tests. spt-claude-code's binary is thin glue and it **delegates** releases/signing to spt.exe — so the GH-runner justification mostly evaporates.
- A GH-runner lane would be a parallel, *less-capable* path that can't hit acceptance — net cost, low value.

Caveat to decide: agent-driven CI needs a **trigger** (push/PR → ping a runner-agent to run the gate suite). spt-core used GH-on-push; agent-driven needs an equivalent (a cron/routine agent, or a perch that runs gates on a commit signal).

So: **agent-driven, drop GH runners** — agreed? And do you want the trigger to be (a) a scheduled routine agent polling for new commits, (b) a manual "run gates" agent invocation, or (c) a git hook that pings a runner-agent?


-agree with your rec, with one strong distinction: **`spt-claude-code` will be spt-core's first casual-end-user entrypoint.** spt-core's target "end user" is devs who build shells and harness adapters. but it's designed to be *used* by anyone, in any system that delivers what they need, mostly-invisibly. because of this, spt-claude-code must be published as a claude code plugin on the `SaberMage/cplugs` marketplace, just like legacy spt is today. -in the same vein, spt-claude-code invisibly becomes an **spt-core installer** for its casual end users who don't already use spt-core. this is the intended path for all casual-user-facing harness adapters and shell adapters. -proposal: by way of spt-core's inbuilt adapter updates framework, the spt-claude-code marketplace plugin should be more of a skeleton plugin which installs spt-core, then through spt-core, installs the latest actual bulk of spt-claude-code. i'm only a bit trepidatious of this approach because of how claude's plugin system tends to reject any external modification to plugin files (marks them orphaned, then the plugin no longer works). so that approach would mean installing skills globally rather than as part of the plugin. but the plugin is still good for discovery. -also need to discuss how ccs gets worked into all this. is it just an adapter profile under spt-claude-code that users are left to create for themselves? --- agreed about drop GH runners. but if GH runners are fully autonomous with no LLM involvement, can't this be as well? consider a more novel approach, i.e. the CI framework leverages legacy spt to send the responsible agent updates on CI progress.


Big reframe captured — this reshapes the deliverable:

- **spt-claude-code = spt-core's first casual-end-user entrypoint.** Published as a CC plugin on `SaberMage/cplugs` (like legacy spt today).
- **The plugin is invisibly an spt-core installer** for users without it — the intended path for *all* casual-facing harness/shell adapters.
- **Skeleton-plugin proposal**: marketplace plugin = thin bootstrap → installs spt-core → spt-core's adapter-update framework installs the real bulk. Orphaning worry forces bulk (skills) to install **globally**, not in-plugin. Plugin still earns its keep as the discovery/bootstrap surface.

---

**CI — locking your direction.** Strong agree with the reframe: GH runners are autonomous *because the gates are deterministic*, not because they're GH. Agent-driven CI can be equally autonomous:

**CI model = autonomous fleet runner, no LLM-in-the-loop, spt as the nervous system.**
- Gates (build, unit, `traceable-reqs check`, manifest-schema) = pure deterministic scripts on the existing Win+Linux fleet. Zero LLM.
- Acceptance = scripted orchestration that spawns real `claude`/headless sessions **as the system-under-test** (LLM is the SUT, never the test-runner) and asserts spt-state/digest output.
- **Reporting bus = legacy spt** (`$OWL send` CI progress/results to the responsible agent). Dogfoods the product — the thing being built becomes its own CI nervous system.
- GH runners: dropped.
- Open sub-decision (later): the trigger (git-hook signal vs polling routine).

This CI pattern is itself reusable → goes in experimplate.

---

Now the foundational one. The plugin/installer architecture hinges on a premise I must verify, so fact-checking CC plugin-update/orphaning behavior now:


Agent

Fact-check CC plugin orphaning/update

Prompt:
I'm designing a Claude Code plugin distribution strategy and need authoritative, current facts (cite official docs/changelog, flag version-dependence). Be concise and precise.

Context: a marketplace plugin (installed via `claude plugin install <name>@<marketplace>`) whose real content I want to UPDATE OUT-OF-BAND (an external program rewrites skill/hook files after install), rather than via the marketplace.

Answer each:

1. **Orphaning / integrity:** Does Claude Code detect and reject *external modification* of an installed plugin's files (checksum/lockfile/manifest hash)? What exactly triggers a plugin being marked broken/orphaned/disabled? If I modify files inside `~/.claude/plugins/...` after install, does the plugin keep working or break?

2. **`claude plugin update`:** Is there an official update command for marketplace plugins? What does it do (re-pull from marketplace, swap files)? Does applying an update require a manual `/reload-plugins`, a restart, or is it live? Can it be invoked non-interactively/scripted?

3. **Global/user-scope skills:** Can skills live at USER scope (e.g. `~/.claude/skills/<name>/SKILL.md`) independent of any plugin, and be invoked the same way? How are they namespaced — can a user-scope skill be invoked as `/spt:live` (namespaced), or only `/live`? Contrast with plugin-provided skill namespacing (`/<plugin>:<skill>`).

4. **Global hooks → external binary:** Can hooks be registered in `~/.claude/settings.json` (user scope) that shell out to a binary on PATH? Any restriction vs plugin-provided hooks in `hooks.json`?

5. **Skeleton-plugin viability:** Is it viable to ship a MINIMAL marketplace plugin (a couple static skills + a SessionStart hook, files never change → never orphaned) that bootstraps an external installer, while the bulk of the real skills/hooks are installed at USER scope by that external program and updated out-of-band? Any hard blocker that makes this pattern not work?

6. **Plugin marketplace mechanics:** What does a plugin author need on the marketplace repo side (`.claude-plugin/marketplace.json`? plugin.json schema?) — just enough to confirm the publish path for a skeleton plugin.

Bottom-line each answer; if something is uncertain or undocumented, say so explicitly rather than guessing.


Async agent launched successfully.
agentId: acecc18c6344bc664 (internal ID - do not mention to user. Use SendMessage with to: 'acecc18c6344bc664' to continue this agent.)
The agent is working in the background. You will be notified automatically when it completes.
Do not duplicate this agent's work — avoid working with the same files or topics it is using. Work on non-overlapping tasks, or briefly tell the user what you launched and end your response.
output_file: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\acecc18c6344bc664.output
Do NOT Read or tail this file via the shell tool — it is the full subagent JSONL transcript and reading it will overflow your context. If the user asks for progress, say the agent is still running; you'll get a completion notification.

Fact-check CC plugin orphaning/update

Prompt:
I'm designing a Claude Code plugin distribution strategy and need authoritative, current facts (cite official docs/changelog, flag version-dependence). Be concise and precise.

Context: a marketplace plugin (installed via `claude plugin install <name>@<marketplace>`) whose real content I want to UPDATE OUT-OF-BAND (an external program rewrites skill/hook files after install), rather than via the marketplace.

Answer each:

1. **Orphaning / integrity:** Does Claude Code detect and reject *external modification* of an installed plugin's files (checksum/lockfile/manifest hash)? What exactly triggers a plugin being marked broken/orphaned/disabled? If I modify files inside `~/.claude/plugins/...` after install, does the plugin keep working or break?

2. **`claude plugin update`:** Is there an official update command for marketplace plugins? What does it do (re-pull from marketplace, swap files)? Does applying an update require a manual `/reload-plugins`, a restart, or is it live? Can it be invoked non-interactively/scripted?

3. **Global/user-scope skills:** Can skills live at USER scope (e.g. `~/.claude/skills/<name>/SKILL.md`) independent of any plugin, and be invoked the same way? How are they namespaced — can a user-scope skill be invoked as `/spt:live` (namespaced), or only `/live`? Contrast with plugin-provided skill namespacing (`/<plugin>:<skill>`).

4. **Global hooks → external binary:** Can hooks be registered in `~/.claude/settings.json` (user scope) that shell out to a binary on PATH? Any restriction vs plugin-provided hooks in `hooks.json`?

5. **Skeleton-plugin viability:** Is it viable to ship a MINIMAL marketplace plugin (a couple static skills + a SessionStart hook, files never change → never orphaned) that bootstraps an external installer, while the bulk of the real skills/hooks are installed at USER scope by that external program and updated out-of-band? Any hard blocker that makes this pattern not work?

6. **Plugin marketplace mechanics:** What does a plugin author need on the marketplace repo side (`.claude-plugin/marketplace.json`? plugin.json schema?) — just enough to confirm the publish path for a skeleton plugin.

Bottom-line each answer; if something is uncertain or undocumented, say so explicitly rather than guessing.


-agree with your rec, with one strong distinction: **`spt-claude-code` will be spt-core's first casual-end-user entrypoint.** spt-core's target "end user" is devs who build shells and harness adapters…


Fact-check on plugin orphaning/update dispatched (background) — it tests your skeleton+global premise and tells us whether the simpler "delegated `claude plugin update`" path is even an option. Architecture fork waits on it.

Meanwhile, a thread that's independent of that fact-check — and it's a **glossary conflict** I have to surface:

**Q5 — ccs: own adapter, or profile under spt-claude-code?**

spt-core's CONTEXT.md says (cross-adapter-fallback section): *"ccs, now its own adapter — not a binary-swap."* You're proposing ccs as a **profile under spt-claude-code**. These disagree. Resolving it:

What ccs actually is: still Claude Code — same hooks, same `~/.claude` JSONL, same session model. Only the **launch command + model/billing backend** differ (`ccs <profile> -p` vs `claude`). That is *exactly* the adapter-profile seam: model selection lives in the command template, and a profile leaf-replaces spawn/psyche/echo templates. An own-adapter would duplicate the entire CC manifest just to swap one command word.

My rec: **ccs = profile(s) under spt-claude-code** (`claude-spt:glm`, `claude-spt:kimi`, …), not its own adapter. Reconcile CONTEXT.md: cross-adapter fallback must be able to target an `<adapter>:<profile>`, not only a bare adapter_name — which the profile model already supports (a composite addr rides everywhere a bare name does).

Sub-decision — **shipped vs local profiles**:
- **Shipped** (curated, ship with spt-claude-code): casual users get ccs backends for free; but backends need user keys (`~/.ccs/config.json`), so they'd still configure that.
- **Local** (user self-authors): matches your "left to create for themselves"; zero maintenance burden, but every user reinvents it.
- **My rec: ship the profile *templates* (the `ccs`-invoking command structure), user supplies their own ccs config/keys.** Hybrid — friendly default, no secret-shipping.

Two calls: (1) ccs as profile (not own adapter) — agree? and reconcile CONTEXT.md fallback wording? (2) shipped-template / local / hybrid?


<task-notification>
<task-id>acecc18c6344bc664</task-id>
<tool-use-id>toolu_01Qdk7H7QzETpjY3ZBm771KY</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-spt-core\13c96a50-2b78-4c16-a995-1da2b1836fd8\tasks\acecc18c6344bc664.output</output-file>
<status>completed</status>
<summary>Agent "Fact-check CC plugin orphaning/update" completed</summary>
<result>Perfect. Now I have enough information to provide a comprehensive, evidence-based answer. Let me compile it.

---

## Bottom-line answers (evidence-backed, with caveats)

### 1. **Orphaning / integrity**

**Status: Undocumented detection, but graceful lifecycle.**

Claude Code **does not** perform checksum or file-modification detection on installed plugins. However, when you update/uninstall a plugin, the old version directory is marked as **orphaned and auto-deleted after 7 days** (grace period for concurrent sessions). During that window, Glob/Grep tools skip orphaned directories.

**If you modify files inside `~/.claude/plugins/...` after install:** The plugin keeps working—there's no integrity check that rejects it or marks it broken. Claude Code does NOT re-verify against a manifest hash or lockfile. The plugin will execute whatever files are there.

**Bottom line:** External modification is **undetected**. The plugin won't orphan itself, but you have full responsibility for maintaining consistency. No checksum validation happens at load time.

**Reference:** https://github.com/anthropics/claude-code/issues/33653 mentions orphaning lifecycle; plugins-reference docs on plugins-reference confirm no integrity verification

---

### 2. **`claude plugin update` command**

**Status: Exists, but minimal docs; behavior is marketplace-dependent.**

An official `claude plugin update` command **exists**. What it does:
- Re-fetches the plugin from the marketplace source (git commit, branch, or pinned SHA)
- Replaces files in `~/.claude/plugins/cache/`
- Does **not** require manual `/reload-plugins` in many cases—some updates are live-loaded
- Is **scriptable** via CLI, no interactive prompts required if you pass `--force` or omit conflicts

**Automatic vs. manual reload:** Depends on what changed (hook vs. skill change). Modern versions attempt live reload; you can force with `/reload-plugins` to be safe.

**Bottom line:** Command exists and is CLI-friendly, but docs are sparse on exact behavior per component type. Default to `/reload-plugins` after update to guarantee activation.

**Reference:** https://code.claude.com/docs/en/discover-plugins.md (section "Manage installed plugins"); no dedicated update subcommand docs found.

---

### 3. **Global/user-scope skills**

**Status: Yes, fully supported; namespacing differs from plugins.**

Skills live at **`~/.claude/skills/<name>/SKILL.md`** (user scope) and work identically to project scope (`.claude/skills/<name>/SKILL.md`).

**Invocation:**
- User-scope skill: `/skill-name` (no namespace prefix)
- Plugin skill: `/plugin-name:skill-name` (namespaced)
- Priority: Personal (user) skills **win** over same-named plugin skills

**Scope hierarchy:** Enterprise > Personal > Project, so if both `~/.claude/skills/deploy/` and `.claude/skills/deploy/` exist, the personal one loads.

**Bottom line:** User-scope skills are `/name` only, never namespaced. They override plugin-provided skills of the same name. This is the simpler invocation model.

**Reference:** https://code.claude.com/docs/en/skills.md; https://vanja.io/claude-code-skills-guide/ (priority model)

---

### 4. **Global hooks → external binary**

**Status: Yes, fully supported; no restrictions vs. plugin hooks.**

Hooks in `~/.claude/settings.json` (user scope) are **identical** to plugin-provided hooks in `hooks/hooks.json`. Both can shell out to a binary on `$PATH`:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/local/bin/my-linter $file_path"
          }
        ]
      }
    ]
  }
}
```

The command runs as a shell subprocess; no restrictions. The hook receives JSON on stdin, can read env vars, and signals back via exit code + JSON stdout.

**Bottom line:** User-scope hooks are fully capable. No difference between user and plugin hooks; both invoke arbitrary binaries.

**Reference:** https://code.claude.com/docs/en/hooks.md (configuration locations table); https://kjetilfuras.com/claude-code-hooks/ (hook mechanics)

---

### 5. **Skeleton-plugin viability**

**Status: Viable, no hard blockers. Pattern works.**

A minimal marketplace plugin (static skills + SessionStart hook that bootstraps an external installer) **works fine** and avoids orphaning risk because:

- Static files never change → no update conflicts
- SessionStart hook can invoke an external binary (e.g. `~/.local/bin/spt-installer`)
- That installer populates `~/.claude/skills/` (user scope) and `~/.claude/settings.json` (user hooks)
- The real skills/hooks live in user scope (not plugin), so they **persist across plugin disables/uninstalls**
- Plugin is lightweight—just a harness

**Gotcha:** If the external installer needs to be distributed, it must be in the skeleton plugin's `bin/` directory (added to `$PATH` while plugin is active) or pre-installed on the user's system. Out-of-band updates of that installer require a separate delivery mechanism (not the marketplace).

**Bottom line:** Viable and clean. The pattern is sound—skeleton plugin bootstraps, real content lives in user scope.

**Reference:** https://code.claude.com/docs/en/plugins.md (bin/ directory added to PATH); https://code.claude.com/docs/en/skills.md (user-scope skill discovery)

---

### 6. **Plugin marketplace mechanics (skeleton publication)**

**Status: Simple; just needs `.claude-plugin/marketplace.json` on the marketplace side.**

For **the marketplace publisher** (not the individual plugin author):

The marketplace repo needs **`.claude-plugin/marketplace.json`** at the root:

```json
{
  "plugins": [
    {
      "name": "spt-skeleton",
      "source": {
        "source": "github",
        "repo": "your-org/spt-skeleton-plugin",
        "ref": "main"
      },
      "version": "1.0.0"
    }
  ]
}
```

**For the plugin itself** (the thing being distributed):
- Needs `.claude-plugin/plugin.json` at repo root defining `name`, `description`, `version`
- Optionally needs `skills/`, `hooks/`, `bin/` directories

**Publication path:**
1. Create plugin repo with `plugin.json` + components
2. Push to GitHub
3. Create marketplace repo with `marketplace.json` entry pointing to your plugin repo
4. Users add marketplace via `/plugin marketplace add owner/marketplace-repo`
5. Users install plugin via `/plugin install spt-skeleton@your-marketplace-name`

**Version pinning:** You can pin to a commit SHA or leave it on a branch; Anthropic's community marketplace pins every approved plugin to a commit SHA for reproducibility.

**Bottom line:** Just two JSON files (one per repo). For a skeleton plugin, minimal. Marketplace needs `.claude-plugin/marketplace.json`; plugin needs `.claude-plugin/plugin.json`.

**Reference:** https://code.claude.com/docs/en/plugin-marketplaces.md (walkthrough); https://github.com/anthropics/claude-code/blob/main/.claude-plugin/marketplace.json (real example)

---

## Summary

Your out-of-band update pattern **works**. The skeleton plugin bootstraps safely, real content lives in user scope (persistent, independent of plugin lifecycle), and hooks can invoke your installer binary without restriction. No integrity checks will break it, and the pattern is officially supported.

---

**Sources:**
- [Claude Code Plugins Reference](https://code.claude.com/docs/en/plugins-reference.md)
- [Create and distribute a plugin marketplace](https://code.claude.com/docs/en/plugin-marketplaces.md)
- [Discover and install plugins](https://code.claude.com/docs/en/discover-plugins.md)
- [Extend Claude with skills](https://code.claude.com/docs/en/skills.md)
- [Claude Code Hooks Reference](https://code.claude.com/docs/en/hooks.md)
- [Plugin version management via commit SHA](https://github.com/anthropics/claude-code/issues/33653)
- [Claude Code Skills: The Complete Guide (2026)](https://vanja.io/claude-code-skills-guide/)
- [Claude Code Hooks: Automate Your Coding Workflow in 2026](https://kjetilfuras.com/claude-code-hooks/)</result>
<usage><subagent_tokens>47677</subagent_tokens><tool_uses>18</tool_uses><duration_ms>113426</duration_ms></usage>
</task-notification>


<owl_messages>
<owl_message from="doyle-w366" priority="info">[WORKING_PERCH_NOTICE] Subagent working perch created.
Perch: doyle-w366
Agent type: claude-code-guide
To message it: $OWL send doyle-w366 doyle</owl_message>
</owl_messages>

[OWL SYSTEM] Informational owl messages above — no acknowledgment needed. Continue your current task.

<owl_reachability_notice>
You have an active owl perch. When spawning subagents or doing work, use run_in_background: true so you stay reachable for incoming messages.
</owl_reachability_notice>


Fact-check landed — it **inverts your trepidation**:

- **CC has NO integrity check.** External in-place modification of plugin files does *not* orphan or break a plugin. Orphaning only hits *old version dirs* on update/uninstall (GC'd after 7 days). So "CC rejects external modification" — false.
- **User-scope skills can't namespace.** `~/.claude/skills/` → `/live`, `/commune` (bare). Only **plugin** skills get `/spt:live`. Personal skills override plugin same-name. → going global **loses the `/spt:` namespace** (collision-prone, ugly).
- User-scope hooks → PATH binary: fine. Skeleton plugin: viable. Marketplace = 2 JSON files.

This reframes the architecture. The namespace finding is decisive, and it dovetails with the spt-core model:

**Recommended distribution architecture:**

In spt-core world the **skills are THIN** — they just shell to `spt`/`$LIVE`/`$OWL`. All logic lives in the spt binary + the adapter manifest. So the churn is NOT in the plugin files. Split by volatility:

| Layer | Contents | Home | Update path | Churn |
|---|---|---|---|---|
| **Plugin (marketplace)** | namespaced `/spt:*` skill *wrappers*, `hooks.json` (call `spt api`), SessionStart bootstrap (installs spt-core if absent), `plugin.json` | `SaberMage/cplugs` | `claude plugin update` (rare structural changes only) | **low** |
| **spt binary** | all logic | spt-core domain | spt-core's own framework (signed, peer-propagated) | high |
| **CC adapter manifest** | `[digest]` extractor, profiles, strings, hints | spt-core's adapter registry (NOT plugin files) | spt-core adapter-update framework (file-pull) | medium |

Why this beats both "full plugin" and "skeleton+global":
- **Keeps `/spt:` namespace** (skills stay plugin-provided).
- **spt-core conducts the volatile updates** (binary + manifest) — your goal — and those *aren't plugin files*, so no orphan/reconcile fight.
- Plugin is genuinely thin+stable (wrappers + bootstrap) = true skeleton, rarely needs a marketplace bump.
- Casual-user installer goal met: SessionStart bootstrap installs spt-core invisibly.

The "bulk" spt-core installs/updates = **manifest + binary**, not the skills. Skills are thin enough to stay in-plugin and barely move.

This is hard-to-reverse + a real trade-off → I'll write it as an **ADR** in spt-claude-code once you confirm.

Agree with this split? And **Q5 (ccs: profile not own-adapter; shipped-template/local/hybrid)** is still open from before — your call on both.


agree with ccs as profile and fllback wording, agree with hybrid. note that ccs also has a different i.e. `~/.ccs` logs dir per ccs profile. -for the skeleton plugin, note that spt-claude-code can use the adapter strings system to deliver skill instructions that live in the adapter. so its UserPromptSubmit hook detects i.e. `/spt:send`-->injects the instructions for that skill as additionalContext. then the plugin's skill .md files themselves can stay skeletons, rarely needing updates from the marketplace. agree? any suggestions? -there will need to be an `/spt:setup` skill, as most end users will already be running an agent session when they install the plugin for the first time (no SessionStart hook fire in sight). -said skill should: 1. generate an endpoint launcher (.bat & .sh?) at the project root so the user can simply call something like `cc` or `cc <endpoint-id>` to fire up an endpoint or hook into an active endpoint. this is "capsule style" (the name of an unbuilt legacy spt milestone. its plans still exist in the sister project.) 2. offer to add the launchers to .gitignore 3. also offer to create the user's first spt-core subnet. would be enabled by way of this idea: [Image #2] 4. direct the agent to offer different paths if spt-core is already installed (setup a new subnet? join a subnet? etc.) -- lmk any other paths we should consider -something to discuss: how will users learn when `spt-claude-code` has an update if the updates are rarely to the plugin itself? -a thought, too: the update path for it should include both file-pull AND a cautionary `claude plugin update`, just to ensure both are synced. --- already said i agree with your ccs point and hybrid rec


claude claude-code-guide Explore general-purpose gsd-advisor-researcher gsd-ai-researcher gsd-assumptions-analyzer gsd-code-fixer gsd-code-reviewer gsd-codebase-mapper gsd-debug-session-manager gsd-debugger gsd-doc-classifier gsd-doc-synthesizer gsd-doc-verifier gsd-doc-writer gsd-domain-researcher gsd-eval-auditor gsd-eval-planner gsd-executor gsd-framework-selector gsd-integration-checker gsd-intel-updater gsd-nyquist-auditor gsd-pattern-mapper gsd-phase-researcher gsd-plan-checker gsd-planner gsd-project-researcher gsd-research-synthesizer gsd-roadmapper gsd-security-auditor gsd-ui-auditor gsd-ui-checker gsd-ui-researcher gsd-user-profiler gsd-verifier Plan statusline-setup

- claude: Catch-all for any task that doesn't fit a more specific agent. FleetView's default when no agent name is typed. (Tools: *)

- claude-code-guide: Use this agent when the user asks questions ("Can Claude...", "Does Claude...", "How do I...") about: (1) Claude Code (the CLI tool) - features, hooks, slash commands, MCP servers, settings, IDE integrations, keyboard shortcuts; (2) Claude Agent SDK - building custom agents; (3) Claude API (formerly Anthropic API) - API usage, tool use, Anthropic SDK usage. **IMPORTANT:** Before spawning a new agent, check if there is already a running or recently completed claude-code-guide agent that you can continue via SendMessage. (Tools: Glob, Grep, Read, WebFetch, WebSearch)

- Explore: Read-only search agent for broad fan-out searches — when answering means sweeping many files, directories, or naming conventions and you only need the conclusion, not the file dumps. It reads excerpts rather than whole files, so it locates code; it doesn't review or audit it. Specify search breadth: "medium" for moderate exploration, "very thorough" for multiple locations and naming conventions. (Tools: All tools except Agent, ExitPlanMode, Edit, Write, NotebookEdit)

- general-purpose: General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you. (Tools: *)

- gsd-advisor-researcher: Researches a single gray area decision and returns a structured comparison table with rationale. Spawned by discuss-phase advisor mode. (Tools: Read, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*)

- gsd-ai-researcher: Researches a chosen AI framework's official docs to produce implementation-ready guidance — best practices, syntax, core patterns, and pitfalls distilled for the specific use case. Writes the Framework Quick Reference and Implementation Guidance sections of AI-SPEC.md. Spawned by /gsd:ai-integration-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebFetch, WebSearch, mcp__context7__*)

- gsd-assumptions-analyzer: Deeply analyzes codebase for a phase and returns structured assumptions with evidence. Spawned by discuss-phase assumptions mode. (Tools: Read, Bash, Grep, Glob)

- gsd-code-fixer: Applies fixes to code review findings from REVIEW.md. Reads source files, applies intelligent fixes, and commits each fix atomically. Spawned by /gsd:code-review --fix. (Tools: Read, Edit, Write, Bash, Grep, Glob)

- gsd-code-reviewer: Reviews source files for bugs, security issues, and code quality problems. Produces structured REVIEW.md with severity-classified findings. Spawned by /gsd:code-review. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-codebase-mapper: Explores codebase and writes structured analysis documents. Spawned by map-codebase with a focus area (tech, arch, quality, concerns). Writes documents directly to reduce orchestrator context load. (Tools: Read, Bash, Grep, Glob, Write)

- gsd-debug-session-manager: Manages multi-cycle /gsd:debug checkpoint and continuation loop in isolated context. Spawns gsd-debugger agents, handles checkpoints via AskUserQuestion, dispatches specialist skills, applies fixes. Returns compact summary to main context. Spawned by /gsd:debug command. (Tools: Read, Write, Bash, Grep, Glob, Agent, AskUserQuestion)

- gsd-debugger: Investigates bugs using scientific method, manages debug sessions, handles checkpoints. Spawned by /gsd:debug orchestrator. (Tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch)

- gsd-doc-classifier: Classifies a single planning document as ADR, PRD, SPEC, DOC, or UNKNOWN. Extracts title, scope summary, and cross-references. Spawned in parallel by /gsd:ingest-docs. Writes a JSON classification file and returns a one-line confirmation. (Tools: Read, Write, Grep, Glob)

- gsd-doc-synthesizer: Synthesizes classified planning docs into a single consolidated context. Applies precedence rules, detects cross-ref cycles, enforces LOCKED-vs-LOCKED hard-blocks, and writes INGEST-CONFLICTS.md with three buckets (auto-resolved, competing-variants, unresolved-blockers). Spawned by /gsd:ingest-docs. (Tools: Read, Write, Grep, Glob, Bash)

- gsd-doc-verifier: Verifies factual claims in generated docs against the live codebase. Returns structured JSON per doc. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-doc-writer: Writes and updates project documentation. Spawned with a doc_assignment block specifying doc type, mode (create/update/supplement), and project context. (Tools: Read, Bash, Grep, Glob, Write)

- gsd-domain-researcher: Researches the business domain and real-world application context of the AI system being built. Surfaces domain expert evaluation criteria, industry-specific failure modes, regulatory context, and what "good" looks like for practitioners in this field — before the eval-planner turns it into measurable rubrics. Spawned by /gsd:ai-integration-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*)

- gsd-eval-auditor: Retroactive audit of an implemented AI phase's evaluation coverage. Checks implementation against the AI-SPEC.md evaluation plan. Scores each eval dimension as COVERED/PARTIAL/MISSING. Produces a scored EVAL-REVIEW.md with findings, gaps, and remediation guidance. Spawned by /gsd:eval-review orchestrator. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-eval-planner: Designs a structured evaluation strategy for an AI phase. Identifies critical failure modes, selects eval dimensions with rubrics, recommends tooling, and specifies the reference dataset. Writes the Evaluation Strategy, Guardrails, and Production Monitoring sections of AI-SPEC.md. Spawned by /gsd:ai-integration-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, AskUserQuestion)

- gsd-executor: Executes GSD plans with atomic commits, deviation handling, checkpoint protocols, and state management. Spawned by execute-phase orchestrator or execute-plan command. (Tools: Read, Write, Edit, Bash, Grep, Glob, mcp__context7__*)

- gsd-framework-selector: Presents an interactive decision matrix to surface the right AI/LLM framework for the user's specific use case. Produces a scored recommendation with rationale. Spawned by /gsd:ai-integration-phase and /gsd-select-framework orchestrators. (Tools: Read, Bash, Grep, Glob, WebSearch, AskUserQuestion)

- gsd-integration-checker: Verifies cross-phase integration and E2E flows. Checks that phases connect properly and user workflows complete end-to-end. (Tools: Read, Bash, Grep, Glob)

- gsd-intel-updater: Analyzes codebase and writes structured intel files to .planning/intel/. (Tools: Read, Write, Bash, Glob, Grep)

- gsd-nyquist-auditor: Fills Nyquist validation gaps by generating tests and verifying coverage for phase requirements (Tools: Read, Write, Edit, Bash, Glob, Grep)

- gsd-pattern-mapper: Analyzes codebase for existing patterns and produces PATTERNS.md mapping new files to closest analogs. Read-only codebase analysis spawned by /gsd:plan-phase orchestrator before planning. (Tools: Read, Bash, Glob, Grep, Write)

- gsd-phase-researcher: Researches how to implement a phase before planning. Produces RESEARCH.md consumed by gsd-planner. Spawned by /gsd:plan-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*)

- gsd-plan-checker: Verifies plans will achieve phase goal before execution. Goal-backward analysis of plan quality. Spawned by /gsd:plan-phase orchestrator. (Tools: Read, Bash, Glob, Grep)

- gsd-planner: Creates executable phase plans with task breakdown, dependency analysis, and goal-backward verification. Spawned by /gsd:plan-phase orchestrator. (Tools: Read, Write, Bash, Glob, Grep, WebFetch, mcp__context7__*)

- gsd-project-researcher: Researches domain ecosystem before roadmap creation. Produces files in .planning/research/ consumed during roadmap creation. Spawned by /gsd:new-project or /gsd:new-milestone orchestrators. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*)

- gsd-research-synthesizer: Synthesizes research outputs from parallel researcher agents into SUMMARY.md. Spawned by /gsd:new-project after 4 researcher agents complete. (Tools: Read, Write, Bash)

- gsd-roadmapper: Creates project roadmaps with phase breakdown, requirement mapping, success criteria derivation, and coverage validation. Spawned by /gsd:new-project orchestrator. (Tools: Read, Write, Bash, Glob, Grep)

- gsd-security-auditor: Verifies threat mitigations from PLAN.md threat model exist in implemented code. Produces SECURITY.md. Spawned by /gsd:secure-phase. (Tools: Read, Write, Edit, Bash, Glob, Grep)

- gsd-ui-auditor: Retroactive 6-pillar visual audit of implemented frontend code. Produces scored UI-REVIEW.md. Spawned by /gsd:ui-review orchestrator. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-ui-checker: Validates UI-SPEC.md design contracts against 6 quality dimensions. Produces BLOCK/FLAG/PASS verdicts. Spawned by /gsd:ui-phase orchestrator. (Tools: Read, Bash, Glob, Grep)

- gsd-ui-researcher: Produces UI-SPEC.md design contract for frontend phases. Reads upstream artifacts, detects design system state, asks only unanswered questions. Spawned by /gsd:ui-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*)

- gsd-user-profiler: Analyzes extracted session messages across 8 behavioral dimensions to produce a scored developer profile with confidence levels and evidence. Spawned by profile orchestration workflows. (Tools: Read)

- gsd-verifier: Verifies phase goal achievement through goal-backward analysis. Checks codebase delivers what phase promised, not just that tasks completed. Creates VERIFICATION.md report. (Tools: Read, Write, Bash, Grep, Glob)

- Plan: Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs. (Tools: All tools except Agent, ExitPlanMode, Edit, Write, NotebookEdit)

- statusline-setup: Use this agent to configure the user's Claude Code status line setting. (Tools: Read, Edit)


[Image: source: C:\Users\decid\Documents\ShareX\Screenshots\2026-06\Discord_M7VztH2xhz.png]


agree with ccs as profile and fllback wording, agree with hybrid. note that ccs also has a different i.e. `~/.ccs` logs dir per ccs profile. -for the skeleton plugin, note that spt-claude-code can use…


Dense batch — confirming, investigating two premises, engaging the open ones.

**Quick agreements (recorded):**
- ccs **per-profile `~/.ccs` log dir** → folds cleanly into the profile: the history/`[digest]` locate-template leaf-replaces to the profile's log dir. Same mechanism, no new machinery.
- **Adapter-strings deliver skill instructions** — yes, strong agree. It's the same channel as `[hints]`: one UserPromptSubmit hook detects `/spt:X`, `get-string`s X's instructions, injects as additionalContext. Skill .md files stay true skeletons; instruction churn lives in spt-core-conducted strings. This is what makes the thin-skill split actually hold.
- **Dual update path** (file-pull + cautionary `claude plugin update`) — agree; keeps spt-core's authoritative copy and the marketplace skeleton from drifting.

Two premises I need to verify before recommending — dispatching:


Fact-check UPS hook on slash-skill

Prompt:
Authoritative, current facts (cite docs, flag version-dependence). Concise, bottom-line each.

Scenario: a Claude Code plugin ships slash-command skills namespaced like `/spt:send`. I want a `UserPromptSubmit` hook to detect the invocation and inject the skill's real instructions as additionalContext (so the skill's own SKILL.md can stay a near-empty skeleton, with instructions delivered dynamically by the hook).

Answer:
1. When a user types a plugin slash-command/skill invocation like `/spt:send hello`, does the `UserPromptSubmit` hook fire, and does it receive the literal text `/spt:send hello` on stdin? Or does Claude Code intercept slash-commands/skills BEFORE UserPromptSubmit so the hook never sees them?
2. Can a `UserPromptSubmit` hook inject `additionalContext` that lands in the SAME turn the user invoked the command (so the injected instructions are present when the skill/command executes)?
3. How do a plugin SKILL.md's own body and UserPromptSubmit-injected additionalContext combine in one turn — does the skill body still load + execute, with the additionalContext as extra context? Any ordering/precedence gotcha?
4. Is there a BETTER native mechanism than UserPromptSubmit for "dynamically supply a skill's instructions at invocation time from an external source" — e.g. does a skill/command support an exec/generated body, or a hook event specific to skill invocation (PreSkill / SlashCommand)? List any relevant hook events.
5. Bottom line: is the "skeleton SKILL.md + UserPromptSubmit injects real instructions" pattern viable and reliable, or is there a failure mode (e.g. hook doesn't see slash invocations, or additionalContext doesn't reach the executing turn)?

If uncertain/undocumented, say so explicitly.