@labelbox/recursion-cli
v0.0.65
Published
`recursion` — the Recursion CLI. It mirrors the TypeScript SDK (`@labelbox/recursion-sdk`) exactly: where the SDK is `rl.synthesizers.create(...)`, the CLI is `recursion synthesizers create …`. Dots become spaces; you get `--help` at every level. The shor
Downloads
2,710
Maintainers
Keywords
Readme
@labelbox/recursion-cli
recursion — the Recursion CLI. It mirrors the TypeScript SDK
(@labelbox/recursion-sdk) exactly: where the SDK is rl.synthesizers.create(...), the
CLI is recursion synthesizers create …. Dots become spaces; you get --help at every
level. The short rl executable remains a permanently supported convenience alias and
runs the same command tree; documentation uses the canonical recursion spelling.
recursion --help # list nouns (synthesizers, synthesizer-runs)
recursion synthesizers --help # list verbs (create, get, list, …)
recursion synthesizers create --help # list flagsHow it works (fully live, zero per-operation code)
The CLI ships no baked API reference and has no @labelbox/recursion-sdk dependency.
On each run it revalidates the manifest from GET /cli/manifest when the server
selected by --base-url is reachable (production by default, or staging, or
localhost). If the server is unavailable, it falls back only to a locally cached
manifest that was previously validated. From that manifest it builds its entire
command tree, --help, request/response shapes, and docs browse surfaces
(src/manifest.ts). Dispatch is generic (src/dispatch.ts):
each request is built straight from the manifest operation's HTTP method + path
template + params + body — there is no hand-written command per operation and no
baked client.
The result: adding or changing a backend endpoint needs zero CLI release — the
live CLI reflects it as soon as the backend deploys. The CLI is re-released only when
its own engine code changes. When the server is reachable, the manifest is
revalidated on every run via a conditional fetch (ETag / If-None-Match) and cached
per base-url under ~/.cache/recursion/. When the server is unreachable, the CLI may
use the last locally validated copy so commands remain available offline. Validated
fresh HTTP 200 responses use atomic same-directory rename and therefore retain
last-network-writer behavior. Replacement preserves an existing file's POSIX mode
bits, but deliberately publishes a new inode and does not preserve its ACLs or
extended attributes. Publication requires parent-directory write/search permission;
if unavailable, the CLI keeps using the validated in-memory result and never falls
back to a partial direct write.
Docs browse surfaces
Beyond the executable recursion <noun> <verb> operations, the manifest carries the docs,
exposed as one consistent positional shape — recursion <group> [<id>] (bare lists, an id
shows that one):
recursion resources [<id>] # Reference — resource hubs: object shape, operations, recipes
recursion recipes [<id>] # How-to — multi-step user-goal guides (--format cli|ts|curl)
recursion explain [<concept>] # Explanation — concept pages
recursion tutorials [<id>] # Tutorials — getting-started docsInstall / run
Published to public npm as @labelbox/recursion-cli — no token, no repo access, no
setup beyond Node itself.
npm uninstall -g @recursion/cli @labelbox/rl-cli # no-op unless a pre-rename package is installed
npm install -g @labelbox/recursion-cli # old packages also own the `rl` alias — EEXIST otherwise
# or, zero-install:
npx --package @labelbox/recursion-cli recursion --helpThe CLI is standalone, so this pulls in no @labelbox/recursion-sdk.
Full setup steps and install-failure triage live in
apps/horizon/docs/public/docs/cli-getting-started.md — that page owns them; don't
restate them here.
The CLI is released independently of the SDK (it no longer depends on it): a
packages/cli/** change cuts a CLI release via the Release / CLI GitHub
Action — see yarn commands release.
From a monorepo checkout, run the bin directly without installing:
yarn workspace @labelbox/recursion-cli build
node ./packages/cli/dist/bin.js --helpAuth
Set LABELBOX_API_KEY in the environment, or pass --api-key <key>. Override the
host with --base-url <url> (defaults to the public Recursion API gateway, see
DEFAULT_BASE_URL in src/manifest.ts).
Flags
- Path / query params are individual flags:
--environment-id,--limit, … Required path and query params must be passed as flags. A query param whose type is an array or object (e.g.--models,--enrichment-filters) takes a JSON value (--models '["a","b"]'); its help text is tagged[pass as JSON]. - Operation headers declared by the API are individual flags too. Required
concurrency and replay controls therefore appear as
--if-matchand--idempotency-keyand are forwarded under their declared HTTP names. - Request body: scalar top-level fields are individual flags (
--name,--system-prompt, …); pass the full body — including complex fields likecontextInputs/targetFields— with--from-json <file>or--data <json>(mutually exclusive — pass only one). Scalar flags override values from--from-json/--data. A required scalar body field can be supplied by either its flag or the JSON body. - Output: prints the result as JSON by default. An operation may declare one
scalar response field as its direct output; those commands print only that
value in both normal and quiet mode (for example, the handoff-access command
prints its ephemeral URL). Otherwise,
--quietprints only the resulting resource'sid(a blank line for results without one, e.g. list or no-content operations).
recursion synthesizers get --synthesizer-job-id sj_01HX...
recursion synthesizers create --environment-id env_01HX... --from-json ./body.json
recursion synthesizer-runs trigger --problem-version-id pv_01HX... --from-json ./run.jsonThe command surface is the live server
There is nothing to regenerate or commit for the CLI — the command surface is
revalidated against the target server's GET /cli/manifest on every run when the
server is reachable, with a validated local-cache fallback when it is offline. A
backend change therefore flows through automatically after deploy with no CLI step.
The manifest itself is assembled by yarn generate cli:manifest (included in
yarn generate prerequisites) from the spec-derived reference files and embedded
into the backend; to add or change a command, change the backend @SdkRoute — not
this package.
The engine (manifest fetch + cache + validation, generic dispatch, flag mapping,
help formatting, the request-body / returns shape trees, and the docs browse
renderers) is verified by src/*.test.ts, which build the program from a fixture
manifest in-memory and assert the realized flags + --help + browse output — no
committed golden snapshot to maintain.
