session-portal
Skill0 starsChanged 44 days agoMITView on GitHub
Safe bidirectional message portal between Claude Code and Codex sessions. A durable local SQLite queue with an authenticated stdio MCP interface lets one session drop a short, authored message into another session's inbox; delivery is pull-only, so the recipient itself picks it up at a safe turn boundary, acknowledges, and acts under its own permissions. Identity is derived from a bearer token (not caller-asserted) and elevated actions need operator grants. Never writes transcripts, never pushes into or resumes another session, never runs message content. Use to hand a follow-up from Claude Code to Codex (or back) without manual relay. Monitoring stays separate and read-only (monitor-agent-thread).
In this repository15 other files it gives its agents.
- chat-arch-thrash-detectSkill
- chat-history-searchSkill
- email-editorial-passSkill
- fable-seatSkill
- gemini-imageSkill
- global-review-loopSkill
- monitor-agent-threadSkill
- pattern-retrospectiveSkill
- review-loopSkill
- seo-index-validationSkill
- session-endSkill
- session-handoffSkill
- ship-itSkill
- transcript-analysisSkill
- weekly-work-logSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
Not a way to approve permissions, publish, merge, push, or delete on another session's behalf.
- Distinctive: line 22
Not a transcript writer or a session resumer.
- Distinctive: line 24
Not a place where a caller asserts its own identity or authorization.
- Distinctive: line 26
Not a network service. It binds nothing.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Session portal
A safe mailbox between Claude Code and Codex sessions on this machine. One session queues a short message for a specific session of the other product; the recipient drains its inbox only when it is between turns, acknowledges, and decides what to do. The portal is durable (SQLite), idempotent, and timid: it never edits a transcript, never wakes or resumes a working session, and never executes the contents of a message.
monitor-agent-thread stays read-only. Monitoring and steering are separate capabilities.
What it is not
- Not a way to approve permissions, publish, merge, push, or delete on another session's behalf. A message is untrusted data with a recorded author; the recipient acts under its own gates.
- Not a transcript writer or a session resumer. It never writes a conversation log and never pushes into or resumes a session — delivery happens only when the recipient itself pulls.
- Not a place where a caller asserts its own identity or authorization. Identity comes from an authenticated token; sending steering or speaking as the user needs an operator grant.
- Not a network service. It binds nothing; the queue is a local user-level database.
Delivery model: pull-only
A message is marked delivered only when the authenticated recipient pulls it from its own
inbox — that pull is the only real proof the recipient received it. The portal never
fabricates a "delivered", "resumed", or "native-delivered" receipt it cannot back with a
pull. Sender-side push, auto-resume, and Codex-native delivery are not in this MVP;
portal_adapters.py only classifies whether a recipient looks safe to notify (advice, not
delivery).
Setup (authenticated MCP server)
The portal is a local stdio MCP server. Identity is bound at launch by a bearer token the operator mints for each session; the server derives the session's identity from it, so a session can never claim to be another.
Mint a token (operator, once per session) and copy it — it is shown only once:
python "{{SKILL_HOME}}/scripts/portal_admin.py" issue-principal --product claude --session <runtime-session-id> --label "what I'm doing"Register the server with that product, passing the token in the environment (see
references/mcp-config.md):SESSION_PORTAL_TOKEN=<token> python "{{SKILL_HOME}}/scripts/portal_mcp.py"
Health check (no token needed):
python "{{SKILL_HOME}}/scripts/portal_admin.py" healthCore workflow (MCP tools, acting AS the bound principal)
- Register/announce the current session (identity from the token):
portal_register_session {label}. - Send to another session's inbox — source is your authenticated identity, not an
argument; idempotent with
idempotency_key:portal_send_message {dest_session_id, body}. - Receive — draining your OWN inbox is the pull that delivers:
portal_list_inbox {deliver: true}. - Acknowledge what you acted on (as your bound identity):
portal_acknowledge {message_id}. - Audit any message you are a party to:
portal_message_events {message_id}.
Tools: portal_list_sessions, portal_get_session, portal_send_message,
portal_list_inbox, portal_acknowledge, portal_cancel_message,
portal_get_message_status, plus portal_register_session, portal_message_events,
portal_health. The operator CLI (portal_admin.py) mints tokens, issues grants, and offers
health/recovery/uninstall.
Authorization: operator grants (not caller booleans)
Elevated actions are operator-issued, scoped, expiring capability grants — never a flag a caller can set:
# let claude:B accept steering FROM codex:A for the next hour
python "{{SKILL_HOME}}/scripts/portal_admin.py" grant --to claude:B --capability accept-steering --scope codex:A --ttl 3600Capabilities: send-steer (send a steering message to a scoped destination),
accept-steering (receive one from a scoped sender), speak-as-user (record
authorship=user).
Safety and privacy invariants
- Identity is authenticated, not asserted: source, inbox owner, and acknowledger are derived from the bound token server-side.
- Message content is untrusted data; it is never executed and cannot bypass any product's permission, publish, merge, push, or delete gate.
- Steering needs an operator
send-steergrant to send AND anaccept-steeringgrant on the destination to deliver;authorship=userneeds aspeak-as-usergrant. No caller boolean. - Prohibited content is rejected, never stored: hidden reasoning, raw tool arguments, signatures, encrypted blobs, system/developer instructions, credentials, tokens, environment values, and other secrets.
- Delivery is pull-only over the transport: a message becomes delivered only when its authenticated recipient pulls it. Nothing is ever pushed into, or resumed for, another session. (The operator CLI can force a drain by vouching for the boundary; the audit trail records that as an operator attestation, not a recipient pull.)
- Loops and ping-pong are prevented by a forward-depth cap and a reversed-pair guard.
Documentation
references/architecture.md— components, storage, lifecycle, discovery.references/threat-model.md— trust boundaries, prohibited data, non-capabilities.references/mcp-config.md— per-product MCP registration.references/troubleshooting.md— health, stale-lock recovery, uninstall, rollback.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

