GoodMemory
About
Local-first, auditable memory for AI agents, with durable SQLite, MCP recall, and opt-in governed writeback.
Details
- Author
- hjqcan
- Categories
- AI
Jump to
3. Deploy GoodMemory As A Backend Memory-Layer Service
Use this when another backend should call GoodMemory as a service, especially when the product backend is Python/FastAPI or when a product such as OneLife should keep memory server-side instead of bundling GoodMemory into a mobile or browser client.
Deploy the packagedgoodmemory-http-bridgein a Node/Bun sidecar. Your backend then calls:
- /memory/recall-contextbefore its own model call
- /memory/rememberafter a user-confirmed or product-approved signal
- /memory/feedbackfor procedural corrections
- /memory/exportand/memory/forgetfor audit and deletion
- /memory/revisefor targeted correction by explicit memory id
Your service still owns auth, product policy, UI, and model orchestration. GoodMemory owns memory storage, recall, context assembly, write governance, and audit/export/delete behavior. Start with](#installed-host-writeback)Python/FastAPI HTTP Bridge— the official Python client (pip install goodmemory-client) and a hosted bridge instance atgoodmemory.vibenest.netare documented there — then checkRuntime And Storagefor SQLite/Postgres choices.
During a model turn, GoodMemory does four jobs:
- Resolve memory for the currentscope.
- Build a prompt-ready context fragment.
- Record selected post-response signals when your app or host allows it.
- Provide audit, correction, export, and deletion paths for user control.
Your app or installed agent still owns auth, UI, model calls, and product policy. GoodMemory owns the memory loop and storage boundary.
The published registry baseline is GoodMemory0.7.5. Use the pinned registry commands below for reproducible installs.
Use the global CLI when you want memory enhancement inside installed coding agents:
npm install -g goodmemory@0.7.5 goodmemory setup goodmemory status
Use the package dependency when you are building an application:
If you want to typegoodmemorydirectly, install the global CLI. A project-localnpm install goodmemory@0.7.5does not putgoodmemoryon your shellPATH. Usenpx goodmemory,npm exec -- goodmemory, or./node_modules/.bin/goodmemoryfrom that project instead.
Tarball verification for this release source:
The installed CLI is Bun-backed for non-version commands. The package bin is Node-safe forgoodmemory -Vandgoodmemory --version; other commands delegate to Bun.
For most users, the first useful path is installed-host memory.
npm install -g goodmemory@0.7.5 goodmemory setup goodmemory status
goodmemory setupdetects Codex and Claude Code, installs managed host wiring, and asks for:
- host:codex,claude, or both detected hosts
- activation: global, current workspace, or manual opt-in
- GoodMemory user id
- optional Postgres storage
- optional embedding provider
- optional LLM extraction provider
- writeback mode:off,observe,review, orselective
Interactive setup defaults to global activation with workspace-derived isolation and recommendsselectivefor new host configs so high-signal writes start working immediately with audit and undo. Choosereviewwhen you want Inspector approval before durable writes. Existing host configs keep their current writeback mode when the interactive prompt default is accepted. Scripted installs stay safe with--jsonor--no-interactive. Skipping provider setup is valid: GoodMemory still works with local SQLite and rules-only extraction.
goodmemory setup --host codex goodmemory status codex --workspace-root . goodmemory enable codex --workspace-root . --writeback observe goodmemory enable codex --workspace-root . --writeback selective goodmemory disable codex --workspace-root . goodmemory uninstall codex
The installed host path has four pieces:
- Managed pre-action for Codex:pre-tool-usecan deny or redirect risky Bash andgoodmemory codex actionexecutes the vetted first step on the same installed config, storage, provider, and scope path used by recall and writeback.
- Recall injection:session-startanduser-prompt-submithooks callrecall()plusbuildContext()and fail open if config, parsing, or storage is unavailable.
- Deep inspection:goodmemory mcp serve --host codexandgoodmemory-mcp --host codexexpose read-only context, trace, stats, and artifact tools.
- Optional writeback:session-stopand explicit writeback commands can turn selected after-response signals into durable memory.
Hosts without a managed install path (Cursor, Windsurf, Cline, Claude Desktop, Gemini CLI, OpenCode, or your own MCP client) can run the same MCP server in standalone mode — nogoodmemory setup, no host config files. Scope and storage come from flags/env; the served surface is the same 8 read-only tools, plus an opt-in governed write tool:
{ "mcpServers": { "goodmemory": { "command": "goodmemory-mcp", "args": ["--standalone", "--user-id", "YOUR_USER_ID"] } } }
Equivalent invocation:goodmemory-mcp --standalone --user-id <id>(requires Bun on PATH;GOODMEMORY_USER_IDworks as the flag's env fallback).--allow-write(orGOODMEMORY_MCP_ALLOW_WRITE=1) registersgoodmemory_remember, which writes through the normal governed remember pipeline. Agent-tagged memories written by installed hosts stay private to their agent; add--agent-id codexplus the shared--storage-urlto opt into reading an installed host's store. Full flag/env matrix, scope notes, and per-host recipes:docs/GoodMemory-Standalone-MCP-Setup-Guide.md(Cursor·Gemini CLI·OpenCode).
Installed Host Writeback is opt-in. Runtime config defaults and new scripted installs remainoffunless the user explicitly chooses a writeback mode. Existing configs keep their current writeback mode when no explicit override is provided. New interactive installs recommendselectiveso high-signal writes start working immediately with audit and undo; choosereviewwhen you want Inspector approval before durable writes.
goodmemory enable codex --writeback observe goodmemory codex writeback --json goodmemory enable codex --writeback review goodmemory inspector serve goodmemory enable codex --writeback selective goodmemory codex writeback --json
goodmemory inspector serveopens the built-in local React console for users and scopes, categorized memory and supersession history, candidate decisions, recall evidence traces, and audit events. The startup token is passed in a URL fragment, cleared immediately into session storage, and sent only as a Bearer header. Revision and destructive actions require confirmation, ETags, and idempotency keys. SeeInspector And Admin API.
- off: no after-response memory extraction.
- observe: store local bounded/redacted candidate previews for review without raw transcripts or durable memory writes.
- review: queue bounded/redacted candidates for Inspector approval; no durable memory is written until an operator approves a candidate.
- selective: write selected candidates through the publicremembersurface.
- Raw transcripts are not persisted as memory.
- Assistant-originated durable memory is blocked unless the host confirms or verifies it and the active profile allows it.
- remember: "never"masks annotated content before deterministic, custom, or assisted extraction.
goodmemory codex writeback inspect --json goodmemory codex writeback forget --event-id <event-id> --review-outcome false_write
The audit ledger stores bounded redacted candidate previews, candidate keys, typed linked record ids, status, reasons, host, mode, timestamps, scope/session digests, and optional manual review metadata. It does not store raw host payloads.forget --event-iddeletes linked memory/evidence records through publicforget()before marking durable audit events forgotten; for observe-only events it marks the candidate dismissed without callingforget().
Claude Code has deterministic CLI parity for hook and writeback commands; Codex is the canonical live-evidence path.
Usegoodmemory install <host>when you want a fully non-interactive setup:
goodmemory install codex \ --user-id <user-id> \ --activation-mode global \ --writeback observe \ --storage-provider postgres \ --storage-url "postgres://user:pass@host:5432/goodmemory" \ --embedding-provider openai \ --embedding-model text-embedding-3-small \ --embedding-api-key <key> \ --llm-provider openai \ --llm-model gpt-4o-mini \ --llm-api-key <key> \ --no-interactive
Managed config lives under~/.goodmemory/<host>.json. Re-running install with provider flags updates the same config and keeps MCP/hook registration idempotent. Package uninstall does not delete~/.goodmemory, repo-local.goodmemory, local SQLite files, or remote Postgres data. Usegoodmemory uninstall <host>to remove managed host wiring, and usegoodmemory forget ...or explicit storage deletion to remove memory data.
Use the root package when you are building a chatbox, copilot, or product agent. The recommended Node service path is the same thin loop used by the Express and Fastify examples. A longer walkthrough lives indocs/GoodMemory-15-Minute-App-Integration.md.
import type { GoodMemoryTraceSpan } from "goodmemory"; import { createGoodMemory } from "goodmemory"; const traceSpans: GoodMemoryTraceSpan[] = []; const memory = createGoodMemory({ observability: { traceSink: { emit(span) { traceSpans.push(span); }, }, }, }); const scope = { userId: "u-1", workspaceId: "workspace-a", sessionId: "s-1", }; const userMessage = "Remember that the migration rollout is blocked on QA signoff."; // Call startSession once when the product opens a new session. For later turns // with the same sessionId, append to the existing runtime state instead. await memory.runtime.startSession({ scope }); await memory.runtime.appendMessage({ scope, message: { role: "user", content: userMessage, }, }); const recall = await memory.recall({ scope, query: "What should the assistant know before replying?", retrievalProfile: "general_chat", }); const context = await memory.buildContext({ recall, output: "system_prompt_fragment", }); const assistantText = await callYourModel({ memoryContext: context.content, userMessage, }); await memory.runtime.appendMessage({ scope, message: { role: "assistant", content: assistantText, }, }); const writeJob = await memory.jobs.enqueueRemember({ scope, messages: [ { role: "user", content: userMessage, }, { role: "assistant", content: assistantText, }, ], idempotencyKey: "turn-1", reason: "post_response_memory_write", }); const drained = await memory.jobs.drain({ maxJobs: 1 }); const committedJob = drained.jobs.find((job) => job.jobId === writeJob.jobId) ?? writeJob; console.log({ traceCount: traceSpans.length, writeJobId: writeJob.jobId, writeJobStatus: committedJob.status, }); async function callYourModel(input: { memoryContext: string; userMessage: string; }): Promise<string> { void input.memoryContext; return Got it. I will keep that in mind: ${input.userMessage}; }
The core memory loop is intentionally small:
- remember()writes selected user, app, or host signals.
- recall()retrieves scoped memory for a query.
- buildContext()turns recall hits into a prompt fragment or JSON payload.
- feedback()records explicit corrections and procedural preferences.
- forget()deletes wrong or obsolete memory.
Built-in packs cover English, Simplified Chinese, Traditional Chinese (zh-TW/zh-HK/zh-MO), Japanese, Korean, French, and Spanish. Set a host-known locale explicitly; otherwise auto-detection falls back todefaultLocalefor inherently ambiguous Han-only or unmarked Latin text.
3. Deploy GoodMemory As A Backend Memory-Layer Service
Use this when another backend should call GoodMemory as a service, especially when the product backend is Python/FastAPI or when a product such as OneLife should keep memory server-side instead of bundling GoodMemory into a mobile or browser client.
Deploy the packagedgoodmemory-http-bridgein a Node/Bun sidecar. Your backend then calls:
- /memory/recall-contextbefore its own model call
- /memory/rememberafter a user-confirmed or product-approved signal
- /memory/feedbackfor procedural corrections
- /memory/exportand/memory/forgetfor audit and deletion
- /memory/revisefor targeted correction by explicit memory id
Your service still owns auth, product policy, UI, and model orchestration. GoodMemory owns memory storage, recall, context assembly, write governance, and audit/export/delete behavior. Start with](#installed-host-writeback)Python/FastAPI HTTP Bridge— the official Python client (pip install goodmemory-client) and a hosted bridge instance atgoodmemory.vibenest.netare documented there — then checkRuntime And Storagefor SQLite/Postgres choices.
During a model turn, GoodMemory does four jobs:
- Resolve memory for the currentscope.
- Build a prompt-ready context fragment.
- Record selected post-response signals when your app or host allows it.
- Provide audit, correction, export, and deletion paths for user control.
Your app or installed agent still owns auth, UI, model calls, and product policy. GoodMemory owns the memory loop and storage boundary.
The published registry baseline is GoodMemory0.7.5. Use the pinned registry commands below for reproducible installs.
Use the global CLI when you want memory enhancement inside installed coding agents:
npm install -g goodmemory@0.7.5 goodmemory setup goodmemory status
Use the package dependency when you are building an application:
If you want to typegoodmemorydirectly, install the global CLI. A project-localnpm install goodmemory@0.7.5does not putgoodmemoryon your shellPATH. Usenpx goodmemory,npm exec -- goodmemory, or./node_modules/.bin/goodmemoryfrom that project instead.
Tarball verification for this release source:
The installed CLI is Bun-backed for non-version commands. The package bin is Node-safe forgoodmemory -Vandgoodmemory --version; other commands delegate to Bun.
For most users, the first useful path is installed-host memory.
npm install -g goodmemory@0.7.5 goodmemory setup goodmemory status
goodmemory setupdetects Codex and Claude Code, installs managed host wiring, and asks for:
- host:codex,claude, or both detected hosts
- activation: global, current workspace, or manual opt-in
- GoodMemory user id
- optional Postgres storage
- optional embedding provider
- optional LLM extraction provider
- writeback mode:off,observe,review, orselective
Interactive setup defaults to global activation with workspace-derived isolation and recommendsselectivefor new host configs so high-signal writes start working immediately with audit and undo. Choosereviewwhen you want Inspector approval before durable writes. Existing host configs keep their current writeback mode when the interactive prompt default is accepted. Scripted installs stay safe with--jsonor--no-interactive. Skipping provider setup is valid: GoodMemory still works with local SQLite and rules-only extraction.
goodmemory setup --host codex goodmemory status codex --workspace-root . goodmemory enable codex --workspace-root . --writeback observe goodmemory enable codex --workspace-root . --writeback selective goodmemory disable codex --workspace-root . goodmemory uninstall codex
The installed host path has four pieces:
- Managed pre-action for Codex:pre-tool-usecan deny or redirect risky Bash andgoodmemory codex actionexecutes the vetted first step on the same installed config, storage, provider, and scope path used by recall and writeback.
- Recall injection:session-startanduser-prompt-submithooks callrecall()plusbuildContext()and fail open if config, parsing, or storage is unavailable.
- Deep inspection:goodmemory mcp serve --host codexandgoodmemory-mcp --host codexexpose read-only context, trace, stats, and artifact tools.
- Optional writeback:session-stopand explicit writeback commands can turn selected after-response signals into durable memory.
Hosts without a managed install path (Cursor, Windsurf, Cline, Claude Desktop, Gemini CLI, OpenCode, or your own MCP client) can run the same MCP server in standalone mode — nogoodmemory setup, no host config files. Scope and storage come from flags/env; the served surface is the same 8 read-only tools, plus an opt-in governed write tool:
{ "mcpServers": { "goodmemory": { "command": "goodmemory-mcp", "args": ["--standalone", "--user-id", "YOUR_USER_ID"] } } }
Equivalent invocation:goodmemory-mcp --standalone --user-id <id>(requires Bun on PATH;GOODMEMORY_USER_IDworks as the flag's env fallback).--allow-write(orGOODMEMORY_MCP_ALLOW_WRITE=1) registersgoodmemory_remember, which writes through the normal governed remember pipeline. Agent-tagged memories written by installed hosts stay private to their agent; add--agent-id codexplus the shared--storage-urlto opt into reading an installed host's store. Full flag/env matrix, scope notes, and per-host recipes:docs/GoodMemory-Standalone-MCP-Setup-Guide.md(Cursor·Gemini CLI·OpenCode).
Installed Host Writeback is opt-in. Runtime config defaults and new scripted installs remainoffunless the user explicitly chooses a writeback mode. Existing configs keep their current writeback mode when no explicit override is provided. New interactive installs recommendselectiveso high-signal writes start working immediately with audit and undo; choosereviewwhen you want Inspector approval before durable writes.
goodmemory enable codex --writeback observe goodmemory codex writeback --json goodmemory enable codex --writeback review goodmemory inspector serve goodmemory enable codex --writeback selective goodmemory codex writeback --json
goodmemory inspector serveopens the built-in local React console for users and scopes, categorized memory and supersession history, candidate decisions, recall evidence traces, and audit events. The startup token is passed in a URL fragment, cleared immediately into session storage, and sent only as a Bearer header. Revision and destructive actions require confirmation, ETags, and idempotency keys. SeeInspector And Admin API.
- off: no after-response memory extraction.
- observe: store local bounded/redacted candidate previews for review without raw transcripts or durable memory writes.
- review: queue bounded/redacted candidates for Inspector approval; no durable memory is written until an operator approves a candidate.
- selective: write selected candidates through the publicremembersurface.
- Raw transcripts are not persisted as memory.
- Assistant-originated durable memory is blocked unless the host confirms or verifies it and the active profile allows it.
- remember: "never"masks annotated content before deterministic, custom, or assisted extraction.
goodmemory codex writeback inspect --json goodmemory codex writeback forget --event-id <event-id> --review-outcome false_write
The audit ledger stores bounded redacted candidate previews, candidate keys, typed linked record ids, status, reasons, host, mode, timestamps, scope/session digests, and optional manual review metadata. It does not store raw host payloads.forget --event-iddeletes linked memory/evidence records through publicforget()before marking durable audit events forgotten; for observe-only events it marks the candidate dismissed without callingforget().
Claude Code has deterministic CLI parity for hook and writeback commands; Codex is the canonical live-evidence path.
Usegoodmemory install <host>when you want a fully non-interactive setup:
goodmemory install codex \ --user-id <user-id> \ --activation-mode global \ --writeback observe \ --storage-provider postgres \ --storage-url "postgres://user:pass@host:5432/goodmemory" \ --embedding-provider openai \ --embedding-model text-embedding-3-small \ --embedding-api-key <key> \ --llm-provider openai \ --llm-model gpt-4o-mini \ --llm-api-key <key> \ --no-interactive
Managed config lives under~/.goodmemory/<host>.json. Re-running install with provider flags updates the same config and keeps MCP/hook registration idempotent. Package uninstall does not delete~/.goodmemory, repo-local.goodmemory, local SQLite files, or remote Postgres data. Usegoodmemory uninstall <host>to remove managed host wiring, and usegoodmemory forget ...or explicit storage deletion to remove memory data.
Use the root package when you are building a chatbox, copilot, or product agent. The recommended Node service path is the same thin loop used by the Express and Fastify examples. A longer walkthrough lives indocs/GoodMemory-15-Minute-App-Integration.md.
import type { GoodMemoryTraceSpan } from "goodmemory"; import { createGoodMemory } from "goodmemory"; const traceSpans: GoodMemoryTraceSpan[] = []; const memory = createGoodMemory({ observability: { traceSink: { emit(span) { traceSpans.push(span); }, }, }, }); const scope = { userId: "u-1", workspaceId: "workspace-a", sessionId: "s-1", }; const userMessage = "Remember that the migration rollout is blocked on QA signoff."; // Call startSession once when the product opens a new session. For later turns // with the same sessionId, append to the existing runtime state instead. await memory.runtime.startSession({ scope }); await memory.runtime.appendMessage({ scope, message: { role: "user", content: userMessage, }, }); const recall = await memory.recall({ scope, query: "What should the assistant know before replying?", retrievalProfile: "general_chat", }); const context = await memory.buildContext({ recall, output: "system_prompt_fragment", }); const assistantText = await callYourModel({ memoryContext: context.content, userMessage, }); await memory.runtime.appendMessage({ scope, message: { role: "assistant", content: assistantText, }, }); const writeJob = await memory.jobs.enqueueRemember({ scope, messages: [ { role: "user", content: userMessage, }, { role: "assistant", content: assistantText, }, ], idempotencyKey: "turn-1", reason: "post_response_memory_write", }); const drained = await memory.jobs.drain({ maxJobs: 1 }); const committedJob = drained.jobs.find((job) => job.jobId === writeJob.jobId) ?? writeJob; console.log({ traceCount: traceSpans.length, writeJobId: writeJob.jobId, writeJobStatus: committedJob.status, }); async function callYourModel(input: { memoryContext: string; userMessage: string; }): Promise<string> { void input.memoryContext; return Got it. I will keep that in mind: ${input.userMessage}; }
The core memory loop is intentionally small:
- remember()writes selected user, app, or host signals.
- recall()retrieves scoped memory for a query.
- buildContext()turns recall hits into a prompt fragment or JSON payload.
- feedback()records explicit corrections and procedural preferences.
- forget()deletes wrong or obsolete memory.
Built-in packs cover English, Simplified Chinese, Traditional Chinese (zh-TW/zh-HK/zh-MO), Japanese, Korean, French, and Spanish. Set a host-known locale explicitly; otherwise auto-detection falls back todefaultLocalefor inherently ambiguous Han-only or unmarked Latin text.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.
