Help us shape the future of Go! Take the 2026 Go Developer Survey

pager

module
v0.0.0-...-ad6a9f4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: MIT

README

pager

English · 한국어

Send messages between coding-agent sessions. Works across tools and across projects.

It behaves like a pager, not a phone. You send; the other session reads it the next time it does anything. Nothing polls, and nothing interrupts a session mid-thought.

codex session                     claude session
    │                                 │
    │  pager send review-box "…"      │
    ├────────────► ~/.pager/msg.db    │
    │                                 │
    │                        (on its next hook run)
    │                                 │◄── injected into its context

What it's for

You have two agent sessions open: one in the API repo, one in the web repo. The API one changes a response shape, and the web one needs to know. Today you read that off one terminal and retype it into the other.

That retyping is what pager automates. It does not try to automate noticing — see Out of scope.

Install

make build     # builds to ~/.local/bin/pager

No C toolchain needed: the SQLite driver is pure Go, so it cross-compiles too. Everything lives in one file, ~/.pager/msg.db, created as 0600 in a 0700 directory on macOS and Linux. Windows has no mode bits for that to mean anything, and pager does not set ACLs, so there the file is only as private as the directory it sits in.

Then register a hook, because the hook is what delivers. Sending writes to the database; only a hook can put text into a session's context.

Claude Code — ~/.claude/settings.json:

{
  "hooks": {
    "UserPromptSubmit": [
      { "matcher": "", "hooks": [
        { "type": "command", "command": "pager hook", "timeout": 10000 }
      ]}
    ],
    "SessionStart": [
      { "matcher": "", "hooks": [
        { "type": "command", "command": "pager hook", "timeout": 10000 }
      ]}
    ]
  }
}

Codex CLI — ~/.codex/config.toml:

[[hooks.UserPromptSubmit]]
[[hooks.UserPromptSubmit.hooks]]
type = "command"
command = "pager hook"
timeout = 10

UserPromptSubmit is the one you cannot skip. SessionStart is recommended so a fresh session sees waiting mail right away. Pass no event name — pager hook reads it from the payload, so it cannot be misspelled.

Send your first message

pager who                          # who can I reach?
pager send hica "parser is yours"  # send
pager ls                           # what came to me
pager whoami                       # my session, my name

Sessions get a four-letter name like hica on their first hook run. The name is pronounceable and means nothing on purpose. Pick your own with pager alias review-box if you prefer.

When does it arrive?

Sending is always immediate. What varies is when the other side looks.

  • If it's reachable, right away. send knocks on the recipient's host and it takes a turn within a few seconds; that turn's hook delivers.
  • Otherwise, on its next activity. No knock, no loss — the message waits in the inbox until a hook runs.

The knock carries no content. It only says "you have mail"; delivery is always the hook's job, so a failed knock costs you latency and nothing else. pager send tells you which path it took.

The one caveat

Delivery is conditional, not guaranteed. If the recipient's hook never runs, pager never gets a chance to output anything, and it will not tell you — every hook path exits quietly rather than blocking a session.

You may also see the same message twice: retry is what makes delivery survivable, and duplication is its price. reference.md states the exact terms.

Everyday commands

Command What it answers
pager who Who can I send to, and is anyone actually behind that name?
pager send <name> "…" Send.
pager send <name>@<peer> "…" Send to a session in another store, carried by a relay.
pager ls What came to me.
pager ls --waiting What nobody has picked up yet.
pager inbox Which inboxes have mail waiting, across all sessions.
pager whoami Which session am I, and what is my name?
pager alias <name> Choose my own name.
pager claim <name> Take over an inbox whose session is gone.
pager export Dump the whole store as JSONL.

Using it from inside an agent (optional)

The CLI is enough. If you want tool calls instead:

claude mcp add pager -s user -- pager mcp
codex  mcp add pager       -- pager mcp

Three tools: msg_send to send, msg_list to read your own mail, msg_roster to see who you could send to. An agent learns its own name from the hook, but learns other names only from mail it receives — hence the roster.

Sessions on another machine (optional)

Each machine keeps its own store. To reach a session on another one, pair the two stores and let a transport you run carry mail between them — pager itself never opens a connection:

laptop$ pager peer add vm --store "$(ssh vm pager relay id)"
vm$     pager peer add laptop --store <id from `pager relay id` on the laptop>
laptop$ pager send kipa@vm "the parser work is yours"
laptop$ pager relay out --peer vm | ssh vm pager relay in --peer laptop | pager relay ack --peer vm

The causal hop crosses with the message, so the loop guard holds across machines too. The full contract — statuses, exit codes, record format, peer lifecycle — is in reference.md.

One safety note

A message body is text another agent wrote, landing in your context. That is a prompt-injection path, and it cannot be designed away — only reduced. pager always shows the sender, wraps the body as data rather than instructions, and caps its length.

The store is local to your user account, and pager never opens a network connection. Mail relayed from another store is marked as such on a line pager writes itself.

Documentation

  • reference.md — configuration, retention, rate limits, column meanings, troubleshooting
  • hooks.md — hook contract: events, inputs, outputs, fail-open
  • session-binding.md — how a session is identified

Korean versions of all four are alongside them as *.ko.md.

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
pager command
Command pager delivers messages between coding-agent sessions, across projects and across tools.
Command pager delivers messages between coding-agent sessions, across projects and across tools.
internal
clock
Package clock provides an injectable time source.
Package clock provides an injectable time source.
deliver
Package deliver implements pager's delivery rules: how a reference resolves to an inbox, who may take over an alias, how causal depth is computed, and which pending messages a hook may claim.
Package deliver implements pager's delivery rules: how a reference resolves to an inbox, who may take over an alias, how causal depth is computed, and which pending messages a hook may claim.
dispatch
Package dispatch is the one send path the CLI and the MCP server share: classify the target, write the message, then say what is behind the name.
Package dispatch is the one send path the CLI and the MCP server share: classify the target, write the message, then say what is behind the name.
hookio
Package hookio adapts pager to the hook contract Claude Code and Codex share: a JSON payload on stdin, and an optional hookSpecificOutput.additionalContext object on stdout that the host folds into the agent's next turn.
Package hookio adapts pager to the hook contract Claude Code and Codex share: a JSON payload on stdin, and an optional hookSpecificOutput.additionalContext object on stdout that the host folds into the agent's next turn.
mcpsrv
Package mcpsrv serves pager over MCP stdio, so an agent can page another session with a tool call instead of a shell command.
Package mcpsrv serves pager over MCP stdio, so an agent can page another session with a tool call instead of a shell command.
relay
Package relay moves mail between two pager stores without knowing how.
Package relay moves mail between two pager stores without knowing how.
sessionref
Package sessionref resolves which session a pager invocation belongs to.
Package sessionref resolves which session a pager invocation belongs to.
store
Package store owns the pager database: schema, connection policy, and the retention prune.
Package store owns the pager database: schema, connection policy, and the retention prune.
wake
Package wake pokes a recipient session so it reads its mail now rather than whenever its user next types.
Package wake pokes a recipient session so it reads its mail now rather than whenever its user next types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL