Exit codes

tsr distinguishes "my task failed" from "the runner itself broke" so CI pipelines see the real signal.

CodeMeaning
0Success.
child's codeOn task failure, the first failed child's exact exit code is propagated verbatim (1, 2, 130, …).
64Runner-level error.
130The run was interrupted (Ctrl-C / SIGTERM).

What counts as a runner-level error (64)

  • config parse failure or invalid TOML;

  • dir and packages both set on a task;

  • an unknown task name, or a dependency cycle;

  • a delegate binary (or any command) that can't be launched;

  • an undefined $VAR referenced in a run string;

  • a rejected mini-shell metacharacter (|, >, *, $(…), …);

  • a packages pattern that matches no package;

  • a rejected security guard — a path outside the workspace, a guarded environment variable, a world-writable config.

Why the distinction matters

A child code (like 1 or 130) means your task failed. Code 64 means tsr itself couldn't proceed — a config or setup problem, not a test that went red. Pipelines can branch on the difference.

Fail-fast propagation

When several tasks run in a batch and one fails, tsr stops launching new work, kills running siblings, and propagates that child's exact code. In a parallel batch, the reported failure is whichever child exited non-zero first in wall-clock time.