@everme/pi
EverMe long-term memory for the Pi coding agent: profile and recall injection, automatic turn capture, and four memory tools.
Package details
Install @everme/pi from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@everme/pi- Package
@everme/pi- Version
0.7.2- Published
- Sep 22, 2026
- Downloads
- 677/mo · 86/wk
- Author
- junquan.yao
- License
- Apache-2.0
- Types
- extension, skill
- Size
- 43.9 KB
- Dependencies
- 1 dependency · 1 peer
Pi manifest JSON
{
"skills": [
"./skills"
],
"extensions": [
"./src/extension.js"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@everme/pi
EverMe long-term memory for the Pi coding agent: profile and recall injection, automatic turn capture, and four memory tools.
Verified against pi 0.80.10. Requires pi >= 0.80.4 — the
agent_settled event this extension uploads on was added in that release.
Install
evercli plugin install pi
That provisions the credentials (~/.pi/agent/everme.env, mode 0600) and runs
pi install npm:@everme/pi, which records the package in the packages array
of ~/.pi/agent/settings.json. Start a new pi session afterwards.
To install the package without evercli and provide credentials yourself:
pi install npm:@everme/pi
printf 'EVERME_AGENT_ID=agt_...\nEVERME_AGENT_TOKEN=evt_...\n' > ~/.pi/agent/everme.env
chmod 600 ~/.pi/agent/everme.env
/everme prints the status: which agent, which credential file, whether the
profile was injected, how many turns were saved, and the last error if any.
What it does
| pi event | what the extension does |
|---|---|
session_start |
resets per-session state; on resume/reload/fork checks whether this session already carries the profile |
before_agent_start |
injects <everme_profile> (once per session) and <everme_recall> (every turn) as a custom_message — model context, not TUI output |
agent_end |
buffers that run's messages |
agent_settled |
uploads the buffered turn (no flush: the gateway extracts on its own, and waiting for it is ~30x slower) |
Memory write tools retain model-authored content as assistant, never as a
human statement. mem_save_turn.role remains accepted for compatibility but
is ignored. Both write tools require Pi's native session ID; no timestamp-based
session is invented. Automatic capture retains actual user message roles.
Tools: mem_search, mem_context, mem_save_fact, mem_save_turn. The
everme skill tells the model when to reach for them.
Why the buffer
Automatic and explicit turn writes use task-aware batching, as does cold import. Fitting user tasks keep original tool output. Oversized tasks try 4, 3, then 2 KiB tool-result budgets before semantic splitting; calls, arguments, source ordering, and the existing flush behavior are unchanged.
agent_end is the only event that carries messages, and it can fire several
times for one user turn — pi may auto-retry, auto-compact and retry, or run a
queued follow-up. agent_settled is the guarantee that nothing more will run
automatically, but its payload is empty (verified in pi's own type
declarations: { type: "agent_settled" } and nothing else). So the transcript
is collected at agent_end and uploaded at agent_settled.
Assistant text and tool-call blocks retain their source order. A single native assistant message can become several gateway messages without changing its timestamp or tool IDs; thinking blocks are excluded. Tool results keep empty text without invented placeholders, and cold-start import does not apply an additional 8000-character tool-result cap. Normal redaction still applies.
Native tool calls require nonblank string IDs and names, and object arguments
are JSON-encoded for the gateway. The literal name unknown remains valid.
Malformed tool fields are excluded with bounded aggregate diagnostics; IDs are
never generated or coerced. A result is excluded with a rejected call only
when its native ID uniquely identifies that call. Repeated IDs are not enough
to infer ownership. Valid neighboring text and tool blocks keep their order.
Cold-start diagnostics are recorded in the conversation's warnings; this does
not imply that the CLI currently prints those warnings to stderr.
Turn completion comes from native assistant stopReason: "stop", not from
agent_settled. Only real final text in a source message without any tool-call
block is marked complete. Other assistant messages are explicitly incomplete;
thinking-only or empty stops do not create a closing message. The optional
turnComplete field reaches the gateway for batching, never the EverOS wire.
Failure policy
Recall and profile injection are best-effort and bounded by their own
deadlines (6s / 8s), well inside anything a user would wait for. On timeout or
error the turn proceeds with no injection: a memory lookup must never be the
reason a prompt hangs. pi's own provider layer can already stall — an
openai-codex OAuth refresh was observed hanging a whole run — and this
extension refuses to add to that.
Saves are reported, never faked. A failed upload surfaces in /everme and in
the tool result; nothing is silently queued or dropped.
Notes for maintainers
- The extension is plain ESM JavaScript, like every other package here. pi's
loader accepts
.jsand.tsequally;.jsneeds no jiti transform and keeps this package consistent with the rest ofplugins/. typeboxis a peer dependency: pi validates tool parameters with its own copy, and bundling a second one is what pi's packaging docs warn against. It is also a devDependency so the tests can build schemas.- The SDK's
runHook()is deliberately not used. It arms a watchdog that callsprocess.exit(0)near the host's kill deadline, which is right for a hook process and fatal inside the long-lived pi TUI. This package uses the SDK primitives (client,runInject,saveAgentMemory, rune caps, redaction) and owns its own deadlines. - Nothing is written to
process.env. pi spawns tools and user bash commands from the same environment, so an agent token placed there would leak into every child process. - Cold-start import for pi sessions lives in evercli
(
evercli import conversations run --platform pi), which reads~/.pi/agent/sessions/**directly. The extension does not backfill history. Import follows the selected branch's original messages, including history retained on disk before compaction. Compaction and branch summaries are runtime context, not conversation messages, and are not imported. - Automatic saves report discarded invalid tool IDs, names, or arguments as fixed reason/count warnings, without source content or credentials. This does not enable the SDK's otherwise quiet progress logging.
Tests
npm test --workspace @everme/pi # from plugins/
The extension tests drive the real event chain through a stand-in pi object
against a local HTTP backend, asserting the injected block shapes and the
upload body. The install path itself was verified on a real pi 0.80.10:
pi install <path> is headless, pi list shows the package, pi remove
restores settings.json byte-for-byte, and a live run reached
/mem/context, /mem/search and /mem/agent-memory in that order.