You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If your issue is specifically about the TUI input prompt history (the arrow-up/down history in the opencode prompt editor) being shared across sessions, this appears to be the same underlying behavior. If it is about something different (e.g. AI conversation context bleeding between sessions), please clarify in the issue.
Confirming this is still present in v1.18.2 (tag v1.18.2, commit 70b56a0a9), and adding a source-level root cause + fix direction. This is the same underlying behavior as the auto-closed #25811 (global, not project-scoped) and #19536 / #19436 (multi-instance clobbering) — none of which were fixed before the inactivity bot closed them.
Root cause
The TUI prompt-recall history is persisted to a single global file with no project/session/directory key and no locking:
$XDG_STATE_HOME/opencode/prompt-history.jsonl
Every concurrent opencode TUI process reads from and writes to this same file regardless of project/dir/session.
Path is keyed only by the global state dir + a constant filename — packages/tui/src/prompt/history.tsx:52-53:
paths.state = global.state = $XDG_STATE_HOME/opencode (packages/tui/src/app.tsx:260, packages/core/src/global.ts), identical for every invocation.
The persisted record PromptInfo (history.tsx:9-25) stores only input/mode/parts — no project or session id, so it can't be filtered even in principle.
Read path loads the whole file unfiltered on mount (history.tsx:54-61); write path appends on every submit (history.tsx:85-108, called from packages/tui/src/component/prompt/index.tsx:1121,1273); recall bindings are Up/Down → history.move() (config/keybind.ts:199-200,402-403; component/prompt/index.tsx:879,915).
That fully explains the arrow-up recall showing another session's prompts.
The over-cap branch rewrites the whole file from the process's stale in-memory snapshot (history.tsx:103-104), overwriting entries other instances appended since this process last read — a lost-update race. No lock / atomic write on this path (packages/tui/src/util/persistence.ts:12-20), even though the repo already has Flock (packages/core/src/global.ts, Flock.setGlobal({ state })) and writeJsonAtomic (persistence.ts:22-33, unused here).
Scope / not-scope
Session transcripts are not affected — DB rows are correctly isolated by project_id/directory. I verified two concurrent sessions in different projects: distinct project_id, distinct directory, distinct message counts. Only the prompt-recall file leaks.
Same global-file design affects siblings under paths.state and may show the same bleed: prompt-stash.jsonl (prompt/stash.tsx:36), frecency.jsonl (prompt/frecency.tsx:42), model.json/session.json (context/local.tsx:164,420), kv.json (context/kv.tsx:15) — i.e. the umbrella client state clobbered w/ multiple instances of opencode #19436.
Suggested fix direction
Scope per project. Key the filename by project.id (already available via useProject(), packages/tui/src/context/project.tsx:49-50,78-80), falling back to a hash of worktree/cwd for unsynced/non-git dirs; e.g. paths.state/prompt-history/<key>.jsonl. Resolve reactively — project.id is briefly undefined before the first sync() (project.tsx:38-53), so don't capture a single const at init.
Fix the race. Prefer append-only on the hot path + enforce the 50-entry cap lazily on read (the mount-time self-heal at history.tsx:58-60 already trims). If a rewrite is kept, guard with Flock and/or a JSONL-preserving atomic write.
Tests worth adding: two-projects-concurrent (leak), same-project interleaved over the 50-entry cap (race), non-git dir and cd-within-repo (isolation vs continuity).
Activity
github-actions commentedon Jul 6, 2026
This issue might be a duplicate of or related to existing issues. Please check:
If your issue is specifically about the TUI input prompt history (the arrow-up/down history in the opencode prompt editor) being shared across sessions, this appears to be the same underlying behavior. If it is about something different (e.g. AI conversation context bleeding between sessions), please clarify in the issue.
Blade1024 commentedon Jul 6, 2026
Actually, if I break one of the sessions, it repeats the history of the active one. Crazy....
fariello commentedon Jul 15, 2026
Confirming this is still present in v1.18.2 (tag
v1.18.2, commit70b56a0a9), and adding a source-level root cause + fix direction. This is the same underlying behavior as the auto-closed #25811 (global, not project-scoped) and #19536 / #19436 (multi-instance clobbering) — none of which were fixed before the inactivity bot closed them.Root cause
The TUI prompt-recall history is persisted to a single global file with no project/session/directory key and no locking:
Every concurrent
opencodeTUI process reads from and writes to this same file regardless of project/dir/session.packages/tui/src/prompt/history.tsx:52-53:paths.state=global.state=$XDG_STATE_HOME/opencode(packages/tui/src/app.tsx:260,packages/core/src/global.ts), identical for every invocation.PromptInfo(history.tsx:9-25) stores onlyinput/mode/parts— no project or session id, so it can't be filtered even in principle.history.tsx:54-61); write path appends on every submit (history.tsx:85-108, called frompackages/tui/src/component/prompt/index.tsx:1121,1273); recall bindings are Up/Down →history.move()(config/keybind.ts:199-200,402-403;component/prompt/index.tsx:879,915).That fully explains the arrow-up recall showing another session's prompts.
Secondary defect (the "#19536" clobbering)
The over-cap branch rewrites the whole file from the process's stale in-memory snapshot (
history.tsx:103-104), overwriting entries other instances appended since this process last read — a lost-update race. No lock / atomic write on this path (packages/tui/src/util/persistence.ts:12-20), even though the repo already hasFlock(packages/core/src/global.ts,Flock.setGlobal({ state })) andwriteJsonAtomic(persistence.ts:22-33, unused here).Scope / not-scope
project_id/directory. I verified two concurrent sessions in different projects: distinctproject_id, distinctdirectory, distinct message counts. Only the prompt-recall file leaks.paths.stateand may show the same bleed:prompt-stash.jsonl(prompt/stash.tsx:36),frecency.jsonl(prompt/frecency.tsx:42),model.json/session.json(context/local.tsx:164,420),kv.json(context/kv.tsx:15) — i.e. the umbrella client state clobbered w/ multiple instances of opencode #19436.Suggested fix direction
project.id(already available viauseProject(),packages/tui/src/context/project.tsx:49-50,78-80), falling back to a hash of worktree/cwd for unsynced/non-git dirs; e.g.paths.state/prompt-history/<key>.jsonl. Resolve reactively —project.idis brieflyundefinedbefore the firstsync()(project.tsx:38-53), so don't capture a singleconstat init.history.tsx:58-60already trims). If a rewrite is kept, guard withFlockand/or a JSONL-preserving atomic write.Tests worth adding: two-projects-concurrent (leak), same-project interleaved over the 50-entry cap (race), non-git dir and
cd-within-repo (isolation vs continuity).Workaround for affected users
Give each instance its own state dir:
github-actions commentedon Sep 14, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.