ocs is a small, dependency-free CLI for opencode
sessions. It lets you search, inspect, relocate and rename them from any folder,
without having to remember where each session was started.
opencode binds every session to the directory you launched it from, and its
session list only shows sessions for the current directory. So a session you
recorded in ~/code/app is invisible when you later run opencode in
~/code/other. Over time your sessions get scattered across many folders, and
there is no built-in way to:
- search across all sessions,
- see which folder a session belongs to,
- move a session to the project it actually belongs to,
- give a session a meaningful title (opencode's
sessioncommand has no rename), - find sessions that still have a meaningless auto-generated title.
ocs reads opencode's SQLite database directly and solves all of the above.
- Python 3.8 or newer (standard library only — no dependencies).
- The
opencodeCLI onPATHonly forocs move,ocs exportandocs import; every other command talks to the database directly.
Run it straight from a clone (no install):
git clone https://github.com/adrianiftode/ocs.git
cd ocs
python ocs.py --helpOr install the ocs command into your environment:
pipx install . # or: pip install .
ocs --helpThe repository ships three thin launchers next to ocs.py, so you can call
ocs without typing python ocs.py every time:
| Platform | File | Call it with |
|---|---|---|
| Linux / macOS / Git Bash / WSL | ocs |
./ocs <args> |
| Windows (cmd.exe) | ocs.cmd |
ocs <args> |
| Windows (PowerShell) | ocs.ps1 |
.\ocs.ps1 <args> |
Each launcher locates ocs.py next to itself and forwards all arguments. Set
$PYTHON to force a specific interpreter.
ocs resolves opencode.db in this order:
--db PATH(global flag),- the
OPENCODE_DBenvironment variable, - the default
~/.local/share/opencode/opencode.db, opencode db pathas a last resort.
Run ocs db to print the path that will be used:
ocs db| Command | What it does |
|---|---|
db |
Print the resolved database path. |
projects |
List projects/directories and their session counts. |
list |
List sessions across all folders (newest first). |
search |
Full-text search inside message text, across all sessions. |
show |
Print a session transcript. |
context |
Compact digest of a session, for AI title generation. |
untitled |
List sessions whose title is still a placeholder. |
stats |
Database statistics. |
rename |
Set session titles (single session or bulk from JSON). |
export |
Export a session to JSON via the opencode CLI. |
move |
Relocate a session to another project directory. |
backup |
Make a consistent copy of opencode.db. |
Every command accepts the global --db PATH flag, and most accept --json for
machine-readable output.
ocs projects # all folders + session counts
ocs list -n 20 # 20 most recently updated sessions
ocs list --sort created # order by creation time
ocs list --untitled # only sessions with placeholder titles
ocs list -d ~/code/app --json # one folder, as JSON
ocs list --nested # include subagent/nested sessionslist prints the session id, title, and the directory it belongs to.
Search runs a SQL LIKE prefilter followed by an exact match in Python, so it
is fast even on large databases and still matches non-ASCII text (accented
characters, emoji).
ocs search "connection refused" # anywhere, any folder
ocs search "NullReferenceException" -d ~/code/app
ocs search "MaximumReadableBytes" --types all # include reasoning text
ocs search "sub.?titr" --regex # regular expression
ocs search "warning" --case-sensitive
ocs search "TODO" -C 120 --max-hits 5 -n 50 # wider context, more hits
ocs search "migration" --role user --json # only user messages, as JSONOptions: -d/--dir, -p/--project, --nested, -r/--regex,
--case-sensitive, --types {text,reasoning,all}, --role {user,assistant,both},
-C/--context (chars of context around a hit), --max-hits (per session),
-n/--limit (number of sessions).
ocs show ses_0123456789abcdef # full transcript (text parts)
ocs show ses_0123456789abcdef -n 6 # only the last 6 messages
ocs show ses_0123456789abcdef --tools # include tool calls + input/output
ocs show ses_0123456789abcdef --reasoning --role assistant# one session
ocs rename ses_0123456789abcdef "Fix flaky integration test"
# preview without writing anything
ocs rename ses_0123456789abcdef "Fix flaky integration test" --dry-run
# bulk, from a JSON file
ocs rename --file titles.json--file accepts any of these shapes:
{ "ses_0123456789abcdef": "Fix flaky integration test" }[ { "id": "ses_0123456789abcdef", "title": "Fix flaky integration test" } ]A BOM (as written by some Windows editors) is tolerated.
By default rename writes a fresh, consistent backup of opencode.db to your
temp directory first (pass --no-backup to skip, --backup-dir DIR to choose
where it goes).
Restart opencode (or switch to another session and back) to see new titles — the TUI caches the session list.
opencode sometimes leaves a session with a generic title (or none). List them, grab a compact digest of each, then apply a title:
ocs untitled --json
ocs context ses_0123456789abcdef # human-readable summary
ocs context ses_0123456789abcdef --json # same, for an AI agent
ocs rename ses_0123456789abcdef "Add CSV export to reports"ocs move exports the session and re-imports it from the target folder.
opencode's importer upserts by session id and rewrites the project/directory
binding, so this moves the session (it does not duplicate it).
ocs move ses_0123456789abcdef --to ~/code/app
ocs move ses_0123456789abcdef --to ~/code/app --yes # skip confirmationThe target directory must already exist. Restart opencode afterwards.
ocs backup # -> <temp>/ocs-backups/opencode-<timestamp>.db
ocs backup -o ~/backups/opencode.db
ocs export ses_0123456789abcdef # -> ses_0123456789abcdef.json
ocs export ses_0123456789abcdef --stdout # pipe it somewhere
ocs import exported-session.json # import from current directory
ocs import exported-session.json --to ~/code/appbackup uses SQLite's online backup API, so it is safe while opencode is
running.
ocs can also point at a copied database, which is handy for sharing an
anonymised or archived session set:
ocs --db ~/shared/opencode.db list
ocs --db ~/shared/opencode.db search "error"ocs reads two tables that hold JSON:
session— one row per session (id,title,directory,project_id, …),message+part— the conversation;part.datais compact JSON such as{"type":"text","text":"…"}.
All read commands open the database read-only (file:…?mode=ro). Only
rename and move write, and rename backs up first.
MIT © 2026 Adrian Iftode. See LICENSE.