Artitrack
Artitrack is a local-first experiment tracker and launcher built on xmanager, task-spooler, and ML Metadata. It provides a Python API for defining experiments and a CLI for querying and managing runs, executions, artifacts, and metrics. CLI output is plain text and fzf-friendly.
Core Concepts
- Experiment: A top-level grouping of related pipeline runs.
- Run: A tracked execution of a pipeline within an experiment.
- Execution (job): A single step submitted to task-spooler.
- Artifact: Inputs/outputs tied to executions (datasets, models, reports).
- Metric: Values extracted from job logs or registered manually.
Requirements
- Python 3.10 or 3.11
- task-spooler
qcommand on PATH - ml-metadata for local tracking (Linux only)
Data Directory
Artitrack stores metadata in ~/.at by default. Override with
ARTITRACK_DATA_DIR.
Python API (xmanager style)
Artitrack's launcher subclasses xm.Experiment/xm.WorkUnit — it is genuinely
xmanager-compatible, not just vocabulary-compatible. Two surfaces are available,
trading portability for artitrack's DAG/dedup features:
Portable subset — xm.Job/JobGroup, args, role, identity, exp.add(),
wait_until_complete() follow real xmanager's own contract, so a script written to
this shape ports to real xmanager by swapping the import for xmanager's own
xm_local (or another real backend) and its executor — no other code changes.
xm_local.TaskSpooler() itself, and the experiment_title= kwarg spelling, are
artitrack-specific and have no real-xmanager equivalent to swap in verbatim:
from xmanager import xm
from artitrack.launcher import xm_local
def main() -> None:
with xm_local.create_experiment(experiment_title="quick_test") as exp:
exp.add(
xm.Job(
name="train",
executable=xm.Binary(path="python train.py"),
executor=xm_local.TaskSpooler(),
args={"learning_rate": 0.001},
)
)
Artitrack-native surface — adds dependency ordering and artifact-based dedup, at the cost of portability to real xmanager:
from xmanager import xm
from artitrack.launcher import xm_local
def main() -> None:
with xm_local.experiment(name="quick_test") as exp:
with exp.run(title="train_then_eval") as run:
train_handle = run.add(
xm.Job(
name="train",
executable=xm.Binary(path="python train.py"),
executor=xm_local.TaskSpooler(),
args={"learning_rate": 0.001},
),
output_artifacts={"model": {"path": "/data/model.pt", "type": "Model"}},
)
run.add(
xm.Job(
name="eval",
executable=xm.Binary(path="python eval.py"),
executor=xm_local.TaskSpooler(),
),
depends_on=train_handle,
input_artifacts={"model": {"path": "/data/model.pt", "type": "Model"}},
)
depends_on/input_artifacts/output_artifacts/force/at_resume/est_time
are keyword-only extras on run.add() — they are not part of exp.add()'s
inherited xmanager signature, so mixing surfaces per-job is a TypeError, not a
silent no-op.
Examples live in examples/.
Quick start:
python examples/quick_pipeline.py
A sync-sentinel job is submitted automatically after all pipeline jobs to record terminal state in MLMD when the experiment context exits.
CLI
The CLI reads from the local metadata store and provides management tools.
Quick Commands
# What's running right now?
at status
# Show recent runs
at runs
at runs --failed
at runs -e my-experiment -n 5
# Show a specific run
at run <run-id>
# Most recent run
at run last
# Why did it fail? Grab the job log
at runs --failed
at log <job-id>
# Jobs and artifacts
at jobs
at job <job-id>
at query --entity artifact
Management
at infoshows database stats.at syncrefreshes run/job status from task-spooler.at cancel <run-id>...cancels one or more runs.at deletecleans runs from the store.at updateedits runs or executions.at metrics --run <run-id>shows metrics for a run.
Artifact Provenance
Find all runs that produced or consumed a given artifact:
# Which runs produced this model?
at query --entity run --output "models/model.pt"
# Which runs used this dataset as input?
at query --entity run --input "data/train.csv"
# Combine input and output filters
at query --entity run --input "data/train.csv" --output "models/model.pt"
Run Commands and Git Info
Inspect the exact commands, repository, and commit for each job in a run:
# Show full run detail (jobs, commands, artifacts, metrics)
at query --entity run <run-id>
# Show a single job's command, git repo, and commit
at query --entity execution <ts-job-id>
The job detail view includes:
- command: the full shell command used to launch the job
- git_repo: the remote URL of the repository (for python/uv scripts)
- git_commit: the exact commit SHA at submission time
- git_dirty: whether the repo had uncommitted changes
Dirty Repo Guard
When submitting from a git repository with uncommitted changes, artitrack prompts for confirmation. You can either auto-commit (recommended) or skip the check:
# Default: prompts to auto-commit if dirty
at submit -n train -- python train.py
# Skip the check entirely
at submit -n train --allow-dirty -- python train.py
The auto-commit creates a chore: artitrack auto-commit <timestamp> commit
with all modified tracked files, so the recorded git_commit always points
to reproducible code. The same guard applies to the Python launcher API —
it is controlled by the same --at_allow_dirty CLI flag (not a Python
kwarg), off by default, read once when experiment()/create_experiment()
runs.
Advanced Queries
The query command supports full filtering, ordering, and lineage queries:
# Filter by status
at query --entity run --status failed
# Filter by artifact lineage
at query --entity run --input "data/train.csv"
at query --entity run --output "models/model.pt"
# List jobs or artifacts
at query --entity execution
at query --entity artifact
# fzf-friendly output
at query --entity run --format fzf
Run at query --help for the full filter syntax.
Update Cheatsheet
# Change run status or tags
at update run <run-id> --status cancelled
at update run <run-id> --tag baseline --tag sweep
at update run <run-id> --remove-tag baseline
# Add artifacts or metrics to a job
at update execution <ts-job-id> --artifact /data/model.pt:model
at update execution <ts-job-id> --metric accuracy=0.95
Shell Completion
The completion command prints a shell snippet you can source:
# Print the snippet for the current shell
at completion
Use --shell fish to target a specific shell.
To print the fzf alias snippet:
at completion fzf-aliases --shell fish
fzf Workflow
Artitrack provides tab-delimited output that works well with fzf. Use the
--format fzf flag on query to get one-line rows without headers.
# Pick a run and preview details
at query --entity run --format fzf \
| fzf --delimiter='\t' --with-nth=2,3,4 \
--preview 'at query --entity run {1}'
# Pick a job and preview details
at query --entity execution --format fzf \
| fzf --delimiter='\t' --with-nth=1,3,4 \
--preview 'at query --entity execution {1}'
The fzf alias snippet (fish only) defines these functions:
at-runs— browse runs, sorted finished-firstat-jobs RUN_ID— browse jobs/steps for a run; Enter opens the log, ctrl-i shows job detailat-tb— pick metrics logdirs and print atensorboard --logdir_specstringat-trace PATH— trace a file path to the run that produced or consumed itat-watch [RUN_ID | QUERY]— live-monitor a running pipeline, refreshing every 5s
MCP Server
Use the MCP server to expose Artitrack data to LLM clients:
at-mcp
The server uses the same local metadata store as the CLI. CLI output is plain
text (or fzf tab-delimited), while MCP tools return JSON. For MCP list calls,
some large fields are omitted (for example config and
resolved_pipeline_path), so use get_run for full details.
Remote Access via SSH Tunnel
ml-metadata only runs on Linux. To query experiments on obelix from a Mac, tunnel the MCP server over SSH:
at mcp-tunnel obelix
This starts at-mcp on obelix (if not already running), opens an SSH
port forward on localhost:8000, and prints the config snippet for
~/.claude/mcp_servers.json:
{
"artitrack-remote": {
"type": "streamable-http",
"url": "http://localhost:8000/mcp"
}
}
Custom ports and remote working directory:
at mcp-tunnel obelix --port 9000 --remote-port 8001
at mcp-tunnel obelix:/home/hicham/project
Press Ctrl+C to stop the tunnel.
Metadata
Release files for artitrack 2026.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| artitrack-2026.9.1.tar.gz | 514.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| artitrack-2026.9.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 974.2 kB
Release files / artitrack-2026.9.1.tar.gz
| Download URL | artitrack-2026.9.1.tar.gz |
|---|---|
| Size | 514.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
86761931446e3806734c6f51d3721da7c635db795ca982db4a702ef5ee648ddf
|
|
BLAKE2b-256 checksum How to use checksums |
e75e400a3589f0188357235fa2ba83ec98015434db7a796363c26c711585873c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency logRelease files / artitrack-2026.9.1-py3-none-any.whl
| Download URL | artitrack-2026.9.1-py3-none-any.whl |
|---|---|
| Size | 459.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a7ae1f34c652bf95676c274952d2d2d460549cd6e9b07659b2c4ef50e209a0ba
|
|
BLAKE2b-256 checksum How to use checksums |
44c637251ef1f1f937bc01d701c9317b4f6f17f194bfb08f2fd60ef8cdf5d273
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency log