klypix-mcp 1.108.0 → 1.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -93,8 +93,9 @@ has the details.
93
93
  | **Claude Desktop** | A one-time config entry | The KLYPIX app's Settings, or by hand |
94
94
  | **Claude, as a plugin** | One pinned version, keyword search, no hooks | [klypix-plugin](https://github.com/dahshanlabs/klypix-plugin) |
95
95
 
96
- klypix-mcp has 27 MCP tools on Linux and macOS and 28 on Windows, where `show_in_klypix` is
97
- added. `npx klypix-mcp doctor` shows the count for your install.
96
+ klypix-mcp has 28 MCP tools on Linux and macOS and 29 on Windows, where `show_in_klypix` is
97
+ added (one fewer in plugin mode, which leaves out `prepare_video`). `npx klypix-mcp doctor` shows
98
+ the count for your install.
98
99
 
99
100
  > **One project. Many agents. One current understanding.**
100
101
 
@@ -128,10 +129,10 @@ tool's official documentation and says that KLYPIX wrote it) · [klypix.com/klyp
128
129
  [Overlap warnings](#overlap-warnings) ·
129
130
  [Teammates on other computers](#teammates-on-other-computers-klypix-network) ·
130
131
  [Handoffs and messages](#handoffs-and-messages) · [Evidence-gated completion](#evidence-gated-completion) ·
131
- [Human control in KLYPIX](#human-control-in-klypix) · [Measure it yourself](#measure-it-yourself) ·
132
+ [Human control in KLYPIX](#human-control-in-klypix) · [Prepare a video for your own AI](#prepare-a-video-for-your-own-ai) · [Measure it yourself](#measure-it-yourself) ·
132
133
  [Git and concurrency](#git-and-concurrency) ·
133
134
  [The git guard for a shared checkout](#whose-is-this-the-git-guard-for-a-shared-checkout) ·
134
- [The command line](#the-command-line) · [The verbs](#the-verbs-27-and-28-on-windows) ·
135
+ [The command line](#the-command-line) · [The verbs](#the-verbs-28-and-29-on-windows) ·
135
136
  [One file you can hold](#one-file-you-can-hold) · [Use it as a library](#use-it-as-a-library) ·
136
137
  [A2A](#also-speaks-a2a-protocol-v030--experimental) ·
137
138
  [Updates](#updates--the-propagation-contract) · [Security and permissions](#security-and-permissions) ·
@@ -477,7 +478,7 @@ behaviour is unverified.
477
478
 
478
479
  | Host | Level | Wired by | Brief into context | Decision capture | Live presence |
479
480
  |---|---|---|---|---|---|
480
- | **Claude Code** | Full automatic (6 lifecycle hooks since 1.105.0) | `install` | Automatic at session start, task-ranked retrieval per prompt | **Automatic** at turn end | Yes |
481
+ | **Claude Code** | Full automatic (8 lifecycle hooks since 1.109.0; subagents get child ids) | `install` | Automatic at session start, task-ranked retrieval per prompt | **Automatic** at turn end | Yes |
481
482
  | **Codex** | Native MCP + presence + Context Gateway; optional `--codex-hooks` | `install` | Via `brain_sync`; per-prompt injection only with `--codex-hooks` | **Explicit only** (`brain_note`) — never automatic | Yes |
482
483
  | **Cursor** | MCP config + always-on rules file | `link` | Model must call `brain_sync` | Model must call `brain_note` | For the MCP connection |
483
484
  | **Cline** | MCP config + always-on rules file | `link` | Model must call `brain_sync` | Model must call `brain_note` | For the MCP connection |
@@ -547,7 +548,8 @@ first is npx downloading the pinned package when the plugin starts the server. T
547
548
  tags, log) for coordination and release checks. Also `brain_reopen`, described at the end of this
548
549
  section. And on Windows, `show_in_klypix` with `bring_to_front: true` while KLYPIX is closed asks
549
550
  Windows to open that canvas file in KLYPIX (PowerShell `Start-Process`), at most once every 30
550
- seconds; it never does so while KLYPIX is running.
551
+ seconds; it never does so while KLYPIX is running. `prepare_video`, which runs ffmpeg, yt-dlp and
552
+ Whisper, is not registered at all in plugin mode, and refuses if it is ever called there.
551
553
 
552
554
  **The KLYPIX app, when it is running (local, not the network).** On Windows, a tool call that needs
553
555
  the KLYPIX app (*App mode*, under *Human control in Klypix*) talks to the app over a local named
@@ -740,6 +742,48 @@ Future hosts get baseline support merely by connecting the MCP server. A deeper
740
742
  `peekMessages` and `receiveMessages`. The shared contract accepts `id`, `client`, `surface`,
741
743
  `model`, `branch`, `intent`, touched `files`, and adapter `channel`.
742
744
 
745
+ ### Who did what: subagents, model and role (1.109.0)
746
+
747
+ Three small labels, each recorded only where the host reports it.
748
+
749
+ **Subagents.** When Claude Code starts a subagent, its `SubagentStart` hook reports an `agent_id`
750
+ and `agent_type`, and every tool call inside the subagent carries the same `agent_id`. KLYPIX
751
+ records the subagent as a child of its session, named `<session>/sub-<6 hex>` (for example
752
+ `7ff6f074/sub-1a2b3c`):
753
+
754
+ - files it edits land on its child entry (and, as before, on the session's own files);
755
+ - a subagent about to edit a file a sibling subagent of the same session already edited is warned
756
+ before the edit (a warning, not a lock);
757
+ - `🧠 BRAIN` lines it writes are captured from its own transcript at the session's next turn end,
758
+ stamped with the child id, instead of being lost;
759
+ - its `brain_sync` lands on the child entry when it passes `agent: "sub-1a2b3c"`. The id is handed
760
+ to the subagent when it starts. A subagent shares its session's MCP connection, and that
761
+ connection carries no subagent identity, so this one step depends on the subagent passing the
762
+ id. KLYPIX accepts only an id the hook recorded; any other id is ignored and the call is recorded
763
+ under the session, as before.
764
+
765
+ Peers see a session's subagents under it in `brain_sync` and the presence footer. Codex and the
766
+ other hosts do not report subagents to hooks or MCP, so their subagents' work stays under the parent
767
+ session. `npx klypix-mcp doctor` says which applies on your machine.
768
+
769
+ **Model.** A captured card records `capturedBy: { session, agent?, tool, model }`. The model is
770
+ what the host wrote: the `model` of the transcript entry that holds the marker (Claude Code), or the
771
+ model Codex sends with each hook event. When the host did not report it, the stamp says `unknown`.
772
+ A card or handoff written through an MCP tool from Claude Code says `unknown`, because nothing tells
773
+ the MCP server about a `/model` switch between turns. Presence shows the model each session last
774
+ reported.
775
+
776
+ **Role.** `brain_sync { role: "reviewer" }` puts a free-text label on the session for its lifetime.
777
+ Peers see it, and `brain_handoff { action: "write", for: "reviewer", … }` addresses a handoff to
778
+ it: a session that declares that role sees the card first, marked as addressed to its role. Every
779
+ other session still sees it. A role is a label only. It carries no history, reputation or authority
780
+ from earlier sessions, and nothing reserves the work. Persistent seats with inherited history were
781
+ considered and deferred: a new session or model in an old seat would read earlier conclusions as
782
+ its own.
783
+
784
+ All three are optional additive fields. Older brains, lane rows and peers without them work as
785
+ before.
786
+
743
787
  ### Overlap warnings
744
788
 
745
789
  `brain_sync` reports three kinds of overlap with other live sessions on the same brain:
@@ -1082,6 +1126,59 @@ Limits, and why:
1082
1126
  it while it runs), so it cannot be handed over from the saved canvas; the answer says so.
1083
1127
  - Cards inside a box locked from AI tools are never read, copied or attached.
1084
1128
 
1129
+ ### Prepare a video for your own AI
1130
+
1131
+ `prepare_video` turns a video into evidence your AI tool reads with **its own model and your own
1132
+ subscription** (Claude Code, Claude Cowork, Codex and other MCP hosts on your PC). KLYPIX makes no
1133
+ AI call for it, so it costs nothing in KLYPIX AI. Everything runs on your computer:
1134
+
1135
+ 1. **The video.** A local file needs nothing else. A public link on a known video platform
1136
+ (YouTube, Vimeo, TikTok, Instagram, Facebook, X, Reddit, Loom, Twitch and a few others) is
1137
+ downloaded with **your** yt-dlp, and only when the call passes `allow_download: true`. Your AI
1138
+ tool should ask you first. You are responsible for following the platform's terms and the
1139
+ creator's rights. Links to other sites, to local or internal addresses, or with a user name or
1140
+ password are refused. For those, download the file yourself and pass its path.
1141
+ 2. **Keyframes.** ffmpeg finds scene changes, and the frames are spread over the whole timeline:
1142
+ the timeline is cut into equal parts and each part takes its nearest scene change, or its
1143
+ middle when nothing changed there. 24 frames by default, at most 48, JPEG, at most 640 pixels
1144
+ wide. A few come back inside the answer as images (8 by default, within a size budget that
1145
+ keeps the answer under 1 MB); every frame is listed with its time and a local file path your AI
1146
+ tool can open.
1147
+ 3. **Transcript with timestamps.** The platform's own captions when yt-dlp finds them (the video's
1148
+ original language first, then English, or the `language` you ask for). Otherwise local Whisper,
1149
+ if one is installed. Otherwise the answer says there is no transcript and why. A long transcript
1150
+ comes in parts (`transcript_chunk`), answered from the cache without preparing the video again.
1151
+ 4. **Metadata.** Title, uploader and duration.
1152
+
1153
+ The downloaded or decoded media is deleted before the call returns. Only the frames, the
1154
+ transcript and a small manifest are kept, in `<system temp>/klypix-video-prep/<id>/` (or
1155
+ `KLYPIX_VIDEO_CACHE`), and folders older than 7 days are removed on the next call. Calling again
1156
+ with the same video answers from that folder; `refresh: true` prepares it again.
1157
+
1158
+ **What you need installed.** klypix-mcp never ships or installs any of these. It finds them on your
1159
+ `PATH`, and the answer says what is missing:
1160
+
1161
+ | Program | Needed for | Install, for example |
1162
+ |---|---|---|
1163
+ | `ffmpeg` and `ffprobe` | Every video | `winget install ffmpeg`, `brew install ffmpeg`, `apt install ffmpeg` |
1164
+ | `yt-dlp` | Links only | `winget install yt-dlp`, `brew install yt-dlp`, `pip install yt-dlp`. Keep it current (`yt-dlp -U`): platforms often break older versions |
1165
+ | A Whisper CLI | A transcript when the video has no captions (optional) | `whisper-cli` from whisper.cpp with `KLYPIX_WHISPER_MODEL` set to a ggml model file; `whisper-ctranslate2` (faster-whisper); or `whisper` (openai-whisper), where `KLYPIX_WHISPER_MODEL` may name a model such as `small` |
1166
+
1167
+ **Privacy.** Frames, transcript and metadata are made on your PC. The only network traffic is
1168
+ yt-dlp downloading a link you allowed, from that platform. KLYPIX servers are not involved. What
1169
+ your AI tool does with the frames and transcript is between you and your AI provider.
1170
+
1171
+ **Safety.** Programs are started with an argument list, never through a shell; on Windows only
1172
+ `.exe` programs are run. yt-dlp runs with `--ignore-config` (so a config file cannot add commands),
1173
+ `--no-playlist`, a 2 GB size cap and `--` before the link. A link's host must not be, or resolve
1174
+ to, a loopback, private or link-local address. ffmpeg reads local files with
1175
+ `-protocol_whitelist file`. Every step has a time limit and stops when the request is cancelled.
1176
+ Transcripts and metadata are returned as data, never as instructions.
1177
+
1178
+ **Not yet.** Reading a video by its KLYPIX space source id (fetching the original link from your
1179
+ KLYPIX account) needs a KLYPIX account sign-in in klypix-mcp, which it does not have. Today, pass
1180
+ the link or the file.
1181
+
1085
1182
  ### Measure it yourself
1086
1183
 
1087
1184
  Claims about a shared brain — "nothing is lost", "it stays fast" — are unfalsifiable until a
@@ -1251,7 +1348,7 @@ The MCP verbs below are what agents call. These are what **you** call:
1251
1348
  | `npx klypix-mcp rescue` | Rescue copies the git guard saved before a discard: `list`, `show <id>`, `restore <id> [paths…]`, `prune` |
1252
1349
  | `npx klypix-mcp sessions` | This project's closed sessions and the notes waiting for them; `sessions reopen <id>` reopens one |
1253
1350
 
1254
- ### The verbs: 27, and 28 on Windows
1351
+ ### The verbs: 28, and 29 on Windows
1255
1352
 
1256
1353
  | Tool | What it does |
1257
1354
  |---|---|
@@ -1262,7 +1359,8 @@ The MCP verbs below are what agents call. These are what **you** call:
1262
1359
  | `brain_insights` | Hubs, orphaned decisions, stale questions, area sizes |
1263
1360
  | `brain_lens` | Machine-readable freshness, provenance, activity, timeline, orrery and unresolved views; on a canvas open in KLYPIX (Windows), the first five come from KLYPIX's own lens code |
1264
1361
  | `brain_garden` | Maintenance pass — proposes first; consolidation cannot apply without an approval code the human generates. The separate `repair:"duplicate-partials"` pass is dry-run first and needs no code (it removes only exact repeats and archives nothing) |
1265
- | `brain_rules` | Project rules made from the brain's lessons: `propose` routes each lesson to rule, instruction or note; `add` writes candidates to `.klypix/rules.json`; `promote` and `retire` need the person's approval code, and a rule warns unless the person approved it with `--block`; `check` runs the rules on a diff; `status` shows blocks, overrides, false alarms and retirement suggestions. No AI at check time ([docs/brain-rules.md](docs/brain-rules.md)) |
1362
+ | `brain_rules` | Project rules made from the brain's lessons: `propose` routes each lesson to rule, instruction or note; `add` writes candidates to `.klypix/rules.json`; `promote` and `retire` ask the person in an MCP form or Windows review dialog (terminal code fallback); blocking requires approval of `block:true`; `check` runs the rules on a diff; `status` shows blocks, overrides, false alarms and retirement suggestions. No AI at check time ([docs/brain-rules.md](docs/brain-rules.md)) |
1363
+ | `brain_review` | Opt-in independent first pass for a review or decision: `start` withholds other sessions' assessments and objections on the topic from brain_sync and brain_ask (facts and decisions stay visible), `submit` records yours and then shows theirs. KLYPIX controls only what it returns, so this records independence; it does not enforce it. Related crowd safeguards in every answer: a claim repeated by several cards is shown as one claim with its source, restatements and re-checks, and an `OBJECTION:` card stays open until a decision that links it closes it ([docs/crowd-safeguards.md](docs/crowd-safeguards.md)) |
1266
1364
  | `brain_doctor` | Self-diagnosis: version, core/enhanced host adapters, active sessions, tool count, projection drift |
1267
1365
  | `brain_message` | Session-to-session coordination notes — to a live session, or queued for one that is not running until it next starts — with a fixed send-time audience and per-recipient pending / offer / acknowledgement / consumption / failure receipts (a directed note is kept 7 days, a broadcast 24h; never written into the brain) |
1268
1366
  | `brain_message_receipt` | Explicitly record model-side consumption using the exact message id and per-recipient offer token; acknowledgement alone never consumes a note |
@@ -1283,8 +1381,9 @@ The MCP verbs below are what agents call. These are what **you** call:
1283
1381
  | `create_canvas` | New `.klypix` from cards + connections |
1284
1382
  | `add_to_canvas` | Append cards/connections (positions preserved), bordered and readable on KLYPIX's dark and Paper themes; a card's `group` puts it in that titled box. On a canvas open in KLYPIX (Windows) the cards go to KLYPIX itself: live, attributed, one undo. When KLYPIX cannot take them it refuses (`OPEN_IN_APP`, `ACCESS_OFF`, `BLOCKED`), a box locked from AI tools (`SCOPE_LOCKED`) or a frozen box (`FROZEN`), and writes nothing; project brains are the exception to the first. Returns the new card ids |
1285
1383
  | `list_canvases` | List every `.klypix` in the vault |
1384
+ | `prepare_video` | Keyframes (scene changes across the whole timeline, up to 48 JPEGs), a timestamped transcript (platform captions, else local Whisper, else an honest "none") and title, uploader and duration of a local video file or a public video link, made on this PC with the user's own ffmpeg, yt-dlp and Whisper, for the calling AI to analyse with its own model. Links are downloaded only with `allow_download: true`; the media is deleted after extraction. Not registered in plugin mode. See *Prepare a video for your own AI* |
1286
1385
 
1287
- Exactly 27 on Linux and macOS and 28 on Windows, where `show_in_klypix` is registered; machine-verifiable with `npx klypix-mcp doctor`, whose TOOLS line applies the same rule and whose App bridge line says whether KLYPIX is running, with access on or off.
1386
+ Exactly 28 on Linux and macOS and 29 on Windows, where `show_in_klypix` is registered (one fewer in plugin mode, without `prepare_video`); machine-verifiable with `npx klypix-mcp doctor`, whose TOOLS line applies the same rule and whose App bridge line says whether KLYPIX is running, with access on or off.
1288
1387
 
1289
1388
  > **`canvas_view`:** no MCP Apps host has been observed rendering the UI resource yet — there is no
1290
1389
  > screenshot and no host-level test. Hosts without the extension get clean text, which is the path
@@ -351,7 +351,10 @@ const flatten = (code) => code
351
351
  // formatHandoffCards from it directly (1.99.0 only reached it via core).
352
352
  // brain-rules (project rules): the worker's brain_rules tool and the
353
353
  // dispatcher's `check` / `rules` verbs import it lazily.
354
- .replace(/\.\.\/src\/(bench|brain-doctor|agent-presence|agent-rules|capture-gap|enrichment|finding-routing|mcp-presence|mcp-supervisor|mcp-auto-update|presence-relay|repo-state|semantic-memory|runtime-inspector|project-graph|git-capture-install|app-lease|app-tools|app-bridge-protocol|app-bridge-client|session-handoff|brain-rules)\.mjs/g, './$1.mjs')
354
+ // video-prep: the worker's prepare_video tool imports it lazily.
355
+ // crowd-safeguards / crowd-review: the worker's brain_sync crowd block and
356
+ // brain_review tool import them directly.
357
+ .replace(/\.\.\/src\/(bench|brain-doctor|agent-presence|agent-rules|capture-gap|enrichment|finding-routing|mcp-presence|mcp-supervisor|mcp-auto-update|presence-relay|repo-state|semantic-memory|runtime-inspector|project-graph|git-capture-install|app-lease|app-tools|app-bridge-protocol|app-bridge-client|session-handoff|brain-rules|video-prep|crowd-safeguards|crowd-review)\.mjs/g, './$1.mjs')
355
358
  .replace(/klypix-worker\.mjs/g, 'klypix-mcp-worker.mjs')
356
359
  .replace(/const PKG_VERSION = \(\(\) => \{[\s\S]*?\}\)\(\);/, `const PKG_VERSION = '${VERSION}'; // baked at install (flat layout has no package.json)`);
357
360
 
@@ -497,7 +500,7 @@ try {
497
500
  // a newer klypix-format cannot. merge-brains and the driver ship here so
498
501
  // brain-history's restore merge, the KLYPIX core and the git driver all
499
502
  // find one engine in this directory.
500
- for (const f of ['global-brain-hook.mjs', 'klypix-format.mjs', 'brain-graveyard.mjs', 'merge-brains.mjs', 'klypix-merge-driver.mjs', 'capture-gap.mjs', 'brain-semantic.mjs', 'semantic-memory.mjs', 'enrichment.mjs', 'provenance.mjs', 'brain-note.mjs', 'brain-evidence.mjs', 'brain-git-hook.mjs', 'git-capture-install.mjs', 'brain-history.mjs', 'app-lease.mjs', 'klypix-core.mjs', 'app-bridge-protocol.mjs', 'app-bridge-client.mjs', 'app-tools.mjs', 'card-files.mjs', 'brain-write-lock.mjs', 'brain-rules.mjs', 'agent-rules.mjs', 'brain-doctor.mjs', 'editor-detect.mjs', 'agent-presence.mjs', 'mcp-presence.mjs', 'repo-state.mjs', 'result-reconcile.mjs', 'finding-routing.mjs', 'presence-relay.mjs', 'network-bridge.mjs', 'mcp-supervisor.mjs', 'mcp-auto-update.mjs', 'runtime-inspector.mjs', 'project-graph.mjs', 'bench.mjs', 'codex-brain-hook.mjs', 'codex-hooks.mjs', 'session-handoff.mjs', 'live-projection.mjs', 'whose.mjs', 'whose-classify.mjs', 'whose-ledger.mjs', 'whose-rescue.mjs', 'canvas-view-app.html']) {
503
+ for (const f of ['global-brain-hook.mjs', 'klypix-format.mjs', 'brain-graveyard.mjs', 'merge-brains.mjs', 'klypix-merge-driver.mjs', 'capture-gap.mjs', 'brain-semantic.mjs', 'semantic-memory.mjs', 'enrichment.mjs', 'provenance.mjs', 'brain-note.mjs', 'brain-evidence.mjs', 'crowd-safeguards.mjs', 'crowd-review.mjs', 'brain-git-hook.mjs', 'git-capture-install.mjs', 'brain-history.mjs', 'app-lease.mjs', 'klypix-core.mjs', 'app-bridge-protocol.mjs', 'app-bridge-client.mjs', 'app-tools.mjs', 'card-files.mjs', 'brain-write-lock.mjs', 'brain-rules.mjs', 'agent-rules.mjs', 'brain-doctor.mjs', 'editor-detect.mjs', 'agent-presence.mjs', 'mcp-presence.mjs', 'repo-state.mjs', 'result-reconcile.mjs', 'finding-routing.mjs', 'presence-relay.mjs', 'network-bridge.mjs', 'mcp-supervisor.mjs', 'mcp-auto-update.mjs', 'runtime-inspector.mjs', 'project-graph.mjs', 'bench.mjs', 'codex-brain-hook.mjs', 'codex-hooks.mjs', 'session-handoff.mjs', 'live-projection.mjs', 'whose.mjs', 'whose-classify.mjs', 'whose-ledger.mjs', 'whose-rescue.mjs', 'video-prep.mjs', 'canvas-view-app.html']) {
501
504
  const s = path.join(SRC, f); if (exists(s)) staged.push({ dst: f, content: fs.readFileSync(s, 'utf8') });
502
505
  }
503
506
  for (const [src, dst] of [
@@ -582,6 +585,12 @@ try {
582
585
  // next session read a dead peer as "live" and refused to continue its
583
586
  // work (round-4 continuity bench, 2026-10-20). Codex already had this.
584
587
  ['SessionEnd', { hooks: [{ type: 'command', command: brainCmd('--end'), timeout: 10 }] }],
588
+ // Subagent identity (1.109.0): Claude Code reports each subagent it
589
+ // starts and stops (agent_id / agent_type). The hook records it as a
590
+ // child of the session, so its files and markers keep their own name
591
+ // instead of merging into the parent's.
592
+ ['SubagentStart', { hooks: [{ type: 'command', command: brainCmd('--subagent-start'), timeout: 10 }] }],
593
+ ['SubagentStop', { hooks: [{ type: 'command', command: brainCmd('--subagent-stop'), timeout: 10 }] }],
585
594
  ];
586
595
  const stripOurs = (arr) => (Array.isArray(arr) ? arr : [])
587
596
  .map(g => (g && Array.isArray(g.hooks)) ? { ...g, hooks: g.hooks.filter(h => !(typeof h?.command === 'string' && h.command.includes(HOOK_MARK))) } : g)
@@ -657,7 +666,7 @@ try {
657
666
  // leave the brain LIVE but not LEARNING — liveness ≠ readiness). Warn, don't fail.
658
667
  const verify = RUNTIME_ONLY ? null : (() => { try { return JSON.parse(fs.readFileSync(SETTINGS, 'utf8')); } catch { return null; } })();
659
668
  const wiredFor = (evt) => Array.isArray(verify?.hooks?.[evt]) && verify.hooks[evt].some(g => Array.isArray(g?.hooks) && g.hooks.some(h => typeof h?.command === 'string' && h.command.includes(HOOK_MARK)));
660
- const notWired = ['SessionStart', 'UserPromptSubmit', 'Stop', 'PostToolUse', 'PreToolUse'].filter(e => !wiredFor(e));
669
+ const notWired = ['SessionStart', 'UserPromptSubmit', 'Stop', 'PostToolUse', 'PreToolUse', 'SubagentStart', 'SubagentStop'].filter(e => !wiredFor(e));
661
670
 
662
671
  releaseInstallLockSync(installLock);
663
672
  // Search by meaning: installed AFTER the brain itself is committed, so a
@@ -688,7 +697,7 @@ try {
688
697
  console.log(`✓ installed klypix brain v${VERSION} → ${BRAIN_DIR} (${n} scripts, ${deps} dep packages)`);
689
698
  reportSemantic(semanticStep);
690
699
  if (RUNTIME_ONLY) console.log('✓ runtime-only update: host settings and project files were preserved');
691
- else if (!notWired.length) console.log('✓ wired 6 hooks: SessionEnd (--end) · SessionStart · UserPromptSubmit (--prompt) · Stop (--capture) · PostToolUse (--live) · PreToolUse (--guard) → settings.json');
700
+ else if (!notWired.length) console.log('✓ wired 8 hooks: SessionEnd (--end) · SessionStart · UserPromptSubmit (--prompt) · Stop (--capture) · PostToolUse (--live) · PreToolUse (--guard) · SubagentStart / SubagentStop (--subagent-start / --subagent-stop) → settings.json');
692
701
  else console.error(`⚠ readiness: ${notWired.length} hook(s) did NOT take (${notWired.join(', ')}) — the brain will read but not capture/sync. Re-run \`npx klypix-mcp install --force\` or check ${SETTINGS}.`);
693
702
  console.log(`✓ MCP supervisor runs from the local bundle (node ${fwd(path.join(BRAIN_DIR, 'klypix-mcp-server.mjs'))}) — compatible core updates activate without restarting the host.`);
694
703
  if (migrated) console.log(`✓ migrated ${migrated.file} klypix-canvas server: ${migrated.from} → ${migrated.to} (backup: .mcp.json.klypix-bak). Reconnect (/mcp) or restart to pick it up.`);