Skip to content

Repository files navigation

ocs

One picker for every OpenCode and Claude Code session on your machine.
Search across all your projects and Claude accounts, then jump back in — or carry the conversation into the other tool.

CI License: MIT Node >=20">https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg"> Zero TUI dependencies

ocs listing OpenCode and Claude Code sessions side by side, filtering them, and forking one into a second Claude account

The demo runs against synthetic sessions — see demo/.

Why

Your work is scattered. Some of it is in OpenCode, some in Claude Code, some in a second Claude account, and all of it is split across a dozen project directories. Finding the session where you actually solved that thing means remembering which tool you were in, cd-ing to the right repo, and paging through a resume list per tool per account.

ocs reads both tools' stores directly and puts everything in one list, newest first, searchable by what you actually typed.

Install

Needs Node 20+ and, obviously, OpenCode and/or Claude Code.

git clone https://github.com/sergio-gimenez/opencode-sessions.git
cd opencode-sessions
npm install
npm run build
npm run install:local     # puts `ocs` in ~/.local/bin, no root needed

Then just:

ocs

Try it without touching your own sessions

npm run demo

This builds a synthetic history — two Claude accounts, an OpenCode store, four fake projects — and runs the real picker against it with opening stubbed out. Nothing of yours is read and nothing is launched. Details in demo/README.md.

Keys

Key What it does
type Filter by title, directory and your prompts
Move the selection
PgUp PgDn Home End Jump
Enter Follow the displayed route
Tab Open in the other tool, as a transcript-seeded fork
Ctrl+T Cycle the target Claude account
Shift+Tab Open into the displayed target Claude account
Esc Ctrl+C Cancel

Reading the list

Each row carries a badge telling you where the session lives and where Enter will take it:

Badge Meaning
[OC] An OpenCode session. Enter resumes it natively.
[CC1] A Claude session in account cc1, and cc1 is the current target. Enter resumes it.
[CC1→CC2] A Claude session in cc1 while cc2 is the target. Enter forks it into cc2.

The right column previews the selected session: title, directory, id, your most recent prompts, and — with --assistant — recent assistant replies. Search terms are highlighted in both columns.

Migration is a fork, not a move

Cross-tool and cross-account opens do not migrate a session. Session ids are not portable between OpenCode and Claude Code, or between two Claude accounts, so ocs starts a new session in the target and pastes the old transcript in as context. Consequences worth knowing:

  • The original session still exists in its own tool, untouched.
  • Ping-ponging (CC → OC → CC …) leaves a chain of partial copies, and every hop reconstructs state from a transcript rather than resuming real state.
  • Always fork from the most recent node (top of the list) so you carry the latest work forward, not a stale branch.

Best practice: drive migration deliberately, at a natural boundary — a task is finished and you want to keep the general context while continuing in the other tool. Don't treat Tab as a live round-trip; treat it as "start fresh over there, with this history."

Multiple Claude accounts

Use Claude Code's normal home for the first account and an isolated CLAUDE_CONFIG_DIR for each additional one:

cc1() { command claude "$@"; }
cc2() { CLAUDE_CONFIG_DIR="$HOME/.claude-cc2" command claude "$@"; }

Authenticate each once (cc1 auth login, cc2 auth login), then tell ocs about them in ~/.config/ocs/config.json:

{
  "skipPermissions": false,
  "claudeAccounts": [
    { "name": "cc1" },
    { "name": "cc2", "configDir": "~/.claude-cc2" }
  ],
  "defaultClaudeAccount": "cc1"
}

Omit configDir for Claude Code's normal default account. ocs scans each account's projects directory and preserves account ownership when resuming, so a cc1 session resumes in cc1 unless you deliberately retarget it.

Pick the starting target from the command line when useful:

ocs --claude-account cc2

Full Linux, macOS and PowerShell setup, verification and troubleshooting lives in Using multiple Claude Code accounts.

Permissions

Launch the target tool with permission checks bypassed (claude --dangerously-skip-permissions / opencode --auto):

ocs --dangerous     # also --skip-permissions / --yolo
ocs --safe          # force checks back on, overriding the config default

Set the default in ~/.config/ocs/config.json with "skipPermissions": true. The CLI flag wins per run.

Note Skipping permission checks lets the agent act on your filesystem without prompting. Turn it on only for directories where you accept that.

Command line

Flag Effect
--print List the 25 most recent sessions and exit, no picker
--query <text> Start the picker with a filter already applied
--assistant Search assistant replies too, not just your prompts
--claude-account <name> Start with this Claude account as the target
--dangerous, --skip-permissions, --yolo Bypass permission checks
--safe, --no-skip-permissions Force permission checks on
--help, -h Usage

Dry run

Set OCS_DRY_RUN=1 and ocs prints what it would launch — command, Claude account, working directory — instead of launching it. Useful for checking how a route resolves, and for bug reports:

$ OCS_DRY_RUN=1 ocs
would run CLAUDE_CONFIG_DIR=~/.claude-cc2 claude <transcript seed, 1297 chars>
  in ~/code/pixel-forge

Where the data comes from

ocs reads both tools' existing stores. It never writes to them.

Source Path Override
OpenCode ~/.local/share/opencode/opencode.db (SQLite) OPENCODE_DB_PATH
Claude Code ~/.claude/projects/**/*.jsonl, plus each account's configDir CLAUDE_PROJECTS_PATH
ocs config ~/.config/ocs/config.json OCS_CONFIG_PATH

A missing or unreadable source is skipped rather than fatal — if OpenCode isn't installed you still get your Claude sessions, and vice versa.

Development

npm run dev          # run the picker from source
npm run print        # list recent sessions, no TUI
npm run demo         # picker against synthetic sessions, opening stubbed out
npm run typecheck
npm test
npm run build

See CONTRIBUTING.md.

License

MIT © Sergio Gimenez

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages