Skip to main content

tart — live terminal artifacts

A live terminal artifact is a dashboard that stays open, keeps its own data fresh — or says plainly that it hasn't — and can be found and read again later, by you or by an agent. Local, and authorable in a few lines.

uv tool install tartifacts   # the command is `tart`

Installed as tartifacts because PyPI's tart is an unrelated radio-telescope library, which owns the tart import name too. The command you type, and the .tart/ directory, are unaffected.

Why not just let each agent hand-roll a TUI?

Mostly, you should. rich already draws tables, panels and sparklines well, and tart doesn't replace it — you still write rich code, and render() may return any rich renderable. tart is not a rendering framework.

What repeats isn't the drawing. It's everything wrapped around it:

  • raw-mode terminal setup, and teardown that survives a dead tty
  • an event loop and key dispatch, with q/r handled for you
  • watching a data file and redrawing when it changes
  • knowing when data went stale, and re-running the thing that produces it
  • finding the dashboard again from any directory, on any machine
  • rendering one frame headless — an agent can't see a TUI it just wrote; without --once/--json it would have to drive a multiplexer and screen-scrape its own output

Each is a day of small annoyances, and every hand-rolled TUI rewrites them slightly differently.

The sharper argument is that the bugs repeat too. Two artifacts here independently grew a byte-identical sparkline() — with the same defect, because rich crops at the right edge, so a 30-day series in a narrow panel silently hid today. And every artifact under-reserved its height by exactly 4 rows (a table's border and header), losing its help line off the bottom. Both only appear at a particular terminal width. A green test suite and a quick eyeball won't catch either. Fixed once here, they're fixed everywhere.

When you don't need this: a script that prints a table and exits. That is the whole distinction — live is the word doing the work. Reach for tart when something should stay open, stay fresh, and be findable later.

How much does it actually take over? Across the five artifacts built on it, 14–23 lines out of 178–273 touch tart at all. The rest is yours.

An artifact is three pieces

.tart/thing.json     manifest — name, what produces the data, when it goes stale
fetch script         writes JSON to tartifacts.data_path()
render script        render(state, console) -> any rich renderable

The manifest is the only place a path is written down, so neither script repeats it:

{
  "title": "Bedrock spend",
  "run":   "uv run --with rich --with tartifacts python bin/dash.py",
  "data":  "bin/data/bedrock_usage.json",
  "fetch": "uv run --with tartifacts python bin/snapshot.py",
  "stale_after": "4h",
  "auto_refresh": true
}

Only title and run are required. The rest declare provenance, which is what lets tart run refresh stale data on its own, diagnose a dead dashboard, and another agent on another machine repair it from the manifest alone. With auto_refresh`, an external cron is optional rather than load-bearing.

The render script

from tartifacts import app, widgets

def render(state, console):
    return widgets.stack(
        widgets.header(f"{len(state['data']['rows'])} rows"),
        widgets.trend(state["data"]["daily"], style="green"),
    )

app.run(render=render, state={"cursor": widgets.Cursor()})

Only render is required — the title and the data source come from the manifest. You get --once/--json, refresh, and discovery for free.

CLI

tart list                    # what's declared, and what's live right now
tart run <name>              # launch it (fetches first if data is stale)
tart render <name>           # one frame, headless — no terminal needed
tart render <name> --json    # its numbers as JSON, for agents and pipelines
tart fetch <name>            # re-run its data-producing command
tart roots add <path>        # a workspace to scan for artifacts
tart reindex                 # re-find manifests too deep for the normal scan
tart --skill                 # the full reference, written for an agent

TART_HOME relocates tart's own state (default ~/.tart).

Quick start

uv tool install tartifacts
tart roots add ~/dev/quarkle    # scan a workspace, once

Full reference

tart --skill prints everything: the manifest schema, the app.run contract, the widget set, responsive-layout rules, and the gotchas. It's written to be read by an agent before it builds or debugs an artifact, and it's kept honest by tests that fail when a CLI subcommand, manifest field, app.run parameter, widget, or environment variable exists but isn't documented.

Development

make check    # lint + tests
make install  # (re)install the CLI from this checkout

When working on tart itself, point artifacts at your checkout with --with-editable /path/to/tart, never --with — uv run --with <path> builds and caches a wheel, so your edits silently don't apply.

A running artifact won't pick up tart changes. Python imports at startup, so quit and relaunch after upgrading. The failure is silent — a keypress appears to do nothing rather than erroring.

Metadata

Release files for tartifacts 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tartifacts 0.1.0
File Size Uploaded
tartifacts-0.1.0.tar.gz 83.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tartifacts 0.1.0
File Interpreter ABI Platform
tartifacts-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 136.6 kB

Release files / tartifacts-0.1.0.tar.gz

Download URL tartifacts-0.1.0.tar.gz
Size 83.0 kB
Tags Source
SHA-256 checksum
How to use checksums
83597471727017a74dd76bc2048157f8b09fe4484b7490e1447aba81bef10d55
BLAKE2b-256 checksum
How to use checksums
82fee55cde5575887e769fe34e6ca18ee5e4409424efdc2754b3ef867ab27708
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.15

Release files / tartifacts-0.1.0-py3-none-any.whl

Download URL tartifacts-0.1.0-py3-none-any.whl
Size 53.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78e4b75bffe7c0d0776c6fa8fc0d58cd1190675d674bc6b33a9cae05e4d013a9
BLAKE2b-256 checksum
How to use checksums
201ba34a9074682ea1fecea968b8e7a28930efba0a60e1fd8e74084c21f12476
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.15

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page