Skip to content

[FEATURE]: Search across my message history to quickly locate past conversations/content ("find what I told opencode before") #41354

Closed as not planned

Description

Problem

Over time I have hundreds of sessions across many projects. When I remember that "I told opencode something important a while ago" (a requirement, a decision, a constraint, a command I typed), there is currently no way to find it:

  • The TUI/Desktop session list only shows sessions by title/project — no content search.
  • Ctrl+F inside a session ([FEATURE]: Implement message search (Cmd+F / Ctrl+F) in the Desktop App #19143) only searches the currently open session — it cannot find that phrase I typed three weeks ago in another project.
  • The only workaround is recalling the approximate session/title, then scrolling through it manually. For long-running threads this is extremely inefficient; for forgotten sessions it's often impossible.

This is especially painful for agent-driven work: users increasingly delegate multi-day tasks, and "what did I tell the agent earlier" becomes a recurring lookup need.

Feature request

Add a content search across the user's message history:

  1. Scope: search my (user) messages — preferably all sessions, with per-project filtering (project:name, date range).
  2. Trigger: a search entry from the session list / project page (e.g. a search box or a /search command in the TUI); shortcut in Desktop.
  3. Result view: list of matches with session title, project, timestamp, and the surrounding message snippet; clicking a result opens that session (optionally scrolled to the matched message — which is exactly what todowrite/todoread cannot be enabled for subagents via agent permission config #19101-style in-session find would then support).
  4. Constraints: search user messages by default; option to include assistant messages/tool calls; fuzzy match would beat SQL-like exact match for human recall.

Relationship to existing issue

Environment

  • OpenCode Desktop 1.18.15 + CLI, Windows 11
  • Many projects/sessions accumulated daily; data presumably already stored in local session store (opencode.*.dat), so a local index/search over it should be feasible without server-side changes.

Activity

  1. liudongyan13701205717-source commented on Aug 15, 2026

    @liudongyan13701205717-source
    Author

    Cross-link with #19143 (message search Ctrl+F in Desktop) — same underlying need (find past conversations/content). #19143 is the in-session UI; #41354 the cross-session/history search. Tracking together covers the full "search my opencode history" request. +1, would test on Windows Desktop.

  2. AllanSantos-DV commented on Aug 23, 2026

    @AllanSantos-DV

    The ask in this thread — semantic search across message history — has no substrate to run on today: transcript storage is keyed by id, no content index of any kind (no FTS/vector table anywhere in packages/core).

    Checked on current dev: persistence is now event-sourced SQLite (<data>/opencode.db, bun:sqlite — packages/core/src/database/database.ts). Messages/parts are projections (MessageTable/PartTable, packages/core/src/session/sql.ts) kept current by a projector subscribed to durable MessageUpdated/PartUpdated events published from Session.updatePart.

    That makes an opt-in local embedding index incremental and fully off the hot path:

    • Background embedder subscribes to post-commit durable events — zero changes to turn handling
    • Rebuild/backfill = replay durable events or scan PartTable; deletion parity already mirrored by the projector
    • One deterministic anchor chunk per session (title + compaction summaries) sits on top of per-part chunks, so aggregate questions get a high-precision entry point; a hierarchical/graph index over that substrate is a natural follow-up
    • Provider pluggable, local-first by default (no network, data stays on device); API providers via existing config
    • Gated behind OPENCODE_EXPERIMENTAL_*, following existing precedent

    Why core rather than a plugin: plugins can't subscribe to internal EventV2 durable events (server SSE only), so incremental indexing needs core access.

    Positioning vs prior art: #20322/#39772 target native auto-memory/learning; this is mechanical retrieval over the same substrate — different consumer, complementary. Cross-project/cross-session recall comes almost free once indexing exists, detail dropped by compaction (#40614) stays queryable, and subagents get fast lookup without extra model calls.

    Out of scope: replacing compaction, remote sync, auto-injecting recalled context into prompts.

    I have a working POC on this exact design (verified end-to-end: live incremental indexing, cross-session recall through the tool, deletion parity, clean rebuild on restart). Happy to open a draft PR behind the flag — would that be a useful next step here?

  3. liudongyan13701205717-source commented on Aug 27, 2026

    @liudongyan13701205717-source
    Author

    Thanks a lot for the detailed POC! A working local semantic index over the existing SQLite store is exactly the direction I was hoping for. Please go ahead and open a draft PR — I'm happy to help test against real conversation exports and give feedback on indexing performance. Really appreciate you picking this up.

  4. AllanSantos-DV commented on Aug 28, 2026

    @AllanSantos-DV

    Thanks — really appreciate the green light! Draft PR opened: #45920

    It's the POC behind the OPENCODE_EXPERIMENTAL_TRANSCRIPT_RECALL flag: background embedder on durable events, per-session anchor chunks from titles/summaries, and a recall tool. Happy to prioritize indexing-performance feedback or testing against real conversation exports as you'd like.

  5. liudongyan13701205717-source commented on Aug 30, 2026

    @liudongyan13701205717-source
    Author

    跟进:社区提出的 POC PR #45920(本地语义索引 / OPENCODE_EXPERIMENTAL_TRANSCRIPT_RECALL)已被作者自行关闭(draft 未合并,needs:title 也未解决)。这意味着"跨会话/全文搜索"目前仍没有任何代码落地,本需求 track 依旧开放。

    想确认维护者的态度,三选一即可:

    1. 认可该方向 → 是否由我/社区基于原 POC(可复用其设计:EventV2 持久事件订阅、session 锚块、per-part 分块)续开一个正式的 non-draft PR;
    2. 另有内部方案 → 请把本 issue 挂到对应 track,避免重复工作;
    3. 暂不打算在 Desktop/CLI 做全文索引 → 明确一下,让我方知道期待边界。

    保持本 issue 作为"搜索消息历史"的需求 track。

  6. AllanSantos-DV commented on Aug 31, 2026

    @AllanSantos-DV

    Thanks for the engagement check. Rebased + non-draft PR opened: #46397

    Same design as before (EventV2 durable events, session anchor chunks, per-part chunking, deterministic hash provider), rebased on current dev. Clean commit history (11 files, 499 insertions), zero new typecheck errors in packages/core or packages/opencode, existing loader tests pass.

    Ready for feedback on indexing performance or testing against real conversation exports whenever you are.

  7. AllanSantos-DV commented on Sep 2, 2026

    @AllanSantos-DV

    @liudongyan13701205717-source thanks for the +1 and the design feedback! The previous PR #46397 was auto-closed by the compliance bot (missing PR template sections). Rebased + non-draft PR opened with the full template: #46823

    What changed since the auto-close (increment, not new feature):

    • M7: write metrics immediately (was buffered, never flushed on nssm stop)
    • M5: LRU cache in search() (28x speedup on cache hit)
    • M3 + D8: auto-invoke recall on regex trigger or semantic fallback (gated by OPENCODE_RECALL_AUTO_INVOKE, default off)
    • M6: pluggable OpenAI-compatible provider (default remains hashing, no external service wired)
    • D8 regex tightening (removed broad triggers like 'antes' and 'decidimos' that caused 20% FP)

    Lab validation on real conversation data:

    • H1 P50 cache hit: 3ms (was full scan, ~85ms)
    • H2 quality: 100% top-3/5
    • H3 adoption: 80% with trigger, 60% semantic fallback
    • H5 FP: 0% (was 20%)

    Tested end-to-end with 9router/free-combo + isolated lab DB. Happy to iterate on indexing performance or run against your real conversation exports.

  8. vshulcz commented on Sep 2, 2026

    @vshulcz

    For anyone who needs this before an in-core index lands: it works today from outside the core, because opencode already keeps every session in ~/.local/share/opencode/opencode.db.

    deja indexes that database in place (BM25, no LLM, no network) and gives you the lookup from the OP — "what did I tell opencode three weeks ago in another project":

    brew install deja-vu          # or: npm i -g @vshulcz/deja-vu
    deja "the retry budget we agreed on"
    deja last --harness opencode  # recent sessions, any project
    

    And as an opencode plugin (npm i opencode-deja, or deja install opencode-auto) the agent gets the same search as tools — deja_recall, deja_session, deja_blame — so "didn't I tell you X" is answered from the transcript rather than from memory. It reads the sessions from before it was installed; there is no capture step.

    Not a substitute for #46823 in the Desktop UI, and I maintain deja, so weigh that. Mentioning it because the thread reads as if the only path is waiting for core.

  9. added a commit that references this issue on Sep 4, 2026
    87ab3b0
  10. AllanSantos-DV commented on Sep 5, 2026

    @AllanSantos-DV

    Hi! Quick ping — no human reply since 2026-09-02, so heads-up that the draft is still live with updated and locally tested code:

    PR #46850 (OPEN draft, updated 2026-09-05, 9 commits): \ eat(core): transcript recall index for semantic session history
    #46850 — Closes #41354

    What's new since #46823/#46397: sprint 5 per-session call cap (M7), sprint 6 hybrid search (FTS5 + semantic with RRF/MMR), M4 endpoint re-add + wire-error fix, auto-invoke flag \OPENCODE_EXPERIMENTAL_RECALL_AUTO_INVOKE, typed errors, lab E2E H1/H3/H4/H5 PASS (H2 80% top-1 by content, dataset mismatch documented).

    GW test: P50 11ms / P95 59ms, 18.96 KB/part, 0% FP. Lab isolation verified, DB real untouched.

    Let me know if you'd like a rebase or a narrower scope — happy to adjust to the preferred design direction.

  11. ggbdpq commented on Oct 4, 2026

    @ggbdpq

    Context: I independently opened #53063 with a full-text search proposal before finding this thread (my pre-flight search only covered open PRs, not prior issues — my miss). Consolidating the technical content here and closing mine, since this thread is the right track.

    What #53063 added that this thread doesn't have yet — a concrete zero-dependency implementation path:

    No ask that wasn't already made above — @liudongyan13701205717-source's three-way question to maintainers from Aug 30 still stands, and #46823's author already paid the compliance-bot toll once. Just adding the cheaper-third-option data point to the track: if maintainer bandwidth is the constraint, the FTS5 slice is small enough to review as a single Phase-1 PR (migration + query + HTTP route, no UI).

  12. liudongyan13701205717-source commented on Oct 4, 2026

    @liudongyan13701205717-source
    Author

    ggbdpq's FTS5 zero-dependency path is the right shape for v1 — the session list query only matching session.title is the actual gap, and an external-content session_message_fts over the existing message storage adds no embedding infra, no background worker, and no new dependency.

    That said, two points worth threading together before closing this out:

    1. Write-path cost: triggers on every message insert need measuring against the p95 turn latency on a busy session. If the trigger adds even 1-2 ms per write, that compounds across 80K+ parts.
    2. Scope of recall: full-text over message content is table-stakes, but the semantic recall that AllanSantos-DV's PR feat(core): transcript recall index for semantic session history #46823 adds (hybrid FTS5 + semantic with RRF/MMR, gated behind OPENCODE_RECALL_AUTO_INVOKE) is what actually answers "what did I tell opencode three weeks ago" when you don't remember the exact wording.

    Practically: the FTS5 table is the dependency-free foundation, and the semantic layer can sit on top as an opt-in later. Both deserve a home in this thread.

  13. ggbdpq commented on Oct 4, 2026

    @ggbdpq

    Ran the write-path measurement for point 1 (@liudongyan13701205717-source's trigger-cost concern). Methodology: bun:sqlite (same driver family opencode uses), in-memory, external-content FTS5 + AFTER INSERT trigger, synthetic parts (~60 words each, mixed text/reasoning), 80K rows.

    • baseline insert: 0.46µs/row
    • with FTS5 trigger: 15.13µs/row (+14.7µs)
    • a typical turn at ~40 parts pays ~0.6ms total added latency — noise against any realistic p95 turn latency
    • one-time backfill of 80K existing parts: ~1.2s
    • MATCH query at 80K rows: ~4ms

    Caveats: synthetic schema (opencode's real part rows carry more columns; WAL and on-disk I/O will shift both baselines), but the delta is dominated by FTS5 index construction, so the order of magnitude should hold. Even at 10× this density the trigger doesn't meaningfully move turn latency.

    On point 2 — agreed: FTS5 as the zero-dependency v1 floor, semantic recall layered on top as opt-in. If useful, I can prepare the Phase-1 slice (migration + backfill + query + HTTP route) as a PR so the thread has something concrete to review.

  14. AllanSantos-DV commented on Oct 24, 2026

    @AllanSantos-DV

    Revalidated on V2 dev (c272a63). Still no content index; session.list({search}) is title-only, and #58445 adds a LIKE scan as Code Mode tools. Proposing FTS5-only as v1, as discussed above, scoped to be additive to that PR:

    • Index only text users and assistants wrote (user text and assistant text parts). No reasoning, tool input/output or shell. Standalone FTS5 table with its own text, bm25 ranking, snippet() excerpts. No embeddings, no background worker, no new dependency.
    • Kept in sync by triggers on session_message; created lazily on first search (derived data; users who never search pay nothing). Not a drizzle migration, because fresh databases bootstrap from the generated schema and virtual tables are not drizzle-expressible. Looking for guidance on the preferred place for this.
    • Lesson from our V1 prototype (feat(core): transcript recall index for semantic session history #46850, closed): a score threshold cannot tell relevant from irrelevant, but "none of the query words occur in any transcript" is a reliable signal. In that case the tool returns the most common indexed words so the model can rephrase instead of concluding there is no history. Short EN+PT stopword list; OR of content words ranked by bm25.
    • Measured on 100K synthetic messages: backfill 1.3 s, rare-word query 1.5 ms, about 55 us added per indexed insert.
    • Open questions: (1) migration vs lazy creation as above; (2) should cross-project reads be behind a permission or config switch; (3) background vs first-use backfill for databases with about a million messages; (4) should this be the backend for session_list({search}) in feat(core): add session_list and session_read tools #58445 rather than a second tool?
    • A working local branch exists; I will open a PR once the shape is agreed.
  15. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed write-up! Being able to search your messages across all sessions to find which one has something you told OpenCode earlier sounds really useful.

    You're on OpenCode Desktop 1.18.15, which is OpenCode v1. v1 now only gets fixes for critical bugs (data loss, security problems, crashes with no workaround), so a new feature like this is unlikely to be added there.

    New work goes into OpenCode v2 (2.x, the @opencode/cli package), and we'd encourage you to upgrade. To be upfront: as far as I can tell, v2 doesn't have search across session content yet either. If you'd like this in v2, reply here (or open a new request) saying so and that you've tried v2. That way maintainers can consider it alongside related requests:

    If you think this is critical, please reply here too.

  16. opencodejr commented on Oct 29, 2026

    @opencodejr
    Contributor

    Closing this as not planned. The report is about OpenCode v1 (Desktop 1.18.15), which only gets fixes for critical bugs, so search across all sessions won't be added there, and we haven't heard back since the last comment.

    Thanks again for the detailed suggestion. If you move to OpenCode v2 and still want to search past messages across sessions, please open a new feature request saying you're on v2. Related in-session search issues are #19101 and #19143.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions