Metadata-Version: 2.4
Name: origami-trace
Version: 0.1.0
Summary: Local-first experiment history CLI.
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# 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:

```bash
pip install origami-trace
```

You can also run the published CLI without a persistent install:

```bash
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:

```bash
cd /Users/alansong/Documents/Projects/origami/trace
python3 -m trace_cli.cli ui
```

Open:

```text
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:

```bash
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:

```bash
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/`:

```bash
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:

```bash
python3 -m pip install -e .
```

Or run the repo checkout directly with uvx:

```bash
uvx --from . otrace --help
```

After installation, run `otrace` from any research project directory:

```bash
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:

```bash
which otrace
otrace --help
```

If `otrace` is not found, put your Python environment's `bin` directory earlier on `PATH` or reinstall the CLI:

```bash
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:

```bash
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:

```bash
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:

```bash
cd /Users/alansong/Documents/Projects/origami/trace/notebook
```

## Initialize Trace

```bash
otrace init
```

Creates:

```text
.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:

```bash
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.

```bash
otrace run \
  --intent "Describe why this run exists" \
  --setup "Describe the relevant setup and assumptions" \
  --config PATH \
  --expect-artifact PATH \
  -- <command> [args...]
```

Example:

```bash
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:

```yaml
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"
```

```bash
otrace run --spec otrace_my-project_runspec.yaml
```

Options:

```bash
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-runspec` is 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 `--config` paths as `config` artifacts.
- 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-artifact` and `--expect-log` after 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:

```text
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:

```text
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:

```bash
otrace import --spec trace-import.json --dry-run
```

Import after validation:

```bash
export TRACE_API_KEY="trc_your_key_here"
otrace import --spec trace-import.json
```

Manifest example:

```json
{
  "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:

```bash
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:

```text
metrics
figure
log
other
```

## Checkout An Experiment

```bash
otrace checkout EXP_ID
```

Default destination:

```text
../<project-name>.trace-checkouts/<EXP_ID>/
```

Options:

```bash
otrace checkout EXP_ID --path /absolute/or/relative/path
otrace checkout EXP_ID --in-place
```

Important:

- `--in-place` is declared but intentionally not automated in the MVP; it returns an error.
- The destination must be empty or absent.
- Prefer `--path` when 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:

```bash
cd <checkout-path>
bash reproduce.sh
```

## Export A Project Snapshot

```bash
otrace export --format zip
```

Options:

```bash
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/`, and `dist/`.
- Adds `trace-export-manifest.json` with export metadata.
- Adds `TRACE_EXPORT_README.txt` with restore steps.
- Skips the snapshot ZIP file itself while the archive is being written.
- Use repeated `--exclude` flags for additional bulky paths, or `--no-default-excludes` if you really want every rebuildable dependency copied too.

## Start The Web UI

```bash
otrace ui
```

Default URL:

```text
http://localhost:8000
```

Option:

```bash
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

```bash
otrace notebook generate
```

Options:

```bash
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:

```text
.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:

```text
run
```

Resolution behavior:

- Every successful `run` sets 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:

```bash
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:

```bash
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:

```bash
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

```text
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]
```
