A dispatch room for your coding agents. One brief, answered by five vendor CLIs side by side — Claude Code, Codex, Antigravity, Cursor and Grok — each column claiming only what was measured about that vendor. Under the room, an honest gauge: a statusline and a cross-vendor HUD where every number is traceable to measured tool output, nothing narrated, nothing guessed.
A telltale is the ribbon on a sail that shows true airflow. Sailors watch whether it streams smoothly or flutters to judge the sail's trim. It doesn't interpret; it just tells you what's actually happening.
Status: v1 shipped as v0.2.0 on 2026-08-14; development continues daily. All three
surfaces are shipped — the room, the statusline and the HUD. The same binary carries
five more modes that render no surface of their own: the relays (telltale hook,
telltale otel), the preflight (telltale doctor), and the observation modes
(telltale events, telltale snapshot).
v1 is a snapshot, not a freeze. It cuts when three checkable gates hold — nothing on the surface is half-finished or unused by its own author, the README is verified true against the code, and no breaking change to the grammar or keymap is planned — not when development goes quiet, because it doesn't: this room is driven daily. Cutting v1 as gauges only — statusline and HUD, with declared vendor version pins — was the standing alternative and it is rejected: a release names the product, and the product is the room. The gates and the argument are in docs/design.md §1.
Every adapter here was verified against something real rather than against vendor docs — a
live on-disk corpus, a live payload capture, or the vendor's own persistence code read at a
pinned version — and docs/design.md §3 itemizes per vendor which of those
it was, what the verification changed about this project's guesses, and what each one still
owes. Cursor (Composer) is the first IDE-resident agent here, and the first whose store
also holds live credentials, which is why that adapter's most load-bearing property is the
list of things it does not read (docs/design.md §3.9). telltale council seats the 5-vendor fleet, and every sandbox and streaming claim in it was
measured against a live run of that CLI rather than read off its --help
(docs/design.md §9).
v0.2.0 is released (2026-08-14, the first release; the snapshot gates held). The
repo's own CI gate ran before any artifact was built, and the release attaches four
archives with a checksums.txt. Read the per-download verification labels on the
release itself before you pick one — they say what was measured, and they differ by
platform.
One honest note on the scoop line below, in this project's usual terms: the install was
exercised once, on Windows 11 on 2026-08-14 — scoop verified the archive's SHA-256
itself, the installed binary reported telltale 0.2.0, and telltale doctor ran clean
through it. One exercised install is one data point, not a support matrix. Building from
source is the path this project runs every day.
From source — works now:
go build -o telltale.exe ./cmd/telltale
./telltale.exe council
However you installed: run telltale with no arguments for a short first frame — the
three modes that need no configuration, and which one to start with. telltale doctor
is that one. It reports which vendor CLIs are on this machine, where each was found and
what version it reports, and says out loud what it never checked: it runs
<binary> --version and nothing else — no turn, no login, no network, and it writes
nothing. On a machine with no vendor store yet, the HUD is not blank either: it names
every path it looked in, and points at doctor for the one thing it cannot see —
whether the vendor binaries are installed at all.
Windows, scoop — the bucket is live; exercised once on 2026-08-14 (above):
scoop bucket add telltale https://github.com/sanlee-ys/telltale
scoop install telltale
telltale council
Windows, winget — pending submission to microsoft/winget-pkgs; the manifest
draft and the flow are in packaging/. winget install sanlee-ys.telltale
does not work yet — use scoop or a source build until the submission lands.
Direct download — each release attaches archives for windows_amd64,
darwin_amd64, darwin_arm64 and linux_amd64 with a checksums.txt. Unpack one,
put telltale on your PATH, and:
telltale council
macOS, the whole arrival, measured on 2026-08-17. This sequence ran on an
Intel MBP on macOS 26.5.2, against the published v0.2.0 archive. Substitute
the tag and the architecture you want:
curl -fLO https://github.com/sanlee-ys/telltale/releases/download/v0.2.0/telltale_0.2.0_darwin_amd64.tar.gz
curl -fLO https://github.com/sanlee-ys/telltale/releases/download/v0.2.0/checksums.txt
shasum -a 256 -c checksums.txt --ignore-missing
tar -xzf telltale_0.2.0_darwin_amd64.tar.gz
./telltale doctor
shasum printed telltale_0.2.0_darwin_amd64.tar.gz: OK on that run. A
mismatch prints FAILED instead, and you stop there.
A browser download needs one more command, and without it macOS kills the
binary. curl does not mark a file with com.apple.quarantine, but a browser
does, and tar copies that mark onto the binary it extracts. Gatekeeper then
refuses the binary, because no archive here is signed or notarized. The refusal
was measured on 2026-08-17 on the same machine, with the quarantine mark applied
by hand to reproduce a browser download. macOS killed the process and showed a
dialog:
"telltale" Not Opened
Apple could not verify "telltale" is free of malware that may harm your Mac or compromise your privacy.
[Move to Trash] [Done]
The terminal reported Killed: 9 and exit status 137. The binary printed
nothing and stayed on disk. Right-click-open does not apply here, because
telltale is a command-line binary and not an app bundle. Clear the mark, then
run it:
xattr -d com.apple.quarantine telltale
./telltale doctor
That was the measured remedy: doctor then ran to completion at exit 0. Run
xattr -d only after shasum says OK, because clearing the mark is the step
that lets an unverified download run. The command reports No such xattr and
exits 1 on a curl download, which has no mark to clear.
The binaries do not all claim the same thing, and each release says so per
download. Windows is the continuously verified target — every commit runs the
suite, the build and binary-level smokes on windows-latest. darwin_amd64 is
smoke-verified on Intel macOS, point-in-time and SHA-bearing. darwin_arm64 and
linux_amd64 are built, not verified: cross-compiled and never run by this
project. That is the same flagged-limitation rule the gauges apply to a segment,
applied to a platform (docs/design.md §8).
No binary here is signed, on any platform. The release workflow runs no
signing step, so every archive is unsigned and the macOS archives are not
notarized. Windows raises no signature to check, and scoop and winget install
that same unsigned binary. On macOS, Gatekeeper refuses an unsigned, un-notarized
binary that a browser downloaded and marked with com.apple.quarantine. Check
the SHA-256 in checksums.txt before you run a download — it proves the archive
is the one the release built, which is a weaker claim than a signature and is the
claim this project can make today. SECURITY.md states the per-platform
detail and says why signing is an owner decision rather than a to-do.
telltale version prints the tag a binary was built from; a source build says dev.
telltale.exe council opens the room, which is the mode this project is for and has its
own section below. The two gauges wire in underneath it.
Then wire the statusline into Claude Code (~/.claude/settings.json):
{
"statusLine": {
"type": "command",
"command": "C:\\path\\to\\telltale.exe statusline"
}
}…and/or into Antigravity CLI (~/.gemini/antigravity-cli/settings.json — same block,
same binary; telltale detects the vendor from the payload's documented product
field):
{
"statusLine": {
"type": "command",
"command": "C:\\path\\to\\telltale.exe statusline"
}
}…and/or into Cursor CLI (~/.cursor/cli-config.json, a top-level key). This one needs
--vendor cursor: unlike the other two, Cursor's payload carries no vendor name to
detect, so the flag is the only way to route it.
{
"statusLine": {
"type": "command",
"command": "C:\\path\\to\\telltale.exe statusline --vendor cursor"
}
}Cursor's statusline is interactive-only — it does not fire in -p print mode or over
ACP (measured; docs/design.md §7.16). To see it, start an interactive session in a
folder you have opened with cursor-agent before:
cursor-agent
…and run the HUD:
telltale.exe hud
That picture is emitted from the HUD's own render by the test suite, not drawn by hand,
and it is doing the thing this project is about: the Claude, Gemini and Antigravity rows' context cells are em
dashes because none of those vendors writes a context-window size to disk, the Codex
row's ~ marks a percentage telltale computed rather than read, the Gemini row's ⑂~2
chip is a sub-agent count telltale derived (and marks as derived) from the vendor's
nested transcript tree, and the COST column is missing entirely because no vendor puts
a session total in dollars on disk — Grok writes a per-turn figure and still gets no COST
cell for it. None of those is rendered as a zero. Read the CU and GR rows against the
CX row: all three show a context bar, and only the Codex one is marked an estimate,
because Cursor and Grok write their own percentages down and telltale reads them. The AG
row is labelled by its conversation id for a different reason: Antigravity writes no
session title anywhere, and the only free text on its disk is your prompts, which
telltale will not read.
In the HUD, ↑/↓ move the selection and enter opens a detail pane for it — quota
windows, the vendor extras, and the session's own diagnostics and degraded-field marks,
plus a line naming the fields that vendor cannot source at all. That last line is the
answer to "why is this cell empty?", and it is the difference between "we have no value
right now" and "this vendor never had one". / narrows the rows by name or path.
telltale hud flags: --vendor all|claude|codex|gemini|agy|cursor|grok, --hide gemini,cursor (a standing hide list; TELLTALE_HUD_HIDE is its default, the footer
states the hide), --ascii (also TELLTALE_ASCII=1), --no-title. NO_COLOR is
honoured through the standard mechanism.
- A dispatch room —
telltale council, one brief typed once and answered by Claude Code, Codex, Cursor, Antigravity and Grok side by side. The one mode that spawns vendor CLIs instead of reading their files; it gets its own section below. - In-prompt statusline for Claude Code — model, context %, session cost, and quota
pacing (
rate_limitswindows), rendered from the JSON Claude Code hands your statusline command on stdin. No network calls, no credential reads. - A watch-mode HUD (TUI) for parallel sessions — the cross-vendor surface, and a first-class UI investment (Go + Bubble Tea/Lipgloss; Windows Terminal is the reference environment). Ships with adapters for Claude Code, Codex CLI, Gemini CLI, Antigravity CLI, Cursor (Composer), Grok CLI, and Pi, each reading that vendor's own native on-disk data — for Antigravity and Cursor that means a read-only SQLite reader written into this repo rather than a 9 MB dependency added to it.
- A machine-readable read mode —
telltale snapshotprints the fleet's current state as one JSON document, for a reader that is a program rather than a person. It gets its own section below. - A documented adapter interface — one module per vendor — so you can wire in anything else that leaves session data on disk. The worked example in docs/design.md §4a.7 is the method the Gemini adapter was actually built with, kept alongside what live verification changed about its guesses.
- A drop-file relay for everything else — a tool telltale ships no adapter for can write
one small JSON file under
~/.telltale/dropfile/and get a fleet row, with no plugin and no code of yours running inside telltale. Those rows are marked self-reported everywhere they appear, because telltale measured the file and not the session. docs/dropfile.md is the format spec.
One binary, three surfaces: telltale statusline, telltale hud and telltale council —
and they are not three co-equal products. The room is the product; the gauges are the
infrastructure under it. The statusline and the HUD are where this project surveyed each
vendor's seam and wrote down what it found, and the honest-gauge rule they were built
under is the rule a council column inherits when it states a sandbox posture. They are
finished, they are load-bearing, and they are not the thing this is for. The statusline
code path never initializes the TUI framework (the single binary links it, but no Bubble
Tea code runs on a statusline invocation).
Three surfaces are not the whole binary, and this file does not claim they are. The
binary has eight modes, and telltale run with no argument prints all of them. The
five that draw no surface stand behind these three: the
relays (telltale hook <vendor>, telltale otel <vendor>) read one turn's token
counts and print nothing; the preflight (telltale doctor) reports which vendor
binaries this machine has; and the observation modes (telltale events, telltale snapshot) answer a program rather than a person, except for telltale events view,
which reads the sink's own store back for a person. telltale snapshot, telltale events and telltale doctor get their own sections below; the two relays are described
under the read/write boundary, because a relay is a write.
Honest claim, stated precisely: dispatch across the 5-vendor fleet (Claude Code, Codex,
Cursor, Antigravity, Grok); cross-vendor monitoring; vendor-native statusline where the seam
exists — and it exists twice: Claude Code and Antigravity CLI. (Codex CLI has
no statusline hook today. Antigravity was statusline-only until a re-survey found the
transcript its own docs advertise, which is what made its HUD adapter buildable — the
first verdict and the reversal are both in docs/design.md §2.1/§3.8.
Cursor reaches telltale both ways: a built-in HUD adapter because its seam is on disk,
and a council seat driven through cursor-agent's own bundled node.exe — the cursor
binary on PATH is only the editor launcher and council never drives it. Grok is a council
seat and a HUD adapter on the same binary — the seat has no fleet guards wired yet, which
is an open obligation on the fleet rather than a reason the column is missing.)
The gauges never write to anything that isn't theirs. telltale statusline and
telltale hud read vendor files, make no network calls, read no credentials, and no
keybinding can mutate vendor state or send anything to a running agent. What the gauges
and the room write is three stores of their own under ~/.telltale/, all keys and
numbers, never content: council's room file (council/room.json — the vendor session ids
reattaching needs and the room's workspace, no transcript, output or brief content),
the statusline's quota relay (quota/<vendor>.json — the rate-limit windows it
just rendered, so the HUD can show account quota per vendor instead of only for
vendors whose stores carry it; docs/design.md §7.15), and the
token relay (usage/<vendor>.json — a running total of per-turn token counts,
with two writers: telltale hook cursor reads Cursor's afterAgentResponse
payload on stdin, and telltale otel grok is a loopback listener grok's own
OpenTelemetry exporter pushes to; docs/design.md §7.16, §7.16a).
That last one is spend, not quota: there is no denominator anywhere in it, so it
never renders as a percentage or a bar, and Cursor's and grok's account quota
stay visibly absent.
A fourth store carries content, and it is named as an exception rather than
counted with the three. The event sink (telltale events, below) stores each hook payload
VERBATIM under ~/.telltale/events/ — content, not keys and numbers. What contains
it is scope, not redaction: it is its own foreground mode that you start, its server
binds loopback only, a web page is not a sender, and no gauge reads or renders those
files. Its reader (telltale events view) is its own foreground mode for that last
reason: a gauge that read this store would have spent the containment. The
keys-and-numbers rule above still binds every store the gauges themselves write
(docs/design.md §7.21).
telltale council remains the one mode that acts on the world, and it is labelled as one
everywhere it can be: it spawns vendor CLIs, it is entered only by typing the
subcommand, it is not reachable from the HUD, and it shares no keybinding with it.
"Reads no credentials" stopped being free with the Cursor adapter — that vendor
keeps its access tokens, refresh tokens and OAuth secrets in the same SQLite file as
its session state — so it is enforced there as a read allowlist with a test that plants
credential-shaped strings in the fixtures and asserts none of them reaches anything the
HUD can display (docs/design.md §3.9). The Cursor hook is the same
discipline against a different hazard: its payload carries the model's reply text and
the user's email address beside the four numbers, so the parser's struct is the
allowlist and markers planted in a real payload shape must reach neither the parse nor
the file.
telltale council is one brief, typed once and answered by five vendors side by side —
Claude Code, Codex, Antigravity, Cursor and Grok, each in its own
column, in your terminal. It exists because the alternative is five terminals and a
clipboard.
telltale.exe council
Every column carries its own sandbox posture and its own streaming granularity, because the
five vendors differ on both and one blanket claim would be false for at least one of them —
and each of those claims was measured against a live run of that CLI rather than read off
its --help. A plain telltale council can write, and says so in the header for the whole
session; --read opens a room that only talks. But no badge is what keeps this room out of
your files — the directory it was pointed at is, and --cd is how you move it.
An unaddressed brief goes to Claude alone; @codex, @agy, @cursor, @grok and @all
route a turn, -@claude addresses everyone but that seat, and the composer prices the route before
you press enter. Each seat keeps its own conversation and rides that vendor's own native
resume rather than a re-sent transcript, so no session ever holds another's history.
docs/council.md is the room's own guide — the frame, the badge
vocabulary, the routing grammar, the reading keys and the turn view, taking an answer out
of the room with y, and every flag. docs/design.md §9 is the record
behind it: what was measured per vendor, what each seam cost, and what is still unverified.
telltale.exe snapshot
One scan, one JSON document on stdout, exit 0. It reads the same vendor stores the HUD
reads, and it prints numbers instead of a frame — so an agent gets its answer from one
command and one parse, and never from scraping a TUI or reading ~/.telltale/ behind
telltale's back.
Three flags: --vendor <id> reports one vendor, --compact prints the document on one
line, and --timeout <dur> bounds the scan (default 10s). An unknown flag, an unknown
vendor or a stray argument is refused with the correction and prints no document — a
script that mistypes a flag must not receive a well-formed answer to a different
question.
The schema is {schema_version, generated_at, scan_error, fleet, vendors[]}, and it
carries this project's honesty rules rather than restating them in prose:
| the document says | it means |
|---|---|
"cost_usd_total": 0 |
measured zero |
"cost_usd_total": null |
no reading right now |
"unsupported": ["cost"] |
this vendor exposes no such thing, ever |
"estimated": ["context_pct"] |
the adapter computed that value; it was not reported |
"quota": [] |
no relayed account reading — never an implied 0% |
No optional key is ever omitted, so an absent value and a changed schema can never look
alike. fleet is the pre-computed rollup — the session count, the liveness census, the
vendor census by status, the highest context percentage anywhere and the total cost — so
the common question costs no arithmetic on the reader's side.
It renders numbers and keys, never content: no session names, workspace paths,
transcripts, briefs or reply text, and no per-session rows at all. It writes nothing, calls
no network and reads no credential. docs/design.md §7.22 is the full
schema record and the reasoning; internal/snapshot/testdata/golden/zero-vs-absent.json
is the build-failing test that the two kinds of nothing stay apart.
tools/fleet-prompt.ps1 is one PowerShell function that runs
the command once, parses the line, and returns a fleet segment for a prompt:
. .\tools\fleet-prompt.ps1
Get-TelltaleFleetLine
Driven on Windows PowerShell 5.1 against this machine's real stores, that prints:
tt 6 watching | 1554 sessions, 3 live | ctx ~75.8% codex | quota 12.2% agy/gemini-weekly
It carries the rules above into a caller rather than restating them. A null prints
nothing: a fleet with no context reading anywhere has no ctx segment at all, while a
measured zero prints as 0%. The ~ is there because codex's block lists context_pct
under estimated. An unknown schema_version prints an empty line rather than a guess.
docs/snapshot.schema.json is the contract it reads against
— the same file CI validates the built binary's output with. Its -FromFile parameter
reads a document instead of running the binary, which is how the refused store, the
drifted store and the scan error were driven: those are shapes a healthy machine does not
produce, and internal/snapshot/testdata/golden/ carries all four.
telltale.exe events
telltale.exe events view
One hook event per POST on loopback, appended to a durable log under
~/.telltale/events/ and rebroadcast to every client connected to /stream. Any
process that can pipe JSON is a source: wire tools/emit-event.py as a hook command,
where --source-app <name> is the one per-repo edit. Two flags: --addr <host:port>
(default 127.0.0.1:4519; any other host is refused at startup) and --retain <days>
(default 30).
telltale events view is the sink's reader, and it is its own foreground mode rather
than a line on a gauge. It lists the newest events, filters by --source, --session,
--type or --day, and follows the store with --follow. It reads the day files
directly and opens no socket, so it answers with no sink running and after the sink has
exited; --interval is therefore the honest latency bound in follow mode, not a push.
Each row shows the keys. The payload is stored VERBATIM and prints only under
--payload.
This is the one store that holds content rather than keys and numbers, and the read/write boundary above names it as the fourth exception. What contains it is scope: the operator starts the mode, the server binds loopback, a web page is not a sender, and no gauge reads these files — which is exactly why the reader is a separate mode. docs/design.md §7.21 carries the record and the 2026-08-17 amendment that added the viewer.
telltale.exe doctor
Which vendor binaries are on this machine, where each one was found, and what version
each one reports — plus, said out loud rather than left blank, what was never checked.
Auth and network always read not checked: nothing here probes a login or calls the
network, and a preflight that implied otherwise would be trusted on the one day it was
wrong. It runs each vendor bounded to <binary> --version, writes nothing, and gives
each seat its own --timeout (default 15s) so a wedged vendor costs its own deadline
and not the report. The report is words and no colour, so it reads the same in a
terminal, in a pipe and in a pasted issue.
A segment may only display a value read from tool or vendor output. Anything inferred is either omitted or visibly marked as an estimate. Every segment's data source is named in docs/design.md, and the eval harness asserts each segment's render against fixture inputs — including empty and degraded states. A gauge that can't tell "no data" from "zero" fails the build.
That last sentence is a literal test. internal/hud renders one session at 0% and one
session whose vendor exposes no context source, and asserts the two rows differ: 0% draws
a full track, absent draws nothing at all.
Fixtures are synthesized — fake session ids, fake text, fake paths, realistic in shape only. No real session content is in this repository.
- docs/council.md — the dispatch room in use: the badge vocabulary, the routing grammar, the reading keys, and every flag
- docs/design.md — segments, data sources, the normalized schema, the adapter contract, the HUD UI specification, and the council record (§9)
- STATE.md — where the project is right now: what is in flight, what is unsettled, and what is known-missing and unowned
- PARITY.md — cross-platform and cross-machine differences, and which of them are measured rather than assumed
MIT