litmus-ai command and an
org token. No console, and no help from us. It takes four steps, and the
same command runs them again if one is interrupted.
Words this page uses
- Org token: the secret that proves a call is from your org. A
pushtoken can store evidence;readcannot. Get a token says who mints one. - Evidence: anything you store in your org for Litmus to read: session transcripts, traces, documents. A push stores evidence.
- Session: one conversation between a user and your agent, with the tool calls it made. A transcript file holds one or many.
- Request: one HTTP call the command makes. A folder is sent in requests of up to 8 MB each, so a large export is several requests.
- Job: work the workspace does in the background after it has answered
you. A large request is stored at once and read by a job; you follow the
job until it is done. Its id starts with
job_. - Already in: a file the org already holds exactly as sent. It is counted and never stored twice, so running the same push again is safe.
- Data access: what the push shares with Litmus, declared on every push. The four levels are on the CLI page.
1. Install
GET /litmus.py, so you can check one
against the other.
2. Say which workspace and which org
Either pin them once:LITMUS_TOKEN (your
org token) and LITMUS_ORG (your org’s tag). LITMUS_URL is the workspace,
and defaults to the hosted one. The variables win over the pinned values when
both are set. Nothing on this page prints a token; the command masks it in
everything it says.
3. Push the folder
./sessionsis a folder (or a.zip,.tar,.tar.gz). Every file in it is read: session transcripts and trace files as sessions,.md,.txt,.pdf,.pptxand.docxas documents. A file of a kind Litmus does not read is listed as refused, by name; hidden files and a Mac folder’s metadata are skipped.--surfacenames the system your agent drives. With it, the push starts the pipeline on that system once, after the last request.--data-accesssays what the push shares. Leave it off on a terminal and the command asks, with the four levels numbered; in CI or a script a push without it is refused before anything is read or sent.--request-bytes <n>changes how much one request holds (default 8 MB). You will not normally need it; the command comes down on its own when a request does not get through.
What the lines mean
The command says what it is doing before each request, not after:request k of n · files · size → sendingis one request leaving your machine. A small push is one request and is answered in it.- A line starting
job_means the workspace stored that request whole and is reading it in the background.plannedis how many of the request’s files it has read so far,storedhow many it has kept (new, or replacing an earlier version of the same session), and the last number is how long you have waited. The line is printed each time the numbers move, every two seconds at most, untildone. - If a request does not get through (the gateway answers 502 or 504, or the connection drops), the command says so and sends the same files again in two requests of half the size. It never sends a file the job had already stored. If the smaller request fails too, the push stops and prints the request it stopped at and the line that resumes it:
The summary
After the last request, one line per outcome and reason — its count and up to three example paths — and then the totals, in the workspace’s own words:- accepted / replaced / already in / refused / skipped are the workspace’s
outcomes for each file. Replaced means the org held an earlier version of
that session and now holds this one; the earlier one is kept, not counted.
Files that met the same outcome for the same reason share one line, so a
reason thousands of files share is read once, not thousands of times; pass
--verboseto print every file’s outcome on its own line (<path>: refused — <reason>) when you need to find one file. - formats counts the sessions by the format each file was read as. Only the formats that arrived are named.
- tool map appears when the push held session transcripts and a
toolmap.json: how many of the recorded tool calls map onto the system you named, and the tool names left unmapped (no counterpart on it) or undecided (no rule names them). Those two lists are what to settle next; they hold tool names only, never a line of a transcript. - pipeline is the job the push started on your system, when it started one.
4. Follow a job from Claude
Everyjob_ id above is a job you can read from anywhere a tool reaches the
workspace. From Claude, attached as Attach Claude
shows, ask:
Where is job job_3f9c2a1b7d04?
Claude calls job_status with {"job_id": "job_3f9c2a1b7d04"} and reads
the same record the command was printing from. While the job runs, tally
holds files_done of files, what is accepted, replaced, already in,
refused and skipped so far, and each landed file’s name and outcome; step
says which of its three steps (open, ingest, finish) it is on. Once it is
done, result holds the whole answer the summary above was printed from.
Over HTTP the same record is GET /v0/jobs/{job_id} on the
Runs page.
If something is refused
- A whole folder is refused before anything is sent when one of its files
holds something shaped like a secret. The message names the file and the
count. Re-run with
--allow-secretsif they are not secrets. - One file is refused when it is larger than one request holds, or of a kind Litmus does not read; the summary names it with the reason, and the rest of the push is unaffected.
- A whole request is refused (the answer is
422) when an archive holds a path that leaves it, a link, or more than 2,000 entries. Nothing of it is stored; fix the archive and push again.