* feat: warn on every command when the CLI is outdated
Every orx command now prints a warning to stderr when the running version
is behind the latest release, because the backend API is versioned and a
stale client can hit breaking changes. The message escalates with the gap:
a breaking (pre-1.0 minor / post-1.0 major) gap warns that commands can
start failing now; a smaller gap is a gentler upgrade nudge.
This reworks the existing interactive-only update nudge:
- Shows on every command (piped/scripted/CI too), not just interactive
terminals; ORX_NO_UPDATE_CHECK / NO_UPDATE_NOTIFIER /
OPENRESEARCH_CLI_DISABLE_UPDATE=1 silence it.
- Prints in start() before the command runs, so it shows even for commands
that std::process::exit on their own (e.g. the not-logged-in path).
- Latest version still comes from the cached prior check (instant, zero
latency); a fire-and-forget background task refreshes the cache, given a
brief grace window in finish() to commit before the runtime tears down.
- Cache write is now atomic (temp + rename) so concurrent orx processes
never read a torn file.
- Version comparison ignores build metadata (semver's Ord compares it, the
spec says it shouldn't) to avoid a false 'outdated' on local builds.
Excludes the version/update commands, which manage updates themselves.
* feat: bold the warning label on a TTY and set it off in its own block
The outdated-version warning now prints with a blank line above and below
so it reads as its own block, and bolds just the `Warning:` label
(gh/cargo-style) when stderr is an interactive terminal. Pipes, files, and
CI logs stay plain text — the ANSI is gated on `stderr().is_terminal()`
and honors NO_COLOR — so non-interactive output never gets raw escape codes.
Hand-rolled \x1b[1m/\x1b[22m (no color dependency, matching the codebase's
plain-text style); `render`/`bold` are pure and unit-tested.
* refactor: apply review findings (CI latency, label const, doc cleanup)
From the multi-agent code review:
- finish() now skips the 250ms refresh wait when stderr isn't a terminal.
In ephemeral CI (fresh config dir per run) the cache is always cold, so
the wait warmed a cache that's immediately discarded — pure per-call cost
across a pipeline. The refresh is still spawned; we just don't wait. The
warning still prints on every command. Interactive runs keep the wait so
the cache warms for the next command.
- Hoist a shared WARNING_LABEL const used by both warning_for (builder) and
render (styler), so the bolded label can't silently drift from the emitted
prefix on a copy edit.
- Drop the now-inaccurate "passive" framing from the module header, section
banner, struct doc, and main.rs wiring comment (the warning is always-on).
- s/nudge/update check/ in the version/update command comments.
- Add prerelease-axis tests for warning_for (rc-behind-final is soft, a
cross-minor prerelease is breaking, a local dev prerelease ahead is silent).
* simplify: drop the breaking/soft warning tiers, always show one message
Per request, remove the two-tier distinction entirely. The warning no longer
classifies the version gap as breaking vs. non-breaking — every outdated client
gets the same calmer message:
Warning: orx X is outdated (latest Y). A newer release is available; upgrade
to stay compatible with the API. Run `orx update` to upgrade.
Deletes `is_breaking_gap` (and its RE-CONFIRM-AT-1.0 note), the second message
arm in `warning_for`, and the tier-specific tests; collapses the gap-coverage
tests into one that asserts the single message fires for every kind of gap.
`precedence` (the build-metadata comparison guard) is unrelated and stays.
* feat: add --provider to exp run and a standalone `orx instance create`
Two ways to spin up compute from any provider, not just RunPod:
- `orx exp run --provider <name>` provisions an experiment run on the
chosen provider (omit = server default, RunPod).
- `orx instance create <orgId> (--gpu ... | --cpu ...)` spins up a
standalone org-level instance via POST /sandboxes — the CLI equivalent
of the dashboard's "Spin up" panel (omit --provider = cheapest offer).
* chore: bump version to 0.1.29
The backend `GET /compute/catalog` wire format changed: each offer's flat
`diskPerGbHour` became a nested `disk` discriminated union, `region` became
optional, and new `bandwidth*` fields were added. The CLI decodes strictly, so
the missing `disk_per_gb_hour` field broke `orx compute` (and `--cpu`) at JSON
decode. This fixes the deserialization and broadens the command:
- Add a `Disk` struct mirroring the backend `zDisk` union (keyed on the
`sizable` bool, optional payloads), replacing `disk_per_gb_hour` on both
`GpuOffer` and `CpuOffer`. Round-trip tests pin both disk shapes, a missing
region, and the ignored `bandwidth*` fields.
- Remove the RunPod-only filter so the catalog shows every configured provider
and region; add a case-insensitive `--provider` filter.
- Add a DISK column to the GPU and CPU tables.
`orx exp run` new instances remain RunPod-only server-side; docs clarify that
`orx compute` now browses all providers regardless.
* Add Cursor to install-skills
Cursor discovers skills under ~/.cursor/skills/<name>/SKILL.md using the
same Agent Skills format as Claude Code, so it reuses the existing shim.
Detected via ~/.cursor like the other agents, so login auto-install now
covers Cursor-only machines (previously they relied on Cursor scanning
~/.claude/skills, which only helps if Claude Code is also installed).
* 0.1.20
* Make the post-login skill install consent-based
orx login no longer writes into agent config dirs unprompted. When run
interactively it lists exactly what would be installed — file count and
name -> path per detected agent — and asks [Y/n]; nothing is written
without a yes. Non-TTY (CI, agents, pipes) skips the offer entirely.
Explicit orx install-skills is unchanged.
* Remove orx diff; compute run diffs locally via the cache-dir clone
- Delete the diff command and its client plumbing (the server endpoint
stays for the web UI).
- orx exp status now prints the node's branch, the parent's branch, the
latest run's full commit SHA, and a ready-to-paste local git diff
recipe (owner/repo resolved via a new find_project client helper).
- SKILL.md/README: the clone in ~/.cache/openresearch/repos is the
standard way to read, diff, and edit experiment code.
- Bump version to 0.1.17.
* Add clone-if-missing guard to local diff recipes
The diff recipe (SKILL.md and the one orx exp status prints) started at
git fetch, which fails on a cold cache. Prepend the same idempotent
guard the editing recipe uses.
- `orx --version` (clap) and `orx version [--check] [--json]`: prints the
CLI version and compares it to the latest GitHub release. `--json` is
the agent-facing form (stable stdout object, exit 0 either way).
- `orx update [--dry-run] [--force]`: updates in place by re-running the
cargo-dist release installer pinned to the existing install prefix
(CARGO_DIST_FORCE_INSTALL_DIR), the same mechanism as axoupdater/uv but
without the native-tls dependency that conflicts with our musl builds.
Guarded by the cargo-dist install receipt (refuses cargo-install copies,
path/version mismatches, Nix/Homebrew paths, unwritable bin dirs), an
exclusive flock against concurrent updates, and run via `sh script` so
noexec /tmp mounts don't break it.
- Passive nudge: at most one background latest-version check per 24h
(cached in the config dir), printed to stderr only on interactive
terminals, never in CI/pipes, never altering exit codes. Opt out with
ORX_NO_UPDATE_CHECK, NO_UPDATE_NOTIFIER, or OPENRESEARCH_CLI_DISABLE_UPDATE=1.
Latest-version discovery uses the releases/latest/download/dist-manifest.json
permalink (CDN redirect, no GitHub API rate limit) instead of the REST API,
whose 60 req/h/IP unauthenticated cap is routinely exhausted on the
datacenter IPs agents run from.
Drop the --repo/--ref flags and the empty-baseline path. A project's repo is
now bound at project-creation time on the web, so create-experiment has two
shapes: a child off --parent, or a baseline materialized on the project's
already-bound repo. Replace CreateEmptyBaselineBody/import-from-repo wiring
with a simplified ImportBaselineBody (optional title/description plus
generateSuggestions).