ods is onyx.app's devtools utility script.
It is packaged as a python wheel and available from PyPI.
A stable version of ods is provided in the default python venv
which is synced automatically if you have pre-commit
hooks installed.
While inside the Onyx repository, activate the root project's venv,
source .venv/bin/activateSome commands require external tools to be installed and configured:
-
Docker - Required for
compose,logs, andpullcommands- Install from docker.com
-
uv - Required for
backendcommands- Install from docs.astral.sh/uv
-
GitHub CLI (
gh) - Required forrun-ci,cherry-pick, andtracecommands- Install from cli.github.com
- Authenticate with
gh auth login
-
AWS CLI - Required for
screenshot-diffcommands (S3 baseline sync)- Install from aws.amazon.com/cli
- Authenticate with
aws sso loginoraws configure
ods provides autocomplete for bash, fish, powershell and zsh shells.
For more information, see ods completion <shell> --help for your respective <shell>.
Linux
ods completion zsh | sudo tee "${fpath[1]}/_ods" > /dev/nullmacOS
ods completion zsh > $(brew --prefix)/share/zsh/site-functions/_odsods completion bash | sudo tee /etc/bash_completion.d/ods > /dev/nullNote: bash completion requires the bash-completion package be installed.
Launch Onyx docker containers using docker compose.
ods compose [profile]Profiles:
dev- Use dev configuration (exposes service ports for development)multitenant- Use multitenant configuration
Flags:
| Flag | Default | Description |
|---|---|---|
--down |
false |
Stop running containers instead of starting them |
--wait |
true |
Wait for services to be healthy before returning |
--force-recreate |
false |
Force recreate containers even if unchanged |
--tag |
Set the IMAGE_TAG for docker compose (e.g. edge, v2.10.4) |
Examples:
# Start containers with default configuration
ods compose
# Start containers with dev configuration
ods compose dev
# Start containers with multitenant configuration
ods compose multitenant
# Stop running containers
ods compose --down
ods compose dev --down
# Start without waiting for services to be healthy
ods compose --wait=false
# Force recreate containers
ods compose --force-recreate
# Use a specific image tag
ods compose --tag edgeView logs from running Onyx docker containers. Service names are available as arguments to filter output, with tab-completion support.
ods logs [service...]Flags:
| Flag | Default | Description |
|---|---|---|
--follow |
true |
Follow log output |
--tail |
Number of lines to show from the end of the logs |
Examples:
# View logs from all services (follow mode)
ods logs
# View logs for a specific service
ods logs api_server
# View logs for multiple services
ods logs api_server background
# View last 100 lines and follow
ods logs --tail 100 api_server
# View logs without following
ods logs --follow=falsePull the latest images for Onyx docker containers.
ods pullFlags:
| Flag | Default | Description |
|---|---|---|
--tag |
Set the IMAGE_TAG for docker compose (e.g. edge, v2.10.4) |
Examples:
# Pull images
ods pull
# Pull images with a specific tag
ods pull --tag edgeRun backend services (API server, model server) with environment loaded from
.vscode/.env. On first run, copies .vscode/env_template.txt to .vscode/.env
if the .env file does not already exist.
Enterprise Edition features are enabled by default with license enforcement
disabled, matching the compose command behavior.
ods backend <subcommand>Subcommands:
api- Start the FastAPI backend server (uvicorn onyx.main:app --reload)model_server- Start the model server (uvicorn model_server.main:app --reload)
Flags:
| Flag | Default | Description |
|---|---|---|
--no-ee |
false |
Disable Enterprise Edition features (enabled by default) |
--port |
8080 (api) / 9000 (model_server) |
Port to listen on |
Shell environment takes precedence over .env file values, so inline overrides
work as expected (e.g. S3_ENDPOINT_URL=foo ods backend api).
Examples:
# Start the API server
ods backend api
# Start the API server on a custom port
ods backend api --port 9090
# Start without Enterprise Edition
ods backend api --no-ee
# Start the model server
ods backend model_server
# Start the model server on a custom port
ods backend model_server --port 9001Run npm scripts from web/package.json without manually changing directories.
ods web <script> [args...]Script names are available via shell completion (for supported shells via
ods completion), and are read from web/package.json.
Examples:
# Start the Next.js dev server
ods web dev
# Run web lint task
ods web lint
# Forward extra args to the script
ods web test --watchManage the Onyx devcontainer. Also available as ods dc.
Requires the devcontainer CLI (npm install -g @devcontainers/cli).
ods dev <subcommand>Subcommands:
up- Start the devcontainer (pulls the image if needed)into- Open a zsh shell inside the running devcontainerexec- Run an arbitrary command inside the devcontainerrestart- Remove and recreate the devcontainerrebuild- Pull the latest published image and recreatestop- Stop the running devcontainer
The devcontainer image is published to onyxdotapp/onyx-devcontainer and
referenced by tag in .devcontainer/devcontainer.json — no local build needed.
Examples:
# Start the devcontainer
ods dev up
# Open a shell
ods dev into
# Run a command
ods dev exec -- npm test
# Restart the container
ods dev restart
# Pull latest image and recreate
ods dev rebuild
# Stop the container
ods dev stop
# Same commands work with the dc alias
ods dc up
ods dc intoManage PostgreSQL database dumps, restores, and migrations.
ods db <subcommand>Subcommands:
dump- Create a database dumprestore- Restore from a dumpupgrade/downgrade- Run database migrationsdrop- Drop a database
Run ods db --help for detailed usage.
Generate OpenAPI schemas and client code.
ods openapi allCheck that specified modules are only lazily imported (used for keeping backend startup fast).
ods check-lazy-importsPull requests from forks don't automatically trigger GitHub Actions for security reasons. This command creates a branch and PR in the main repository to run CI on a fork's code.
ods run-ci <pr-number>Example:
# Run CI for PR #7353 from a fork
ods run-ci 7353Cherry-pick one or more commits to release branches and automatically create PRs.
Cherry-pick PRs created by this command are labeled cherry-pick 🍒.
ods cherry-pick <commit-sha> [<commit-sha>...] [--release <version>]Examples:
# Cherry-pick a single commit (auto-detects release version)
ods cherry-pick abc123
# Cherry-pick to a specific release
ods cherry-pick abc123 --release 2.5
# Cherry-pick to multiple releases
ods cherry-pick abc123 --release 2.5 --release 2.6
# Cherry-pick multiple commits
ods cherry-pick abc123 def456 ghi789 --release 2.5Compare Playwright screenshots against baselines and generate visual diff reports. Baselines are stored per-project and per-revision in S3:
s3://<bucket>/baselines/<project>/<rev>/
This allows storing baselines for main, release branches (release/2.5), and
version tags (v2.0.0) side-by-side. Revisions containing / are sanitised to
- in the S3 path (e.g. release/2.5 → release-2.5).
ods screenshot-diff <subcommand>Subcommands:
compare- Compare screenshots against baselines and generate a diff reportupload-baselines- Upload screenshots to S3 as new baselines
The --project flag provides sensible defaults so you don't need to specify every path.
When set, the following defaults are applied:
| Flag | Default |
|---|---|
--baseline |
s3://onyx-playwright-artifacts/baselines/<project>/<rev>/ |
--current |
web/output/screenshots/ |
--output |
web/output/screenshot-diff/<project>/index.html |
--rev |
main |
The S3 bucket defaults to onyx-playwright-artifacts and can be overridden with the
PLAYWRIGHT_S3_BUCKET environment variable.
compare Flags:
| Flag | Default | Description |
|---|---|---|
--project |
Project name (e.g. admin); sets sensible defaults |
|
--rev |
main |
Revision baseline to compare against |
--from-rev |
Source (older) revision for cross-revision comparison | |
--to-rev |
Target (newer) revision for cross-revision comparison | |
--baseline |
Baseline directory or S3 URL (s3://...) |
|
--current |
Current screenshots directory or S3 URL (s3://...) |
|
--output |
screenshot-diff/index.html |
Output path for the HTML report |
--threshold |
0.2 |
Per-channel pixel difference threshold (0.0–1.0) |
--max-diff-ratio |
0.01 |
Max diff pixel ratio before marking as changed |
upload-baselines Flags:
| Flag | Default | Description |
|---|---|---|
--project |
Project name (e.g. admin); sets sensible defaults |
|
--rev |
main |
Revision to store the baseline under |
--dir |
Local directory containing screenshots to upload | |
--dest |
S3 destination URL (s3://...) |
|
--delete |
false |
Delete S3 files not present locally |
Examples:
# Compare local screenshots against the main baseline (default)
ods screenshot-diff compare --project admin
# Compare against a release branch baseline
ods screenshot-diff compare --project admin --rev release/2.5
# Compare two revisions directly (both sides fetched from S3)
ods screenshot-diff compare --project admin --from-rev v1.0.0 --to-rev v2.0.0
# Compare with explicit paths
ods screenshot-diff compare \
--baseline ./baselines \
--current ./web/output/screenshots/ \
--output ./report/index.html
# Upload baselines for main (default)
ods screenshot-diff upload-baselines --project admin
# Upload baselines for a release branch
ods screenshot-diff upload-baselines --project admin --rev release/2.5
# Upload baselines for a version tag
ods screenshot-diff upload-baselines --project admin --rev v2.0.0
# Upload with delete (remove old baselines not in current set)
ods screenshot-diff upload-baselines --project admin --deleteThe compare subcommand writes a summary.json alongside the report with aggregate
counts (changed, added, removed, unchanged). The HTML report is only generated when
visual differences are detected.
Download Playwright trace artifacts from a GitHub Actions run and open them
with playwright show-trace. Traces are only generated for failing tests
(retain-on-failure).
ods trace [run-id-or-url]The run can be specified as a numeric run ID, a full GitHub Actions URL, or omitted to find the latest Playwright run for the current branch.
Flags:
| Flag | Default | Description |
|---|---|---|
--branch, -b |
Find latest run for this branch | |
--pr |
Find latest run for this PR number | |
--project, -p |
Filter to a specific project (admin, exclusive, lite) |
|
--list, -l |
false |
List available traces without opening |
--no-open |
false |
Download traces but don't open them |
When multiple traces are found, an interactive picker lets you select which
traces to open. Use arrow keys or j/k to navigate, space to toggle,
a to select all, n to deselect all, and enter to open. Falls back to a
plain-text prompt when no TTY is available.
Downloaded artifacts are cached in /tmp/ods-traces/<run-id>/ so repeated
invocations for the same run are instant.
Examples:
# Latest run for the current branch
ods trace
# Specific run ID
ods trace 12345678
# Full GitHub Actions URL
ods trace https://github.com/onyx-dot-app/onyx/actions/runs/12345678
# Latest run for a PR
ods trace --pr 9500
# Latest run for a specific branch
ods trace --branch main
# Only download admin project traces
ods trace --project admin
# List traces without opening
ods trace --listBoth run-ci and cherry-pick support --dry-run to test without making remote changes:
# See what would happen without pushing
ods run-ci 7353 --dry-run
ods cherry-pick abc123 --release 2.5 --dry-runTo upgrade the stable version, upgrade it as you would any other requirement.
Generally, go build . or go install . are sufficient.
go build . will output a tools/ods/ods binary which you can call normally,
./ods --versionwhile go install . will output to your GOPATH (defaults ~/go/bin/ods),
~/go/bin/ods --versionTypically, GOPATH is added to your shell's PATH, but this may be confused easily during development
with the pip version of ods installed in the Onyx venv.
To build the wheel,
uv build --wheelTo build and install the wheel,
uv pip install .Releases are deployed automatically when git tags prefaced with ods/ are pushed to GitHub.
The release-tag package can be used to calculate and push the next tag automatically,
tag --prefix odsSee also, .github/workflows/release-devtools.yml.