Skip to content

v0.3.0 (beta)

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 07 Oct 14:47
· 4 commits to 621936ef25578f3c53aff7b4c2645cc64428a086 since this release
f63e614

thunc 0.3.0 lets you watch a program's calls and agent runs live. thunc watch app.py runs your program with a dashboard in the terminal: the calls waiting on a model, retries and why each reply was rejected, timings for each function, each agent's steps as they happen, and the --profile report when the program ends. A program needs nothing added to be watched.

It also brings an experiment, thunc write: a function declared with @thunc.function(write=True) writes its own body into your file on its first call, and runs as plain Python from then on. A program that uses neither behaves exactly as in 0.2.3.

pip install --upgrade "thunc[watch]"
thunc watch support_inbox.py --limit 20   # a script and its arguments, as with thunc run
thunc watch -m myapp.triage               # a module
thunc watch -- uv run app.py              # any command
thunc watch --agents                      # agent runs in ./.thunc_agents, from any process
thunc watch --plain app.py                # one line per event, for CI logs and pipes
 thunc watch  support_inbox.py                     claude-code/sonnet   00:18.0   ● running
 1 Overview   2 Agents   3 Calls   4 Summary
────────────────────────────────────────────────────────────────────────────────────────────
 IN FLIGHT  4 running
   ⠙ draft_reply       ticket="Password reset email never… attempt 1    4.2s  ████████████
   ⠙ urgency           ticket="Refund still not showing a… attempt 2    4.1s  ██████████░░
   FUNCTION          CALLS  CACHED  RETRIES  FAILED      MEAN       P95     MODEL   RECENT
   category              8       0        0       0      1.5s      2.5s     11.7s   ▃▄▅█▆▇▃▄
   urgency               7       0        1       0      2.4s      4.7s     16.9s   ▂▄▄▆▃█▅
 AGENTS  0 running
   ✓ repo-guide      tests_for(feature="caching")            finished · 6 steps       12.4s
 EVENTS
   17:38:13  ✓ find_order      → Order(id='A-1043')                                    1.8s
   17:38:15  ↻ urgency         attempt 1: not valid JSON: 'high'                       2.8s

The dashboard (#59)

  • Five screens: Overview (calls in flight, a table per function, running agents, results per second, recent events), Agents (each run's steps, time split, changed files and denials), Calls (each attempt of a call: the reply and why it was rejected), Summary (the thunc run --profile tables, opened when the program ends) and Output (what the program printed).
  • Mouse or keys. Click a row to select it and again to open it, or use ↑ ↓ and ⏎. f shows only retries, failures and denials; p pauses the display while the program keeps running; ? lists every key.
  • --agents [DIR] follows the agent runs recorded in a folder, from another terminal, a web app or a worker. A run whose process died partway through shows as interrupted.
  • --save-events and --replay keep a run and play it back, which is a good thing to attach to a bug report. --replay also plays one agent run's session record.
  • --plain prints one line per result, retry and agent step to stderr, then the report. It's what you get when the output isn't a terminal.

How it's packaged

  • The dashboard is a Rust binary in its own package, thunc-watch 0.1, with wheels for macOS, Linux (glibc and musl) and Windows. thunc[watch] installs it, so thunc itself stays pure Python with no dependencies. It's also on your PATH as thunc-watch.
  • Without it, thunc watch says how to install it.

THUNC_EVENTS

  • When THUNC_EVENTS names a file, thunc appends one JSON line to it per call start, model reply, call end, agent tool call and agent end; thunc watch sets it for the program it runs. To watch a program started some other way, set it yourself and run thunc watch --events FILE.
  • Inputs, replies and values are cut to 120-character previews; --capture (or THUNC_EVENTS_CAPTURE=1) sends them whole. Like a trace, they can contain personal data.
  • When it isn't set, nothing is written.

thunc write, experimental (#63, #64)

Experimental. Its behavior, options and the code it writes may change, or it may be removed, in a later release without a deprecation period. It edits your source files, only while you develop; review each change as a diff before you commit it.

@thunc.function(write=True)
def minutes(duration: str) -> int:
    """Convert a duration like '1h 30m', '90 min' or '2 hours' to whole minutes."""
    ...


minutes("1h 30m")  # -> 90, and minutes() is now Python in your file
thunc: writing minutes() in durations.py (first call)
thunc: checked against 6 model answers: all agree
thunc: wrote durations.py lines 5-27 in 14s (answer 4s, draft 11s, test calls 9s; side by side). Removed @thunc.function. Review: git diff durations.py
  • On the first call, three requests start side by side: the call's answer, a draft of the body from the docstring and signature, and five test calls, each answered by the model on its own. The draft is linted, run on the call and the test calls, and has to match every answer; one that doesn't goes back with the failing calls, up to three drafts.
  • A passing draft goes into the file in place of ..., the decorator is removed, the checked calls become doctest examples, and the call runs the new code.
  • When it isn't written, because the task needs judgment or no draft passed, the call returns the model's answer and the file is untouched. The reason is kept in .thunc_write/ until the docstring or signature changes.
  • It's refused, with a warning, in CI or with THUNC_WRITE=0 (set it in production), outside your project, and for read-only, installed or changed files and nested functions.
  • thunc write FILE::FUNCTION [--dry-run] writes one ahead of its first call, or shows the diff.

Tested

  • Offline tests run on Python 3.10–3.14 on Ubuntu, and on Windows, including the events and the thunc watch command. CI runs the dashboard's cargo fmt, clippy and tests on Linux, macOS and Windows, and on Linux builds the PyPI wheel and runs thunc watch from it.
  • thunc write: 45 offline tests of the source editing and the writing, end to end against a scripted model, including CRLF files; live, live_tests/test_writing.py on Codex wrote a function whose doctests pass.
  • watch/demo/demo_app.py runs the support-inbox functions and an agent against a scripted backend, with delays and bad replies, and makes no model calls.

Behavior changes

  • None. thunc watch, THUNC_EVENTS and write= are new; nothing is written unless THUNC_EVENTS is set, and no file is edited unless a function has write=True. Nothing is removed.

Known issues: the dashboard only watches: it can't stop a single agent run or approve ask: actions yet. --agents sees one folder, not every project on the machine. On Windows, Ctrl+C and quitting end the program at once, without the KeyboardInterrupt it gets on macOS and Linux. thunc write's checks are only as good as the model's answers, so review the code it writes; thunc write can't write methods ahead of their first call, and it doesn't run on jev. The full list is in CONTRIBUTING.md, and every change is in CHANGELOG.md.

Full changelog: v0.2.3...v0.3.0