agentsclimarketplace

Opencode session recovery

Skill mvarge/agent-skills/skills/opencode-session-recovery

Public agent skills for OpenCode, Claude Code, Cursor, and other agent runtimes

Install
npx -y skills add mvarge/agent-skills --skill opencode-session-recovery

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 27 days oldThe repository was created 27 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Find, search, and resume past OpenCode sessions by querying the local SQLite session store directly. Auto-load whenever the user asks "which session was that", "find the session where we discussed X", "what did we do about Y last time", "resume the X session", "list my recent OpenCode sessions", or otherwise wants to locate or continue prior OpenCode work. Do not ask the user to click around the TUI picker — query the DB instead.

SKILL.md

7.7 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it

OpenCode session recovery

OpenCode stores every session in a local SQLite database. When the user asks to find or resume a past session, do NOT tell them to open the session picker in the TUI — query the DB or use the helper scripts bundled with this skill. The built-in picker is title-only and doesn't support content search, which is usually what the user actually needs ("the session where we discussed the load balancer", not "the session titled exactly X").

Where the data lives

  • DB path: ~/.local/share/opencode/opencode.db — SQLite, safe to read while OpenCode is running.
  • sqlite3 on the CLI is the simplest way in; anything that speaks SQLite works.
  • Session titles are auto-generated by whatever the user has configured as their small_model. If titles look like New session - <ISO timestamp> for every session, title generation is silently failing — see the "Titles broken" section at the bottom.

Schema cheat sheet

Three tables matter:

  • session — one row per session.
    • id (text, e.g. ses_0ae748691ffeKYezWOjxug2Ure)
    • title (text, human-readable; may be New session - … if untitled)
    • directory (text, absolute path of the cwd when the session started)
    • time_created, time_updated (integers, milliseconds since epoch — divide by 1000 before datetime())
    • time_archived (integer or NULL — filter IS NULL for live sessions)
  • message — one row per message.
    • id, session_id
    • data (JSON blob; role lives inside as $.role)
  • part — the actual content chunks.
    • message_id, session_id
    • data (JSON blob; text parts are {"type":"text","text":"…"})

To search message text, LIKE against part.data. It's JSON, but plain-text substring match works fine for keyword hunting since the text is embedded verbatim.

The three helper scripts (preferred)

This skill bundles three scripts in scripts/. The user should symlink them into their PATH (e.g. ln -s $PWD/scripts/oc-* ~/bin/) — do this once during install. They're tuned for the common cases; use them before hand-writing SQL.

oc-ls — list recent sessions

oc-ls                       # sessions whose directory starts with cwd
oc-ls -a                    # all sessions everywhere
oc-ls -p ~/Projects/foo     # sessions for a specific path prefix
oc-ls -n 50                 # bump the row limit (default 30)
oc-ls moon                  # keyword filter (case-insensitive, slug/title/dir)
oc-ls -a "load balancer"    # combine with -a/-p/-n; multi-word joins as one substring

Columns: slug | title | updated | dir | session_id. session_id is what you feed to oc-resume or opencode -s. Slugs (like neon-moon) are OpenCode's short human handles for sessions and are usable directly with oc-resume.

oc-grep — search sessions by message content

oc-grep "load balancer weekly"
oc-grep -p ~/Projects/foo "release"
oc-grep -n 5 "supabase migration"

Searches part.data for the substring across all sessions (or filtered by path prefix). Same output columns as oc-ls.

oc-resume — resume by slug, title fragment, or ID

oc-resume neon-moon                 # exact slug match (case-insensitive)
oc-resume "load balancer"           # substring on slug OR title; if unambiguous, drops into that session
oc-resume ses_0b40615a5ffe...       # by explicit ID
oc-resume -l "release"              # list matches instead of resuming

Resolution order: (1) exact slug match on session.slug, (2) fall back to substring on slug OR title. If either pass returns more than one row, oc-resume refuses and prints the candidates so you can pick by ID. Under the hood it just runs opencode -s <id>.

Raw SQL when the scripts aren't enough

For anything the scripts don't cover (grouping, joining, custom time ranges), query the DB directly.

How many sessions did I have on a specific date?

sqlite3 ~/.local/share/opencode/opencode.db "
  SELECT COUNT(*) FROM session
  WHERE date(time_updated/1000, 'unixepoch', 'localtime') = '2026-07-10'
    AND time_archived IS NULL;
"

Sessions per project, most active first:

sqlite3 -header -column ~/.local/share/opencode/opencode.db "
  SELECT directory, COUNT(*) AS n
  FROM session WHERE time_archived IS NULL
  GROUP BY directory ORDER BY n DESC LIMIT 20;
"

Find the first user message of a specific session (great for "what was I asking about?"):

sqlite3 ~/.local/share/opencode/opencode.db "
  SELECT substr(p.data, 1, 300)
  FROM part p JOIN message m ON m.id = p.message_id
  WHERE p.session_id = 'ses_XXX'
    AND json_extract(m.data, '$.role') = 'user'
  ORDER BY p.rowid ASC LIMIT 1;
"

SQLite's json_extract works fine on both message.data and part.data.

Resuming a session from the CLI

  • opencode -s <session_id> — drop into the TUI on that session (this is what oc-resume does).
  • opencode run --session <session_id> "your continuation prompt" — one-shot headless, useful when the user just wants to fire a follow-up without opening the TUI.
  • opencode run --continue "…" — continue the most recent session, no ID needed.
  • Add --fork to any of the above to branch off a copy instead of appending to the original.

Safe-query hygiene

  • Read-only by default. Never UPDATE, DELETE, or INSERT on opencode.db without explicit permission — this file is the user's entire session history. Back up first (cp opencode.db opencode.db.bak.$(date -u +%Y%m%dT%H%M%SZ)) if you must mutate.
  • Escape single quotes in user input by doubling them (''') when interpolating into SQL. The helper scripts already do this.
  • Full-text scans of part.data are fine — the DB is typically a few hundred MB and stays snappy.

Titles broken (triage playbook)

If a bunch of recent sessions come back titled New session - <ISO>, the small_model is failing to generate titles and OpenCode is swallowing the error.

  1. Tail the log for title/summary/HTTP errors:
    tail -200 ~/.local/share/opencode/log/opencode.log | grep -iE 'title|summar|400|401|429|error'
    
  2. Common causes seen in the wild:
    • Anthropic thinking-mode conflict: if the small model has extended thinking enabled AND temperature != 1, Anthropic returns a 400. Either set reasoning: false on that model in ~/.config/opencode/opencode.json, or leave temperature at its default. Titles need a low temperature, so reasoning: false is usually the right fix.
    • Auth / rate limit: 401 or 429 from the provider — check credentials or quota.
    • Model not available: provider returns 404 or the model id has been renamed.
  3. Fix the underlying cause; new sessions will get titles again. Existing "New session - …" rows stay untitled — either accept it, or write a small backfill script that reads the first user message from part and calls your small-model API to generate a title, then UPDATE session SET title = ? WHERE id = ?. Back up the DB before you run it.

When NOT to use this skill

  • If the user asks about a session in a different tool (Claude Code, ChatGPT, Cursor) — this skill only knows OpenCode.
  • For real-time state of the current session — that's just conversation memory, not the DB.

What ships with it: 3 files

7.7 KB alongside SKILL.md, 3 of them executable

scripts/

Keep looking

Skills are one crate of 326,984. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.