Any agent: the record through hooks
Portable profiles add explicit source selection and recording policy to all
six supported clients. Use setup --profile NAME (or the standalone
installers’ --profile NAME) and inspect the capture fields, destination and
profile_support report. New profiles capture off by default; startup context
and memory remain available. Local/shared recording requires both profile and
binding consent, filtering precedes the spool, and new conversation IDs retain
native identity as provenance under a workspace namespace. Read neosian docs profiles for this policy. The session-ID and automatic-recording behavior
below describes existing profile-free hooks.
neosian is the state layer for the agent you already use. The memory
half is the MCP server and neosian mcp install (neosian docs mcp).
The record half is neosian record: the agent’s hooks call it with one
payload on stdin per event, and a prompt-to-stop span lands in the store
as one turn with a foreign actor (claude-code:<session_id>) in a
conversation keyed by the session id, plus a small sessions document
under the scope. Transcript files are never read: the documented hook
payloads are the import path.
Install
Section titled “Install”setup and status are provided by the binary.
Setup registers the executable running it, or the binary named by
--binary PATH. The binary also provides the standalone record install and mcp install forms below. MCP installation also supports
Claude Desktop, which has no recording hooks.
neosian setup --write # select clients, once per machineneosian setup --check --client codex # inspect saved settings and test MCP locallyneosian setup --url http://127.0.0.1:6367 --write # the same, behind the state processneosian record install --client claude-code # print the user-level hooksneosian record install --client codex --writeneosian record install --client opencode --level project --scope user:me --writeneosian setupruns this installer andmcp installfor every client it finds (their config directories are the evidence), prints first. On a terminal--writeasks which clients to connect, all selected initially. Scripts use--write --yesfor all detected clients or repeated--client Cfor an explicit selection. JSON never prompts. Both setup and status accept invocation-only--at CLIENT=DIRoverrides and report where they searched; a missing client home is never created. Claude Code setup also installs the cache plugin and observation bridge described below; the standalone MCP/hook installers do not. Codex setup installs the native upkeep skill described below. Setup and status show running, selected and PATH executable paths.statusalso reports the MCP and hook executables separately, their storage selection and capture policy. PATH differences remain visible even when only one command is on PATH and another binary is running by absolute path.neosian setup --checkinspects existing registrations and runs a bounded MCP initialize/list/create/read probe through the running binary, using a temporary file store that is removed afterward. It does not execute commands found in client configuration, open configured stores, contact a model, or rewrite registrations. Missing executables, differing MCP/hook storage, incomplete profile bindings or credentials and duplicate hook files produce exit 1; passing checks produce exit 0.--jsonseparatesinstallation,storage,clients,probeandissues. An explicit--root,--urlor--profilealso checks registrations against that requested selection. Checks use this shell’s environment; each client still needs its own credential variables. Source access isnot_checked, and client connection/hook delivery arenot_observed. Restart the client, review hook trust and confirm its MCP connection.--checkand--writeare separate steps.- Once per machine. By default the hooks land in the client’s own
settings (
--level user) and serve every project: with no store flag the line names~/.neosian(or$NEOSIAN_HOME) and no mount, and the verb derives each session’s layout where it runs:user:<login>at/user,user:<login>/proj:<slug>at/project, the slug the project directory’s name. Nothing is written into a project. CLI operations use the same local defaults (neosian docs quickstart). --level projectwrites this directory’s file instead, with its layout spelled into the line: a scope of your own for one project (--scope,--mount), or recording only where you ask for it. A lighter per-project override needs no second registration: setNEOSIAN_SCOPEin that project’s environment for the client. Muse clears this variable at launch, as does Cursor for MCP children; name their scopes explicitly when installing.- One level per client. Every client merges its hook sources, so
ours at two levels would run twice and land each span twice. A
user-level
--writeremoves this directory’s project-level entry (ours only, by its command; every other hook and key survives) and says so; a project-level install beside user-level hooks is refused. A project that still carries hooks from an earlier install showslevel bothinneosian status, with the fix: runneosian setup --writethere. Inside a repository that commits those hooks, that edits the committed file. - Which project. Claude Code runs a hook in a working directory
that moves when the agent runs
cd, so its line ends on--project "$CLAUDE_PROJECT_DIR", the directory the session started in, which stays put. Codex runs hooks in the session’s directory and needs nothing; the OpenCode plugin passes the directory it was opened with. Cursor uses the payload’s workspace roots; see its section below. A directory with no name to derive a project from (/) records to/useralone; a hook never exits 2, which Claude Code reads as “block the prompt”. - Print mode (the default) puts the paste-able
hooksfragment on stdout (Muse shows its multi-file change preview instead; the one command onUserPromptSubmit,PostToolUse,StopandSessionStart) and guidance on stderr. --writemerges it into~/.claude/settings.json(under$CLAUDE_CONFIG_DIRwhen set), preserving every other key, event and hook; a group carrying our command is replaced, so a re-run is idempotent.~/.claudemust exist: neosian never creates another program’s config home.- The store flags are
mcp install’s; the hook line adds--spool(absolute) and--agentwhen not the default. A DSN is never written into a hook line;--urlcarries the token throughNEOSIAN_CLIENT_TOKENin the client’s own environment, which is now a setting for the machine, not for one project. - Hooks and MCP can share a local FileStore root through its cooperating process
lock. For remote storage,
neosian setup --url URL --write --yesselects an explicitly operated state process, or use Postgres. Readneosian docs topology. - Codex takes the same fragment at
~/.codex/hooks.json(~/.codex, or$CODEX_HOME, must exist). At the user level there is no project trust step, but Codex runs a new hook only once you have reviewed it in its/hookscommand; automation that has vetted them runscodex exec --dangerously-bypass-hook-trust. At--level projectit is the project’s.codex/hooks.json, loaded only for a trusted project. The hook line carries--agent codex, so the writer iscodex:<thread_id>; Codex’sStophook expects JSON on stdout, and the verb answers{}there. The memory half is TOML Codex’s own CLI writes:neosian mcp install --client codexprints the[mcp_servers.neosian-memory]table and thecodex mcp add …line, andneosian setup --writeruns that line for you. - OpenCode has no shell hooks; it has a plugin API. The same command
writes a small plugin file,
plugins/neosian-record.jsin OpenCode’s own config directory (~/.config/opencode, or$OPENCODE_CONFIG_DIR, which must exist;.opencode/plugins/in the project at--level project): OpenCode 2’s one plugin definition, whosesetupmaps thepromptandexecute.afterhooks and the session’s execution events onto the verb’s three write payloads and pipes them in, carrying the inbox frame as a system part of the turn’s requests and the assistant’s reply from the text events; ours whole, overwritten on re-run, never merged; print mode prints its source. OpenCode 1.x loads only the file an earlier release wrote. The writer isopencode:<session_id>. OpenCode has no start hook, but it shows an MCP server’s instructions to the model whole, so its read side is the server’s instructions: the memory index, the pending handoff note and “where we left off”, rendered per connection (DESIGN §33). The memory half is JSON:neosian mcp install --client opencodemerges{"mcp": {"neosian-memory": {"type": "local", …}}}into OpenCode’s config in the same directory: intoopencode.jsoncwhen that file stands there holding plain JSON (the file OpenCode’s own init leaves), else intoopencode.json. OpenCode reads both files and merges them, the.jsonclast, so beside a commented.jsoncthe entry lands inopencode.jsonand the report says so (and warns when the.jsoncnamesneosian-memoryitself, since that entry would win). Any model OpenCode can run works, its free models included.
Codex upkeep in the prompt picker
Section titled “Codex upkeep in the prompt picker”neosian setup --client codex --write installs $neosian-upkeep alongside
MCP and hooks. Run setup again after upgrading an older installation, then
neosian setup --client codex --check. In the Codex prompt area, type:
$neosian-upkeep Review /project and show proposed changes before applying anything.The entry is also available through Codex’s /skills picker. Restart Codex
if the picker has not refreshed. The existing conversation loads the live
builtin:upkeep workflow through MCP and performs the review. Profiles must
select builtin:upkeep; new profiles do. Approval, paused writers and mounted
permissions still govern apply. Nothing is scheduled by installing the skill.
Setup writes skills/neosian-upkeep/SKILL.md and its display metadata under
the selected Codex directory (~/.codex, $CODEX_HOME, or --at codex=DIR).
The neosian-skills.json receipt identifies managed bytes. Preview writes
nothing; repeated setup refreshes owned files, repairs missing files and
resumes interrupted updates. Foreign files survive. Local edits, unmanaged
name collisions and symlinks are refused before changing registrations.
setup --check fails on missing, outdated or conflicting managed entries.
It checks files; actual Codex discovery and client enablement remain unobserved.
neosian setup --client codex --codex-skills off --write removes the managed
entry and persists the opt-out. Normal setup preserves that choice; use
--codex-skills on --write to re-enable it. User-edited files are preserved
and must be moved or reconciled before removal or update. Other native skills
and stored neosian skills are left alone.
Claude Code cache maintenance
Section titled “Claude Code cache maintenance”neosian setup --client claude-code --write installs the bundled
neosian-cache@neosian-local plugin through Claude’s public plugin CLI and
composes a local observation bridge with your existing statusline. Restart
Claude Code after setup. Ordinary claude launches work; no patched binary,
extra mode, separate model account or background Neosian daemon is needed.
Claude Code 2.1.314 is the tested baseline. The plugin accepts subsequent
2.1 patches only while the required public events and receipt fields match.
Keep-warm defaults on until the session closes. After a successful ordinary
request, it matches Claude’s documented cache observation to that request’s
usage. An observed one-hour subscription cache becomes eligible for a hidden
refresh near minute 55 from that request’s start, while idle. Normal conversation
activity postpones refresh; verified refreshes also renew the deadline.
The request uses Claude’s public model.fork API and the session’s current
model and account; it creates no main conversation turn and cannot run tools.
The Rust memory, search, capture and MCP paths do not run the timer or model.
If the laptop wakes after expiry, the cache lifetime is unknown, context or model changes, or a refresh fails verification, automatic calls stop and the badge warns. The feature stays enabled: the next successful ordinary message can establish a new warm cache and rearm maintenance. It does not deliberately rebuild an expired cache just to produce a small reply. Five-minute caches are observed without automatic refresh; setup does not change Claude’s TTL.
| In Claude Code | Effect |
|---|---|
/neosian-cache or /neosian-cache status |
Show status without making a model request |
/neosian-cache off |
Stop maintenance for this session |
/neosian-cache on |
Enable until close; still requires an observed warm one-hour cache |
/neosian-cache 2h |
Enable for a duration (minutes or hours, at most seven days) |
/config |
Persist the plugin’s enabled and allowApi preferences |
Subscription usage indicators and a one-hour TTL are required by default.
An explicit on, duration or persistent allowApi also opts usage-billed
sessions into maintenance when a warm one-hour cache is observed. Requests
consume the account’s normal usage. There is no promise of quota savings.
The compact neosian line above the prompt shows expected warmth and keep-warm
state, wrapping in narrow terminals. Healthy caches have no warning icon;
amber indicates a paused or uncertain state. /neosian-cache opens a details
panel with pause reasons and the last refresh’s actual cache reads, writes and
output tokens. Press Esc to close it; the panel adds nothing to the conversation.
A successful refresh
must read nearly all the observed prefix and return the expected short reply;
a surprising receipt prevents further automatic attempts. Reported usage can
include reasoning tokens even for a one-word visible reply. Checks
allow at most 256 output tokens, 1,024 uncached input tokens and 2,048 cache-write
tokens, require at least 90% prefix reuse, and allow at most 2,048 unreused prefix
tokens. These limits are checked after completion. Cache status is a TTL
estimate, not a live server probe. Claude’s public fork API
has neither an only-if-cached condition nor a hard output-token cap: an
unexpected miss can only be detected after that one request has occurred.
Setup preserves the previous statusline command and feeds it the original
JSON. The bridge uses Bash, or Git Bash/PowerShell on Windows, bounds delegated
output to 64 KiB and waits at most five seconds. On Windows it honors
CLAUDE_CODE_GIT_BASH_PATH and finds standard Git Bash locations before falling
back to PowerShell. Its refresh interval is at most 30 seconds, preserving any
faster existing interval. A missing plugin heartbeat produces a fallback
warning. neosian status --json and neosian setup --check inspect installed
assets and observation wiring; they explicitly do not claim live delivery.
After a Neosian update, repeat setup to refresh the bundled plugin. Normal
claude update does not remove the plugin; incompatible behavior pauses it.
To remove the integration from this setup scope, run
neosian setup --client claude-code --claude-cache off --write. This disables
the plugin and restores the saved statusline if Neosian still owns its wrapper.
Project removal restores inheritance when no project statusline existed.
Disabling stops future refreshes; an already-sent request may finish.
An explicit plugin disable survives later setup runs. To restore installation,
enable neosian-cache@neosian-local through /plugin, then repeat setup.
The bridge stores bounded observations and refresh receipts under
neosian-cache/observations/ beside the selected Claude settings file. These
contain session IDs, host/model IDs, counts, status and UTC times; no prompts,
response text, transcripts, credentials or memory documents. One observation
and one receipt are overwritten per session. They are local diagnostics,
not memory or an authority to resume refresh after a restart; old session
files may be removed while Claude is closed.
Standalone cache display
Section titled “Standalone cache display”neosian statusline --client claude-code also works independently: read
Claude’s documented statusline JSON from stdin and print a compact badge, or
use --json for normalized fields. Without the installer-owned --bridge DIR,
it stores nothing and makes no model or network request. For example:
cache estimate warm ~4m59s | last main read 17633, wrote 637 | misses 0 | cold rebuild ~18272 tokensThe cold rebuild count estimates context tokens, not money. Read/write counts and misses describe main requests; side requests may have a different TTL. Invalid JSON or input larger than 1 MiB exits 1 without echoing the payload. See Claude’s statusline documentation and mod API.
What a span becomes
Section titled “What a span becomes”Native memory files are separate from conversation history. With an explicit
native-memory add ... --write registration, Claude Code and Codex hooks also
capture selected Markdown into guarded local snapshots and remind the agent to
use neosian memory. Ordinary setup leaves this off. Read
neosian docs native-memory for source selection, consent, limits and recovery.
| hook | the record |
|---|---|
UserPromptSubmit |
the USER message that opens the turn (spooled) |
PostToolUse |
an ASSISTANT tool call + its TOOL result, whole up to 1 MiB (its head and tail above that); a subagent’s rounds (agent_id) are skipped |
Stop |
the final ASSISTANT text (last_assistant_message); the span lands as one append_turn by claude-code:<session_id>, and the sessions document is written by claude-code:<session_id>#<turn> |
SessionStart |
prints the context (below), which the client adds to the model’s window; an enabled native-memory registration can capture files first |
The sessions document lives at sessions/<session_id> in the mount at
/project (else the first read-write mount) with agent, conversation,
started, last prompt and turn count, so the next agent finds the listing
in its index. Between the prompt and the stop the span waits in a
per-session spool (spool/ under the home; --spool DIR), never the store; a
failed landing keeps it, and the next stop carries the whole span.
Exit tiers bend once, for the hook’s sake: Claude Code reads a hook’s
exit 2 as “block”, so the verb exits 2 only for a bad invocation
(caught at install time) and 1 for everything after (a broken store
never blocks the agent) and prints nothing on stdout unless --json,
except on SessionStart and supported context-bearing responses, including
native-memory reminders. Cursor uses JSON hook responses, described below.
Session start: where we left off
Section titled “Session start: where we left off”Startup injection remains a bounded index. The separate search_memory
tool searches current permitted documents when a filename or the initial
index is insufficient, including documents added during the session. It
returns excerpts and source/version references for the agent to read. It
does not rebuild the host’s prompt or manage its context cache.
Claude Code, Codex, Cursor and Muse Code add a SessionStart hook’s
output to the model’s context, so on that event the verb prints three
blocks. Without an enabled native-memory registration, it writes nothing:
- The memory index of the scope, so the sessions documents are listed (the MCP server’s instructions then carry the write discipline alone: one window, one copy).
- The handoff note, when one is pending (DESIGN §33): the note the
last departing agent wrote with
handoff, in full, naming thecontinue_sessioncall that picks it up; one line once it is a week old; nothing once a session picked it up. - Where we left off: the scope’s recent sessions, log-projected
the way a conversation view is (
neosian docs memory): one line per turn, its number in square brackets, newest session first (older turns fold into a count line: paging, never deletion). Which sessions depends onsource: after a compaction (source: compact) the session’s own record comes back and no note, the re-injection of what the client just paged out; onstartup,resume,clearorforkthe three most recently written sessions, the own one included when it is among them.
The three blocks share one budget, the client’s own ceiling on what a hook may inject (Claude Code 10,000 characters, Codex 2,500 tokens, Cursor 10,000, Muse Code 16 KiB), counted exactly: the index up to three eighths of it, the note up to 2048, the sessions the rest, so a busy scope folds and never trips a client into a file-path preview. A client with no start hook, OpenCode, reads the same blocks from the MCP server’s instructions, which it shows whole.
A handoff is declared, never assumed. The block offers; a session that
says nothing is new work. When the user says “continue”, the agent makes
one call, continue_session(), and receives the conversation whole: the
note’s session, else the most recent one listed. The block names every
turn it shows, and the footer names the call that re-reads one:
recall_turn(n, conversation="<id>") on the neosian-memory MCP server
(neosian docs mcp), and search_history(query) on the same server finds a
turn of any session by its words, listed or not. Bodies stay behind
tools; the block is a table of contents, not the transcript. An empty
scope still prints the frame, so the agent knows the door exists.
For Codex, the text is carried in the hook response’s
hookSpecificOutput.additionalContext JSON field: its parser treats the
frame’s leading [ as JSON, so a plain-text response would be rejected.
--json still selects neosian’s diagnostic envelope.
A store that cannot be reached exits 1 with nothing on stdout:
SessionStart never blocks.
The window stays each agent’s own: neosian feeds it at the client’s
extension points (session start, the post-compaction re-injection)
and never replaces it. The three lifetimes hold across clients
(neosian docs memory): skills are how (the skills/ documents of
the mounts, the same list and the same MCP prompts from every client,
neosian docs skills), memory is what we know, the board is what we
are doing now, and the record is history, recallable
turn by turn, never in the window whole. Reflection at pre-compact is not offered: a hook
process is keyless, and the foreign agent’s own model is the only one
in the room.
Read it back on any substrate:
neosian audit # current project scopeneosian audit --scope user:me --conversation <session_id> --root ~/.my-agent/stateneosian audit --scope user:me --actor claude-code:<session_id> --url http://127.0.0.1:6367Muse Code
Section titled “Muse Code”neosian setup --client muse-code --write installs both halves. Muse’s
configuration directory must already exist: $XDG_CONFIG_HOME/muse, or
~/.config/muse. Its user settings.json holds both mcpServers and
hooks; a new file includes schema_version: 1. Existing malformed or
unsupported settings are refused, and other settings survive a merge.
The writer is muse-code:<session_id>.
FileStore hooks use this user settings file, or .muse/hooks.json with
--level project. Project hooks require a trusted workspace, such as
muse exec --trust-workspace. Muse runs lifecycle hooks in the session’s
workspace and tool hooks in the tool’s effective directory; the stop
lands the shared spool in the session’s scope. Startup context is plain
text, capped below Muse’s 16 KiB stdout limit without splitting UTF-8.
Muse clears the environment of hooks and MCP processes. For --url or
Postgres, the installer therefore uses user-level managed hooks:
neosian-hooks.json beside settings, named by managed_hooks_path.
managed_hooks_env_vars gains only NEOSIAN_CLIENT_TOKEN or
NEOSIAN_POSTGRES_DSN. MCP entries reference the same variable with
${NAME}; values are never written to a registration or printed.
Credential-backed project hooks are refused: use --level user.
An existing managed pointer to another file is preserved and automatic
installation is refused with a manual merge explanation.
Switching stores removes only neosian’s displaced hook groups. status
reads ordinary, managed and project hooks, and reports duplicates.
Muse hook print mode shows a path-keyed change preview: merge,
remove_neosian_hooks, and add_managed_hooks_env_vars name the edits;
it does not print unrelated settings. setup validates both halves
before writing either. Its JSON hook envelope includes this files map.
Muse and Claude Code share the project MCP file .mcp.json. Installing
Muse at user level preserves its existing neosian entry, which overrides
Muse’s user registration. Both the installer and status report its
path as mcp_shadowed_by; change the shared entry deliberately when
moving stores.
References: Muse’s hooks and MCP configuration, verified against Muse Code 1.3.0.
Cursor
Section titled “Cursor”neosian setup --client cursor --url URL --write installs user MCP at
~/.cursor/mcp.json and native version-1 hooks at ~/.cursor/hooks.json.
Cursor clears custom environment variables for MCP children; the entry
forwards credential names as ${env:NAME} references, never their values.
Hooks inherit the client environment. The .cursor directory must exist.
Both halves are checked before setup writes; unrelated configuration
survives, and reinstall is idempotent.
record install --client cursor --level project writes trusted project
hooks instead. Cursor’s MCP installer remains user-level only.
User hooks run from ~/.cursor, so the recorder derives /project from
one absolute workspace_roots entry in the payload. Missing or multiple
roots use /user alone, with a diagnostic. Supply --project DIR on the
record command or explicit --scope/--mount at installation to select a
project; NEOSIAN_SCOPE also takes precedence. Tool cwd changes do not
change the session’s project.
beforeSubmitPrompt supplies the prompt, postToolUse the tool round
(including its JSON-string output, whole up to 1 MiB), and
afterAgentResponse the assistant text. A completed turn lands once both
stop and afterAgentResponse have arrived, in either order. Cursor’s
interactive CLI can send the stop first. Aborted or failed turns can land
without assistant text. The actor is cursor:<conversation_id>.
A per-session advisory spool lock serializes concurrent hook processes
through the store write; it is released if a process exits. Its small
hidden lock file stays in the spool to keep
waiting processes on the same lock. This does not permit multiple direct
writers to a FileStore root.
sessionStart returns the same index and recent sessions through JSON
additional_context; other successful hooks return {}. --json
continues to return the recorder’s diagnostic envelope.
Cursor can also load Claude Code hooks. The Claude recorder ignores payloads carrying Cursor’s version marker, leaving recording and startup context to the native Cursor registration. Both configurations stay in place. This CLI imports Claude configurations containing a matcher; matcherless groups alone did not load in the probe.
The measured target is the interactive Cursor CLI 2026.09.10-fd3934a.
Its --print mode emitted startup and tool hooks, but omitted prompt,
response and stop events: full recording is unavailable there. Use the
interactive CLI for recording. Transcript parsing is not a fallback.
The installer escapes JSON slashes so this version’s comment reader
preserves daemon URLs inside hook commands.
References: Cursor’s hooks and third-party hooks.
neosian setup --client pi --write installs both halves for Pi 1.0.1 or
later. The user registration is ~/.pi/agent/mcp.json, with native
mcpServers and direct tool exposure. The recorder is
~/.pi/agent/extensions/neosian-record.ts. PI_CODING_AGENT_DIR relocates
that agent directory; it must exist before installation. Project level
uses .pi/mcp.json and .pi/extensions/neosian-record.ts and requires
Pi’s project trust. One recording level per client prevents duplicate
spans. Re-running setup replaces our extension and preserves unrelated
MCP entries.
The extension runs in interactive and print modes. It sends actual user
messages, completed tool rounds (including nested MCP calls and error
results), and the final assistant text to neosian record --agent pi.
Writes are serialized and each span lands at agent_settled, after
automatic retries, rather than the earlier agent_end. Orderly shutdown
drains an unfinished span. A killed process may leave a spool for the
next stop; recorder failures never prevent Pi from continuing. The writer
is pi:<session_id> and the project comes from Pi’s extension context.
No transcript files are parsed.
Pi does not show a server’s full instructions automatically. The
extension reads the memory instructions and three startup blocks into a
named neosian system-prompt section, preserving other sections. It
refreshes after compaction, including a retry without a new user prompt. The section’s
10,000-character budget is neosian’s conservative policy, not a claimed
Pi limit. Resume, new-session and fork events reset the context and
recording identity. Pi reads AGENTS.md natively.
For shared recording, use neosian setup --client pi --url URL --write
and set NEOSIAN_CLIENT_TOKEN in Pi’s environment; the token is inherited
by both subprocesses and never written to either configuration file.
The extension requires Pi’s built-in MCP support; an extension replacing
/mcp can disable the native registration. Check pi mcp list and
neosian status when diagnosing setup.
Validation: Pi 1.0.1 passed a real Claude Code → Pi → Claude Code → Pi
walkthrough on 2026-10-03 with Sonnet 5. Each arrival called
continue_session, all three links landed in the recorded sessions,
and the final handoff linked to the last Pi session. The shared memory
instructions require the continue call even when a startup summary
already contains the answer: reading it alone does not pick up the note
or declare the continuation. A separate keyless runtime check exercises
Pi’s event pipeline; the adapter checks cover compaction and shutdown.
References: Pi’s configuration, MCP and extensions.
The client table
Section titled “The client table”A row exists only while its walkthrough is green on a real install. “Per
machine” is the default registration: one run of neosian setup --write,
two project directories, each session in its own proj: scope.
| client | memory (mcp install) |
record (record install) |
per machine | session start |
|---|---|---|---|---|
| Claude Code | ✓ user scope through claude mcp add-json |
✓ walkthrough green 2026-09-02; headless claude -p denies the MCP tools unless --allowedTools mcp__neosian-memory__… names them (the prompt before that variadic list) |
✓ 2026-09-19 (2.1.278): the server is spawned in the session’s directory, the hook line’s project directory expands | ✓ SessionStart, stdout as context (2026-09-03); the handoff run for real 2026-10-03 (2.1.288) |
| Codex | ✓ through codex mcp add |
✓ walkthrough green 2026-09-03 (codex exec) |
✓ 2026-09-19 (0.154.0): the same, user-level hooks with no project trust step | ✓ JSON additionalContext; cross-client recall verified on 0.157.1 (2026-09-27) |
| OpenCode | ✓ (opencode.jsonc when it holds plain JSON, else opencode.json) |
✓ walkthrough green 2026-09-03 (opencode run, a plugin); the 2.0 definition verified 2026-10-17 (2.0.25, which refuses the 1.x export) |
✓ 2026-09-19 (1.18.30, a free model): the same, the plugin passing the directory it was opened with; 2026-10-17 (2.0.25) through the binary | ✓ the server’s instructions (shown whole, 1.18.30+): the index, the note and the sessions per connection; no hook |
| Claude Desktop | ✓ | no hooks surface | one file by nature; no project, so /user alone |
— |
| Cursor | ✓ user MCP, credential names forwarded | ✓ interactive CLI 2026.09.10-fd3934a; --print lacks full recording; MCP rounds through afterMCPExecution |
✓ one user registration, payload workspace roots | ✓ sessionStart, JSON additional_context |
| Muse Code | ✓ user settings or shared project .mcp.json |
✓ walkthrough green 2026-09-22 (muse exec, 1.3.0); headless muse exec can stall on a shell approval no one can give, so a handoff leg says “no shell commands” |
✓ two projects, one user registration; authenticated managed hooks and MCP on the state process | ✓ SessionStart, plain stdout; prior turn recalled over MCP; continued and handed off for real 2026-10-03 (1.4.2) |
| Pi | ✓ native MCP, direct tools (1.0.1) | ✓ print-mode walkthrough green 2026-10-03; extension commits at final settlement | ✓ two projects through one user registration and the state process; PI_CODING_AGENT_DIR honored |
✓ named system section, startup and compaction; Claude Code → Pi → Claude Code → Pi with all continuation links verified |
Durable messages and reminders
Section titled “Durable messages and reminders”See neosian docs messaging for the shared messages tool, conversation and
scope destinations, history annotations, explicit acknowledgment and claims.
Reminders can be snoozed with a finding and a new due time on the same ID.
Regenerate client adapters after upgrading for automatic
delivery. Pi and OpenCode also support wake requests while attached.
Hear about it first: [email protected]· Apache-2.0 · a Mausa AI project · neosian.com