A terminal multiplexer for coding-agent sessions — browse, attach, clone, and
resume conversations from Claude Code, Codex, and OpenCode in one
place, backed by a provider-agnostic data model called UniversalType that
lets the same in-memory representation be read or written in any agent’s
native on-disk shape.
codex ──from_codex──▶ UniversalType ──to_claude──▶ claude
▲ │
│ ▼
opencode ↔ …
Three storage shapes, one unified surface:
| Agent | Storage |
|---|---|
| Claude Code | JSONL files under ~/.claude/projects/<encoded-cwd>/<sid>.jsonl (+ optional tool-results/ sidecar) |
| Codex | JSONL “rollout” files under ~/.codex/sessions/YYYY/MM/DD/, indexed by ~/.codex/state_5.sqlite::threads |
| OpenCode | SQLite database at ~/.local/share/opencode/opencode.db (tables: session, message, part, …) |
cokacmux normalizes all three into one model so the TUI can browse, preview, clone, attach, and resume sessions across providers from a single place. The same model is also exposed as a Rust library for other apps to embed.
claude --resume, codex resume, and opencode pick it up.provenance.raw.cokacmux crate ships the entire conversion and
discovery surface; the TUI is just one consumer.curl -fsSL https://cokacmux.cokac.com/manage.sh | bash
The installer detects your OS/arch, downloads the matching prebuilt binary
from dist_beta/, places it in /usr/local/bin (or ~/.local/bin if that
isn’t writable), and adds a shell wrapper so cokacmux can cd you into the
session’s working directory on exit. Run cokacmux to start.
irm https://cokacmux.cokac.com/manage.ps1 | iex
Installs to %LOCALAPPDATA%\cokacmux\cokacmux.exe and adds that directory
to your user PATH. Restart the terminal afterwards.
git clone https://github.com/kstost/cokacmux
cd cokacmux
cargo build --release --bin cokacmux
./target/release/cokacmux
Requires Rust 1.74+ (uses 2021 edition). The opencode feature (default)
pulls in a bundled SQLite via rusqlite, so a working C toolchain is
required on first build; disable the feature if you only need JSONL
providers (see Cargo features).
build.py orchestrates cross-compilation for Linux, macOS, and Windows
using locally installed zig + cargo-zigbuild (for Linux/macOS) and
cargo-xwin or GNU/LLVM toolchains (for Windows). Tools install under
builder/tools/, never globally.
python build.py --setup # install Rust + cross toolchains
python build.py --all # build all platforms except Windows
python build.py --windows # add Windows targets
python build.py --status # show installed tools
On Windows hosts, build.py prefers Rust’s GNU/LLVM Windows toolchains
when the MSVC linker isn’t available, avoiding the need for a Visual
Studio Developer Prompt:
python build.py --setup-rust --no-color
python build.py --setup-windows --no-color
python build.py --windows --no-color
The Windows path installs Zig locally, generates the required GNU import
libraries under builder/tools/winlibs/, and builds both
windows-x86_64-gnullvm and windows-aarch64-gnullvm.
cokacmux # launch interactive TUI
cokacmux --check # headless sanity check (no TTY needed)
cokacmux --version # print version
cokacmux --help # short usage summary
--check is useful in CI or smoke tests — it scans your ~/.claude,
~/.codex, and OpenCode database, prints the discovered session count and
status, and exits without touching the terminal.
The TUI has two top-level views: the sessions view (default) and the
agent view (active when attached to a running agent). Press Ctrl+]
to flip between them; the agent stays alive in the background.
| Key | Action |
|---|---|
q / Ctrl+Q |
quit |
Tab / Esc |
switch focus between session list and preview |
↑↓ / j k |
navigate list, or scroll preview when preview is focused |
PgUp / PgDn |
jump 10 in list, or page preview when preview is focused |
g / Home, G / End |
top / bottom of focused pane |
Alt+↑ / Alt+↓ |
move selection within the agents sidebar |
Alt+← / Alt+→ |
resize the sessions pane (saved to settings) |
Enter |
toggle preview summary/full |
/ |
filter by substring (id / cwd / title) |
f |
cycle provider (ALL → claude → codex → opencode) |
v |
toggle session list / tree view |
t |
edit selected session’s title |
r |
refresh from disk |
c |
clone or cross-provider convert the selected session |
d |
delete selected session (with confirm) |
e / Ctrl+] |
attach (or start) the selected agent session |
Ctrl+B |
toggle the agents sidebar visibility |
The sessions pane opens in tree view by default — clone children
appear under their parents. Press v to switch to a flat list. The
choice is persisted in ~/.cokacmux/settings.json.
When attached to a running agent (Claude Code / Codex / OpenCode):
| Key | Action |
|---|---|
Ctrl+] |
detach back to the sessions view (agent keeps running) |
Ctrl+K |
kill the selected / current agent |
Ctrl+PgUp / Ctrl+PgDn |
cycle to the previous / next live agent |
All other keys are forwarded to the agent’s terminal so the agent UI behaves exactly as if you ran it directly.
cokacmux stores everything user-facing under ~/.cokacmux/:
| Path | Purpose |
|---|---|
~/.cokacmux/settings.json |
UI preferences (pane sizes, view mode, debug) |
~/.cokacmux/titles.json |
User-supplied title overrides per session |
~/.cokacmux/agents/ |
Live-agent metadata + control sockets |
~/.cokacmux/debug/*.log |
Debug logs (only written when debug is on) |
~/.cokacmux/lastdir |
Last working directory (used by the shell wrapper) |
settings.json schemaAll fields are optional; defaults shown below.
{
"cokacmux": {
"sessions_pane_percent": 50,
"sessions_pane_width": null,
"agent_sidebar_width": 24,
"agent_sidebar_visible": true,
"session_view": "tree",
"debug": false
}
}
sessions_pane_percent — width of the sessions pane as a percentage of
the terminal (used as a fallback when sessions_pane_width is unset).sessions_pane_width — absolute width in columns. Set by Alt+←/→.agent_sidebar_width — width of the agents sidebar in columns.agent_sidebar_visible — toggled by Ctrl+B.session_view — "tree" or "list"; toggled by v.debug — see Debug logging.Unknown top-level keys are preserved on save, so settings files written by future versions remain compatible.
Debug logging is off by default. Turn it on by either:
"debug": true under cokacmux in ~/.cokacmux/settings.json, orCOKACMUX_DEBUG=1 before launching.When enabled, cokacmux writes plain-text logs to ~/.cokacmux/debug/*.log
in the format [HH:MM:SS.mmm] message, split by subsystem:
cokacmux.log — top-level TUI eventslibrary.log — read/write/convert calls into the librarysession.log, preview.log, agent.log — TUI subsystemsclaude.log, codex.log, opencode.log — per-provider adapter traceEach file rotates at 5 MiB. Logging is best-effort and must never affect conversion or session correctness, so it is safe to leave on.
The TUI is just one consumer of the cokacmux crate — the library is the
real surface. The public API is the same whether you use it from the
binary, another Rust app, or your tests.
use cokacmux::{Provider, SessionSource, SessionTarget, read_session, write_session, convert};
// Read any provider's native format into the universal model.
let session = read_session(
Provider::Claude,
&SessionSource::Path("/path/to/session.jsonl".into()),
)?;
// Write it back out in any provider's native format.
write_session(
Provider::Codex,
&session,
&SessionTarget::Path("/path/to/output.jsonl".into()),
)?;
// One-shot read+write across providers.
convert(
Provider::Codex,
Provider::OpenCode,
&SessionSource::Path("rollout.jsonl".into()),
&SessionTarget::OpenCodeDb { db_path: "opencode.db".into() },
)?;
In-memory string / connection helpers — useful for tests and for embedders that already hold their own I/O handles:
use cokacmux::providers;
// pure-string adapters (no library-managed I/O)
let session = providers::claude::from_jsonl_str(jsonl_text, &Default::default())?;
let out = providers::codex::to_jsonl_string(&session, &Default::default())?;
// hand the library your own rusqlite::Connection so opencode.db isn't
// opened twice when your app already has it open
let session = providers::opencode::from_db_connection(&conn, "ses_xxx")?;
Install helpers write the universal session back into each agent’s
native on-disk layout so that claude --resume <sid> / `codex resume