The installer kit
PostMQ ships the session protocol as files you can read, for Claude Code, Codex, ZCode and Antigravity. An agent can install them for you over MCP, the Claude Code plugin registers them, the CLI installs them offline, or you can copy them by hand — every route writes identical bytes.
What the kit is
The MCP tools give an agent somewhere to put build sessions, decisions, backlog items, lessons and rules. The kit is what makes something actually call them at the right moments.
It is deliberately files rather than a feature. The server does not enforce the protocol; the kit is a recipe, the one we run on PostMQ itself, and you are meant to read it and change it to suit your project.
What is in it
The session-state kit — a start-session skill that recovers where the last session stopped and asks which
rules apply before touching a file, an end-session skill that logs the decisions and files the deferrals, and a
SessionStart hook that prints your drift signals. Claude Code, Codex and ZCode; on Antigravity, where the kit wires
nothing, the same drift script ships and the start-session skill runs it.
The usage reporter — reads the session’s transcript, sums the five token classes and the turns, and records
them against the build session. A SessionEnd hook on Claude Code and Codex, a Stop hook on ZCode, and on
Antigravity a command the end-session skill runs. It reads Claude Code transcripts, Codex
rollouts, ZCode rollouts and Antigravity conversation databases, and reports which client it read. Idempotent per
transcript, so re-reporting overwrites rather than double-counting. Worth nothing on its own: it records against the build session the
session-state kit opens.
The numbers it reports are self-reported — as good as the client reporting them. PostMQ stores and rolls up token counts; it does not meter your model provider and prices nothing. Two figures are coarser on Codex and ZCode, because neither transcript carries the finer ones: cache writes are not split by lifetime, and there is no sub-agent turn count. On Antigravity cache writes are not merely coarser but absent — nothing in its store records them — while its input, cache-read, output, turn and model figures come from the client’s own per-request records. A report there is a snapshot of the conversation database at the moment it runs.
Four clients, one set of files
The same files install to different paths depending on the client, because each client looks in its own place:
| Claude Code | Codex | ZCode | Antigravity | |
|---|---|---|---|---|
| Skills | .claude/skills/<name>/SKILL.md | .agents/skills/<name>/SKILL.md | .zcode/skills/<name>/SKILL.md | .agents/skills/<name>/SKILL.md |
| Scripts | .claude/hooks/ | .codex/hooks/ | .zcode/hooks/ | .agents/tools/ |
| Hook wiring | .claude/settings.json | .codex/hooks.json | .zcode/config.json | none — see below |
| Usage reported on | SessionEnd | SessionEnd | Stop — ZCode has no SessionEnd | the end-session skill |
There is one source per file in the manifest whatever the client, so the SHARED entries are paths onto the same
bytes rather than copies that drift. The trees as a whole are not identical and should not be described that way: ZCode gets a wrapper of its own,
and each client’s wiring differs — Antigravity’s install has none at all. Tool names need no translation either: Codex and ZCode both name MCP tools
mcp__<server>__<tool> exactly as Claude Code does, so the names in the skills are the names they call.
The ZCode wiring row is where the kit WRITES, not the only place ZCode reads. ZCode checks two project-config
filenames in each directory — zcode.json first, then .zcode/config.json — in every directory from the nearest
.git ancestor down to your working directory, so a monorepo package and its repo root are both sources (a git
worktree’s .git is a file, which counts, so the walk stops at the worktree root). If you already keep a
zcode.json, wire the hooks there instead; hooks.enabled is OR-ed across every source, so it only has to be true
in one of them.
Antigravity does not name MCP tools individually at all — it dispatches them through one call_mcp_tool tool —
but it resolves the mcp__<server>__<tool> form correctly onto that, so the same skills work unchanged there
too. (mcp(<server>/<tool>), which you will see in its permission rules, is a permission spelling and not a
tool name.)
Two Codex behaviours to expect, both the client protecting you. Codex reads a project’s .codex/
configuration only once you have marked that project trusted, and it asks you to review a hook once before it will
run it — so a freshly installed hook is inert until you approve it, and editing it asks again. And Codex gives a
session-end hook one second by default and three at most; reading a transcript and reporting it does not fit in
that, so the usage reporter is launched by a wrapper that returns at once and finishes the work detached.
Three ZCode behaviours to expect. ZCode also reviews a project hook once before running it. Its hook runner is
off until hooks.enabled is true — the installer sets it, and tells you rather than flipping it if you had turned
it off yourself. And it has no SessionEnd event at all, so usage is reported on Stop, which fires once per
turn: the report is an idempotent upsert, so the turns converge on one row rather than accumulating, and a session
you never formally end still has its usage recorded. The reporter also keeps a high-water mark and refuses, on a
best-effort basis, any report that would reduce the row — which is what stops a rollout ZCode truncated
mid-session from ratcheting the total down for the rest of it. It does not order two reports that are in
flight at once: the server’s upsert replaces every count, so that belongs on the server rather than in the hook,
and it is tracked rather than claimed.
Antigravity has no hook wiring, and that is measured rather than pending. Its binary carries a hook
system, and ~/.gemini/config/hooks.json is a real path that parses — but on Antigravity 2.8.0 no hook could be
made to fire, across seven different ways of binding one, and a project-scoped .agents/hooks.json was never
loaded at all. So the kit ships nothing to wire there: rather than a snippet that would report success and do
nothing, the two scripts install to .agents/tools/ — they are not hooks on this client — and the skills run
them. start-session runs the drift-signal script itself; end-session runs the usage reporter itself.
The cost is real and worth stating plainly: there usage is recorded only when end-session runs, so a session you never formally end records no usage at all. On the other three an event covers that case. When the reporter runs it resolves the conversation opened against the current directory — never simply the most recent one, because a machine accumulates thousands and the newest probably belongs to another project — and it refuses rather than guessing if it cannot find one.
One ZCode difference is worth knowing if you install by hand rather than with an installer: its SessionStart
hook injects only JSON, and discards plain text without saying so. The shared drift-signal script is therefore
wrapped by a small .zcode.sh file that runs it and re-emits its output in the shape ZCode reads — wire the
wrapper, not the script, or the hook will run perfectly and inject nothing.
The current list, with the files each component writes and where they go, is always at postmq.com/kit/manifest.json.
Four ways to install it
Which of them is open to you depends on the client. Copying the files by hand always works. Asking the agent works where the client surfaces the server’s instructions and MCP resources to the model — Claude Code and Antigravity do; ZCode’s CLI reads the tool list and nothing else, so ask it there and it has nothing to read. The plugin is Claude Code’s. The CLI needs a build from source — see below.
Ask your agent
If you have connected the MCP server, your agent already has everything it needs. PostMQ returns
an instructions string on connection telling it to read the kit manifest and offer the components — so “set up
the session protocol for me” is enough.
It will ask before writing anything. That is in the instructions the server sends, not a courtesy: an agent should never write into your project uninvited, and if one does, that is the agent rather than this server.
The Claude Code plugin
claude plugin marketplace add No-Compromise-AI/postmq-plugins
claude plugin install postmq-session@postmq
That registers the /start-session and /end-session skills and wires both hooks in one step, and the plugin
updates with the marketplace rather than needing a re-install per file.
The marketplace is generated from the same manifest as everything else, so the plugin’s skills are byte-identical
to the ones the other routes write. Its hooks run from the plugin directory rather than from your .claude/hooks/,
which is the only difference.
The CLI — and what it costs you today
pmq is not a download. It ships in no package manager and has no release workflow, so the commands below are
reachable only by building it from source, and the repository is private. That is stated here rather than left to be
discovered at the shell prompt: the other three routes need nothing you do not already have, and this one needs a
checkout you may not be able to get.
pmq kit list # what is available
pmq kit install --all --dry-run
pmq kit install --all
pmq kit install --all --client codex
--client chooses which layout to write; it defaults to claude-code.
The kit is embedded in the binary, so this makes no network call and needs no credential. --project-dir installs
somewhere other than the current directory, and the command prints the resolved path before it writes anything.
By hand
Every source the manifest names is served at postmq.com/kit/<path>, where <path> is that source with a leading
kit/ removed — for example the start-session skill and
the usage reporter.
Copy each to the target for your client, which is not always target. That field is the Claude Code path.
For Codex, ZCode and Antigravity, use client_targets.codex / client_targets.zcode /
client_targets.antigravity where a file has one, and the matching client_settings_merge entry for the
settings block — Antigravity has none, deliberately, so there is nothing to merge for it. A file with no target at all — the Codex/ZCode
session-end wrapper and ZCode’s SessionStart wrapper — installs only for the clients its client_targets names,
so a Claude Code install skips it and a Codex or ZCode install must not. Then chmod +x
the shell hooks and merge the settings snippets into the file each one names.
What the installer refuses to do
Three rules, because the kit is installed into a project that already exists and may already work:
It will not overwrite a file you changed. A target that exists with different content is reported and skipped,
not replaced. These skills are meant to be edited — an installer that quietly restored its own version on a routine
re-run would destroy exactly the work the kit exists to start. --force replaces, when you mean it.
It appends to settings arrays; it never replaces them. Merging into hooks.SessionStart adds an entry. If you
already had something wired there, it stays. Replacing that array would silently disable it, and nothing would say
so.
Installing twice does nothing. Files already current are left alone, and a hook already wired is not wired
again. A doubled SessionEnd reporter would submit the same transcript twice.
Afterwards
Restart your client. Skills and hooks are read at start-up, so a client that was running when you installed will not see them. On Codex and ZCode, also approve the hook when it asks — until you do, the skills still work and the drift block is simply absent.
Then check it worked: run the start-session skill — /start-session in Claude Code, ZCode and Antigravity, $start-session in Codex —
and it should name the active build session, or start one, and print the drift block from the hook. After a session ends, get_usage should show a row with a non-zero turn count.
The credential needs the write_session_state scope for either component to write anything. Reads need only an
authenticated caller. Authentication has the scope catalogue.