Momentum customer CLI + experiment-logging SDK — authenticate, upload field data, and report training runs to your workspace.
Project description
flywheel-cli
The Momentum customer CLI + experiment-logging SDK: authenticate and bulk-upload field data straight to your workspace's storage bucket, and report training/eval runs from your own compute into your workspace's experiment tracker.
PyPI distribution: ydderd-momentum-cli · Homebrew formula: momentum-cli · command: momentum.
(The clean momentum-cli PyPI name was taken, so the distribution carries the ydderd- prefix;
the import package momentum_cli, the momentum command, and the brew name are unaffected.)
Why this is a separate package
The CLI talks to the Momentum API purely over HTTP (and to R2 over S3). It shares no Python
code with the backend, so it ships with a tiny dependency set — httpx + boto3 — instead of
the full server stack (torch, opencv, fastapi, …). That keeps the install small and avoids
shipping the backend's AGPL detector to customers.
Install
brew install ydderd/flywheel/flywheel-cli
# or:
pipx install ydderd-momentum-cli
flywheel --help
Usage
momentum auth login # opens a browser; a workspace admin approves
momentum auth whoami # confirm tenant
momentum upload ./your-data --scan # bulk upload + trigger ingest
flywheel ingest status # ingest ledger stats
momentum eval submit --model hf://lab/pi05-fast --benchmark bench_roboarena@3 # open an eval run, print URL
flywheel trials log --policy hf://lab/pi05-fast --n 20 --successes 14 --calibration-set pcsk-…
flywheel trials log --csv trials.csv # bulk floor tallies (per-row partial success)
flywheel secrets set lab-bucket # store a secret (value from stdin); prints its creds_ref
flywheel secrets list # secret names + configured (never values)
upload always writes to your workspace's one raw prefix — there's no target to choose. Whether
what you uploaded is raw drone video (needs extraction) or already-extracted frames is classified
server-side once it lands, not by the client beforehand.
For headless/CI use, skip the browser with a token minted by a workspace admin:
momentum auth login --token <fw_cli_…>.
Config is stored at ~/.flywheel/config.json. Auth precedence: MOMENTUM_CLI_TOKEN env >
config file.
Experiment-logging SDK
Training and eval runs executed on your own compute (Modal, Brev, a lab box) report themselves into your workspace's experiment tracker — W&B-style, and safe to leave in production training code (a logging failure never raises into the train):
import momentum_cli as momentum
run = momentum.init(name="my_sft_run", tags=["sft"], config={"iters": 800, "lr": 2e-4},
provider="modal")
run.log({"train/loss": 0.42}, step=100)
run.finish(status="succeeded", checkpoint_ref="r2://bucket/ckpt", cost_usd=295.26)
# later — scoring results and billed cost arrive after the train, so annotation
# works on finished runs:
momentum.annotate(run.id, results={"auroc": {"value": 0.61, "ci": [0.55, 0.67]}})
Eval runs (policy context — the CI-integration path)
An eval process (a lab rig, Modal, the robot) evaluates model × benchmark@version and streams its
rollouts back. Same never-raise/heartbeat/reattach posture as training runs; rollouts buffer and flush
in batches, each with a client-generated id so a re-sent batch is idempotent:
ev = momentum.eval_run(benchmark="bench_roboarena@3", model="hf://lab/pi05-fast", seeds=3)
ev.log_rollout(scenario="scn_pick", seed=0, status="success",
scorer={"success": True, "task_progress": 1.0}, latency_p50=61.0)
ev.log_rollout(scenario="scn_pick", seed=1, status="fail", scorer={"success": False})
ev.finish() # flushes any buffered rollouts first
ev.annotate(results={"headline": {"value": 0.5, "ci": [0.31, 0.69]}}) # post-hoc scoring
eval_run() prints the run URL on create; eval_run(run_id=…) (or MOMENTUM_EVAL_RUN_ID) reattaches
after a preemption. Runs land in the UI under Eval runs.
Real trials (floor tallies → calibration audit)
Report real-robot trials of a policy; landing trials that ground a calibration set recomputes that world model's τ/ρ trust:
momentum.real_trials.log(policy="hf://lab/pi05-fast", scenario="scn_pick",
n=20, successes=14, operator="alice", calibration_set="pcsk-…")
report = momentum.real_trials.log_csv("trials.csv") # a path or raw CSV text; per-row partial success
print(report["accepted"], report["rejected"])
Secrets & referenced episodes
Register an episode that lives in your own bucket by first storing its credentials in the tenant secret
store (Fernet-encrypted at rest; the value is never returned by a read), then passing the returned
creds_ref:
ref = momentum.secrets.set("lab-bucket", '{"access_key": "…", "secret_key": "…"}') # → "secret://lab-bucket"
momentum.episodes.register("s3://lab-corpus/session_042", creds_ref=ref)
momentum.secrets.list() # {name: {configured: bool}}, incl. provider keys under provider:<name>
Auth: MOMENTUM_API_KEY env (a fw_cli_… token — inject it as a secret in your training
environment), falling back to the token saved by momentum auth login. MOMENTUM_API_URL
overrides the API endpoint. with momentum.init(...) as run: (and momentum.eval_run(...)) marks the
run failed (with the exception) if the block raises. Runs land in the workspace UI under
Experiments / Eval runs.
Release/consumption mechanics (PyPI, git-ref installs, versioning): see PUBLISHING.md.
Developer notes
These knobs exist for Momentum developers and are intentionally hidden from customer-facing help and docs:
--api-url <url>onmomentum auth login— persist a non-production API base URL to the config (e.g. a local API). Hidden viaargparse.SUPPRESS.MOMENTUM_API_URLenv — override the API base per-invocation. Takes precedence over the config file.
Precedence for the API base URL: MOMENTUM_API_URL env > api_url in config > default
(https://flywheeling.fly.dev/api — swap to a custom domain once one is live).
Point the CLI at a local backend during development:
MOMENTUM_API_URL=http://localhost:8000 momentum auth whoami
# or persist it:
momentum auth login --token <fw_cli_…> --api-url http://localhost:8000
Local development
cd cli
uv sync
uv run flywheel --help
uv run pytest
Releasing (PyPI + Homebrew)
PyPI is the source of truth; the Homebrew formula wraps the published PyPI sdist.
1. Publish to PyPI — via GitHub Actions (Trusted Publishing, no token)
The .github/workflows/publish-cli.yml workflow builds and publishes over OIDC. Cut a release
by pushing a namespaced tag from the monorepo default branch:
git tag cli-v0.1.0 && git push origin cli-v0.1.0
The PyPI project is ydderd-momentum-cli, published from ydderd/flywheel via the pypi
environment. (First publish activates the "pending" Trusted Publisher and creates the project.)
2. Update the Homebrew tap formula
After the PyPI release exists, point release.sh at your tap checkout — with SKIP_PUBLISH=1
it skips the upload and only fetches the published sdist's url/sha256, rewrites the formula,
and regenerates its Python resource blocks:
SKIP_PUBLISH=1 \
FORMULA_PATH=/path/to/homebrew-momentum/Formula/flywheel-cli.rb \
cli/scripts/release.sh
Then commit + push the tap. Customers install with:
brew install ydderd/flywheel/flywheel-cli
release.shcan also publish to PyPI itself (UV_PUBLISH_TOKEN=pypi-… cli/scripts/release.sh) if you prefer a token-based local release over the GitHub Action.
Bumping a release: change version in pyproject.toml, push a new cli-v* tag, then re-run
step 2.
Project details
Release history Release notifications | RSS feed
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 ydderd_momentum_cli-0.5.0.tar.gz.
File metadata
- Download URL: ydderd_momentum_cli-0.5.0.tar.gz
- Upload date:
- Size: 59.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa26efe8aa3498bf0c5a54fd73ad4925f411664f16bcd38260856a55f0733bfb
|
|
| MD5 |
5374d0c3795566fc9f9a6526ff99b2c1
|
|
| BLAKE2b-256 |
125a6eb52e2ba96ea721991d905dded58a580c51c0ef69f132fb613622211db9
|
Provenance
The following attestation bundles were made for ydderd_momentum_cli-0.5.0.tar.gz:
Publisher:
publish-cli.yml on ydderd/momentum
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ydderd_momentum_cli-0.5.0.tar.gz -
Subject digest:
aa26efe8aa3498bf0c5a54fd73ad4925f411664f16bcd38260856a55f0733bfb - Sigstore transparency entry: 2165386269
- Sigstore integration time:
-
Permalink:
ydderd/momentum@4da6d5a714525855076a25e3625fcc1758684bd7 -
Branch / Tag:
refs/tags/cli-v0.5.0 - Owner: https://github.com/ydderd
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-cli.yml@4da6d5a714525855076a25e3625fcc1758684bd7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ydderd_momentum_cli-0.5.0-py3-none-any.whl.
File metadata
- Download URL: ydderd_momentum_cli-0.5.0-py3-none-any.whl
- Upload date:
- Size: 40.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65094fbbc6e8e7eeadcbf781b552f0d6096dd84d21272ee96bceb0a97a9e9b8e
|
|
| MD5 |
4aced200a2bfbf187a8d39692f502685
|
|
| BLAKE2b-256 |
e40389968b4ddabcc64647a3a2801e2374b770ca5ecb87ca2e9e2937c946acc1
|
Provenance
The following attestation bundles were made for ydderd_momentum_cli-0.5.0-py3-none-any.whl:
Publisher:
publish-cli.yml on ydderd/momentum
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ydderd_momentum_cli-0.5.0-py3-none-any.whl -
Subject digest:
65094fbbc6e8e7eeadcbf781b552f0d6096dd84d21272ee96bceb0a97a9e9b8e - Sigstore transparency entry: 2165386280
- Sigstore integration time:
-
Permalink:
ydderd/momentum@4da6d5a714525855076a25e3625fcc1758684bd7 -
Branch / Tag:
refs/tags/cli-v0.5.0 - Owner: https://github.com/ydderd
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-cli.yml@4da6d5a714525855076a25e3625fcc1758684bd7 -
Trigger Event:
push
-
Statement type: