SuperAPI AI Directory

sensorium

Records Python, Rust and TypeScript program runs to local SQLite so coding agents can query call trees, exceptions and value flow.

Open website

About this tool

sensorium is positioned as recording what a program actually did, and then asking questions about that record after the fact. It holds that reading logs is like reading a diary, whereas what it does is observe the execution process itself.

Main capabilities and recording methods

It records a single run of a program—every call, return, and exception, as well as captured values—into a SQLite trace file, and then answers debugging questions from that trace in dense plain text, with a text form designed for language models to read. The three recorders share the same format:

  • Python: sensorium run -- <command> instruments a run using PEP 669 (sys.monitoring), requires Python 3.12+, and has no runtime dependencies. On 3.11 it refuses to start rather than falling back to a weaker approach. Traces are SQLite files written using the standard library. One capability is version-limited: witnessing multiprocessing spawn requires the _posixsubprocess.fork_exec audit event that appears only in 3.14; below that version, such spawns are not witnessed.
  • Rust: cargo sensorium test|run instruments the workspace's own crates at build time, and each process writes one trace. Stable rustc, Linux. The Rust recorder is built and installed separately.
  • TypeScript: sensorium ts run [--focus <spec>]… -- vitest run … (or -- node --test …) transforms the user's own source code at load time, and each test file process writes one trace. Requires Node 24, vitest 4.1.

All three write trace format 4, so every query below can act on these three kinds of traces. Per-line state capture is optionally enabled at recording time, so predicates targeting local variables need to be asked on the run that recorded those variables; if asked against a run where that --focus was not enabled, watch does not report zero hits, but instead reports NOTHING WAS CHECKED and prints the exact re-record command.

Recording scope and frame model

Recording captures calls, returns, throws, and handled events for code under the run's starting working directory, so sensorium run -- pytest ... traces your tests andYour code, not pytest's own. --focus module:qualname adds line-level capture and local variable changes for the specified code; --window QUALNAME restricts that capture to the active extent of one function. Trace files land in ~/.sensorium/traces (or $SENSORIUM_DIR/traces), one SQLite file per run, with the Rust and TypeScript recorders writing to the same directory.

On asyncio programs, the tree is grouped by task; since trace format 3, every traced code object opens a frame—whether function, generator, coroutine, or async generator—so a coroutine's callees nest beneath it like ordinary functions, and are annotated [generator], [coroutine], or [async_generator] when the kind is not function. Suspended frames carry a derived trailing state such as ~ cancelled, ~ abandoned, ~ unwound by X thrown in at Ln, ~ suspended at Ln, etc. Parent links are caller frames, verified by code identity, not "the last frame opened on that thread."

Querying and usage

A run reference can be a full run id, a unique prefix, or last. Queries use eN for events and fN for frames; these ids are stable, so one command's answer can be an argument to the next. --fn NAME in grep and frame first matches qualname exactly, then falls back to substring matching against distinct qualnames within the trace; a single substring hit is treated as an exact name, while more than one is rejected as an ambiguous call and all candidates are listed. frame --fn NAME --nth N selects among repeated activations; flow --object accepts e<id>:<name> or <qualname>:<name>.

It also includes: diff compares the causal flow of two runs; refocus reruns a recorded command with deeper capture, then determines whether the rerun was the same execution; tree shows the derived parent-child relationships; and commands such as watch answer questions from the trace. sensorium mcp over the Model Context Protocol via stdio exposes the same store to models with no runtime dependency; every query command above except redact is a tool, and record and refocus are available only under --allow-run. Any MCP client can register the same binary.

Rigor and limitations

Every command's output strives to state its own limitations precisely. diff compares shape, not position: MATCH means the execution shape is the same, not that the values are the same; a function moving files causes a file change on every event, and a pure move reads as DIVERGED; diff --ignore-moves can pair up moves when the pairing is unique and annotate them as moved. refocus gives three verdicts and a bounded license: when it cannot refocus at all (e.g. the original trace is INCOMPLETE, the original run consumed stdin, the target is no longer resolvable, the original working directory has disappeared, etc.) it exits with code 2 and does not rerun; when it can rerun, MATCH permits only one conclusion, namely that the rerun took the same path, so the deeper capture describes the same path. The license lists alongside it the checks that actually passed and agreed; any check that cannot be run also withholds the license and states the reason one by one. DIVERGED is not a tool failure: for programs whose control flow depends on out-of-process state, DIVERGED is the correct answer, and the new trace is still recorded and permanently annotated.

Each invocation appends one line of JSON to <trace root>/invocations.jsonl (by default ~/.sensorium/invocations.jsonl or under $SENSORIUM_DIR), containing only utc, argv, exit, and error, with no environment or working directory; setting SENSORIUM_NO_INVOCATION_LOG to a non-empty value other than 0 disables that log for a single process.

Other facts (such as the specific install commands, the MCP tool list and result headers, limits, audit files, the full description of the server's rejection behavior, and the complete Rust and TypeScript references) are detailed in the repository files docs/mcp.md, docs/agent.md, rust/README.md, and typescript/README.md, whose full contents are not provided here.