Skip to content

tapesctl

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.

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.

Terminal window
curl -sSfL https://download.tapes.dev/tapesctl/install | bash

Confirm it landed:

Terminal window
tapesctl version
tapesctl 0.1.0
All in all, just another tape in the stereo

Both 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.

Terminal window
tapesctl upgrade

Replaces 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.

Terminal window
tapesctl uninstall

Removes 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>.

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:

Terminal window
tapesctl start claude --ingest-url http://localhost:8082

Before 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.log
tapesctl: captured session f47ac10b-58cc-4372-a567-0e02b2c3d479 (pass --web-url for a console link)
tapesctl: logs at ~/.tapes/logs/start-20260813-180411-54233.log

Now read it back, against the read port:

Terminal window
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:

Terminal window
tapesctl sessions get 01JDQ8F3K2M4N6P8R0T2V4X6Z8 --api-url http://localhost:8081

sessions 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.

  • 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 file tapesctl writes.
  • Cassettes — the command surface your deployment serves, discovered at runtime.
  • Troubleshooting — the failures that actually happen, starting with a capture that landed nowhere.
  • No telemetry. tapesctl reports 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. tapesctl does not run, embed, or start a tapes server, and local up is the server’s verb, not this client’s.