postbag
Two agents, one bag of letters. A Claude Code session and a Codex session on the same machine write to each other. Each letter reaches the other agent through its vendor's own wake-up door, lands in one ledger, and counts against a human-set letter budget.
Real commands, real output, fake doors. The recording uses a temporary
ledger, a throwaway socket and a stub codex, so no session or token is
shown. Tape: docs/demo.tape.
Use it to have one agent review the other's diff, to split a task between them and agree the interface by letter, or to get a second opinion without pasting context by hand. Text travels by postbag, code travels by git.
Install
Python 3.10 or later, standard library only.
pipx install postbag
postbag --version
Or from the tag: pipx install git+https://github.com/parasxos/postbag@v1.0.1.
postbag needs Claude Code's per-session messaging socket and the queue
command Codex added in 0.149.
Verified end to end on macOS with
Claude Code 2.1.263 and Codex 0.153.4 from the ChatGPT desktop app. Linux
passes CI but the live exchange is not verified there. Windows is not
supported. The Claude session must export CLAUDE_CODE_MESSAGING_SOCKET
and CLAUDE_CODE_MESSAGING_TOKEN to the commands it runs, the Codex session
must export CODEX_SESSION_ID, and codex queue --help must work. Set POSTBAG_CODEX if the binary is not in
the ChatGPT app or on PATH.
Quick start
Open a Claude Code session and a Codex session on the same machine.
-
Ask Claude to run
postbag join claude. -
Ask Codex to run
postbag join codex. -
In a terminal of your own, outside both sessions:
postbag open --limit 6
-
Ask Claude to send the first letter:
postbag send codex "Review my last commit. Reply with the top three findings."
Codex wakes with the letter. It begins with the letter's number, its sender and the one command that answers it, so neither agent needs instructions. The last letter of the budget says "do not reply", and the next
sendrefuses and tells the agent to stop and ask you. -
Read the bag from anywhere with
postbag read.
After a session restarts, ask it to join again.
How it works
join writes the session's door into the ledger: Claude Code's per-session
messaging socket and token, or Codex's thread id. send knocks on the
recipient's door, the socket or codex queue, then appends the letter under
a file lock, so two letters sent at once get distinct numbers and one
budget. The ledger, ~/.postbag/ledger.jsonl, is the only state, and the
default is shared across projects. Set the same POSTBAG_LEDGER in both
sessions and your terminal for a separate exchange. No daemon, no polling, no hooks, no server, no config file.
CONCEPT.md is the whole specification in a page.
Security and limits
- The ledger holds the Claude session token and every letter. Writes keep
the file
0600and new state directories are0700; an existing custom directory is left alone.readhides the door fields,catdoes not. Keep the raw file out of git, logs and screenshots. - A letter becomes a user turn in the recipient session. Trust both sessions with the task. postbag itself sends nothing off the machine; the vendor sessions forward the letter to their model services like any prompt.
openrefuses inside either session. The check reads the vendors' session variables: a guardrail against mixed-up roles, not authentication against another process running as you.- Unattended delivery to Claude was verified with bypass permissions. Other modes may hold the letter for your approval. Codex needs permission to write the ledger and connect to the Claude socket.
- "Delivered" means submitted through the door, not read. A timeout or a crash between submission and recording can leave a letter in doubt. There are no acknowledgements and no retries; check the recipient before sending again.
postbag is a small bridge for exactly two existing sessions. Tools that do more, and what they do, are listed in docs/readme-research.md.
Concept · Security · Changelog · Contributing · MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file postbag-1.0.1.tar.gz.
File metadata
- Download URL: postbag-1.0.1.tar.gz
- Upload date:
- Size: 22.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5188b222c8b7e0ce461c6c8aa045be054972d6020c5cf5343a92d3ff7df8c9f8
|
|
| MD5 |
f34c6b3c3bf51966f30d222e59c3668e
|
|
| BLAKE2b-256 |
25153ef93eb596288358ba05662b4590c23ebd15f8957f1ca10317cf4392ccd5
|
Provenance
The following attestation bundles were made for postbag-1.0.1.tar.gz:
Publisher:
release.yml on parasxos/postbag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
postbag-1.0.1.tar.gz -
Subject digest:
5188b222c8b7e0ce461c6c8aa045be054972d6020c5cf5343a92d3ff7df8c9f8 - Sigstore transparency entry: 2759983568
- Sigstore integration time:
-
Permalink:
parasxos/postbag@d3dab25cf446ac5634e90e05181f1f54557b5e35 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/parasxos
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d3dab25cf446ac5634e90e05181f1f54557b5e35 -
Trigger Event:
push
-
Statement type:
File details
Details for the file postbag-1.0.1-py3-none-any.whl.
File metadata
- Download URL: postbag-1.0.1-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3db95886f9abf15af066f858c06c8dfc0a7c4af3a4cbebecdde64ba2d4e4a12
|
|
| MD5 |
270d8cc0460395df3447492ba0af2262
|
|
| BLAKE2b-256 |
7bf0cb15d62d9a81f8bed7d3c6eb59713ee535b971b8212f2bc66da5e79a1fa7
|
Provenance
The following attestation bundles were made for postbag-1.0.1-py3-none-any.whl:
Publisher:
release.yml on parasxos/postbag
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
postbag-1.0.1-py3-none-any.whl -
Subject digest:
e3db95886f9abf15af066f858c06c8dfc0a7c4af3a4cbebecdde64ba2d4e4a12 - Sigstore transparency entry: 2759983595
- Sigstore integration time:
-
Permalink:
parasxos/postbag@d3dab25cf446ac5634e90e05181f1f54557b5e35 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/parasxos
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d3dab25cf446ac5634e90e05181f1f54557b5e35 -
Trigger Event:
push
-
Statement type: