Skip to content

[FEATURE] Persistent Session Memory #16077

Closed as not planned
Closed as not planned

Description

@ronique501-a11y

Summary

Add the ability for opencode to load previous conversation context from a local file at startup, enabling continuity between sessions.

Use Case

  • Users who want AI assistant to remember previous conversations
  • CLI-based AI companions that need persistence between sessions
  • Developers wanting a lightweight alternative to database-backed memory

Proposed Solution

Add a --memory-file or --load-context flag that:

  1. Reads a specified markdown/text file before starting the chat
  2. Injects the content as system context at session start
  3. Optionally appends session summary to the file at end of session

Example Usage

# Load previous context
opencode --memory-file ./my-memory.md

# Or with short flag
opencode -m ./my-memory.md

Alternative

Could also support a config option in openclaude.json:

{
  "memory": {
    "enabled": true,
    "file": "./memory.md",
    "autoSave": true
  }
}

Benefits

  • Simple, file-based approach - no database required
  • User has full control over their data
  • Works offline
  • Easy to back up or share

Priority

Medium - useful for personal AI companions and persistent CLI assistants


  • I have verified that this feature has not already been requested
  • I have read the contributing guidelines

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 5, 2026
  2. github-actions commented on Mar 5, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • The title should start with [FEATURE]: for feature requests (e.g., [FEATURE]: Persistent Session Memory)
    • The Feature Request template requires a verification checkbox confirming the feature hasn't been suggested before — this is missing from the issue

    Please edit this issue to address the above within 2 hours, or it will be automatically closed.


    This issue might be a duplicate of existing issues. Please check:

    If you believe this was flagged incorrectly, please let a maintainer know.

  3. changed the title [-]Feature Request: Persistent Session Memory[/-] [+][FEATURE] Persistent Session Memory[/+] on Mar 5, 2026
  4. github-actions commented on Mar 5, 2026

    @github-actions
    Contributor

    Thanks for updating the issue! It now follows the contributing guidelines and feature request template. The request is clear and well-described.

  5. MuhammadOmarMuhdhar commented on Mar 29, 2026

    @MuhammadOmarMuhdhar

    I'd like to take a stab at implementing this. My approach would be slightly different from the --memory-file flag suggested here, I'm thinking automatic extraction on session close, writing learned facts to .opencode/memory.md, with the system prompt automatically picking it up. Happy to discuss the approach before writing any code. Would the team be open to this direction?

  6. ronique501-a11y commented on Mar 29, 2026

    @ronique501-a11y
    Author

    I'd like to take a stab at implementing this. My approach would be slightly different from the --memory-file flag suggested here, I'm thinking automatic extraction on session close, writing learned facts to .opencode/memory.md, with the system prompt automatically picking it up. Happy to discuss the approach before writing any code. Would the team be open to this direction?

    That sounds like a much better approach! A few thoughts:

    User control - Maybe an opt-in setting? Some users might not want automatic extraction, or might want to customize what gets saved (privacy concerns, token limits, etc.)
    What gets extracted - Key facts, user preferences, ongoing project context? Or full conversation summarization?
    Token budget - How would you handle the memory growing unbounded? Maybe prioritize recent/relevant and prune older stuff?
    The .opencode/memory.md location - Is that configurable? Different users might want different paths.
    Really glad someone is working on this. Thank you! 🎉

  7. ronique501-a11y commented on Mar 29, 2026

    @ronique501-a11y
    Author

    That sounds like a much better approach! A few thoughts:

    1. User control - Maybe an opt-in setting? Some users might not want automatic extraction, or might want to customize what gets saved (privacy concerns, token limits, etc.)

    2. What gets extracted - Key facts, user preferences, ongoing project context? Or full conversation summarization?

    3. Token budget - How would you handle the memory growing unbounded? Maybe prioritize recent/relevant and prune older stuff?

    4. The .opencode/memory.md location - Is that configurable? Different users might want different paths.

    Really glad someone is working on this. Thank you! ??

  8. MuhammadOmarMuhdhar commented on Mar 29, 2026

    @MuhammadOmarMuhdhar

    That sounds like a much better approach! A few thoughts:

    1. User control - Maybe an opt-in setting? Some users might not want automatic extraction, or might want to customize what gets saved (privacy concerns, token limits, etc.)
    2. What gets extracted - Key facts, user preferences, ongoing project context? Or full conversation summarization?
    3. Token budget - How would you handle the memory growing unbounded? Maybe prioritize recent/relevant and prune older stuff?
    4. The .opencode/memory.md location - Is that configurable? Different users might want different paths.

    Really glad someone is working on this. Thank you! ??

    Here's what im thinking:

    User control: I agree opt in is preferable, enabled via /memory enable.

    What gets extracted: preferences, project conventions, architectural decisions, ongoing tasks, key facts etc - rather than full on summaries.

    Handling token budget: To stop it growing unbounded I'm considering two directions: a hard limit where if the file exceeds a certain line count the model consolidates/ prunes before injecting, or a soft limit that just warns the user to prune it themselves. Open to thoughts on which is better.

    Location : .opencode/memory.md by default, configurable via memory.file in opencode.json.

    I think this should all be feasible within the current plugin/session architecture without needing anything new. lmk what you think!

    cc @thdxr - also would appreciate your thoughts as well before I start writing any code!

  9. ronique501-a11y commented on Mar 30, 2026

    @ronique501-a11y
    Author

    This sounds great! A few thoughts:

    Hard limit vs soft limit: Go with hard limit + auto-prune. Users won't manually prune - it'll just grow until it becomes a problem. If the model does it automatically, it stays manageable without user effort.

    Config options: Maybe something like:

    • (e.g., 500)
    • (when to trigger consolidation)
    • (custom path)

    Additional command ideas:

      • show current memory content
      • manually add a fact
      • reset memory

    Pruning approach: When hitting the limit, the model could consolidate similar facts, remove outdated info, and keep the most relevant/recent entries.

    Excited to see this coming together! 🚀

  10. ronique501-a11y commented on Mar 30, 2026

    @ronique501-a11y
    Author

    Just to clarify the config options:

    • memory.maxLines (e.g., 500)
    • memory.pruneThreshold (when to trigger consolidation)
    • memory.file (custom path)

    And commands:

    • /memory - show current memory content
    • /memory add - manually add a fact
    • /memory clear - reset memory

    Looking forward to seeing this implemented!

  11. kuitos commented on Apr 3, 2026

    @kuitos

    https://github.com/kuitos/opencode-claude-memory try this plugin, provide a claude code compatible memory system for opencode😎

  12. assigned and unassigned on Apr 26, 2026
  13. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  14. robertn702 commented on Jul 23, 2026

    @robertn702

    I built another option for this, opencode-episodic-memory. Different approach from the memory-file proposals here. It indexes OpenCode's own session database (read-only) and gives the agent tools to semantically search your actual past conversations, instead of maintaining a curated memory file. Embeddings run locally, no API keys, and it reindexes itself on session.idle.

  15. solcoteh commented on Aug 3, 2026

    @solcoteh

    A persistent memory feature would be very useful, especially if it is also manageable from OpenCode Desktop.

    My preferred experience would be a simple Memory page where users can view, edit, disable, or delete saved information and choose whether each memory is global or project-specific.

    It would also be important for OpenCode to ask for confirmation before saving new memories. This would make memory predictable and user-controlled instead of silently storing information.

    The file-based approach proposed here sounds good, and the Desktop UI could simply provide a friendly way to manage the same underlying memory files.

  16. AliYar-Khan commented on Aug 24, 2026

    @AliYar-Khan

    I think it is better to setup a mcp server with a local sqlite. Store the sqlite in a location which survives reinstall or complete removal of the opencode and can be used by other harnesses as well

  17. RemanenetSpy commented on Aug 24, 2026

    @RemanenetSpy

    The MCP server approach suggested by @samvallad33 and @robertn702 is definitely the cleanest interface boundary for OpenCode—it decouples storage from the core binary without requiring heavy database dependencies.

    The architectural challenge with simply indexing raw session transcripts or loading flat markdown files is state invalidation. When a project migrates (e.g. upgrading from Next.js 14 to 15 or changing an API endpoint), a flat memory file or raw transcript retains both the old pattern and the new pattern. The model inevitably retrieves conflicting facts and hallucinates.

    The standard pattern to solve this is an append-only SVO (Subject-Verb-Object) event ledger with explicit valid_to chronological bounds. When a new decision is stored ([Auth] -> [Uses] -> [JWT]), it closes the valid_to timestamp of the prior conflicting fact ([Auth] -> [Uses] -> [SessionCookies]). Retrieval queries simply filter WHERE valid_to IS NULL.

    Whether implemented via local SQLite or a managed backend, adding temporal supersession to the MCP tool definition ensures old project history never pollutes fresh sessions.

  18. liudongyan13701205717-source commented on Sep 13, 2026

    @liudongyan13701205717-source

    +1 — adding a Desktop-side use case that strengthens this.

    On OpenCode Desktop (Electron sidecar, v1.18.30), sessions are resumed via continue/resume so the message history survives — but there is no session-scoped memory mechanism: decisions, learned conventions, and task state from an earlier session do not re-enter context unless you manually paste them. We end up hand-rolling per-session memory via external tools (session transcript search + compact-to-knowledge-files) — which works, but it's exactly the gap this proposal (--memory-file / memory config) would close natively.

    The proposed shape fits Desktop well too:

    • Startup: inject the previous session summary as system context (or make it available to the session's first turn)
    • End: append an auto-generated session summary to the memory file
    • Config-side (memory.file + autoSave) is preferable to a CLI flag for Desktop users, since the desktop app doesn't expose CLI flags — so if both land, the config option is the one Desktop can actually use.

    Also related: #48497 (long-term persistence memory system with /teach /recall /learn /memory commands) and #41453 (persistent session daemon + zero-tool-call recall) — a session-scoped layer (this issue) composes cleanly with both: long-term/global memory answers "who is the user", session memory answers "what happened in this session".

  19. vshulcz commented on Sep 23, 2026

    @vshulcz

    the store @AliYar-Khan describes already exists as a separate process rather than a plugin. deja indexes the session files the agents already write — ~/.local/share/opencode/opencode.db, ~/.claude/projects, ~/.codex/sessions and about thirty more — into its own sqlite under ~/.cache/deja, and serves it over MCP. it survives reinstalling or deleting any of them because it isn't inside them, and it answers about sessions from before it was installed. disclosure: i maintain it — https://github.com/vshulcz/deja-vu

    @robertn702 one thing that bites anything reading opencode's database directly: 2.0 renamed the tables. session is session_v2, and message/part are folded into one session_message table with the role in a type column and an assistant turn's parts inside its data blob. inside a turn, bash is shell, apply_patch is patch, the file a read or edit names is path rather than filePath, and what a tool printed moved from the state.output string to the state.content block list. i only found all of that by installing 2.0.12 and reading what it wrote — a user reported the store as unreadable first.

    @RemanenetSpy on state invalidation: agreed about flat files, they do keep the old pattern and the new one side by side with nothing to separate them. transcripts aren't flat, though — a hit carries its session, its date and the line it came from, so the later decision outranks the earlier one and a reader can see there were two. and for "what actually worked" the useful record isn't a claim at all, it's the command that ran after the failing one and didn't fail again. that doesn't remove your problem, it just keeps the conflict visible instead of merging it into one asserted fact.

  20. RemanenetSpy commented on Sep 24, 2026

    @RemanenetSpy

    @vshulcz That distinction is spot on: the empirical signal of a valid state isn't an unverified natural language claim, it's the execution receipt of the command that succeeded after a failure.

    The tension with relying on chronological transcript ranking ("later decision outranks earlier one") is that it offloads state resolution to prompt-time LLM inference:

    1. Token Bloat & Window Decay: If Session 12 establishes "Deploy via Terraform to AWS" and Session 42 records "Migrate infrastructure to GCP via Pulumi", pulling both raw transcripts into context forces the model to read, compare, and reason through dead turns on every single prompt. Across 50+ sessions, this consumes substantial context budget on obsolete historical churn.
    2. Attention Contradictions: Even frontier models suffer non-zero hallucination rates when two working-looking configurations co-exist in the prompt. Chronological ordering shows when they happened, but doesn't tell the model whether the earlier approach was fully retired or remains an active multi-cloud subsystem.
    3. Write-Time vs Prompt-Time Bounds: When the "command that didn't fail" executes, recording an explicit supersession edge (valid_to = now()) on the old convention allows the startup retrieval query to remain strictly O(1): WHERE valid_to IS NULL. The full transcript history remains queryable for forensic debugging, but zero dead tokens enter the active working context.

    In deja's schema today, do you expose an explicit supersession flag to callers, or does the downstream agent have to execute conflict resolution across sessions on every turn?

  21. vshulcz commented on Sep 24, 2026

    @vshulcz

    both, and the split is the part worth writing down.

    explicit and at write time, by a person: deja promote <id> --state accepted|rejected|superseded|stale [--note "why"]. append-only — a correction appends, nothing rewrites — carried on every hit as lifecycle/lifecycle_at/lifecycle_note in --json and as a line in the MCP block (replaced by a later decision (2026-09-14)), and it moves the ranking rather than only the display.

    the honest half: on a real 1,160-session store, not one of those states had ever been set by hand. so the signal that does the work is derived — superseded is computed at query time from a newer session in the same project, more than a day newer and not stamped ahead of the clock, whose matched passages overlap this hit's by 0.6. the agent reads [earlier attempt — a newer session in this project covers the same ground, updated 2026-09-14]. a heuristic with two guards, not a ledger; both guards came from bugs.

    on token bloat the premise does not hold for this shape: a hit carries the passages that matched, not the session. measured over thirty seeded task chains, reaching the same working context cost a median of 1,096 tokens by recall, against 80,547 by replaying the matched sessions — https://vshulcz.github.io/deja-vu/guide/token-cost.html

    where your design is ahead: my unit is a session, not a fact, so there is no WHERE valid_to IS NULL at [Auth] -> [Uses] -> [JWT] granularity — two overlapping answers arrive dated and marked earlier/later, and the model still reads both. i take that trade knowingly, since a ledger has to pick the fact at write time and the transcript is gone when it picks wrong. but you are right that it costs context on every prompt.

  22. RemanenetSpy commented on Sep 25, 2026

    @RemanenetSpy

    @vshulcz That 1,096 vs 80,547 token benchmark is a fantastic empirical result—it cleanly proves that selective passage recall beats raw transcript replay by ~73x. And your observation that zero users run manual promote --state superseded across 1,160 sessions matches reality: if memory maintenance requires active human curation, it doesn't happen.

    Your trade-off analysis hits the exact architectural frontier:

    "i take that trade knowingly, since a ledger has to pick the fact at write time and the transcript is gone when it picks wrong. but you are right that it costs context on every prompt."

    The way we resolve that false dilemma in Smriti (our dedicated bi-temporal knowledge graph engine) is by treating the architecture as a Two-Tier Ledger & Evidence Hybrid:

    1. Tier 1 (The Immutable Evidence Store): The raw session transcript and tool outputs are never thrown away. They are stored in an append-only event log referenced by an immutable hash (source_session_id, receipt_digest). When a developer needs forensic debugging or an agent needs to audit why a decision was made, the full raw dialogue remains accessible.
    2. Tier 2 (The Bi-Temporal Fact Ledger): Structured SVO assertions ([Auth] -> [Uses] -> [JWT]) live in a relational layer with explicit chronological validity (valid_from, valid_to). When a new verified decision is recorded, it closes the previous assertion (valid_to = now()), binding the pointer to the Tier 1 receipt digest.
    3. Non-Destructive Re-extraction: If an automated extraction ever extracts the wrong fact, the underlying transcript is still intact. A re-indexing run or explicit correction simply invalidates the flawed triple and mints a corrected one, preserving complete provenance.

    By decoupling the active prompt context (WHERE valid_to IS NULL costing ~80 tokens) from the historical evidence store, the model gets clean, zero-contradiction startup orientation without losing transcript forensic fidelity.

    For OpenCode and deja-vu, a lightweight SQLite implementation of this split (a facts table with valid_to referencing passage hashes in deja.db) could allow callers to request --mode active ($O(1)$ facts) or --mode forensic (dated passage overlap), bridging the gap between prompt economy and audit safety.

  23. neriousy commented on Oct 1, 2026

    @neriousy
    Member

    Closing as not planned for now. Session memory or continuity is a broad design area, and this request doesn't describe something specific we can build. Memory across sessions can already be done with plugins, and several community plugins in this thread do that.

    If you have a concrete proposal, for example a specific plugin hook OpenCode is missing, please open a new issue describing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions