Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,79 @@ Download a release binary for macOS, Linux, or Windows, or install from source:
go install github.com/operatorstack/pitot/cmd/pitot@latest
```

Inspect the effective local boundary:
Inspect the effective local boundary at any time:

```bash
pitot doctor
```

Start Pitot with repository-owned configuration and an owner-only runtime
## Quickstart

From a clean repository to one real allow/deny decision in two commands.

**1. Scaffold a project.** `pitot init` detects the language from the files
already in the directory, or prompts you to choose when it cannot. It writes a
runnable project — source, package manifest, and `.pitot.yaml` — and never
overwrites existing files unless you pass `--force`:

```bash
pitot init
```

```
Detected python project in .
Initialized python controller in .
Files written: .pitot.yaml, main.py, pyproject.toml, requirements.txt
Next: cd . && pitot dev --host claude --exec "python3 main.py"
```

You can skip detection and prompts with flags — handy for CI:

```bash
pitot init --language python --role controller --dir ./approval
```

The four first-class languages (`python`, `typescript`, `go`, `rust`) each
generate a complete project: `python3 main.py`, `npx tsx main.ts`,
`go run main.go`, and `cargo run` all work after installing dependencies.

**2. Run it against an agent.** `pitot dev` starts the runtime on a private
loopback endpoint, waits until it is ready, launches your Controller, and prints
each decision as the agent makes it. `--exec` takes the full command line (or use
`-- CMD ARGS`):

```bash
pitot dev --host claude --exec "python3 main.py"
```

```
Starting Pitot dev environment for host claude...
Runtime ready. Starting agent: python3 main.py
Decisions:
[ALLOW] release.approval (act_7f2) — v1.4.0 is approved for publication.
[DENY] shell.exec (act_1a9) — destructive command blocked
Agent finished. Runtime stopped.
```

`--host` must name a supported agent (`claude`, `codex`, `copilot`, `cursor`,
`gemini`, `kimi`, `opencode`, `pi`, `qwen`). The runtime descriptor lives in a
per-invocation temporary path and is removed on exit, so concurrent `pitot dev`
sessions never collide.

**3. Swap the agent.** The same project — the same Controller and `.pitot.yaml` —
works with any other supported host. Change only `--host`:

```bash
pitot dev --host cursor --exec "python3 main.py"
```

The boundary is language- and agent-neutral: one Controller, every agent.

## Advanced: manual runtime

`pitot dev` is the recommended path. If you need to manage the runtime yourself
(for example, sharing one runtime across several long-lived agent sessions),
start it with repository-owned configuration and an owner-only runtime
descriptor:

```bash
Expand All @@ -185,6 +251,11 @@ $env:PITOT_RUNTIME = Join-Path $env:LOCALAPPDATA "Pitot\project.json"
pitot run --config .pitot.yaml --runtime $env:PITOT_RUNTIME
```

## Connect your agent

The per-host hooks below wire each agent's native blocking boundary to Pitot for
the manual runtime flow. `pitot dev` configures the selected `--host` for you.

### Kimi Code

Install Kimi Code on macOS or Linux using its official installer:
Expand Down
26 changes: 12 additions & 14 deletions UPSTREAM.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"files": {
"CONTRIBUTING.md": "23728d8a132d62b8adfb2e5c3eb9d9bfcf8a4d04543765b1e22ad8d55424af8f",
"README.md": "091e47c27d0ee66a533b9aa9f3046a1bc9b84c0db5021926c6ab573d465ca57a",
"README.md": "77995d36de1a6ac5f5c687fad4a152b8824ea3ad25abe65325a7c4ee9a2ef52d",
"adapter-verification.json": "f8ad4e206571650f698826a8b66d8c00822be425e8d2de8ae98d98239e575eb4",
"adapters/adapters.go": "1b46ba131fa3b2c93eed23526330275a3506451ba4bbd4f497e5378dfab2b6a8",
"assets/pitot-boundary.png": "8a0ddb7d81831d94e14813f50ea4ca8670d77417f339ed2f91f0c653bf52f41d",
Expand All @@ -14,9 +14,10 @@
"bridge/bridge.go": "5adfcd3f743cae46e4446a6e030d53464ada97de0261a8588fa2a9fcd62136b8",
"bridge/bridge_test.go": "6dcc6d05f2b39c25955fc0b2d21d3d148dd9d77600fb12799941f86bdb1acb61",
"cmd/generate-schema/main.go": "6e9d0030290d99e36967433f96e38385a122974f899ad9421aac1ef7e50d8fcb",
"cmd/pitot/main.go": "d78ce2331aed6db847b29bd683bb6df57eb9e3bd82fdb438b29371c02a893a88",
"cmd/pitot/main.go": "14de1d6bf7ef7a75172ffd015c7cab1b66c38706b879de8d354137b34596c7f3",
"cmd/pitot/main_test.go": "544997295e0c4b75ef8f3d698b3de0883153f671b6b8f62057cc6e3452d6dc93",
"cmd/pitot/workbench.go": "3b4fe94e4663842194e9439af3a4049a86cf71fc2b38aac8af8ca1f667a59999",
"cmd/pitot/workbench.go": "2e2522491437c624b241fd594d678be2dab6824fc5aa3235db1ec82e00a669c7",
"cmd/pitot/workbench_test.go": "457caa11cd4b73c1fb4e0dad806b3050b196ddac690a8125f1615a4c695cc073",
"config/config.go": "e6666567d0c0cca41de69361e8f1243adda1ec0a54a9300b39a84d2290bff319",
"config/config_test.go": "87d3e5ddc4a3b43c736070de671d03e03ffe29cdd759771526ad27fd9bc0034c",
"conformance/conformance.go": "43b692114f45c8b52958e34b35aee1cee339d8321c90f92ab4f5b963e79935bb",
Expand Down Expand Up @@ -49,7 +50,7 @@
"runtime/capabilities.go": "76c27bdd7ddfa11a1d639915ac2eb2d573b7ccdd687a5f548b3731b7c1e1828f",
"runtime/descriptor_unix.go": "df41b6867e9840933f186c93b6bc61861e7ea5252a365455686ea0414bfa0044",
"runtime/descriptor_windows.go": "2d9ffefe3af0154fa8042de6b67460d4e86dd3f4cdd9e986f180f7d0c535c9a5",
"runtime/runtime.go": "693189eadd040629b616614e25dcdebb954e9c3546c25d064d0b8c3a7d01394a",
"runtime/runtime.go": "e0624a16ac9f79e8080246042912c73b1588f1b9aeb4f9f95b3711c7acef7e81",
"runtime/runtime_test.go": "afd78d122af20148bf30d0db873ff002544189df0dfec0f6167b8cf5cd0d42b1",
"runtime/transport.go": "83e2218fb28474e875dafa6943bc5b665acef0565aaf5955fa88b1b4fd21614e",
"runtime/transport_test.go": "9b69f590f1e258470adea249b3ac6d4a00f1001f10bb08dfa7b56c6e2d6709ae",
Expand All @@ -69,21 +70,18 @@
"sdk/python/pitot/__init__.py": "9cab11b333536f167d4e7bb6089ef00488690ec7b5cd5701f08e8bbb13cef0f7",
"sdk/python/pitot/runner.py": "8d4537ffc3aee2ea22b1d691559ac1eb1e95521df9ad5bf241ee6ac54c9925b1",
"sdk/python/pitot/types.py": "c9a7221f1ad6627f152f26148155d3c74f249c52262c73a515251f469e8eb4ad",
"sdk/python/pyproject.toml": "3f42de8223640978ad88e3f7b4ad1464053c43a393f0edf48445cacd31dd537c",
"sdk/python/pyproject.toml": "4b43380a1ebc12350ee3c30633695160ba0fc0bb64501b1e16f990a6fbe56d02",
"sdk/runner.go": "e9a8db96d3cf6df7ea7e661e6755650f97e580970995dfe881b4268db0c3f832",
"sdk/rust/Cargo.toml": "b8435f6c600ad0791bd29ada4bc396b14e54b96ee3804896c8e610583cc70c1a",
"sdk/rust/src/lib.rs": "fd2dcb9bf9df47fb58e52e4e94136f95867616d941ba66b4b324413d1c5b1777",
"sdk/rust/src/runner.rs": "96b9a04332b03999449ab24cc4e38df68dfc575a82d8fd599ad5211c7bfeabe6",
"sdk/rust/src/runner.rs": "168eb3f926aed4b86aa27ad66ab605326974b6a345b07a35126d4b66e0968b33",
"sdk/rust/src/types.rs": "82cd5a5ec12effa6688e8b9b6028bbef67ec43f24d9fd9d19b4235934061ffb8",
"sdk/tests/go_test.go": "4700cc0bcebb0be8af79e84438ef47a75d2892fcfef63352620ca22a2ac5fb33",
"sdk/tests/go_test_runner.go": "4700cc0bcebb0be8af79e84438ef47a75d2892fcfef63352620ca22a2ac5fb33",
"sdk/tests/python_test.py": "c52fae5cfa0e433ec95fa8c79a67804857facd456d75b6523d1ed16ddbb2672c",
"sdk/tests/test_runners.py": "19a6f950ee5b53b34d275ec39d3f9536bd2d693c2e11efa0e20ffe423f101f4c",
"sdk/tests/ts_test.ts": "63fe8bd68e4e8aa22d7ae24929f34c502978c19ec41c0f1645c1d513cb17329b",
"sdk/typescript/package.json": "c26c726559ff0bc7c5d92b68303efc3c35314613248fe346fa125aea06c8dba6",
"sdk/tests/test_runners.py": "9e86a03b53b108b70204e797b4c65b3d157c6765543a9bb9d7bb892daaf4d8c4",
"sdk/typescript/package.json": "8bd1fa7716b65c3c6599307d8d2e9398c75ae842c6047e9e0ad7716122db9a03",
"sdk/typescript/src/index.ts": "bddb336bc120ecd979de0288e432ed2b41749d39f11c697f019af5e54c2e9fba",
"sdk/typescript/src/pitot.ts": "9c243824cbb7edc54b1e125abfd828bf2ed77e7151a0bd5c5d4f63e81ca9b00c",
"sdk/typescript/src/runner.ts": "2022d4ee7efedec2c4c3baca2229440aa9773f5c32b58ffed8b1a2915add0278",
"sdk/typescript/tsconfig.json": "e4d7ecb203fcb7d93cd9b9fb235d7fd75d1b6fb2b28eff773f4aecfdc1924d5d",
"sdk/typescript/src/runner.ts": "c58babd3ec3996a05988f3cb7dec061cf7c48f41cd5125625be3408cb9b207f0",
"sdk/typescript/tsconfig.json": "3acd617cc06089125bcd963a3624131d765bb59e1a93db9736e78de6cf4fb40d",
"sensor/decode_fuzz_test.go": "d27f2fbbc069eded26a73c9cd9bace98dd8a9e34949576790b81a08d130fbaf2",
"sensor/sensor.go": "5c503d07ac33e7894d635f2d98bcd6d165d442d60c127ed6aeac80ec319086c5",
"sensor/sensor_test.go": "4ddbdde3e486c9e189a2ed4174ad413df107d43dc98f5242da3667a24c7a5da1",
Expand Down
6 changes: 3 additions & 3 deletions cmd/pitot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func runWithIO(ctx context.Context, args []string, stdin io.Reader, stdout, stde
}
switch args[0] {
case "init":
return runInit(args[1:], stdout, stderr)
return runInit(args[1:], stdin, stdout, stderr)
case "dev":
return runDev(ctx, args[1:], stdout, stderr)
case "doctor":
Expand Down Expand Up @@ -283,8 +283,8 @@ func usage() string {
return `pitot — the open sensor and control transport for coding-agent tooling

usage:
pitot init --language [python|typescript|go|rust] --role [consumer|controller] --dir PATH
pitot dev --host HOST --exec CMD
pitot init [--language python|typescript|go|rust] [--role consumer|controller] [--dir PATH] [--force]
pitot dev --host HOST --exec "CMD ARGS"
pitot doctor
pitot run --config PATH --runtime PATH
pitot hook HOST [--runtime PATH]
Expand Down
Loading
Loading