Pitot
Host boundary field guide / open transport

Field note 00 / The host boundary

Release / v0.1.2 Apache-2.0 · nine hosts supervised

Your agent acts. Your code decides.

Your coding agent runs shell commands, edits files, and calls tools. Pitot puts your own code in the loop at that boundary — to allow, deny, or record each action — without forking the agent or rewriting a host integration for every tool.

Agent action Host hook Pitot Consumers observe· Controller replies Tool result
Your code / strip chart Autoscroll · illustrative
CONSUMERAgent finished editing authentication
SIGNALevent.agent.completed
SLACKMessage sent to #agent-runs
CONSUMERNew project decision observed
MEMORYSaved: auth uses signed sessions
AUDITActivity appended to project log
CONSUMERAgent run completed successfully
METRICS18.4s · kimi-k2 · success
CONTROLLERAgent wants to edit generated code
CHECKSource file is generated and protected
RESPONSEAgent stopped · deny
CONTROLLERAgent wants to run a migration
BACKUPDatabase snapshot confirmed
APPROVALDatabase owner approved
RESPONSEMigration may continue · allow
CONTROLLERAgent wants to publish a release
SIGNALrequest.shell.execute
VERIFYTests 128/128 · branch protected
APPROVALLocal operator approved
RESPONSEAgent may continue · allow
Consumers observeControllers reply

Their coding agent

ClaudeCodex CopilotCursor GeminiKimi OpenCodePi Qwen

Pitot

normalize
project event
correlate request
validate response

One live decision

shell.execute → allow

Their agent → Pitot → your code. Pitot transports. Your code decides.

01 / Boundary

Two roles. One hard line.

Pitot separates two capabilities that are easy to blur: observing what the agent did, and deciding what happens next. A passive Consumer cannot reach the response channel. A Controller is statically registered for one request kind and returns at most one response for the pending action.

Consumer / observes

Build from what happened.

Receive projected events for memory, audit, usage, reports, telemetry, or your own tools. Content projection — full, sha256, or omit — is applied before bytes enter your process.

Receives events · cannot reply · failure cannot block the agent
Controller / decides

Add behavior at the action boundary.

Receive a registered request while the host waits, check your own source of truth, and return one correlated allow or deny. Late, stale, duplicate, and malformed responses are rejected.

Receives a request · returns exactly one response · deadline and defaults declared
Pitot reports. Your controller decides.
02 / Placement

You do not need to replace the whole agent.

Different tools intervene at different points. Pitot sits at the one boundary every coding agent already exposes — the host hook — and keeps the agents your team already chose.

Switch agents

replace the product

Add a skill

advise the model

Add an MCP server

expose tools and data

Use Pitot

connect your code to observable events and waiting actions

03 / Install

Nobody installs Pitot per machine. The repository pins it.

pitot init writes two substrate files: a one-line committed version pin, and a committed shim that hydrates exactly that release — sha256-verified — into a per-user cache and execs it. Fresh clones, CI, and cloud agents run .pitot/bin/pitot with zero setup.

What the repository commits

.pitot/
├── version            # one semver line — the only version authority
├── bin/
│   ├── pitot          # committed shim (sh)
│   └── pitot.ps1      # committed shim (PowerShell)
└── conf.d/            # tenant fragments — see plate 05

What the shim does on first run

  1. Reads the pin from .pitot/version.
  2. Hydrates that release into ~/.cache/pitot/<version>/, verified against the published checksums.txt.
  3. Execs the verified binary. Every later invocation is a cache hit.
  4. No PATH fallback. A missing release with no network fails closed with a named error. PITOT_NO_HYDRATE=1 makes hydration cache-only.
Procedure / from zero to pinned
Installverified against release v0.1.2
01 curl -fsSL https://get.operatorstack.systems/pitot | sh

one-time convenience CLI, from the distribution front door

02 pitot init --template shell-policy --language go --dir agent-policy

writes the pin, the shims, a runnable Controller, and one tenant fragment

03 pitot doctor --host kimi

reports pin, cache, shim, and host-hook wiring

04 pitot dev --host kimi -- kimi -p "Run: echo hello"

runs your agent behind your Controller and prints each decision

Full walkthrough, CI story, and the fail-closed rules → Install & the repo-pinned shim.

04 / Upgrades

An upgrade is a reviewed one-line diff.

pitot upgrade verifies the new release, re-checks every tenant fragment against it, and rewrites the one pin line — nothing else. Commit that diff and every clone hydrates the new version on its next invocation. Roll back by reverting it.

git diff — the entire upgrade
--- a/.pitot/version
+++ b/.pitot/version
-0.1.1
+0.1.2
Procedure
01 pitot upgrade --check

report pinned vs latest

02 pitot upgrade

hydrate, validate tenants, rewrite .pitot/version

03 pitot doctor

inspect the effective boundary, pin, and cache state

What gets re-validated and how drift is surfaced → Upgrades as a reviewed diff.

05 / Configure

Multiple tools. One Pitot. No shared file to fight over.

Every tool or person that registers processes with Pitot owns exactly one fragment in .pitot/conf.d/, and no tenant ever edits another tenant's file. The effective configuration is the deterministic merge of all fragments in filename order.

conf.d/boatstack.yaml

a tool's controller, written by its installer

conf.d/interlock.yaml

another tool's controller, different request kind

conf.d/my-policy.yaml

your own, scaffolded by pitot init

Merge rules
Consumers compose

Any number of tenants can observe the same events.

One owner per kind

Two fragments claiming the same request kind fail discovery with an error naming both files — loud and attributable.

Additive by construction

Installing a second tool drops its own fragment next to yours. Uninstalling it is deleting its fragment.

Fragment anatomy, requires_protocol, and dir:Tenant config & typed SDKs.

06 / Typed SDKs

From your registry. Never public npm or PyPI.

Typed SDKs install from our own registry through the distribution front door, pinned to the CLI's version. They are optional conveniences — the protocol truth is versioned JSON Schemas and newline-delimited JSON. If a program can read JSON Lines from standard input, it can be a Consumer.

TypeScript
pitot install typescript

→ scoped .npmrc + @operatorstack/pitot@<pinned version>

Python
pitot install python

→ .pitot/registry + operatorstack-pitot==<pinned version> · import pitot

No SDK required — a complete Consumer
# ordinary Python — reads projected events from stdin
import json, sys

for line in sys.stdin:
    event = json.loads(line)
    print(json.dumps({
        "host": event["host"]["name"],
        "action_id": event["action"]["id"],
        "kind": event["action"]["kind"],
    }), file=sys.stderr)
07 / Build

What would you add to your coding agent?

Once the boundary is open, the missing feature becomes ordinary code.

01

Remember the useful parts.

Build selective project memory from projected events, without preserving entire chats.

02

Verify before continuing.

Check tests, CI, repository state, or another source of truth before the agent proceeds.

Read the build →
03

Ask for approval.

Route a release or protected action through your own local approval logic.

Read the build →
04

Measure what actually happens.

Track actions, model usage, latency, failures, and outcomes across coding-agent hosts.

Read the build →
05

Build something new.

Use the same boundary to create workflows and tools that coding-agent vendors have not built yet.

08 / Proof

Test the whole loop. Not a mock boundary.

Every supervised adapter must pass a binary-observed loop through the real coding-agent host on Ubuntu, macOS, and Windows:

prompt → real hook → projected Consumer → Controller allow / deny → tool result

Not just generated payloads.
Not just protocol unit tests.
The actual integration boundary.

Ubuntu · macOS · Windows — Claude, Codex, Copilot CLI, Cursor, Gemini, Kimi, OpenCode, Pi, Qwen

01Real prompt
02Host hook
03Projected Consumer
04Controller allow / deny
05Tool result
Honest scope

Pitot transports the event and the decision. Your code decides what approved, verified, safe, complete, or useful means.