Environment: plugin 0.2.0, nmem 0.10.73, ZCode CLI 0.16.5 / App 3.10.0, macOS — two Macs with identical versions of both nmem and the plugin.
We spent a full day diagnosing why one Mac auto-synced ZCode sessions and the other silently synced nothing. Two independent failure modes found; documenting both so others (and the plugin) can short-circuit this.
1. Same plugin, different marketplace source → hooks loaded vs never loaded
- Mac A installed via the GitHub marketplace source → plugin hooks load, sessions auto-sync. ✅
- Mac B installed the same plugin 0.2.0 from a local directory marketplace (local clone registered as a
directory-type source) → ZCode never loads the plugin's hooks. ❌
The only observable signal is in ZCode's startup log (~/.zcode/cli/log/zcode-<date>.jsonl, event bootstrap.app.startup.plugins.completed): hookCount: 0 on Mac B vs a positive count on Mac A. Nothing surfaces in the UI; nmem doctor shows everything green on both. Sessions just silently never sync.
The marketplace registration itself looks healthy on Mac B: plugin listed as enabled, cache populated, commands/skills resolvable.
Suggestions:
- Make hooks from
directory-source marketplaces load identically to GitHub-sourced ones — or fail loudly / document the limitation.
- Add a doctor check "ZCode actually registered the plugin's hooks" (reading the same
hookCount signal), so this failure mode is diagnosable without cross-machine diffing.
2. ZCode 0.16.5's Stop transcript contains only the last assistant message
ZCode 0.16.5's hook runner writes the Stop transcript as a single JSONL line with only the final assistant message:
{"message":{"content":[{"text":"…","type":"text"}],"role":"assistant"}}
(see Hei() in zcode.cjs — JDr("assistant", e.responseText ?? e.responsePreview)).
nmem t sync --from zcode then rejects it with:
ZCode session needs at least one user and one assistant message
So on this ZCode build the stock Stop hook fires but the sync can never succeed — the error only appears in hook stderr.
Workaround we deployed (working reliably on 0.16.5): instead of copying transcript_path, the Stop hook exports the full user/assistant conversation for session_id straight from ~/.zcode/cli/db/db.sqlite (session/message/part schema is OpenCode-compatible), emits it in the same one-line-per-message format, and feeds that to t sync --from zcode --apply. Full conversation per turn, idempotent, and it also survives the assistant-only transcript limitation.
Longer-term options:
- Have the hook script fall back to reading the ZCode sqlite store (like the workaround above), or
- Have
t sync --from zcode tolerate assistant-only transcripts by pulling the missing user turns via --session-id.
Footnote
Two more things that extended our debugging session, in case they help others:
- The MCP server
type must be http (not streamableHttp) in ~/.zcode/cli/config.json — wrong values are silently skipped (only a config.mcp_server.skipped warn in the same log file).
- Hooks are registered when the ZCode process starts; editing
config.json requires a full app restart for hooks (MCP reconnects per session and picks changes up immediately).
Environment: plugin 0.2.0, nmem 0.10.73, ZCode CLI 0.16.5 / App 3.10.0, macOS — two Macs with identical versions of both nmem and the plugin.
We spent a full day diagnosing why one Mac auto-synced ZCode sessions and the other silently synced nothing. Two independent failure modes found; documenting both so others (and the plugin) can short-circuit this.
1. Same plugin, different marketplace source → hooks loaded vs never loaded
directory-type source) → ZCode never loads the plugin's hooks. ❌The only observable signal is in ZCode's startup log (
~/.zcode/cli/log/zcode-<date>.jsonl, eventbootstrap.app.startup.plugins.completed):hookCount: 0on Mac B vs a positive count on Mac A. Nothing surfaces in the UI;nmem doctorshows everything green on both. Sessions just silently never sync.The marketplace registration itself looks healthy on Mac B: plugin listed as enabled, cache populated, commands/skills resolvable.
Suggestions:
directory-source marketplaces load identically to GitHub-sourced ones — or fail loudly / document the limitation.hookCountsignal), so this failure mode is diagnosable without cross-machine diffing.2. ZCode 0.16.5's Stop transcript contains only the last assistant message
ZCode 0.16.5's hook runner writes the
Stoptranscript as a single JSONL line with only the final assistant message:{"message":{"content":[{"text":"…","type":"text"}],"role":"assistant"}}(see
Hei()in zcode.cjs —JDr("assistant", e.responseText ?? e.responsePreview)).nmem t sync --from zcodethen rejects it with:So on this ZCode build the stock Stop hook fires but the sync can never succeed — the error only appears in hook stderr.
Workaround we deployed (working reliably on 0.16.5): instead of copying
transcript_path, the Stop hook exports the full user/assistant conversation forsession_idstraight from~/.zcode/cli/db/db.sqlite(session/message/part schema is OpenCode-compatible), emits it in the same one-line-per-message format, and feeds that tot sync --from zcode --apply. Full conversation per turn, idempotent, and it also survives the assistant-only transcript limitation.Longer-term options:
t sync --from zcodetolerate assistant-only transcripts by pulling the missing user turns via--session-id.Footnote
Two more things that extended our debugging session, in case they help others:
typemust behttp(notstreamableHttp) in~/.zcode/cli/config.json— wrong values are silently skipped (only aconfig.mcp_server.skippedwarn in the same log file).config.jsonrequires a full app restart for hooks (MCP reconnects per session and picks changes up immediately).