The command-line client for tapes — what it does, the two server ports it talks to, and a first capture and read.
tapesctl is the command-line client for tapes. Tapes
records what coding agents actually did — every LLM call an agent made, as
sessions, traces, and spans. The server stores and serves that data;
tapesctl is what captures it and what reads it back.
The split is worth stating once, because it decides which documentation answers a given question:
- tapes is the server. It owns
serve,local up,seed, and the HTTP APIs. Running one is documented in the server’s own docs at https://tapes.dev/docs/. - tapesctl is the client. Every capture and read verb lives here.
You bring your own server. tapesctl never guesses one: with no server
configured, commands that need one refuse to run rather than send a capture to
whatever happens to be listening.
The two ports
Section titled “The two ports”A tapes deployment serves reads and ingest on separate listeners, and
tapesctl commands are split across them. Passing the wrong one is the single
most expensive mistake available here: a capture pointed at the read port still
exits 0. It reports no turns were captured, and the reason — every turn
rejected by a route that does not exist there — is a warning in a log file you
were not watching.
| port | listener | the commands that use it |
|---|---|---|
8081 |
read API | sessions, traces, spans, search, export, seed, skills, cassettes |
8082 |
ingest | start, capture, sync |
Those are the defaults of a local tapes serve. A deployment that fronts both
behind one hostname gives you one URL for everything; check with whoever runs
it. What does not vary is which side of the split a command is on.
Read and ingest have independent configuration and local defaults. Use
--api-url / TAPES_API_URL for reads and --ingest-url /
TAPES_INGEST_URL for capture. See Configuration.
Install
Section titled “Install”curl -sSfL https://download.tapes.dev/tapesctl/install | bashConfirm it landed:
tapesctl versiontapesctl 0.1.0All in all, just another tape in the stereoBoth lines are expected. The second is the release smoke test’s canary.
The version number is not a release identifier — every release to date
reports 0.1.0, because the crate version has never been bumped and releases
are tagged independently. Do not use tapesctl --version to work out which
build you have, and do not treat 0.1.0 in a bug report as meaningful. Read
the version trap before relying on it for anything.
The binary lands in $HOME/.local/bin, which you own — a normal install never
asks for sudo. Because that directory is not on every default PATH, the
installer also writes a guarded PATH export into your shell’s rc file, inside
a sentinel-marked block it rewrites in place rather than duplicating on
re-install. Set TAPESCTL_INSTALL_DIR to put it somewhere else.
Supported platforms are Linux and macOS, on x86-64 and arm64.
Upgrading
Section titled “Upgrading”tapesctl upgradeReplaces this binary with the newest published release, or says already up to date and exits successfully when there is nothing to do. The download’s
SHA-256 is checked against the published sidecar and the staged file is
sanity-probed before anything replaces the installed binary, so a failed
upgrade leaves the one you had still working. --version v0.6.0 pins an exact
release; --nightly takes the rolling nightly build.
Uninstalling
Section titled “Uninstalling”tapesctl uninstallRemoves the binary, ~/.tapes, the cassette cache, and the installer’s PATH
block — leaving the rest of your rc file untouched. Harness-side capture
plugins are removed separately with tapesctl plugin uninstall <harness>.
Two minutes: capture, then read
Section titled “Two minutes: capture, then read”Capture a Claude session. The harness behaves as it would unproxied — its traffic is forwarded to its own provider API — and the capture proxy dies with it. The URL is the ingest port:
tapesctl start claude --ingest-url http://localhost:8082Before the harness launches, and again when it exits, tapesctl prints to
stdout; while the harness holds the terminal it prints nothing at all:
tapesctl: capturing; logs at ~/.tapes/logs/start-20260813-180411-54233.logtapesctl: captured session f47ac10b-58cc-4372-a567-0e02b2c3d479 (pass --web-url for a console link)tapesctl: logs at ~/.tapes/logs/start-20260813-180411-54233.logNow read it back, against the read port:
tapesctl sessions list --limit 20 --api-url http://localhost:8081{ "items": [ { "auth_subject": "local:jasonwc", "harness_id": "claude", "harness_session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "id": "01JDQ8F3K2M4N6P8R0T2V4X6Z8", "last_seen_at": "2026-08-13T18:19:52Z", "rollup": { "status": "ended", "turn_count": 12 }, "started_at": "2026-08-13T18:04:11Z" } ], "next_cursor": ""}Note the two ids. The one start printed is harness_session_id; the one every
read command takes is id. They are different values in different namespaces,
and feeding the printed one to sessions get returns a 404. That is a live
defect, not a misunderstanding — pass the printed id to
sessions list --harness-id claude --harness-session-id <id> to resolve it to
the tapes id; Session ids explains the split and
why the filter comes as a pair.
Read the session with the id from the listing:
tapesctl sessions get 01JDQ8F3K2M4N6P8R0T2V4X6Z8 --api-url http://localhost:8081sessions list renders its listing as a table by default; --json restores
the raw document so it still composes with jq. The other read commands print
the server’s JSON pretty-printed and nothing else.
Where to go next
Section titled “Where to go next”- Capture — how capture actually works: the two lanes, which harness uses which mechanism, what attribution means, and the session-id reality.
- Commands — the full reference: every command, its flags, its environment equivalents, its exit codes and error families.
- Configuration — the precedence chain,
config.toml, and every filetapesctlwrites. - Cassettes — the command surface your deployment serves, discovered at runtime.
- Troubleshooting — the failures that actually happen, starting with a capture that landed nowhere.
What tapesctl does not do
Section titled “What tapesctl does not do”- No telemetry.
tapesctlreports nothing about you anywhere. There is no variable to set because there is nothing to turn off. - No authentication on the read API. Read commands send no credentials.
- No server.
tapesctldoes not run, embed, or start a tapes server, andlocal upis the server’s verb, not this client’s.