session-hub
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@session-hubfind my recent Codex sessions about the auth refactor"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Reads sessions from Pi, Claude Code, Codex, OpenCode, Crush and JCode · local, read-only, no network
The problem
You work across more than one coding agent. You start a refactor in OpenCode, then open Claude Code for a second opinion, or you are deep in a Codex session and want to finish it somewhere else.
Every agent keeps its own history, in its own format, in its own directory. Nothing carries over. So you do the only thing left: re-explain. What the task was, which files you touched, what the error said, which approach you already ruled out. The context window resets and you spend the first ten minutes rebuilding what you already knew.
session-hub removes that step. It reads the session stores every agent already writes,
puts them in one list, and turns the one you pick into a context package the agent you
are in now can actually use. It ships as an MCP server with three read-only tools, plus a
plugin for each agent that puts them inside the chat you are already in.
Related MCP server: voivox-mcp
What it does
One list, every agent | Pi, Claude Code, Codex, OpenCode, Crush and JCode sessions together, each row labelled with its agent, project, age and size. |
Continue here what you started there | Pick a session and its conversation arrives in this one, tiered and budgeted, so your next message already has the context you would have re-explained. |
Or go back to where it lives |
|
Read without spending tokens | The browser and |
Nothing is imported unless you pick it | No session arrives on its own, and no external session is ever rewritten into another agent's format. |
Local and read-only | The only writable path is |
flowchart LR
A["Claude Code<br/>~/.claude/projects"] --> H
B["Codex<br/>~/.codex/sessions"] --> H
C["OpenCode<br/>opencode.db"] --> H
D["Crush · JCode · Pi"] --> H
H["session-hub<br/>local index, read-only"] --> E["The agent you are in now<br/>import its context"]
H --> F["The agent that owns it<br/>verified resume command"]Requirements
Runtime | Node 22.5 or newer |
Dependencies | none. The index uses the built-in |
Build step | none. The hub runs TypeScript directly |
Platform | Linux, macOS, Windows |
Install
git clone https://github.com/Gateton/session-hub
cd session-hub
./install.sh # Linux, macOS
.\install.ps1 # WindowsBoth scripts do nothing but check Node and run the installer, so any platform can call that installer directly. This is the only entry point that exists before session-hub is installed: there is no package to fetch yet.
node install.mjsIt finds the agents on your PATH, shows their versions, and asks which ones you want
session-hub in. Nothing is installed into an agent you did not pick. Then it:
stages the hub in
~/.session-hub/src, so nothing depends on where the code came from and a moved checkout cannot break an installed plugin;installs into your choices;
links
sessionhubinto~/.local/bin(and prints theexport PATHline if that directory is not on yourPATH);wires Codex's delivery hooks and asks before touching its hook-trust setting.
For scripts, where there is nobody to ask:
node install.mjs --only codex --json
node install.mjs --all --dry-run--dry-run prints every command it would run and changes nothing.
Per agent, by hand
Substitute the directory you cloned into for /path/to/session-hub.
Agent | What to run |
Claude Code |
|
Claude Code, from a shell |
|
Codex |
|
OpenCode |
|
Every one of them is a command line entry point, so none of this needs a TUI.
How it works in each agent
The hub underneath is the same everywhere: one binary reads every agent's session store read-only, indexes it locally, and turns the session you choose into a context package. What differs is how you reach for it, and how the conversation arrives.
OpenCode
OpenCode is the only one of the three with an API for a real terminal UI, so it is the
only one with a full-screen browser. Open it with ctrl+shift+h, alt+h, or the command
palette:
What you install | one plugin in two halves: the tools and |
How you open it |
|
The tools |
|
In the conversation |
|
How the conversation arrives | a pick is handed to |
Manual step | none |
The browser. One list of every agent's sessions, a preview of the exact package that would be imported at the budget that will be used, and the keys in the footer.
Key | What it does |
| move the selection; the preview follows |
| move five at a time |
| first or last session |
| switch between the list and the preview |
| import the selected session, after a confirmation showing the cost |
| filter the loaded list; |
| filter by agent ( |
| clear the agent filter |
| re-read the hub index |
| leave the browser |
Each agent has its own marker and its own colour, π Pi, ✻ Claude Code, ⬡ Codex,
⌘ OpenCode, ❯ Crush, ◆ JCode, so a row says which agent it belongs to before you
read the label. Two panes above 90 columns, one pane below it, so 80x24 is a supported
size rather than an accident.
export SESSION_HUB_ASCII=1 # plain letters, for terminals without symbol coverage
export SESSION_HUB_KEYBIND="ctrl+shift+s" # the key that opens the browserClaude Code
What you install | a plugin: one skill, two hooks, one MCP server named |
How you ask | in plain language. "continue what I left in Codex", "the session where we fixed the parser". The skill teaches the model when to reach for the tools |
The tools |
|
How the conversation arrives |
|
Manual step | none |
The plugin carries the hub with it: on the first session start it vendors a copy of the
hub into itself, so claude plugin install works with no global setup and keeps working
even if the checkout it came from moves.
If the injected block is longer than Claude Code's 10,000 character limit for hook
context, it is cut in the middle, the cut says so, and the head and the closing line stay
intact. The rest is one context call away at the same uid.
Codex
What you install | a plugin: one skill, one MCP server, and two hooks |
How you ask | the same plain language. The tools appear as |
How the conversation arrives | the same two paths: |
Manual step | trust the hooks once, in |
Codex refuses to run a hook it has not been told to trust, and trusting happens in its
/hooks dialog, which cannot be driven from a script. Two ways out:
Run
/hooksonce and trust the two session-hub entries. This is the default, and the installer leaves it to you.Let the installer set
bypass_hook_trust = truein~/.codex/config.toml. It asks first, because that line applies to every hook in that file, not only these.--trust-hooksand--no-trust-hooksanswer it in advance, andnode integrations/codex/scripts/install-hooks.mjs --no-trustremoves it again.
Until the hooks are trusted, the tools and the skill still work: you can load a session by asking for it. What you lose is a pick arriving on its own.
Codex runs shell commands under a sandbox, so the hub reads an index it is not allowed to
rewrite and says so. The MCP tools run outside that sandbox and are unaffected; to give
the shell fallback access to the hub home, start Codex with codex --add-dir ~/.session-hub.
The MCP server
The same three read-only tools are available to any MCP client, with or without a plugin.
Tool | What it does |
| Finds sessions across every agent, by words, project or agent. Returns uid, agent, project, time and title for each match. |
| Loads one session's conversation into this one, inside a character budget. |
| The verified command that reopens that session in the agent that owns it. |
All three declare themselves read-only, idempotent and closed-world. Register the server yourself if you would rather not install a plugin:
claude mcp add session-hub -- node /path/to/session-hub/mcp/server.mjs
codex mcp add session_hub -- node /path/to/session-hub/mcp/server.mjsYou get the tools in every session. You lose two things: the automatic delivery of a session you picked, and the skill that tells the agent when to go looking.
How much context arrives
Loading a whole conversation would be wasteful, and the cost would grow without bound as sessions get longer. The package is therefore tiered, with a hard budget (40k characters, about 10k tokens, by default):
Tier | Contents | Cost |
1. Header | objective, repo, model, files changed and read, commands run, tool usage | ~1k characters, always included |
2. Recent tail | the last turns verbatim, because that is what you continue from | up to 26k characters |
3. Earlier | one line per older message, so the shape of the conversation survives | remainder |
4. Omitted | a count, never silence | 0 |
Two decisions make that affordable: tool output is compressed to a short preview in every
tier (on real sessions it was 90% of the bytes and the least useful part for resuming
work), and when the budget runs out the oldest messages condense or drop, never the
tail. The cost is printed every time, and --chars sets the ceiling.
Using it
Ask in plain language. The agent has the tools and a skill that tells it when the hub is worth reaching for, so you never have to name a command or a session id. You do not have to say "session-hub" either.
What you can ask
You want to | Say something like |
Pick up work you left elsewhere | "continue what I was doing in Codex" · "pick up where we left off" · "carry on with what I started in Claude Code" |
Find a session you half-remember | "the session where we fixed the retry loop" · "where did I deal with the timezone bug" · "that conversation about the migration" |
See what you were doing here | "what was I working on in this repo" · "what did I do yesterday" · "what was I doing before lunch" |
Go back to the agent that owns it | "open that in Claude Code" · "take me back to the OpenCode session" · "how do I resume that in Codex" |
Read before you commit to it | "show me that transcript first" · "what did we decide about the schema" · "list my recent sessions" |
Check or cancel a pick | "what is waiting to be imported" · "cancel the session I picked" |
The agent answers with what it found, and only imports a conversation when you pick one.
From the command line
The same hub, without a model in the loop. Every one of these is read-only unless it says otherwise:
sessionhub here # what did I do in this project, every agent
sessionhub list --harness codex --limit 5 # the newest Codex sessions
sessionhub search "retry loop" # titles and transcripts, across every agent
sessionhub show claude-code:7c943ffa # read it, free, no model involved
sessionhub context claude-code:7c943ffa # the budgeted package, ready to paste
sessionhub native claude-code:7c943ffa # the command that reopens it where it lives
sessionhub pick codex:01a0c4f4 --note "retry bug" # arm it for your next message
sessionhub doctor # which agents were found, how many sessionsIn OpenCode there is also /hub, which is the browser and the tools without leaving the
chat:
/hub # sessions of this project, every agent
/hub payment retries # search every transcript
/hub load codex:0191ab... # import it, delivered with the next message
/hub pending # what is waiting to be imported
/hub reopen codex:0191ab... # the command that reopens it in CodexCommands
sessionhub here [--dir D] sessions of the project you are standing in, every agent
sessionhub list [--harness H] newest first, across everything
sessionhub search "words" find sessions
sessionhub search "words" --deep read full transcripts when the index is not enough
sessionhub context <uid> [--chars N] the tiered, budgeted package
sessionhub show <uid> the transcript, read-only, no model involved
sessionhub handoff <uid> a deterministic handoff document
sessionhub native <uid> the verified resume command, or a refusal
sessionhub pick <uid> choose a session to arrive with your next message
sessionhub pending [--take|--peek|--clear] what is armed: print it, peek, or cancel
sessionhub doctor which agents were found, how many sessions each
sessionhub index [--force] rebuild the local index
sessionhub install [--only|--all] install into the agents you choose
sessionhub setup | vendor | version | mcpEvery command takes --json, prints only payload on stdout and diagnostics on stderr, so
sessionhub context <uid> can be piped straight into a prompt. A uid is
<agent>:<nativeId>, and a unique prefix is enough.
Search
sessionhub search and the browser's transcript path use a local SQLite FTS5 index:
bare terms use prefix matching, so
pliegomatchespliego-prod"exact phrase"matches a phrase-termexcludes
The index stores each session's title, metadata and a bounded excerpt of the conversation
(20k characters, sampled from both the start and the end). search --deep goes further
and reads whole transcripts when the excerpt is not enough; it reports how many sessions
it read, so a partial answer never looks complete.
Guarantees
Nothing outside the hub home is written
The only writable path is ~/.session-hub/ (the index, the armed selection, the install
record). Every agent's store is opened read-only, including the SQLite databases. The
acceptance suite fingerprints every store before and after a full scan and fails if
anything changed.
External sessions are never disguised as yours
A Claude, Codex, OpenCode, Crush or Pi conversation is never converted into another agent's session format. There are exactly two paths:
Reopen it where it lives: the hub prints the command the owning agent understands, states how it verified that command, and refuses when it has no verified command rather than handing you one that would fail.
Import its context here: the conversation arrives in a new message labelled with the source agent, session id and path, generated locally and deterministically. No model, no network, nothing uploaded. Fields the source format cannot supply are written as
not availablerather than guessed.
Supported agents
Agent | Store | Format | Resume |
Pi |
| JSONL tree v3 |
|
Claude Code |
| JSONL |
|
Codex |
| JSONL |
|
OpenCode |
| SQLite |
|
Crush |
| SQLite |
|
JCode |
| JSON |
|
Each agent gets its own adapter. A missing, empty or unreadable store degrades to a specific message ("no store at ...", "cannot read ...") instead of an empty list, and one broken adapter never takes down the others.
Privacy
The index lives at
~/.session-hub/index.sqlite. Delete it and the next scan rebuilds it.Credential stores are never opened.
auth.json,.credentials.json,.env,request_dump_*and similar are refused by name before any open is attempted.Transcript text passes through a redactor (bearer tokens,
sk-keys, JWTs,api_key=andpassword=patterns) before it is stored or written into a handoff.No network access, ever, for indexing or searching.
Limitations
Claude Code and Codex formats are undocumented. The parsers are defensive and degrade to filename-derived metadata rather than throwing, but a format change can cost fields until the adapter is updated.
Crush does not record a session working directory, so those sessions show no project and cannot be filtered by one.
Claude sub-agent transcripts are indexed but cannot be resumed by id; the hub refuses instead of offering a command that would fail.
Search covers a bounded excerpt, not the whole history of a very long session.
--deepis the way past that.Installed plugins use the staged copy at
~/.session-hub/src, not your checkout. After changing the code, run the installer again to restage it.
Documentation
Where to go | What you will find |
The browser, | |
The plugin, the two hooks, first-run vendoring and the vendored layout | |
The plugin, hook trust, the MCP wiring and Codex's sandbox | |
How the OpenCode screenshot on this page is produced |
Development
node test/acceptance.mjs # the full suite, against the real stores and a foreign home
node tools/make-demo-image.mjs # regenerate the screenshot (drives OpenCode in a real PTY)The suite runs against the stores on this machine and against a synthetic home this project has never seen, and asserts among other things that no external store file is modified, that every resume command is verified or refused, and that reading a home with no agents says so instead of looking empty.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Search and save your coding work in a CoralSwarm ocean: sessions, decisions, meetings.
Read-only MCP access to authorized Vocci sessions, notes, files, and memory search.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Search and share cited agent findings. Public reads; authenticated writes.
Related MCP Servers
- AlicenseAqualityCmaintenanceSearches and browses local Claude Code and Cowork session histories stored on your machine, enabling questions about past work without uploading data.32MIT
- AlicenseNot gradedqualityAmaintenanceEnables agents to list, read, export, and derive text from local VOIVOX transcript sessions without modifying the immutable source.MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to search and retrieve past coding-tool conversations across Claude Code, Claude Desktop, Codex, and Cursor through a local, read-only index.1MIT
- FlicenseAqualityBmaintenanceEnables selecting a saved Codex or Claude Code session from the same PC and importing its recent context into the other tool, so work can continue across clients with source and omission information.3-