Memory
The CMDOP agent has two kinds of memory: working memory (the messages in the current session) and persistent memory (a shared SQLite store the agent can write to across sessions). They serve different purposes and are wired in different places.
Two layers
| Layer | Lifetime | Where it lives |
|---|---|---|
| Working memory | One session | The message list, rebuilt every turn |
| Persistent memory | Cross-session | A single memory.db SQLite file in the user’s data directory |
Working memory is the conversation history the LLM sees on the current turn. Persistent memory is something the agent explicitly chose to remember by calling a memory tool.
Working memory — the turn cycle
Every turn the runner injects fresh system context (identity, env info, target machine hints) and replays the message history. There are no hidden long-term facts at this layer — what the LLM sees is exactly what is in the message list plus the system prompt.
Working memory carries:
- The user’s prompts.
- The assistant’s previous replies.
- Tool call requests and tool results.
- The current todo list (re-injected each turn so the agent stays oriented).
When the history grows large, the chat layer can call the Jarvis summary agent to produce a brief summary that replaces older turns and reduces token debt.
Persistent memory — the SQLite store
memory.db is a single SQLite file lazy-opened by whichever consumer needs it first. Two
consumers share one file:
| Consumer | Notes |
|---|---|
| Local chat (CLI / TUI / Desktop) | Opens the store on first use |
Remote ask_machine (daemon) | Opens the same store on first remote call |
The store is opened once and shared safely across concurrent callers. If it fails to open, the chat logs a warning and continues without memory tools rather than failing the turn.
Memory tools
When the store is wired, four memory tools become available to the agent:
| Tool | Purpose |
|---|---|
remember_topic | Store a fact under a topic key. |
recall_memory | Look up facts by topic or free-text query. |
list_memories | Browse stored topics. |
forget_topic | Remove a topic and its associated facts. |
If a session never sees these tools despite a healthy DB, the surface hosting that session was started without a memory store attached. That is the canonical debug path.
How the agent decides what to remember
The agent is responsible for calling the memory tools — the system does not auto-summarise into the store. Typical patterns the system prompt encourages:
- Long-lived preferences (“user prefers TypeScript over JavaScript for new components”).
- Project anchors (“the auth service is at
services/auth”). - Cross-session facts the next turn would otherwise have to rediscover.
Things that should not go into persistent memory:
- Secrets or credentials.
- High-churn state (current branch, current todo).
- Arbitrary chat content “just in case”.
Storage and isolation
Persistent memory is per-installation, not per-fleet. The memory.db store in the
user’s data directory is shared across all sessions on that machine for the user that owns
the daemon. If you need fleet isolation, use distinct OS users.
Switching fleets does not switch memory stores. If you store project-specific context, prefix topics with the project name so recall stays clean.
Don’t store secrets in memory. The store is not encrypted and is readable by any process running as the same OS user.
What is not memory
Several adjacent features get confused with memory and are documented elsewhere:
- Sessions — persistent transcripts, see Sessions.
- Todo list — the current plan, replayed each turn but stored in the session, not in
memory.db. Seetodo_writein Tools. - Skill state — skills run as sub-sessions; their internal state is theirs to manage.
Related
Background reading: Persistent Memory Is Not Persistent Execution State — why remembering you started a server is not the same as a server being alive.