Skip to content

plugin: no supported way to pin sessions - storage.store is not the pin store  #52478

Closed as not planned

Description

@mpj

Summary

TUI plugins have no supported way to pin or unpin sessions. The pin list (ctrl+f "Pin or unpin session in the session list", exposed as session.pin.toggle) lives in the TUI's own store at ~/.local/state/opencode/session.json, and context.storage.store("session", …) — the documented storage that "synchronizes across TUI instances" — is a different backing store: plugin-side pins never reach the UI, and pins written directly to the file are silently dropped the next time the TUI toggles any pin (it writes its whole startup-snapshot array back).

Environment

  • opencode version: 2.0.18
  • OS: Ubuntu, Linux 5.15.0-191-generic x86_64
  • Terminal: xterm-256color / truecolor (inside a terminal multiplexer)
  • Shell: /bin/bash
  • Install/channel: npm global install of @opencode/cli@2.0.18 (release)
  • Active plugins: several local package-directory plugins under ~/.config/opencode/plugins/ (a tab/session mirror, a launcher, credits sidebar); the plugin below is a minimal probe of the same shape

Reproduction

  1. In a TUI plugin's setup, join the documented storage and add a pin-shaped entry:

    const [state, update] = context.storage.store("session", { initial: { pinned: [] } })
    await update((draft) => {
      const pinned = Array.isArray(draft.pinned) ? [...draft.pinned] : []
      pinned.push("ses_existingSessionId")
      draft.pinned = pinned
    })
  2. Read ~/.local/state/opencode/session.json and open the session list.

  3. Separately, add the id to session.json by hand (read-modify-write), open the session list in a running TUI, then toggle any pin with ctrl+f and re-read the file.

Expected Behavior

  • Step 1–2: the session appears in the pinned section (and session.json reflects it) — i.e. plugin storage and the TUI's pin state are the same synchronized store, or there is a supported session-pin API for plugins (client.session.pin({sessionID}) / unpin, or the pin store exposed as a data surface with events).
  • Step 3: the plugin-written pin survives the TUI's own pin toggle.

Actual Behavior

  • Step 1–2: state.pinned inside the plugin shows the entry, but ~/.local/state/opencode/session.json is unchanged and the session list never shows the pin. The plugin storage store and the pin store are separate.
  • Step 3: the pin shows in the file (a restarted TUI displays it), but the running TUI's in-memory store never sees it — and its next ctrl+f toggle writes the whole pinned array from its startup snapshot back to the file, silently dropping the plugin-written entry.

Additional Context

  • Deterministic on 2.0.18, probed live 2026-10-01 with a minimal TUI plugin that read and wrote both stores and recorded both files.
  • Use case: a TUI plugin mirroring session pinning onto an external tab bar (terminal multiplexer tabs), where "pinned" is the user's explicit "keep this open" signal. We now treat session.json as the only channel (plugin-side read-modify-write) and design around the clobbering: tabs kept for sessions a plugin pins are additionally tracked plugin-side and are not dropped when the pin vanishes from the file (mpj/holmes-telephoning-journal#1774 if the details help).
  • The plugin docs phrase storage.store as "persists JSON across restarts and synchronizes across TUI instances", which reads as if app-managed lists like pins participate. A one-line clarification — or better, a real pin surface for plugins — would close the trap.
  • Secondary observation while probing: the session list's pin command is session.pin.toggle (bound to ctrl+f), and pin state is pruned to top-level sessions — if a pin API is added, its semantics should match that pruning.

Activity

  1. github-actions commented on Oct 1, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • Please use one of the required issue templates. For a bug report, include the report under a Description field; if this is a feature request, use a title starting with [FEATURE]: and include the verification checkbox. The issue already provides useful reproduction and environment details.

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


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

    For keybind-related issues, please also check our pinned keybinds documentation: #4997

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

  2. github-actions commented on Oct 4, 2026

    @github-actions
    Contributor

    This issue has been automatically closed because it was not updated to meet our contributing guidelines within the 72-hour window.

    Feel free to open a new issue that follows our issue templates.

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