@labelbox/recursion-cli
v0.2.0
Published
Command-line client for the Recursion platform
Maintainers
Keywords
Readme
@labelbox/recursion-cli
Preview command-line client for the Recursion platform. It projects every
CLI-compatible deployed enterprise public preview operation from
apps/managed-agents/api/src/openapi/recursion-public-openapi.preview.generated.json as
one finite recursion managed-agents <command> route. It has no Horizon import,
live manifest, hidden generic route, or Labelbox credential fallback. Three
handwritten commands, validate, plan, and apply, reconcile a checked-in
agent folder through those same public operations. A fourth,
agent-skills, reads an agent's skills as the model is shown
them. Two top-level commands, run-automation and wait-automation-run,
run an automation and wait for its result. The documentation commands and
skills need no API key.
Versions remain below 1.0.0 while the platform API and CLI are changing and
may include breaking changes. For launch workloads, use the Recursion web app
or MCP unless you explicitly accept the preview client lifecycle.
See the client preview upgrade notes before updating an integration.
npm install --global @labelbox/[email protected]The exact version above selects the published enterprise client during the
latest takeover. The enterprise CLI publishes to npm latest starting with
the qualified 0.2.0 release. Use an unqualified install only after that
publication is verified. See the
upgrade notes
for publication status and migration from the Horizon-era 0.0.x CLI. Pin an exact
version when an integration needs reproducible installs, or
run the CLI from a repository checkout.
With RECURSION_API_KEY already present in the environment:
recursion managed-agents list-agents-v2
recursion managed-agents get-agent-v2 --input-file request.jsonUse the -v2 catalog commands for new integrations. The matching v1 commands
remain available for compatibility while their endpoints are deprecated.
The production origin defaults to https://api.recursion.labelbox.com.
--organization-id and --tenant-id are global client selectors and cannot be
overridden inside operation JSON. Operation input is an exact SDK envelope:
path, query, and declared header fields are top-level properties and a JSON
request body is under body. Read it from --input-file <path> or standard
input with --input-stdin; request data is never accepted in process arguments.
The API key is read only from RECURSION_API_KEY; no API-key CLI option exists.
Custom API origins must use HTTPS. Plain HTTP is accepted only for exact local
development hosts: localhost, 127.0.0.1, and [::1].
Automation contract
Operation stdout and stderr are newline-delimited JSON; --help, --version,
and the documentation and skills commands without --json are the plaintext
stdout exceptions. Success is { "ok": true, "data": ... };
failure is { "ok": false, "error": ... }. Response payload object keys are
normalized deterministically, binary responses use the explicit
$recursionBinary base64 envelope, and structured API status, code, details,
and retry metadata are preserved. Input errors exit 2, request errors exit 1,
and a closed stdout pipe terminates without printing a misleading request
failure.
The two canonical session streams emit one success line per SSE record and honor stdout backpressure. Operations with declared ETag caching retain the response ETag and represent a valid 304 explicitly rather than treating it as a failure.
Documentation
recursion recipes
recursion recipes run-an-agent-session [--format cli|curl]
recursion explain [<concept>]
recursion tutorials [<id>]
recursion resources [<id>]
recursion managed-agents create-agent --helpThese commands read the docs catalog: the recipes, each proven against
production on a schedule, with their steps and runnable CLI or cURL code; the
API operations grouped by resource; and the concept and tutorial guides.
recursion --help groups them apart from the commands that act.
The catalog comes from GET <origin>/docs-catalog.json (the --base-url or
RECURSION_API_URL origin, public, no API key) with a 5-second timeout. It is
cached per host in $XDG_CACHE_HOME/recursion/ (default ~/.cache/recursion/),
used unchecked for the response's max-age, then revalidated by ETag. When the
API cannot be reached or answers with something unreadable, the cache answers,
and without one the copy bundled with the CLI does.
Output is text; --json prints { "ok": true, "data": ... } with the catalog
entry or list. A recipe's Related links print as the recursion recipes,
recursion explain, and recursion tutorials commands that open them. An
unknown id exits 2 and names near matches.
recursion managed-agents <command> --help reads only the bundled copy, so help
never waits on the network: the command's input fields (top-level path, query,
and header fields, then body fields, with type, whether required, allowed
values, and description) and a minimal example input, both derived from its JSON
schema, then the recipes that use it.
src/generated/docs-catalog.generated.ts is ignored and materialized by
yarn generate prerequisites. yarn generate recursion:docs-catalog regenerates
all catalog copies; its --check flag checks the tracked API and web copies.
Do not edit the generated copies.
Agent skill
recursion skills install [--agent claude|codex|all] [--force]
recursion skills check [--agent claude|codex|all]install writes the catalog's recursion skill to
~/.claude/skills/recursion/SKILL.md and ~/.codex/skills/recursion/SKILL.md
(both by default), with a skill-version: <version> line added to its
frontmatter. Run again, it replaces a copy of an older version it installed and
leaves a copy edited by hand alone unless --force. check reports each copy
as installed-current, installed-stale, installed-modified, or missing.
Both read the catalog as the documentation commands do, so a newer skill the API
serves updates stale copies, and both exit 3 when a copy does not end current.
Agent folders
recursion managed-agents validate agents/field-agent
recursion managed-agents plan agents/field-agent --target canary
recursion managed-agents apply agents/field-agent --target canary
recursion managed-agents export "Field Agent" agents/field-agent-copyAn agent folder declares one managed agent as files: an agent.yaml manifest,
the Markdown and shell files it references, and optional targets/<name>.yaml
overlays. The three commands use the same global options and
RECURSION_API_KEY as every other command, so the organization is chosen by the
caller and never written in the folder. agents/ at the repository root holds
the checked-in folders.
| Command | Network | Result |
| --- | --- | --- |
| validate <folder> | None. Needs no API key and builds no client. | Checks the manifest, every referenced file, and every target, or only --target. |
| plan <folder> --target <name> | Reads only. | Reports each resource, its action, and the names of the fields that differ. |
| apply <folder> --target <name> | Reads, then writes. | Makes the organization match. A second apply writes nothing. |
| export <agent> <folder> | Reads only. | Writes a live agent version as a new agent folder that apply can recreate in another organization. |
--target is required for plan and apply whenever the folder has a
targets/ directory.
Exporting an agent
export takes an agent id or exact name and a folder that does not exist yet
or is empty. --agent-version <number> picks a version (default: the latest),
--environment <name> declares that environment in the folder, and
--key <key> sets the manifest key (default: derived from the agent name).
The folder references vaults and credentials by name only and carries no
organization or resource id, secret, or ownership marker. Each selected
credential becomes an exact expectation (its name or secret name, type and
permission), so apply refuses a target where it matches none or several.
Skills are expanded the way a session loads them. MCP servers keep their tool
allowlist; their headers are dropped, since a header may carry a secret.
Without --environment, the folder declares a new Runs environment named after
the key.
What a folder cannot declare is listed instead of written: integrations, model
settings, the template, file history, the concurrent session limit, the default
project and evaluator, metadata, memory settings, team members that are other agents, skills with bundled files, and vaults with no nameable selected
credential. Each item
is one not_exported output line and is repeated as a comment at the top of
agent.yaml. The folder is validated before it is moved into place, so a
failure leaves nothing behind. Apply it into a fresh organization: an omitted
field such as the rubric leaves an existing agent's live value alone.
Output and exit codes
Output is the newline-delimited JSON of the automation contract.
plan and apply print one target line naming the manifest, the target, and
the organization the API resolved; one resource line per resource with its
kind, name, action, and changed fields; and one summary line with
changes, inSync, and writes. Lines carry names and field names only, never
a prompt, a script, an id, or any other field value.
Actions are create, update, adopt, unchanged, no_longer_managed, and,
for the resources a manifest only references, verified, missing, and
ambiguous.
| Exit code | Meaning |
| --- | --- |
| 0 | validate passed, plan found the organization in sync, or apply converged. |
| 1 | A request failed, a required reference is missing or ambiguous, or setup verification did not pass. |
| 2 | The arguments or the folder are invalid. |
| 3 | plan found differences. |
Manifest reference
agent.yaml is strict YAML: an unknown field, a duplicate key, an anchor, or an
alias is an error. Every path is relative to the folder and must stay inside
it, symlinks included. A referenced file is UTF-8 and at most 512 KiB; a YAML
file is at most 64 KiB. Any value or line shaped like a credential is refused.
| Field | Meaning |
| --- | --- |
| version | 1. |
| key | Lowercase manifest key. It is the first part of every ownership marker, so changing it disowns the existing resources. |
| agent.name, agent.model, agent.webSearch | Required. The model must be one the organization lists. |
| agent.description | Optional. Omitted leaves the live description alone. |
| agent.systemPromptFile | The system prompt. Trailing whitespace is not sent and is never a difference. |
| agent.rubricFile | Optional. A Markdown rubric of at most 256 KiB with at least one list item; each list item is one criterion. Every session of the agent that starts with a message is graded against it by default. Omitted leaves the live rubric alone, and an empty file clears it. Trailing whitespace is never a difference. |
| agent.multiagent | Optional complete portable roster: type: coordinator, agents containing self entries (optional name), optional team, limits, and slack_reply_review: {model}. Omitted preserves the live roster; declared owns the whole value. All declared models are checked before writes. Catalog agent references remain console-managed because folder declarations contain no resource IDs. |
| agent.oversight | Optional complete oversight block: advisor and supervisor (each optional mode and model) and interventionist (optional mode). A mode is off, shadow or active; omitted, it is the deployment's default. A peer without model runs on the agent's model. Omitted preserves the live block; declared owns the whole value. Peers that run on another agent remain console-managed, and export refuses an agent whose block names one (oversight.<implementation>.agent). |
| agent.mcpServers | name and HTTPS url pairs, compared in any order. Optional headers (static, non-secret header names to values sent on every request to the server; names the platform sets, such as Authorization, are refused at apply) and optional allowedTools (at least one tool name; a session is offered only those tools of the server), and optional approval (tools: 1 to 64 distinct tool names, each also in allowedTools when that is set, or ['*']; approvers.slackUserIds: 1 to 25 distinct Slack user ids who must approve each exact call before a gated tool runs). A secret belongs in a vault credential bound to the same URL. A header, allowlist or approval change alone publishes a new agent version. |
| agent.disabledIntegrationMcpProviders | Integration providers whose MCP tools sessions do not receive. |
| agent.skills | name and optional displayTitle, in the order the agent lists them: a reorder alone publishes a new agent version. Each is exactly skills/<name>/SKILL.md, whose frontmatter name must equal the directory; bundled skill files are not supported. |
| agent.defaultVaults | Names from vaults. The agent defaults to these vaults, narrowed to the credentials the manifest expects. |
| environment.name, environment.provider | Required. provider is runs or docker. |
| environment.setup | scriptFile and timeoutSeconds (10 to 3600, default 600). Omitted leaves setup alone. |
| environment.onCreate | networkPolicy and privileged, sent only when the environment is created. |
| environment.image | Optional expectation. The platform assigns the image; a difference is noted on the resource line and never written. |
| vaults | Required vaults by name, each with expected credentials: a type plus any of name, namePrefix, nameContains (one of these, case-insensitive for nameContains), permission, provider (an env_var credential's proxied service, such as github_packages_npm; a credential whose secret would reach the sandbox does not match), and secretName. |
| automation.name, automation.promptFile | The automation's display name and literal opening prompt. |
| automation.vaults | Names from vaults granted to every run, limited to the credentials their expectations matched, as agent.defaultVaults is; apply replaces a console credential selection. Omitted leaves the grant to the agent's defaults and the operator. |
| automation.triggers | Slack and schedule triggers, each with a stable UUID id. A Slack trigger has type: slack, events, channels, botEvents, and optional ignoreThreadReplies, fromUserIds (Slack user or bot IDs), fromUserGroupIds and notFromUserGroupIds (Slack user-group IDs), textMatches (case-insensitive RE2 pattern), classifier (an AI filter: question, answers of value and description, and a rule of when (wake or skip) and conditions, each an answer and an atLeastPercent (5 to 95); any condition holding does when, none holding does the opposite. Optional mode of preview or on (default preview) and send of text_and_images or text; null removes a console-set one), allowSharedChannels, continuation (new_session or resume_thread), firstResponse (none or platform), and enabled; every Slack trigger must agree on continuation and firstResponse. With platform, a message trigger's automatic root that mentions nobody gets its acknowledgement, reaction and native status at the agent's first tool call rather than at dispatch, so an informational post the agent leaves alone shows nothing; mentions are acknowledged at dispatch. A schedule trigger has type: schedule, a five-field cron, an IANA timezone, and optional overlapPolicy (default skip), jitterSeconds (default 10), catchupWindowSeconds (default 900), and enabled. |
targets/<name>.yaml holds the values that differ between rollouts of the same
resources:
| Field | Meaning |
| --- | --- |
| slackEventSource | Display name of the Slack event source the Slack triggers listen on. Required when the manifest has Slack triggers. |
| channels | Named lists of Slack channel ids. A trigger's channels names one; an empty list accepts every channel, or, when several organizations share the Slack workspace, every channel no other organization lists (runbook). Every list must be used. |
Targets are overlays, not identities: two targets applied to one organization reconcile the same agent, environment, skills, and automation.
Ownership and adoption
Every resource a manifest owns carries the metadata key recursion_managed:
| Resource | Marker value |
| --- | --- |
| Agent | <key>:agent |
| Environment | <key>:environment |
| Automation | <key>:automation |
| Skill | <key>:skill:<skill name> |
Ids are derived from the marker on every run by listing the organization, every page of it. Nothing is stored in the folder and there is no state file.
- Exactly one resource carrying the marker is the resource, whatever it is named now.
- With none, exactly one unmarked resource of the declared name is adopted: it is stamped with the marker and updated in place.
- With none of either, the resource is created.
- Two or more candidates stop the run before any write.
Vaults, credentials, the Slack event source, and the model are references, not
owned resources. They are resolved by name and verified before the first write
and are never created, changed, or marked. A missing or ambiguous one fails
plan and apply with exit code 1. Credential values are never read.
Nothing is ever deleted. A skill or automation that still carries the marker
after the manifest stopped declaring it is reported as no_longer_managed.
What apply writes, and what stays the operator's
After every reference and ownership lookup has resolved, apply writes in
dependency order:
- Environment. Created or patched, then verified: a new or changed setup starts a setup run and waits for its verdict, and a failed verdict stops the run before the agent is written.
- Skills. A new skill version only when the SHA-256 of
SKILL.md, the display title, or the marker differs. - Agent. A new agent version only when a declared field differs, written as a compare-and-swap on the version that was read. A lost race is answered by reading and diffing again, once.
- Automation. Created paused. An existing one is replaced under its
ETagwithIf-Match, with one re-read on a stale validator, and itsagentVersionIdmoves to the agent's latest version.
An apply that fails partway is repaired by running it again: each step diffs live state before writing.
These are read and carried through unchanged, or never sent:
- The environment's network policy and Docker privilege after creation.
- The agent's
built_in_integrations,nativeIntegrations,model_config,multiagentandoversightwhen undeclared,template,fileHistoryEnabled, andmax_concurrent_sessions,defaultProjectId,defaultEvaluatorAgentId, and any extra keys on a declared MCP server. - Every metadata key other than
recursion_managed. - The automation's paused or active status, and its run defaults other than
vaultIds. - On each Slack trigger, matched by its id: the
textContainsandtextExcludesfilters and theworkspaceIdsrouting restriction. The folder ownsfromUserIds,fromUserGroupIds,notFromUserGroupIds,textMatchesandclassifierwhen it declares them; otherwise their live values are carried through an apply. Declaringclassifier: nullremoves a console-set AI filter. - Every trigger of a type the folder cannot declare, such as a webhook or
GitHub trigger added in the console. Member-DM Slack triggers are also carried
whole: agent folders cannot declare them, and a declared trigger with the
same id is rejected before writes. When one is present, declared Slack
triggers must use
continuation: resume_threadandfirstResponse: none; a conflicting folder is rejected before writes. Manage these bindings through the automation API. - On each schedule trigger, matched by its id: its
startAtandendAt.
Ordinary Slack and schedule triggers themselves belong to the manifest: one
added in the console that the folder does not declare is removed by the next
apply.
Agent skills
recursion managed-agents get-agent-skill-disclosure --input-file request.json
recursion managed-agents agent-skills --input-file request.jsonA session lists skills to the model in the agent's saved order, with each group expanded in place. When the list is longer than the budget the model's context window allows, descriptions are dropped from the end, and the model is shown those skills by name only.
Two commands report that list for a saved agent. Both take get-agent's input,
{ "agentId": "<agent id>" }, and write nothing.
get-agent-skill-disclosureis the generated command for the API's own read, and returns the service's answer in one call:budget_chars,used_chars,entriesin the order the model reads them, andwarnings. It answers for the agent's latest version against the budget of the agent's own model, whichever model that is, and it lists and counts the platform skill that a session of an agent with built-in integrations lists first. Each entry of an attached skill carriesattachmentIndex, the zero-based position of its attachment in the agent'sskills, and a catalog skill's entry carriesskillId.agent-skillsis handwritten. It composes three reads, of the agent, the model catalog, and the skill disclosure preview, into one line, and adds apositionfor every skill andnameOnlyFromPosition.
Use get-agent-skill-disclosure when the answer has to be the service's own:
for an agent on a model the catalog no longer lists, for an agent with built-in
integrations, or to learn which attachment to move. Use agent-skills for a
line that already says where descriptions stop, next to the agent's model,
version, and saved attachments. It prints what the console's Skills section
shows, and differs from the service's answer in the two cases described below
its output.
agent-skills writes one success line of the
automation contract:
| Field | Meaning |
| --- | --- |
| agentId, agentVersionId, model | The agent, its latest version, and its model, as read. |
| contextWindowTokens | The model's context window from the model catalog, or null when the catalog lists none. |
| budgetChars, usedChars | The characters the skill list may spend in the prompt, and the characters it spends. |
| skills | The agent's skills in the order the model reads them: position, counted from 1, name, and descriptionIncluded. |
| nameOnlyFromPosition | The position of the first skill shown by name only; every skill after it is name only too. null when every description fits. |
| attachments | The agent's saved skills array, in saved order. A group is one attachment and several skills. The line does not say which attachment a skill came from; attachmentIndex in get-agent-skill-disclosure does. |
| warnings | The preview's warnings, unchanged, after one of this command's own when the budget is only a lower bound. |
The model catalog lists the models offered to new agents. An agent on a model
it no longer lists still runs, on a context window agent-skills cannot read.
Its line is then measured against the smallest budget any model gets, and the
first warning says so: a session of that agent may keep more descriptions.
get-agent-skill-disclosure measures against that model's own budget.
A session of an agent that uses built-in integrations also lists one skill of
the platform's own first, which skills and usedChars do not include.
get-agent-skill-disclosure lists it first and counts it.
Invalid input exits 2 and a failed request exits 1. get-agent-skill-disclosure
fails with not_found for an agent that does not exist, and with
invalid_request on model for an agent whose model can no longer start
sessions.
To move a skill above nameOnlyFromPosition, reorder agent.skills in an
agent folder and run apply, or call create-agent-version
with the agent's full definition and the reordered skills array. A group's
skills keep their creation order and move together with the group's entry.
Run an automation and wait
recursion run-automation "$AUTOMATION_ID" --payload-file payload.json --timeout 1800
recursion wait-automation-run 33333333-3333-4333-8333-333333333333 --require-grade
recursion run-automation "$AUTOMATION_ID" --require-output --summary-file summary.md
recursion run-automation "$AUTOMATION_ID" --no-waitThese commands require @labelbox/recursion-cli 0.2.0 or later; 0.1.0 does
not include them.
AUTOMATION_ID is the automation's UUID, from managed-agents list-automations
or the console; automations are not addressed by name.
run-automation starts a run of a canonical automation and waits for its
result; wait-automation-run attaches to a run started elsewhere, such as by a
webhook. Both use the SDK's runAutomationAndWait and waitForAutomationRun,
which long-poll the run's result endpoint
(GET /managed-agents/v1/automation-runs/{automationRunId}/result, the
generated managed-agents get-automation-run-result) until the server reports
the run finished: the server waits and decides the verdict. The retries and
timeout cancel are the ones the
SDK README
describes. The commands are top-level because managed-agents run-automation
is the generated API call, which only starts the run; --no-wait does the same
and prints the run.
The payload is any JSON value, read from --payload-file or --payload-stdin
(never from an argument); without one the run starts with {}.
--idempotency-key sets the start request's replay key (default: a random
UUID). --timeout is in seconds (default 1800, at most 86400); when it passes
the session is cancelled unless --no-cancel-on-timeout.
Progress goes to stderr, one {"progress": {...}} line per state change or
retry, each with a human message. The result is one {"ok": true, "data": ...}
line on stdout: the server's result (state, verdict, reason,
reasonMessage, run, session, outcome, output, finalMessage,
artifacts, ...) plus timedOut, sessionCancelled, and elapsedMs. On a
timeout verdict is absent and timedOut is true. An API error the helper
cannot retry is a request failure on stderr, with the run and session ids known
so far. A timeout before the start is acknowledged, or before the result could
be read once, has no result: it exits 4 with a timeout failure on stderr and
writes neither file. When the start had already named the session, that session
is still cancelled unless --no-cancel-on-timeout, and the failure says whether
the cancel worked. After an unacknowledged start that failure carries
idempotencyKey; the run may have been admitted, so rerun with
--idempotency-key <key> to replay it rather than start a second one.
--require-grade fails an ungraded completed. --require-output fails a run
that would otherwise exit 0 but has no valid structured output: neither a
valid file at the automation's declared runDefaults.output.path nor, without
one, JSON in the final message. A missing or invalid declared file already makes
the server's verdict error.
Standard output holds the whole result, including what the agent wrote, so in a
CI job send it to a file (> result.json). The job log then shows nothing from
the agent: standard error carries only ids, states and request errors.
--summary-file <path> appends a Markdown summary: the verdict, reason code, run
and session ids, cost and artifact count. It holds text the agent wrote only with
--summary-details, and a job summary can be public in a public repository.
--summary-details adds the explanation, session status, the outcome and its
per-criterion verdicts and rationales, the output JSON in a code block, the final
message in a collapsed block, and a table of artifacts (path, size, file id). Every
value from the run is untrusted, so table cells are escaped and the code blocks use
fences no backtick run in them can close; the output and final message blocks are
cut at 64K characters. --outputs-file <path> appends verdict (timeout
on a timeout), automation-run-id, session-id, reason, final-message,
output-json (the valid output as compact JSON, else empty), artifacts-json,
and result-json in GitHub's multiline-safe name<<delimiter form; a value
over 900 KiB is written empty, since GitHub limits an output to 1 MB. Point
them at $GITHUB_STEP_SUMMARY and $GITHUB_OUTPUT.
To fetch an artifact, pass its fileId to get-file-content, which prints the
bytes in the $recursionBinary base64 envelope:
echo '{"fileId": "'"$FILE_ID"'"}' \
| recursion managed-agents get-file-content --input-stdin \
| jq -r '.data["$recursionBinary"].base64' | base64 --decode > result.json| Exit code | Meaning |
| --- | --- |
| 0 | passed, or completed without a grade unless --require-grade; with --require-output, only when the output is valid. |
| 1 | A request failed. |
| 2 | The arguments or the payload are invalid. |
| 3 | Not passed: failed, needs_attention, cancelled, error, ungraded under --require-grade, or no valid output under --require-output. |
| 4 | Timeout, or the timeout passed before the run was started or its result read. |
Generated authority
src/generated/operation-registry.generated.ts is ignored. The shared typed
Recursion client projector derives command identity, request schemas, media types,
and conditional-response metadata from the tracked canonical public OpenAPI for
both the SDK and CLI. Repository setup, build/check prerequisites,
package archives and docs-catalog generation materialize the registry before
consuming it. Canonical public-contract freshness and production release
qualification remain required.
Regenerate only this projection with:
yarn generate recursion-cli
yarn generate recursion-cli --check # verify an already materialized copyThe bundled docs catalog is also ignored. yarn generate prerequisites
materializes both CLI projections without updating the tracked API or web catalog.
For the raw CLI workspace build, check, test or type-check scripts, run
yarn dx setup:repo first: these also consume compiled SDK/library outputs.
Repeat preparation after removing ignored outputs or changing their inputs.
Do not edit the generated registry. Change the canonical contract or the shared projector instead. Dual-media operations use their JSON SDK envelope. An operation whose only request body is multipart remains available in the SDK but is omitted from the CLI instead of receiving a misleading JSON command.
Release contract
The publishing job uses the main-only recursion-cli-npm GitHub environment.
The CLI is still beta, so publishing does not require a human approval today;
the team plans to add that gate when the package reaches 1.0. Generation,
builds, qualification, and post-publication verification run outside the publish
job.
The manual Release / CLI workflow builds exact SDK and CLI archives, proves
the source contract against production, and publishes the qualified CLI bytes
through npm Trusted Publishing under the latest dist-tag. The SDK remains on
preview, and the CLI archive pins its exact SDK dependency. After publication,
an artifact-only verifier downloads the public npm
tarball, checks its SHA-256 and SHA-512 against the qualified archive, and gates
source tag creation on a match. The workflow retains the qualification receipt
and registry-observed digests as private run evidence for 30 days; the candidate
archive itself remains a 14-day handoff. Source manifests retain placeholder
version 0.0.0; the workflow stamps and tags the reviewed preview version.
Run from a repository checkout
node tools/scripts/install.ts
yarn dx setup:repo
yarn workspace @labelbox/recursion-cli check
yarn workspace @labelbox/recursion-cli test
yarn workspace @labelbox/recursion-cli build
node packages/recursion-cli/dist/bin.js --helpSlack automation triggers in an agent folder can set dmEnabled: true to offer
the automation in the Recursion Slack app's DM picker. Set it to false to
remove DM access; omitting it preserves the live setting during reconciliation.
Only active automations with enabled triggers appear. fromUserIds restricts
DM callers; without it, workspace users can invoke the configured automation.
