Problem
ZCode is a terminal coding agent in the same family as Claude Code / OpenCode: it has skills, plugins, MCP support, and a Stop hook that fires after every turn with a JSON payload (session_id, cwd, …) on stdin. Sessions are stored locally per user at:
~/.zcode/cli/rollout/model-io-sess_<uuid>.jsonl
where the session id reported by hooks carries a sess_ prefix (sess_<uuid>).
memsearch's promise is "a persistent, unified memory layer for all your AI agents", but ZCode is not among the supported harnesses, and today the situation is worse than "no integration": installing the Claude Code plugin under ZCode fails silently.
I verified this end-to-end in my setup:
- The Claude Code plugin's Stop hook does fire under ZCode (the hook contract is compatible), but
capture.sh resolves the transcript via Claude Code's ~/.claude/projects/<project>/<session_id>.jsonl layout.
- With a ZCode session id (
sess_<uuid>), the path construction mangles the id and points at a file that does not exist; capture then falls back / parses an empty transcript and skips the turn without any error surfaced to the user.
- The result is that users believe memory is being saved while
.memsearch/memory/ stays empty — the failure mode is invisible until you go hunting for why recall returns nothing.
Use case: run ZCode alongside Claude Code / Codex / OpenCode and have every agent's turns land in the same shared per-project Milvus collection, so recall works across harnesses — exactly what the other plugins already deliver.
Proposed solution
How would you like this to work?
Add a plugins/zcode/ integration mirroring the existing harness plugins:
-
Capture via ZCode's native Stop hook. ZCode hooks are configured in .zcode/settings.json (user or project scope) and are contract-compatible with Claude Code's hook I/O. The only real difference is transcript resolution: strip the sess_ prefix and map to ~/.zcode/cli/rollout/model-io-sess_<uuid>.jsonl.
-
A ZCode-aware rollout parser. ZCode rollout files differ from Claude Code transcripts in two ways that matter:
- Each JSONL line embeds the full conversation up to that turn, so last-turn extraction should read a tail window of the file instead of scanning it whole — real-world rollouts grow past 1 GB (I have a 1.7 GB one that parses in ~0.3 s with a tail-window reader).
- Noise such as
<task-notification> blocks (background task results) must not be recorded as user turns, and subagent sessions should be skipped.
-
Recall side. Expose the standard tool set (memory_search / memory_get / memory_transcript / memory_capture) either as a fastmcp server registered in ZCode's MCP config, or as ZCode skills — same shared per-project collection as the other harnesses, so all agents recall the same memories.
-
No silent failures. Whatever the capture path, when the transcript cannot be located or parses to zero turns, surface it (non-zero hook exit / log line) instead of skipping quietly. This single behavior change would have saved me a multi-week "why is my memory empty" investigation.
-
README section for ZCode install + hook registration + tool reference, like the other agents.
Alternatives considered
Any workarounds or alternative approaches you've considered?
- User-side Stop hook + custom parser (my current workaround). I run a patched capture hook that strips the
sess_ prefix, does tail-window parsing, per-turn dedup, and error surfacing. It works, but it's a fork of capture logic that will rot as formats evolve, and it doesn't get the shared-index/recall plumbing for free. An official plugin shares code with the other harness plugins and stays in sync.
- Manual capture via the memsearch CLI after each session. Works but relies on remembering to do it; automatic capture is the whole point of the hooks.
- Keep using the Claude Code plugin unchanged. Not viable — it skips every ZCode turn silently (see Problem).
Problem
ZCode is a terminal coding agent in the same family as Claude Code / OpenCode: it has skills, plugins, MCP support, and a Stop hook that fires after every turn with a JSON payload (
session_id,cwd, …) on stdin. Sessions are stored locally per user at:where the session id reported by hooks carries a
sess_prefix (sess_<uuid>).memsearch's promise is "a persistent, unified memory layer for all your AI agents", but ZCode is not among the supported harnesses, and today the situation is worse than "no integration": installing the Claude Code plugin under ZCode fails silently.
I verified this end-to-end in my setup:
capture.shresolves the transcript via Claude Code's~/.claude/projects/<project>/<session_id>.jsonllayout.sess_<uuid>), the path construction mangles the id and points at a file that does not exist; capture then falls back / parses an empty transcript and skips the turn without any error surfaced to the user..memsearch/memory/stays empty — the failure mode is invisible until you go hunting for why recall returns nothing.Use case: run ZCode alongside Claude Code / Codex / OpenCode and have every agent's turns land in the same shared per-project Milvus collection, so recall works across harnesses — exactly what the other plugins already deliver.
Proposed solution
How would you like this to work?
Add a
plugins/zcode/integration mirroring the existing harness plugins:Capture via ZCode's native Stop hook. ZCode hooks are configured in
.zcode/settings.json(user or project scope) and are contract-compatible with Claude Code's hook I/O. The only real difference is transcript resolution: strip thesess_prefix and map to~/.zcode/cli/rollout/model-io-sess_<uuid>.jsonl.A ZCode-aware rollout parser. ZCode rollout files differ from Claude Code transcripts in two ways that matter:
<task-notification>blocks (background task results) must not be recorded as user turns, and subagent sessions should be skipped.Recall side. Expose the standard tool set (
memory_search/memory_get/memory_transcript/memory_capture) either as a fastmcp server registered in ZCode's MCP config, or as ZCode skills — same shared per-project collection as the other harnesses, so all agents recall the same memories.No silent failures. Whatever the capture path, when the transcript cannot be located or parses to zero turns, surface it (non-zero hook exit / log line) instead of skipping quietly. This single behavior change would have saved me a multi-week "why is my memory empty" investigation.
README section for ZCode install + hook registration + tool reference, like the other agents.
Alternatives considered
Any workarounds or alternative approaches you've considered?
sess_prefix, does tail-window parsing, per-turn dedup, and error surfacing. It works, but it's a fork of capture logic that will rot as formats evolve, and it doesn't get the shared-index/recall plumbing for free. An official plugin shares code with the other harness plugins and stays in sync.