Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here
lite-runner logo

lite-runner

lite-runner-marketplace

OtherClaude Codeby moonmath-ai

Summary

Skill for writing run.py scripts with lite-runner: a reproducible CLI experiment runner (training, eval, benchmark, sweep, simulation, distributed launcher) with W&B and local JSON tracking.

Install to Claude Code

/plugin install lite-runner@lite-runner-marketplace

Run in Claude Code. Add the marketplace first with /plugin marketplace add moonmath-ai/LiteRunner if you haven't already.

README.md

LiteRunner

[![Tests][tests-badge]][tests-link] [![codecov][codecov-badge]][codecov-link] [![PyPI version][pypi-version-badge]][pypi-link] [![PyPI platforms][pypi-platforms-badge]][pypi-link] [![Total downloads][pepy-badge]][pepy-link] \ [![Made Using tsvikas/python-template][template-badge]][template-link] [![GitHub Discussion][github-discussions-badge]][github-discussions-link] [![PRs Welcome][prs-welcome-badge]][prs-welcome-link]

Overview

Runner for generative models with local and W&B tracking.

Write a small Python script per model that declares params, outputs, and metrics.

lite-runner handles the rest: CLI parsing, interactive prompts for missing values, subprocess execution, stdout/stderr capture, metric extraction, file uploads to W&B, and code snapshots for reproducibility.

Quick start

Create a run.py for your model:

#!/usr/bin/env -S uv run
# /// script
# dependencies = ["lite-runner"]
# ///
from lite_runner import Runner, Param, Metric

runner = Runner(
    command="python generate.py",
    params=[
        Param("prompt", help="Text prompt"),
        Param("seed", type="int", default=42),
        Param("output-path", value="$output/video.mp4", type="path-video"),
    ],
    metrics=[
        Metric("loss", pattern=r"loss=([\d.]+)"),
    ],
)

if __name__ == "__main__":
    runner.run()

Then run it (requires uv):

chmod +x run.py
./run.py --prompt "a cat walking"           # interactive TUI fills missing params
./run.py --prompt "a cat" --no-interactive  # non-interactive, fail if missing
./run.py --prompt "a cat" --dry-run         # print command, don't run
./run.py --seed=-                           # unset a param (omit from command)
./run.py --image - - -                      # unset a multi-value param

What it does

Each runner.run() call:

1. Parses CLI args (all params are optional in argparse; missing ones trigger TUI prompts) 1. Creates an output directory at ~/lite_runs/<project>/<timestamp>_<run_name>/ 1. Inits a W&B run and logs all params, git info, and host metadata 1. Saves a code snapshot (git archive + dirty diff) as a W&B artifact 1. Builds and runs the subprocess, streaming stdout/stderr to terminal and log files 1. Extracts metrics from stdout via regex 1. Uploads output files (videos, images, artifacts) to W&B 1. Logs duration, exit code, and status to W&B summary

Param

<!-- blacken-docs:off -->

Param("name")                               # basic string param
Param("seed", type="int", default=42)       # typed with default
Param("mode", choices=["fast", "quality"])  # select from choices
Param("verbose", type="bool")               # --verbose flag (store_true, always defaults to False)
Param("image", type="path-image")           # file input, uploaded to W&B before run
Param(
    "output-path",
    value="$output/video.mp4",              # fixed value, $output interpolated
    type="path-video",
)                                           # after the run, uploaded to W&B as a video
Param(
    "input-image",
    type=["path-image", "float", "float"],  # multi-value flag
    labels=["img", "start", "strength"],
)                                           # each part prompted separately in TUI

<!-- blacken-docs:on -->

Type — controls parsing, casting, and file upload intent. All param values are logged to run.config. The path- variants additionally upload the file at that path* to W&B:

| Type | Parsed as | File upload | | ----------------- | --------- | ----------- | | "str" (default) | str | — | | "int" | int | — | | "float" | float | — | | "bool" | flag | — | | "path" | str | — | | "path-image" | str | as image | | "path-video" | str | as video | | "path-artifact" | str | as artifact | | "path-text" | str | as text |

"bool" params are special: they generate a --flag (no value), always default to False (any other default= is ignored), and cannot appear in multi-value type lists.

Other fields:

  • value= makes a param fixed (never prompted, not in CLI). Can be a callable (called at resolve time).
  • default= can be a callable (called at resolve time to compute the default)
  • flag= overrides the CLI flag name (default: --<name with hyphens>)
  • prompt=False skips interactive prompting (falls through to default). Requires a default=. The param still accepts CLI flags and is logged normally.
  • $output in value is replaced with the run's output directory
  • log_when= auto-inferred: "before" for inputs, "after" for $output paths
  • type=[...] gives per-element types for multi-value flags (nargs inferred from length)
  • Pass - on CLI to unset a param (omit it from the subprocess command).

For single-value: --seed=-. For multi-value: --image - - - (one - per element). This mirrors typing - at the interactive TUI prompt.

Output

For files the model writes to uncontrolled locations:

Output("model_metadata.json", log_as="artifact", copy_to="$output/model_metadata.json")

Supports glob patterns and directory zipping:

<!-- blacken-docs:off -->

Output("debug/**/*.png", log_as="image")                # upload each matched png
Output("debug/", log_as="image")                        # upload each file in directory
Output("debug/", log_as="zip")                          # zip entire directory, upload as artifact
Output("$output/frames/*.jpg", log_as="zip")            # zip glob matches into archive
Output("weights/", log_as="zip", name="model-weights")  # name= sets the W&B key (disambiguates zips)

<!-- blacken-docs:on -->

Metric

Extract values from stdout:

Metric("loss", pattern=r"loss=([\d.]+)")
Metric("status", pattern=r"status: (\w+)", type="str")
Metric("steps_per_sec", pattern=r"steps/s=([\d.]+)", type="int")
Metric(
    "elapsed", pattern=r"elapsed: ([\d:.]+)", type="timedelta"
)  # [[HH:]MM:]SS[.ddd] → seconds

Last match wins. Patterns are matched against both stdout and stderr. Stored in wandb.run.summary.

Supported types: "float" (default), "int", "str", "timedelta".

Sweeps

Loop with override(). Runs are grouped in W&B for easy comparison:

runner = Runner(
    command="python gen.py",
    params=[...],
    run_group="lr-sweep",  # groups all runs together in W&B UI
)
for lr in [1e-3, 1e-4, 1e-5]:
    runner.override(learning_rate=lr).run(no_interactive=True)

Each call creates a separate W&B run, all grouped under the same group.

You can also update metadata per-run:

runner.override(seed=42).with_metadata(tags=["baseline"]).run()

Runner options

<!-- blacken-docs:off -->

Runner(
    command="python gen.py",  # str or list[str] (list avoids shell splitting)
    params=[...],
    outputs=[...],
    metrics=[...],
    tags=["experiment-1"],    # W&B run tags
    env={
        "CUDA_VISIBLE_DEVICES": "0",
        "NOISY_VAR": None,
    },                        # set or unset env vars
    secret_env={
        "HF_TOKEN": "hf_xxx",
    },                        # like env, but redacted in logs / recorded config
    project="my-project",     # default: git repo name
    run_group="my-sweep",     # W&B run group for sweeps (None = no grouping)
)

<!-- blacken-docs:on -->

Pipeline API

Each method returns a new Runner (immutable copies), so you can branch:

<!-- blacken-docs:off -->

base = runner.parse_cli()    # parse sys.argv
r1 = base.override(seed=42)  # override params by name
r2 = base.override(seed=99)
r1.run()                     # auto-resolves defaults & prompts
r2.run()

<!-- blacken-docs:on -->

Methods:

| Method | Description | | -------------------------------------------- | --------------------------------------------- | | parse_cli(argv) | Parse CLI args (default: sys.argv[1:]) | | override(**kwargs) | Set param values by name | | with_metadata(project=, run_group=, tags=) | Update W&B metadata | | resolve_defaults() | Apply defaults and fixed values | | ask_user(no_interactive=) | Prompt for missing values | | run(...) | Auto-calls any unapplied steps, then executes |

run() accepts kwargs dry_run, min_free_space_gib, no_interactive, no_wandb, project, run_name as alternatives to CLI flags. It returns a RunResult with fields: output_dir, exit_code, duration, run_name, project, config, param_values, param_sources.

Built-in CLI flags

| Flag | Description | | ------------------------ | --------------------------------------------- | | --dry-run | Print command and exit | | --min-free-space-gib N | Minimum free disk space in GiB (default: 1.0) | | --no-interactive | Fail if required params missing | | --no-wandb | Skip W&B logging (still logs to JSON) | | --run-name NAME | Override W&B run name | | --project NAME | Override project name |

What gets logged to W&B

| Location | Content | | ------------------------------ | ---------------------------------------------------------------------------------------- | | run.config["param/"] | All param values | | run.config["param_source/"] | Where each param value came from (cli, default, fixed, override, prompt) | | run.config["git/"] | commit, branch, repo, dirty | | run.config["meta/"] | hostname, user, cwd, datetime, command, full_command, output_dir, env (secrets as **) | | run.summary | exit_code, duration_seconds, status, metrics | | Artifacts | Log files, code snapshot, artifact-type outputs | | Media | Videos and images from path- type params/outputs |

Using with Claude Code

This repo is also a Claude Code plugin marketplace. Install the lite-runner skill so Claude Code writes idiomatic run.py scripts and drives sweeps correctly:

/plugin marketplace add moonmath-ai/LiteRunner
/plugin install lite-runner@lite-runner-marketplace

See plugins/lite-runner/ for the plugin source.

Contributing

Interested in contributing? See CONTRIBUTING.md for development setup and guideline.

[codecov-badge]: https://codecov.io/gh/moonmath-ai/LiteRunner/graph/badge.svg [codecov-link]: https://codecov.io/gh/moonmath-ai/LiteRunner [github-discussions-badge]: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github [github-discussions-link]: https://github.com/moonmath-ai/LiteRunner/discussions [pepy-badge]: https://img.shields.io/pepy/dt/lite-runner [pepy-link]: https://pepy.tech/project/lite-runner [prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg [prs-welcome-link]: https://opensource.guide/how-to-contribute/ [pypi-link]: https://pypi.org/project/lite-runner/ [pypi-platforms-badge]: https://img.shields.io/pypi/pyversions/lite-runner [pypi-version-badge]: https://img.shields.io/pypi/v/lite-runner [template-badge]: https://img.shields.io/badge/%F0%9F%9A%80_Made_Using-tsvikas%2Fpython--template-gold [template-link]: https://github.com/tsvikas/python-template [tests-badge]: https://github.com/moonmath-ai/LiteRunner/actions/workflows/ci.yml/badge.svg [tests-link]: https://github.com/moonmath-ai/LiteRunner/actions/workflows/ci.yml

Related plugins

Browse all →