Local-first experiment history CLI.
Project description
Trace CLI Agent Reference
This repository contains Trace, a cloud-hosted experiment history tool with local command capture.
Install The CLI
For normal cloud-hosted onboarding, install the published CLI:
pip install origami-trace
You can also run the published CLI without a persistent install:
uvx --from origami-trace otrace --help
Cloud onboarding
Trace uses Supabase Auth for browser sign-up and sign-in. The CLI syncs a local project workspace with a cloud project by using a project-scoped Trace API key created from the cloud-first React app.
For local app development, serve the static React app:
cd /Users/alansong/Documents/Projects/origami/trace
python3 -m trace_cli.cli ui
Open:
http://localhost:8000/account
Use the app to sign up or sign in with Google, create a project, then create a project API key. Copy the trc_... key when it appears; it is shown only once.
Initialize your local workspace with that key:
export TRACE_API_KEY="trc_your_key_here"
cd /path/to/research-project
otrace init
otrace whoami
otrace init validates the API key, initializes .trace/, and syncs the current workspace to the cloud project tied to the key. OTrace does not write .env; it prints the values to add if you want future shells to use workspace-local credentials. otrace whoami should print the account email, project, and API key prefix. otrace run prints the RunSpec filepath being used, validates the API key, and creates a hosted run before local command execution. If hosted run creation fails, the experiment command is not executed.
Create a hosted experiment:
otrace run \
--intent "Smoke test Trace hosted experiment creation" \
--setup "Fresh Trace project with a minimal shell command" \
--expect-log outputs/smoke.log \
-- sh -c 'mkdir -p outputs && echo ok | tee outputs/smoke.log'
For local development from this repository, use the repo-local wrapper from notebook/:
cd /Users/alansong/Documents/Projects/origami/trace/notebook
export TRACE_API_KEY="trc_your_key_here"
otrace init
otrace whoami
otrace run \
--intent "Smoke test Trace hosted experiment creation" \
--setup "Fresh Trace project with a minimal shell command" \
--expect-log outputs/smoke.log \
-- sh -c 'mkdir -p outputs && echo ok | tee outputs/smoke.log'
For local development of this repository, use an editable install:
python3 -m pip install -e .
Or run the repo checkout directly with uvx:
uvx --from . otrace --help
After installation, run otrace from any research project directory:
cd /path/to/research-project
export TRACE_API_KEY="trc_your_key_here"
otrace init
otrace run \
--intent "Train baseline" \
--setup "Baseline training from the default config" \
--config configs/base.yaml \
--expect-artifact outputs/metrics.json \
-- python train.py
Check that the installed command is available:
which otrace
otrace --help
If otrace is not found, put your Python environment's bin directory earlier on PATH or reinstall the CLI:
otrace init
otrace run \
--intent "Train baseline" \
--setup "Baseline training from the default config" \
--config configs/base.yaml \
--expect-artifact outputs/metrics.json \
-- python train.py
Trace stores durable experiment state in Supabase. Runtime logs and snapshots are written under .trace/ while commands execute; that directory should not be committed.
otrace init also writes TRACE_FOR_AGENTS.md into the project root so backend-agnostic coding agents can learn the Trace workflow.
The repo-local wrapper still works:
cd notebook
otrace <command>
Quick Command Index
| Command | Purpose |
|---|---|
otrace init |
Validate a project API key, initialize local Trace state, and sync the workspace to its cloud project. |
otrace run --intent "..." --setup "..." --expect-artifact PATH -- <command> |
Run a command and save it as a new experiment node. |
otrace import --spec PATH [--dry-run] |
Replace the current hosted project's runs with a Trace-native historical run manifest. |
otrace checkout EXP_ID [--path PATH] |
Create a reproducible checkout for an experiment. |
otrace export [--format zip] [--output PATH] |
Zip the project working tree and runtime Trace files for moving between machines. |
otrace ui [--port PORT] |
Start the cloud-first localhost app. |
otrace notebook generate [--mode MODE] [--output PATH] |
Generate a markdown notebook from Trace data. |
Working Directory Rule
Run otrace from the project whose experiments should be tracked:
cd /path/to/research-project
The CLI records paths, snapshots git state, uploads durable records to Supabase, and runs experiment commands relative to the current working directory.
For the bundled CIFAR-10 example, the project root remains:
cd /Users/alansong/Documents/Projects/origami/trace/notebook
Initialize Trace
otrace init
Creates:
.trace/
checkouts/
logs/
notebook/
snapshots/
.traceignore
TRACE_FOR_AGENTS.md
otrace init validates the project API key and syncs workspace metadata to the cloud project. OTrace does not create or update .env. If you want future shells to run OTrace without passing --api-key, add the printed TRACE_* values to your shell or workspace-local .env yourself.
OTrace does not edit .gitignore.
Options:
export TRACE_API_KEY="trc_your_key_here"
otrace init
otrace init --api-key "trc_your_key_here"
otrace init --api-url "$TRACE_API_URL" --api-key "trc_your_key_here"
otrace init --force --api-key "trc_your_key_here"
--api-key is useful for a one-time bind. Future otrace whoami and otrace run commands still need TRACE_API_KEY in the shell or a user-managed .env.
Notes for agents:
- Do not commit
.trace/; it contains runtime logs, snapshots, generated notebooks, and checkouts. - If the user stores Trace credentials in
.env, do not commit it; it contains the project API key.
Run An Experiment
otrace run normalizes the requested run into a RunSpec. By default, each project uses otrace_<project-name>_runspec.yaml, where <project-name> is the sanitized project directory name. OTrace prints the RunSpec filepath it is using and does not ask for confirmation by default. If no default RunSpec exists, a flag-based run writes that YAML file after the run record exists.
Use --verify-runspec to render the RunSpec and require Y/N before OTrace resolves credentials, syncs workspace metadata, creates the hosted run, or executes the command.
otrace run \
--intent "Describe why this run exists" \
--setup "Describe the relevant setup and assumptions" \
--config PATH \
--expect-artifact PATH \
-- <command> [args...]
Example:
otrace run \
--intent "Smoke test Trace capture" \
--setup "Fresh Trace project with a minimal Python command" \
--expect-log outputs/smoke.log \
-- sh -c 'mkdir -p outputs && echo ok | tee outputs/smoke.log'
Users or agents can generate a RunSpec YAML file and maintain it themselves. Agents can validate the equivalent RunSpec object with the side-effect-free trace_validate_run_spec MCP tool when useful:
version: 1
intent: "Train baseline"
setup: "Default config on the validation split"
command:
- "python"
- "train.py"
- "--config"
- "configs/base.yaml"
config_paths:
- "configs/base.yaml"
expected_artifact_paths:
- "outputs/metrics.json"
expected_log_paths:
- "outputs/train.log"
title: "Baseline"
tags:
- "baseline"
otrace run --spec otrace_my-project_runspec.yaml
Options:
otrace run --intent "..." --setup "..." --config PATH --expect-artifact PATH -- <command>
otrace run --intent "..." --setup "..." --expect-log PATH --title "Short display title" -- <command>
otrace run --intent "..." --setup "..." --expect-artifact PATH --tag baseline --tag ablation -- <command>
otrace run --spec otrace_my-project_runspec.yaml
otrace run --verify-runspec
Behavior:
- Prints the RunSpec filepath used for the run.
- Renders a RunSpec preview only when
--verify-runspecis passed. - Validates hosted auth and creates the hosted run record before executing the wrapped command.
- Does not execute the wrapped command if hosted run creation fails.
- Captures declared
--configpaths asconfigartifacts. - Creates the next experiment ID, such as
exp001. - Captures git commit, dirty diff, staged diff, dependency file copies, Python version, platform, stdout/stderr logs, exit code, duration, and a deterministic summary.
- Captures files declared by
--expect-artifactand--expect-logafter the command exits and uploads them with the hosted run details. - Sets the new experiment as the active experiment after the run.
- Returns the wrapped command's exit code.
Dependency files captured when present:
requirements.txt
pyproject.toml
environment.yml
environment.yaml
poetry.lock
uv.lock
Pipfile
Pipfile.lock
The command must appear after --. If omitted, Trace errors with:
No command provided. Use `otrace run --intent ... -- <command>`.
Import Historical Runs
Use otrace import --spec <spec> to import historical experiments into the current hosted Trace project without re-running them. The spec is a Trace-native JSON manifest authored by you or an agent. File paths are resolved relative to the manifest file unless they are absolute.
Import is project-replacing: if the current hosted project already has runs, OTrace asks for confirmation, deletes those project runs, then imports the manifest. Use --dry-run first to validate the manifest without checking credentials, deleting runs, or writing to the cloud.
Dry-run a manifest before writing to the cloud:
otrace import --spec trace-import.json --dry-run
Import after validation:
export TRACE_API_KEY="trc_your_key_here"
otrace import --spec trace-import.json
Manifest example:
{
"version": 1,
"runs": [
{
"title": "baseline linear regression",
"intent": "Train a toy linear regression model",
"setup": "Synthetic one-feature regression with gradient descent",
"command": "python3 train.py",
"status": "completed",
"created_at": "2026-06-01T12:00:00Z",
"started_at": "2026-06-01T12:00:01Z",
"finished_at": "2026-06-01T12:00:04Z",
"exit_code": 0,
"duration_seconds": 3.0,
"tags": ["historical", "baseline"],
"artifacts": [
{ "path": "outputs/baseline/metrics.json", "type": "metrics" },
{ "path": "outputs/baseline/model.json", "type": "other" }
],
"logs": [
{ "path": "logs/baseline.log", "stream": "stdout" }
],
"result_files": [
"outputs/baseline/metrics.json"
],
"results": [
{ "kind": "scalar", "name": "manual_metric", "value": 42, "source_path": "notes.md" }
],
"tables": [],
"snapshot": {
"git_commit": "abc123",
"python_version": "3.12"
}
}
]
}
Required per run: intent, setup, command, and status. status must be one of created, running, completed, failed, or capture_failed. Use artifacts for files that should be stored with the run, logs for log text, and result_files for JSON/CSV/TSV/text files Trace should parse into scalar results and tables. Explicit results and tables are preserved as provided. For large checkpoints or model files, add "store_content": false to the artifact entry so Trace records the path, type, size, and hash without inlining the file contents into the database.
Attach Artifacts
Captured Outputs
Declare outputs before the run starts:
otrace run \
--intent "Train baseline" \
--setup "baseline config" \
--expect-artifact outputs/results.csv \
--expect-artifact outputs/grid.png \
--expect-log outputs/train.log \
-- python train.py
Behavior:
- Globs are expanded after the wrapped command exits.
- Each matched artifact path must be a file.
- Files are copied into
.trace/artifacts/<EXP_ID>/. - Missing expected paths are recorded on the run instead of failing the command.
- Captured artifacts, parsed results, logs, and snapshot metadata are uploaded to the hosted run details endpoint.
Common artifact types are inferred from file suffix and expected path kind:
metrics
figure
log
other
Checkout An Experiment
otrace checkout EXP_ID
Default destination:
../<project-name>.trace-checkouts/<EXP_ID>/
Options:
otrace checkout EXP_ID --path /absolute/or/relative/path
otrace checkout EXP_ID --in-place
Important:
--in-placeis declared but intentionally not automated in the MVP; it returns an error.- The destination must be empty or absent.
- Prefer
--pathwhen an agent needs a predictable checkout location.
Behavior:
- Creates a git worktree at the captured commit when possible.
- Falls back to copying the repo without
.trace,.git, or__pycache__if worktree creation fails. - Applies the captured dirty diff when present.
- Copies captured dependency files.
- Copies captured artifacts into
trace-artifacts/. - Writes
reproduce.sh. - Writes
trace-reproduction.md.
After checkout:
cd <checkout-path>
bash reproduce.sh
Export A Project Snapshot
otrace export --format zip
Options:
otrace export --output path/to/snapshot.zip
otrace export --output path/to/snapshot.zip --force
otrace export --exclude examples --exclude "*.pt"
otrace export --no-default-excludes
Behavior:
- Zips the project working tree, including
.git/and the complete.trace/directory. - Preserves runtime Trace files such as logs, snapshots, notebook files, and ledgers. Durable experiment history lives in Supabase.
- Skips rebuildable/heavy paths by default, including
.venv/,venv/,env/,node_modules/, Python caches, test caches,build/, anddist/. - Adds
trace-export-manifest.jsonwith export metadata. - Adds
TRACE_EXPORT_README.txtwith restore steps. - Skips the snapshot ZIP file itself while the archive is being written.
- Use repeated
--excludeflags for additional bulky paths, or--no-default-excludesif you really want every rebuildable dependency copied too.
Start The Web UI
otrace ui
Default URL:
http://localhost:8000
Option:
otrace ui --port 4321
Behavior:
The alpha app is cloud-first. Use it for account sign-in, project creation, project API keys, workspace sync metadata, and hosted run records.
- Serves the installed Trace UI with the selected port.
- Uses the current working directory as the traced project.
- Serves the Trace React UI and JSON APIs.
- This command is long-running.
Generate Notebook
otrace notebook generate
Options:
otrace notebook generate --mode chronological
otrace notebook generate --mode branch
otrace notebook generate --mode insights
otrace notebook generate --output path/to/notebook.md
Modes:
| Mode | Behavior |
|---|---|
chronological |
Includes all experiments ordered by creation time. This is the default. |
branch |
Includes the active experiment, its ancestors, and its descendants. |
insights |
Includes experiments with at least one #insight note. |
Default output:
.trace/notebook/generated.md
.trace/notebook/generated.json
The generated notebook is deterministic and based on structured Trace data. It explicitly says when no metrics file was captured or parsed.
Active Experiment Rules
Commands that maintain local active experiment state:
run
Resolution behavior:
- Every successful
runsets the new experiment as active. - Local post-run mutation commands have been removed; use a new hosted run to capture additional outputs.
Common Agent Workflows
Initialize and capture a smoke run:
cd notebook
export TRACE_API_KEY="trc_your_key_here"
otrace init
otrace whoami
otrace run \
--intent "Smoke test Trace capture" \
--setup "Fresh Trace project with a minimal Python command" \
--expect-log outputs/smoke.log \
-- sh -c 'mkdir -p outputs && echo ok | tee outputs/smoke.log'
Capture outputs in the run declaration:
otrace run \
--intent "Capture baseline outputs" \
--setup "Baseline training with expected metrics and logs" \
--expect-artifact outputs/results.csv \
--expect-log outputs/train.log \
-- python3 train.py
Reproduce a prior experiment in a separate directory:
otrace checkout exp001 --path /tmp/trace-exp001
cd /tmp/trace-exp001
bash reproduce.sh
Error Handling Notes
Common errors and fixes:
| Error | Fix |
|---|---|
Trace is not initialized. Run \otrace init` first.` |
Run otrace init from the project root. |
| Supabase schema error | Apply docs/supabase/trace_cloud.sql in the Supabase SQL editor. |
Unknown experiment: EXP_ID |
Query existing experiments via UI/API. |
Artifact path is not a file |
Pass file paths or globs that resolve to files. |
Checkout destination is not empty |
Choose an empty path with --path. |
Machine-Readable Command Shapes
otrace init [--force] [--api-key KEY] [--api-url URL]
otrace login [--api-key KEY] [--api-url URL]
otrace whoami
otrace run --intent TEXT --setup TEXT (--expect-artifact PATH | --expect-log PATH) [--title TEXT] [--tag TAG ...] -- COMMAND [ARG ...]
otrace import --spec PATH [--dry-run] [--continue-on-error]
otrace checkout EXP_ID [--path PATH] [--in-place]
otrace export [--format zip] [--output PATH] [--force] [--exclude PATTERN ...] [--no-default-excludes]
otrace ui [--port PORT]
otrace notebook generate [--mode chronological|branch|insights] [--output PATH]
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file origami_trace-0.1.0.tar.gz.
File metadata
- Download URL: origami_trace-0.1.0.tar.gz
- Upload date:
- Size: 120.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5c71156c549cdd9e15db3ac4635919137b241e19265d59f6ad3f10920792147
|
|
| MD5 |
788f4eb6aa99660806c56167197e8110
|
|
| BLAKE2b-256 |
c2c5b9c9e5307a8db6b61ff617eb57db7ee0bf9af2ba418b6458631c7a6cb4c5
|
File details
Details for the file origami_trace-0.1.0-py3-none-any.whl.
File metadata
- Download URL: origami_trace-0.1.0-py3-none-any.whl
- Upload date:
- Size: 130.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c774931be8a0ecc8f02f71571cfe753943bdb4d97ed45bd60983a4e0419c4aa6
|
|
| MD5 |
1c08c5f04065e8e48207f9fe9bc1fc44
|
|
| BLAKE2b-256 |
4f5ea66b263283d3377cc77c5ffab139f5f7de0b2d21fe98e3259e699c9b0d55
|