# TrialONE > TrialONE finds out what went wrong on a robot from a recording of it running, routes the fault to whoever fixes it, and proves the repair on the next recording. Access is by request. ## Get started - [Introduction](https://trialone.dev/docs): Find out what went wrong on a robot from a recording of it running, and prove that the repair held. - [Quickstart](https://trialone.dev/docs/quickstart): From an approved account to your first issue. - [How it works](https://trialone.dev/docs/how-it-works): Deterministic math decides whether something is wrong. An agent layer explains what and why. The next recording proves the repair. ## Ways in - [Recordings](https://trialone.dev/docs/recordings): What TrialONE reads, and what it makes of each kind. - [Live on the robot](https://trialone.dev/docs/live): Watch a running robot and stay silent until something changes. - [Coding agents](https://trialone.dev/docs/coding-agents): Let Claude Code, Codex or Cursor pick up a fault TrialONE found, and report the repair back. - [The CLI](https://trialone.dev/docs/cli): The commands you use, what each is for, and the flags it takes. ## Working with issues - [Issues and recipes](https://trialone.dev/docs/issues): One fault, across every run it appeared in, with what a fix needs. - [Proving a repair](https://trialone.dev/docs/verify): A repair is claimed by a person and proven by the robot. ## Account - [Access and team](https://trialone.dev/docs/access): Who can use TrialONE, and how a team works in one workspace. - [Data](https://trialone.dev/docs/data): You decide per machine how much of a run reaches the website. ## Resources - [For agents](https://trialone.dev/docs/for-agents): This documentation is written to be read by a model as well as a person. --- # TrialONE documentation Find out what went wrong on a robot from a recording of it running, and prove that the repair held. TrialONE reads what a robot recorded (a ROS 2 bag, an MCAP file, a CSV or HDF5 export, a PX4 or ArduPilot log, a firmware crash report) and answers four questions: what happened, why, what to change, and how to check that the change worked. Every answer becomes an issue on your account, with the numbers it rests on. > **In short.** Request access, install the command line tool on the robot or a laptop, sign in once with `trialone login`, and run `trialone diagnose` on a recording. The [Quickstart](https://trialone.dev/docs/quickstart) takes you from there to your first issue. ## The mental model Five terms carry the whole product. | Term | What it is | | --- | --- | | Machine | One robot. Its runs are filed under its name: `--machine`, the variable `TRIALONE_MACHINE`, or the computer's hostname. | | Run | One diagnosis of one recording, or one session of the live watcher. It keeps the state of the machine at the time: the commit, the parameter files, the devices. | | Finding | One thing that left its normal range, with the second it happened, the channels involved and the measured numbers. | | Issue | The same finding across every run it appeared in. It is open, in repair, resolved or ignored. | | Recipe | What a fix needs, in nine fixed fields, from the symptom to an acceptance criterion that a partial fix fails. | ## What do you want to do? - [Quickstart](https://trialone.dev/docs/quickstart): From an approved account to your first issue. - [How it works](https://trialone.dev/docs/how-it-works): What is measured, what is explained, and where the limits are. - [Watch a robot live](https://trialone.dev/docs/live): Attach to the running ROS 2 graph and stay silent until something changes. - [Hand a fault to a coding agent](https://trialone.dev/docs/coding-agents): Claude Code, Codex or Cursor reads the issue and reports the repair back. --- # Quickstart From an approved account to your first issue. You need an approved TrialONE account, Python 3.10 or newer, and one recording of a robot. Linux, Windows and macOS all work. On the robot itself that includes NVIDIA Jetson and Raspberry Pi boards, as long as their system has Python 3.10. ## 1. Request access TrialONE is available by request, and a founder approves every team by hand. [Request access](https://trialone.dev/request-access) with the email you will sign in with. You can sign in with Google or GitHub before the approval arrives; the app opens as soon as it does. ## 2. Install the command line tool ```bash pip install trialone ``` For a microcontroller on a serial port (Arduino, ESP32), install the serial extra: `pip install "trialone[serial]"`. ## 3. Sign in on this machine ```bash trialone login ``` It shows a one-time code and opens [trialone.dev/cli-login](https://trialone.dev/cli-login) when you press Enter. Enter the code there while you are signed in to the app and approve it. On a robot over SSH, open that page on your laptop instead. The terminal receives its own key, checked before it is saved, and `trialone whoami` shows which account it is connected to. Each machine gets its own key: revoking one under [Settings, CLI keys](https://trialone.dev/app/settings/keys) leaves the others working. Scripts can pass a key from there directly: `trialone login `. ## 4. Diagnose a recording ```bash trialone diagnose ./recording.mcap ``` The report prints in the terminal and is written to `output/`. The run is also posted to your account, and the terminal prints its link; `--no-push` keeps one run local. Exit code 0 means the recording was read, with or without findings. Exit code 2 means it could not be read, so nothing in the output is a statement about the machine. Two flags change the answer the most: - `--healthy `: another recording of the same robot that you know ran well. Without one, TrialONE can only compare a recording with itself, and a fault that lasts the whole recording then looks normal. - `--project `: your robot's source tree. Findings then point to a file and a line instead of a topic name, and the parameter, launch and URDF files are found by their content. ```bash trialone diagnose ./today.mcap --healthy ./last-good.mcap --project ~/ros2_ws/src ``` ## 5. Keep it running on the robot On the robot, the watcher attaches to the running ROS 2 graph and reports what changes. On Linux it installs as a user service that survives a closed terminal and a reboot: ```bash trialone install-service --install ``` ## Next steps - [How it works](https://trialone.dev/docs/how-it-works): what is measured, what is explained, and the limits. - [Live on the robot](https://trialone.dev/docs/live): topics, growing files, CAN and serial ports. - [Proving a repair](https://trialone.dev/docs/verify): the next recording decides whether it held. - [Coding agents](https://trialone.dev/docs/coding-agents): let an agent pick up the fault and report back. --- # How it works Deterministic math decides whether something is wrong. An agent layer explains what and why. The next recording proves the repair. ## Detection against the machine's own normal TrialONE does not look faults up in a library. It measures a recording against a reference: the rest of the same recording, earlier recordings of the same machine, or a healthy recording you name with `--healthy`. The same math runs on a file and on a live stream, and it finds faults nobody has named before. The strongest detector compares repeated operations with each other. That is why TrialONE is built for machines that repeat their work: mobile robots, manipulators, quadrupeds and humanoids. The detection is reproducible: the same recording gives the same findings. ## Explanation: what the signal is, and why it moved Channel names are whatever your team called them, so meaning is not guessed from a name table. An agent layer reads the numbers, the log lines and, with `--project`, your source tree, and proposes a physical story. The story has to commit to predictions that must also hold if it is right, and the engine checks each one against the data. A story whose predictions fail is reported as refuted, with the failures named. The explanation never changes what was detected. With `--no-explain` you get the deterministic half on its own. ## Three zones per finding | Zone | When | What you get | | --- | --- | --- | | FAULT | The finding carries itself: a device went silent, a shared timing broke, a reference with a known false-alarm rate, or a mechanism that survived the check. | A repair, routed to whoever fixes it. | | LOOK | Something fired, but none of the above holds. | An observation task: where to look, which channel, which number. | | clear | Nothing fired. | Nothing. A healthy machine stays quiet. | An explanation can raise a zone, never lower it. Every report says how many findings stayed undecided, out of how many. ## Routing: software or hardware Every finding goes to the person who can fix it. A software fault goes to a coding agent, with files and lines. A physical fault (a connector, a part, the mechanics) goes to a technician at the machine. In a robot learning dataset, a fault that the policy's own commands carry goes to the person who trains the policy. ## Proof: the next recording decides A person or a coding agent claims a repair; the robot proves it. `trialone verify` measures a new recording against the earlier diagnosis and rules per finding: gone, still there, or new. A lower peak is not a pass. See [Proving a repair](https://trialone.dev/docs/verify). ## What it does not do yet - A fault on one single channel, with nothing else moving at the same time, produces no finding on the live path. Faults across several channels are found within a second. - Explanations on the live path are leads, not verified answers. Predictions are checked against recordings, not against a running stream. - A fault present in every operation of a recording is invisible without a healthy reference. Pass `--healthy`. - Camera frames and point clouds are not analysed. Numeric channels, log lines and crash reports are. - Drones are read, but every flight is different, so there is no repeated operation to compare against. They are not a focus. --- # Recordings and formats What TrialONE reads, and what it makes of each kind. Point `trialone diagnose` at a file or a folder; the format is recognised from the content, not from the file name. | Kind | Files | Read as | | --- | --- | --- | | ROS 2 | rosbag2 folders, `.mcap`, `.db3` | Every numeric field of every topic becomes a channel. Status topics keep their words. | | ROS 1 | `.bag` | The same. | | Tables | `.csv`, HDF5 | One column per channel. Semicolons and decimal commas are read as written. | | Robot learning datasets | LeRobot v2 and v3, with `pip install "trialone[lerobot]"` | The numeric features per episode, with each joint's action paired with its observation. | | PX4 | `.ulg` | Topics and messages. | | ArduPilot | `.BIN`, MAVLink `.tlog` | Messages, parameters and decoded device IDs. | | CAN | candump logs, Vector `.asc` | Frames per ID, with error frames decoded. | | Network captures | `.pcap`, `.pcapng` | Transport timing, retransmits and connection events. | | Crash reports | ARM Cortex-M hard faults, ESP32 panics, gdb backtraces, Linux kernel oops, ROS console logs | The failing frame, the fault register bits and the call chain. | | A folder of runs | several recordings side by side | Each one on its own, unless the files are parts of one rosbag2 recording. | ## Tables A table with a column called `time`, `timestamp`, `t`, `time_s` or `secs` needs no flags. Otherwise: - `--time-col`: the timestamp column. - `--group-col`: the column that groups rows into operations, for example a cycle or run number. - `--label-col` with `--healthy-label`: a label column and the value that means normal, which then defines the healthy reference. ## A healthy reference A reference has to be the same kind of recording with the same channels. If it is not, the report says so at the top instead of assuming anything. ```bash trialone diagnose ./today.mcap --healthy ./last-good.mcap ``` For the live watcher, `trialone learn` reads recordings the robot already made as its earlier behaviour. They count as earlier, not as healthy: a fault inside them becomes part of the reference. No upload and no model call. ```bash trialone learn ./logs ``` ## What cannot be read An encrypted or unknown file ends with a plain stop that names the one thing needed to go on, never with an invented diagnosis. --- # Live on the robot Watch a running robot and stay silent until something changes. `trialone watch` with no arguments attaches to the running ROS 2 graph and subscribes to every numeric topic it advertises. Nothing is configured and nothing is exported. It reports a fault while the session is still running, including a channel that stops publishing, judged against that channel's own cadence. ```bash trialone watch trialone watch --topics /joint_states,/odom ``` ## Other sources | Source | Flag | | --- | --- | | A file that is still growing: a CSV with a header row, or lines of `key=value` | `--follow ` | | An existing recording, played as if it were live | `--replay ` | | A microcontroller on a serial port: Arduino Serial Plotter lines, ESP32 crash reports | `--serial `, with `--baud` | | Several devices of one machine on one clock: CAN, host board, ROS graph | `--robot ` | The serial port needs the extra: `pip install "trialone[serial]"`. ## As a service ```bash trialone install-service trialone install-service --install ``` The first command prints the systemd user unit. The second writes it, enables it, starts it, and checks that it is really running. No sudo: the service runs as you, with the key `trialone login` stored. From then on the watcher posts what it finds, checks in every minute, and takes jobs from the website, such as building a reference or verifying a repair. ## Silence and incidents When a watcher stops checking in, the website marks the machine as silent and alerts you. A watcher stopped by hand says so first, so a planned stop is not an alarm. When the robot does something wrong while you stand next to it, create the file `incident` in the TrialONE folder (`~/.trialone`). Every instrument lines up the 30 seconds before that moment: what stopped first, and whether it points to hardware, software, or both. ```bash touch ~/.trialone/incident ``` ## Limits - A fault on one single channel, with nothing else moving at the same time, produces no finding here. - Explanations on the live path are leads. Verify them on a recording. --- # Coding agents Let Claude Code, Codex or Cursor pick up a fault TrialONE found, and report the repair back. TrialONE serves an MCP endpoint on the website. A coding agent connected to it can list your issues, read one with its full recipe, claim the repair, and ask the robot to verify it. You can simply say: > **Say to your agent.** Fix the newest open TrialONE issue and tell TrialONE when you are done. ## Connect Create an agent key in the app under [Settings, Coding agents](https://trialone.dev/app/settings/agents). The page shows the block for each agent with the key filled in. Agent keys are separate from robot keys: they read issues and report repairs, and cannot post runs. ### Claude Code ```bash claude mcp add --transport http trialone https://trialone.dev/api/mcp --scope user --header "Authorization: Bearer " ``` ### Codex ``` [mcp_servers.trialone] url = "https://trialone.dev/api/mcp" http_headers = { Authorization = "Bearer " } ``` ### Cursor ``` { "mcpServers": { "trialone": { "url": "https://trialone.dev/api/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Claude Desktop only starts local servers. The settings page shows the `mcp-remote` bridge for it, and the same form works for any client with that limit. ## Tools | Tool | What it gives the agent | | --- | --- | | `list_issues` | What TrialONE found, newest first. | | `get_issue` | The recipe: symptom, cause, numbers, files and lines, acceptance criterion. | | `claim_repair` | What the agent changed; the issue goes to In repair. | | `request_verification` | The robot checks its newest recording. | | `check_repair` | Fixed and proven, looks fixed, waiting, or came back. | ## What an agent cannot do No tool marks an issue resolved. The agent claims the repair; the robot's next recording decides. A passing verification closes the issue, and the fault coming back reopens it. An issue routed as physical needs a person at the machine: a part, a connector, the mechanics. An agent should not change code to make such a symptom quieter. ## Without MCP `trialone fix` hands a finished diagnosis to a coding agent on the same machine. It shows the exact command, the files the recipe names and the verdict, and asks before anything runs. ```bash trialone fix ``` --- # The CLI The commands you use, what each is for, and the flags it takes. Every command explains itself with `--help`. The flags below are read from the command line tool itself, so this page cannot list one that does not exist. ## Account | Command | What it is for | Flags | | --- | --- | --- | | `trialone login` | Connect this terminal to your account. The key is checked before it is saved. | `--no-browser` `--paste` | | `trialone whoami` | Which account this terminal is connected to, and whether it is approved. | none | | `trialone update` | Install the newest version in one step. | none | What changed in each version, and what reads differently after an upgrade, is in the [changelog](https://trialone.dev/changelog). ## Diagnose and prove | Command | What it is for | Flags | | --- | --- | --- | | `trialone diagnose ` | Find the fault in one recording, say what is wrong and how to repair it, routed to the right person. | `--description` `--explain` `--full` `--group-col` `--healthy` `--healthy-label` `--history` `--json` `--label-col` `--machine` `--max-false-alarm` `--max-faults` `--no-explain` `--no-push` `--no-upload-raw` `--out` `--project` `--push` `--robot-hint` `--state` `--symptom` `--time-col` `--upload-raw` | | `trialone verify ` | Measure a new recording against an earlier diagnosis and rule per finding. | `--group-col` `--healthy` `--json` `--max-false-alarm` `--no-push` `--push` | | `trialone push ` | Send a diagnosis that is already on disk to your account, without analysing again. | `--machine` | | `trialone fix ` | Hand a finished diagnosis to a coding agent on this machine, after asking. | `--agent` `--yes` | | `trialone mark` | Say that something just went wrong, now or about a recording, and get one page back. | `--json` `--robot` | ## On the robot | Command | What it is for | Flags | | --- | --- | --- | | `trialone watch` | Watch a running robot and stay silent until something changes. | `--baud` `--expect-silent-after` `--explain-budget` `--follow` `--healthy` `--history` `--incident-at` `--json` `--max-false-alarm` `--no-push` `--no-upload-raw` `--project` `--push` `--replay` `--robot` `--robot-hint` `--seconds` `--serial` `--speed` `--state` `--time-col` `--topics` `--upload-raw` `--window` | | `trialone learn ` | Read recordings the robot already made as earlier behaviour for the watcher. | `--label` `--max` | | `trialone install-service` | Run the watcher as a service that survives a closed terminal and a reboot. | `--github` `--install` `--project` | | `trialone watch-folder ` | Diagnose every new recording that lands in a folder. | `--every` `--github` `--once` `--project` | | `trialone attach` | Record what this robot is: board, OS, ROS distribution and packages, devices. Run it again after changes. | `--json` `--machine` | ## Exit codes | Command | Code | Means | | --- | --- | --- | | `diagnose` | 0 | The recording was read. The report is the answer, with or without findings. | | `diagnose` | 2 | The recording could not be read. Nothing in the output is about the machine. | | `diagnose`, `push` | 3 | The report is complete on disk but did not reach your account. | | `verify` | 0, 1, 2 | Pass, fail, inconclusive. | | any | 77 | This terminal is not signed in with an approved account. | ## Environment | Variable | What it does | | --- | --- | | `TRIALONE_MACHINE` | The machine name runs are filed under, instead of the hostname. | | `TRIALONE_HOME` | Where TrialONE keeps its local state. Default `~/.trialone`. | | `TRIALONE_CLI_TOKEN` | A CLI key without `trialone login`, for CI and containers. | ## Access Every command that starts the engine first checks that the terminal is signed in and the account is approved. It asks the website at most once a day. Without a network, the last confirmation counts for 30 days, so a robot in a hall without Wi-Fi keeps running. `login`, `whoami`, `update` and `--help` work without it. ## Update or remove `trialone update` installs the newest version. To remove the tool, uninstall it with pip. If the watcher runs as a service on this machine, stop it first with `systemctl --user disable --now trialone-watch.service`. ```bash pip uninstall trialone ``` Uninstalling leaves the sign-in and local state in `~/.trialone` (on Windows `%USERPROFILE%\.trialone`); delete that folder too for a clean start. Revoke the key of a machine you no longer use under Settings, CLI keys. --- # Issues and recipes One fault, across every run it appeared in, with what a fix needs. ## From finding to issue A finding gets a fingerprint built from what identifies the fault (its kind, its place, its channels), not from the run. The same fault in a later run lands on the same issue, so you see how often it came back and on which machines. ## States | State | Means | | --- | --- | | Open | Found and not yet worked on. | | In repair | Someone claimed a repair: a person in the app, or a coding agent over MCP, with what changed. | | Resolved | A verification passed. If the fault comes back, the issue opens again as regressed. | | Ignored | Seen and set aside. It stays ignored when it comes back. | ## The recipe Every finding carries the same nine fields. A field that could not be filled says what is missing instead of disappearing. | Field | What it holds | | --- | --- | | Symptom | what the machine did | | Causal chain | how that follows from the cause | | Condition | the measured numbers this rests on | | Change class | what kind of change is needed | | Files and lines | where to make it | | Reference pattern | what the corrected form looks like | | Acceptance criterion | the test that rejects a partial fix | | Blast radius | what else the change touches | | Effort | what it costs to do | `trialone diagnose --json` writes the recipes as JSON with exactly these fields, which is what the website shows and what a coding agent reads. ## The incident page A run and its issue share one page. At the top: the machine at the time (commit, configuration, devices, and what changed since the previous run), then four answers (what happened, why, the fix, what to check first), then the minute around the finding for every channel involved. All channels of the run can be scrubbed below. ## Sharing From an issue you can open a GitHub issue, share it to Slack or Discord, and open the recording in Foxglove when the machine uploads its recordings. Connect these under Settings, Integrations. --- # Proving a repair A repair is claimed by a person and proven by the robot. `trialone verify` measures a new recording against an earlier diagnosis and rules per finding. The rule is blunt on purpose: a partial improvement is the most expensive answer a diagnostic tool can give, because it sends a machine back to work with the fault still in it. ```bash trialone diagnose ./before.mcap --json trialone verify ./after-repair.mcap ``` | Per finding | Means | | --- | --- | | GONE | The finding is absent from the new recording. | | STILL | The same finding is present again. A lower peak is still the same finding. | | NEW | A finding the earlier diagnosis did not have. | The verdict is pass (exit code 0), fail (1) or inconclusive (2). A new candidate that is not certain makes the verdict inconclusive, never a pass. ## Measure both the same way Use the same `--healthy` reference and the same `--max-false-alarm` rate you diagnosed with. Otherwise a finding can appear or vanish because the bar moved, not because the machine changed. ## Crashes A crash does not repeat inside one log. Pass a folder with the logs of several runs of the scenario that triggered it, one log per run; each counts as one repetition. ## From the website On an issue, **Verify on** a machine queues a job for its watcher. The watcher takes the newest recording made after the repair was claimed, never one from before, and posts the verdict next to the diagnosis. Without a new recording there is no verdict, only a sentence that says what is missing. --- # Access and team Who can use TrialONE, and how a team works in one workspace. ## Access is by request We onboard a few robotics teams at a time, and a founder approves each one by hand. [Request access](https://trialone.dev/request-access) with your work email. You can sign in with Google, GitHub or email before the approval; until it arrives the app shows where your request stands. ## Keys | Key | Starts with | For | | --- | --- | --- | | CLI key | `t1cli_` | A robot or laptop that runs TrialONE and posts runs. One per machine, under Settings, CLI keys. | | Agent key | `t1mcp_` | A coding agent over MCP. It reads issues and reports repairs, and cannot post runs. | The database keeps only a hash of each key, so a key is shown exactly once. A revoked key can no longer post runs, and the machine that used it stops running TrialONE at its next daily check. ## A team A workspace is one account that several people work in. Invite people by email under Settings, Team. An invitation arrives by email, and when the address already has an account it also waits inside the app. | Role | Can | | --- | --- | | Owner | Everything, including the workspace itself. | | Admin | Invite and remove people, and see and revoke the keys of everyone in the workspace. | | Member | Work on issues, assign them, and create their own keys. | Issues can be assigned to a person, and every action (a claimed repair, a state change, an assignment) is kept with who did it. --- # What leaves the robot You decide per machine how much of a run reaches the website. By default a run sends the recipe (with the log lines and the few source lines around each file and line it cites), statistics per channel, a trend and a 10 Hz history of every channel, the minute around each finding, and, with `--project`, the commit data and the contents of your parameter, launch and URDF files. The recording itself stays on the machine unless you switch its upload on. ## History | Level | What leaves the machine | | --- | --- | | off | The recipe and statistics per channel. | | incident | Also the minute around each finding: 30 seconds before to 30 seconds after, at 10 points per second. | | full (default) | Also a trend of every channel and a 10 Hz history of every channel that moved. | ## Machine state | Level | What leaves the machine | | --- | --- | | off | Nothing about the code or the files. | | code | The commit, the branch, and the hash, date and subject of the last 50 commits. No source code, no diff, no credentials. | | full (default) | Also the parameter, launch and URDF files next to it, each content sent once per hash. | ## The recording itself Off until you switch it on for a machine, or pass `--upload-raw`. A recording can hold more than numbers (camera frames, point clouds, anything the robot published), and it can be large, so the switch names both. ## Where to change it Per machine under Settings, Robots, or per run with `--history` and `--state`. A flag wins over the setting, and the terminal says which one applied. `--no-push` keeps a run entirely on the machine. ## How long it is kept Trends and histories are deleted after 90 days by default. Runs stay, because issues and verifications refer to them. To have a workspace or a run removed, write to hello@trialone.info. --- # For agents This documentation is written to be read by a model as well as a person. ## Markdown copies Every page has **Copy page**, which copies it as Markdown, ready to paste into an agent's context. ## llms.txt [llms.txt](https://trialone.dev/llms.txt) is the plain-text index of this documentation for language models, followed by the full text of every page. It is served at `https://trialone.dev/llms.txt`. ## A working pattern 1. `list_issues`, then `get_issue` for the one to fix. Without a fingerprint, `get_issue` returns the newest open issue. 2. Change the files the recipe names. If the issue is routed as physical, stop and tell the user who has to go to the robot. 3. `claim_repair` with the fingerprint, one sentence on what changed, and the commit or pull request link. 4. `request_verification` to have the robot check its next recording. 5. `check_repair` for where it stands: proven, waiting, or back again. ## From the command line `trialone diagnose --json` writes one recipe per finding with fixed fields, for an agent that works without MCP.