Skip to content
OpenTrain AIOpenTrain AIOpenTrain AIDocs

Ask OpenTrain

Answers from the documentation, with sources.

What would you like to do with OpenTrain?

AI answers can be mistaken. Check the linked sources. Don’t include private account information.

Open app

DEVELOPER DOCUMENTATION

CLI Command Reference

Core OpenTrain CLI commands with links to dedicated references for rich Instructions, Project To-dos, LMS, and retraining workflows.

This page covers the core opentrain command surface. Rich workflow families use dedicated references so their safety sequence, capability discovery, and complete flags stay together. Commands support --json (raw API response) and --base-url <url> (override the API origin) unless their dedicated page says otherwise. Scope, feature-flag, and claim requirements are those of the wrapped endpoint.

See the CLI overview for installation, credentials, and conventions.

The instructions command group reads, previews, imports, uploads images, atomically revises, and verifies the canonical pages in a real job’s Instructions tab. CLI 0.23.0 adds hosted visual proof through the real employer and designated test-worker renderers. It has its own page.

The todos command group reads and manages the canonical Project To-dos and native quizzes for a job. Its explicit-audience, preview-first workflow, checksum-bound full retakes, selective coaching lifecycle, and hosted Native Forms visual proof have their own page (CLI 0.23.0+ for hosted quiz screenshots).

The lms group begins with opentrain lms capabilities --json, then provides canonical course authoring, Native Forms, assets, Preview, publishing, active-assignment rollouts, assignment, reporting, grading, and mastery operations. Publishing creates an immutable version but does not silently change existing learner assignments. Use lms rollout preview, confirmed lms rollout, then lms rollout status or receipt to advance them safely while preserving compatible progress. See Update an assigned LMS course. Its lms retraining subgroup creates one worker-specific case, returns a deterministic no-write authoring scaffold, runs worker-equivalent Preview, reviews a no-write assignment plan, assigns exactly one Project To-do, and monitors or closes the outcome. CLI 0.17.0 adds hosted desktop/mobile visual proof, closed typed browser steps, and observe-only employer review links. CLI 0.20.0 adds one canonical local-and-remote authoring analyzer plus a fail-closed publish acknowledgement gate. CLI 0.21.0 adds canonical draft authoring intent and the retraining scaffold. See Individualized LMS retraining.

Run the same analyzer locally and remotely before you publish:

Terminal window
opentrain lms validate --dir ./course --remote --key <idempotency-key> --json

Use --intent INDIVIDUAL_MASTERY when the course is intended for individualized mastery. The response may return acknowledgeable warnings for quiz-like lessons without an assessment, repeated answer positions, operational metadata in learner copy, or an overly long first check. A manual-review assessment under individualized mastery is a blocking error and cannot be acknowledged.

Publishing fails with AUTHORING_CONTRADICTION while a blocking error remains. It fails with AUTHORING_ACK_REQUIRED while a warning remains unacknowledged. To accept a reviewed warning, pass the exact acknowledgementId returned by the latest validation:

Terminal window
opentrain lms publish \
--dir ./course \
--intent INDIVIDUAL_MASTERY \
--acknowledge '<acknowledgementId>' \
--confirm-publish \
--key <idempotency-key> \
--json

Acknowledgements apply only to that request. They are not stored on the course, and any content change invalidates the old IDs. lms push may proceed with warnings, but it does not acknowledge them or bypass the publish gate.

The checklists and feedback groups provide adaptive checklist authoring, exact-revision browser preview, submission review, employer-private reviewer reports, and reviewer grant management. They default to one JSON envelope and use --pretty for human output. See Reviewer Feedback and Task Checklists (CLI 0.14.0+).

The manager group is the context-first live-job control surface. It reads and reconciles shared state, polls for real-time changes, claims actions, declares spontaneous-work intents, reviews alternative proposals, separates TEAM, PERSONAL, and SESSION guidance, records typed policies, sends guarded managed messages, and leaves checkpoints or handoffs. See CLI: Shared Job Context (CLI 0.11.0+ for the automatic cross-command workflow).

Terminal window
opentrain --version # print the CLI version (also: opentrain version)
opentrain help # print usage (also: opentrain --help, or no arguments)
Terminal window
opentrain capabilities [--json]

Returns canonical root capability discovery, including every agentSurfaces family status, required and granted scopes, and per-operation authorization. Call it before a multi-step workflow, then call that family’s scoped capability command—for LMS, opentrain lms capabilities --json.

Wraps GET /api/public/v1/capabilities.

Terminal window
opentrain whoami [--json]

Alias of auth status — prints the authenticated user, token label, scopes, and account type.

Wraps GET /api/public/v1/auth/me.

Terminal window
opentrain auth register [--agent-name <name>] [--org-name <name>] [--force] [--json]

Creates an anonymous agent account and saves the pre-claim ot_pat_ token plus the claim token to the credentials file. Fails if credentials already exist unless --force is passed.

FlagDescription
--agent-name <name>Display name for the agent identity (alias --name)
--org-name <name>Name for the employer organization created with the account (alias --organization-name)
--forceOverwrite existing saved credentials
Terminal window
opentrain auth register --agent-name "Hiring agent" --org-name "Acme Research" --json

Wraps POST /api/agent/identity.

Terminal window
opentrain auth claim --email <human-email> [--claim-token <token>] [--json]

Emails the human owner an invitation to claim the agent-registered account. The claim token defaults to the one saved by auth register.

FlagDescription
--email <address>Required. The human owner’s email address
--claim-token <token>Claim token to use; defaults to the saved one

Wraps POST /api/agent/identity/claim.

Terminal window
opentrain auth claim-status [--wait] [--timeout <seconds>] [--claim-token <token>] [--json]

Checks whether the human completed the claim. On success the saved token is upgraded automatically to the claimed account’s scopes. Without --wait it checks once and reports pending; with --wait it polls (respecting slow_down backoff) until claimed or the timeout elapses.

FlagDescription
--waitPoll until the claim completes
--timeout <seconds>Give up waiting after this long (default 1800)
--claim-token <token>Claim token to check; defaults to the saved one
Terminal window
opentrain auth claim-status --wait --timeout 600

Wraps POST /api/agent/oauth/token.

Terminal window
opentrain auth login --api-key <token> [--base-url <url>]

Verifies an existing ot_pat_ token against the API, then saves it to the credentials file.

FlagDescription
--api-key <token>Required. The personal API token (alias --token)

Wraps GET /api/public/v1/auth/me for verification.

Terminal window
opentrain auth status [--json]

Same as whoami. Wraps GET /api/public/v1/auth/me.

Terminal window
opentrain auth logout

Deletes the saved credentials file. Purely local — it does not revoke the token; use tokens revoke for that.

Terminal window
opentrain jobs draft create --description <text> [--title <title>] [--external-id <id>] [--idempotency-key <key>] [--json]

Creates an unpublished draft from a plain-text job description (the primary workflow) or a structured payload. The response includes the validation state: each missing field carries an ask: question, type, allowed enum values, and the field name to set with jobs draft update. Alias: jobs create.

FlagDescription
--description <text>Plain-text job description or project brief
--description-file <path>Read the description from a file instead
--canonical-file <path>JSON file with an OpenTrain canonical job object
--payload-file <path>JSON file with a supported import payload (e.g. schema.org JSON-LD)
--title <title>Title to prepend to plain-text descriptions
--external-id <id>Source-system id for audit
--idempotency-key <key>Reuse to avoid duplicate drafts on retry
Terminal window
opentrain jobs draft create \
--description "Label 5,000 street-scene images with bounding boxes. Native Spanish speakers, \$14/hr." \
--json

Wraps POST /api/public/v1/job-drafts.

Terminal window
opentrain jobs draft update --job-id <id> --set <field=value> [--set <field=value> ...] [--json]

Fills in or corrects fields on an unpublished draft. --set values are auto-coerced (numbers, booleans, JSON arrays; everything else stays a string); repeat the loop until the draft is publish-ready. Alias: jobs update.

FlagDescription
--job-id <id>Required. The draft job id
--set <field=value>Set one field (repeatable) — use the set: field names from the validation output
--patch-file <path>JSON file with a field patch object (alternative to --set)
--patch-json <json>Inline JSON patch object (alternative to --set)
Terminal window
opentrain jobs draft update --job-id <JOB_ID> \
--set paymentType=PAY_PER_HOUR --set pricePerHour=14 --json

Wraps PATCH /api/public/v1/job-drafts/{jobId}.

Terminal window
opentrain jobs list [--status <status>] [--limit <n>] [--cursor <cursor>] [--json]

Lists your own jobs with publish state, proposal counts, and live URLs.

FlagDescription
--status <status>Filter: DRAFT, OPEN, ONGOING, COMPLETED, ARCHIVED, PENDING_APPROVAL
--limit <n>Page size (max 100, default 25)
--cursor <cursor>Pagination cursor from the previous page

Wraps GET /api/public/v1/jobs/mine.

Terminal window
opentrain jobs search [--q <text>] [--category <slug>] [--language <lang>] [--country <iso>] [--pay-type <type>] [--limit <n>] [--cursor <cursor>] [--json]

Searches the public marketplace (all live jobs, not just yours). No token required.

FlagDescription
--q <text>Free-text query
--category <slug>Category filter
--language <lang>Language filter
--country <iso>ISO country code
--pay-type <type>PAY_PER_HOUR, FIXED_PRICE, or PAY_PER_LABEL
--limit <n> / --cursor <c>Pagination

Wraps GET /api/public/v1/jobs.

Terminal window
opentrain jobs publish --job-id <id> [--json]

Publishes a publish-ready draft live on the marketplace, running the same validation and moderation pipeline as the in-app flow. Subject to daily publish limits.

Wraps POST /api/public/v1/jobs/{id}/publish.

Terminal window
opentrain jobs invite --job-id <id> --freelancer-id <id> [--json]

Invites an AI trainer to a published job, creating a proposal. Idempotent — re-inviting returns the existing proposal.

Wraps POST /api/public/v1/jobs/{id}/invites.

Terminal window
opentrain jobs close --job-id <id> [--json]

Archives a published job: it stops accepting proposals and leaves public listings. Existing contracts are unaffected. Idempotent.

Wraps POST /api/public/v1/jobs/{id}/close.

Terminal window
opentrain jobs update-published --job-id <id> --set <field=value> [--set <field=value> ...] [--json]

Patches a live (OPEN) job using the same field names and --set/--patch-file/--patch-json flags as jobs draft update. The revised listing is re-moderated; a blocked result unpublishes the job back to draft.

Wraps PATCH /api/public/v1/jobs/{id}.

Terminal window
opentrain proposals list --job-id <id> [--status <status>] [--limit <n>] [--cursor <cursor>] [--json]

Lists proposals for a job with statuses, bids, and AI-interview scores — the ranking view for deciding who to interview or hire.

FlagDescription
--job-id <id>Required. The job to list proposals for
--status <status>Filter, e.g. UNREVIEWED, SHORTLISTED, HIRED, DECLINED
--limit <n> / --cursor <c>Pagination (max 100, default 25)

Wraps GET /api/public/v1/jobs/{id}/proposals.

Terminal window
opentrain proposals get --proposal-id <id> [--interview] [--json]

Reads the full candidate evaluation: bid, AI-interview score and summary, verification, assessment results, and contract state. --interview also fetches the sanitized AI-interview transcript. Alias: proposal get.

Wraps GET /api/public/v1/proposals/{proposalId} and, with --interview, GET /proposals/{proposalId}/interview.

Terminal window
opentrain proposals hire --proposal-id <id> --amount <usd> [--milestone-name <name>] [--milestone-description <text>] [--due-date <iso>] [--confirm-not-fit-override] [--json]

Requests a hire — never hires anyone or moves money. Records a pending approval and returns 202 with an approvalUrl a signed-in human must confirm in the OpenTrain app; on confirm, the contract is created and the first escrow milestone funded. A 409 payment_method_required includes a billingUrl a human must visit. Alias: proposal hire.

FlagDescription
--proposal-id <id>Required. The proposal to hire from
--amount <usd>Required. First milestone amount in USD
--milestone-name <name>Short milestone name
--milestone-description <text>What the first milestone delivers
--due-date <iso>Milestone due date (ISO 8601)
--confirm-not-fit-overrideConfirm hiring a candidate previously marked “Not a fit” after a 409 not_fit_confirmation_required
Terminal window
opentrain proposals hire --proposal-id <PROPOSAL_ID> --amount 500 \
--milestone-name "First batch" --milestone-description "First 1,000 labeled images" --json

Wraps POST /api/public/v1/proposals/{proposalId}/hire.

Terminal window
opentrain freelancers get --id <user-id-or-slug> [--json]

Reads a masked AI trainer profile (skills, stats, work and labeling experience, education, reviews) by user id or public profile slug. Names stay masked to first name + last initial; personal contact details are never returned. Alias: freelancer get.

Wraps GET /api/public/v1/freelancers/{idOrSlug}.

Terminal window
opentrain messages list [--filter all|job|proposal] [--unread-only] [--limit <n>] [--cursor <cursor>] [--json]

Lists conversation summaries you participate in, with unread counts and the latest message.

Wraps GET /api/public/v1/messages.

Terminal window
opentrain messages unread [--filter all|job|proposal] [--limit <n>] [--cursor <cursor>] [--json]

Shorthand for messages list --unread-only — only conversations with unread messages.

Terminal window
opentrain messages read --conversation-id <id> [--limit <n>] [--direction older|newer] [--cursor <cursor>] [--json]

Reads messages inside one conversation, paginated in either direction.

Wraps GET /api/public/v1/messages?conversationId=....

Terminal window
opentrain messages send --conversation-id <id> --content <text> [--json]

Sends a plain-text message (max 10,000 chars) into an existing conversation. Use --content-file <path> to read the message body from a file.

Wraps POST /api/public/v1/messages.

Terminal window
opentrain messages start-proposal-thread --proposal-id <id> [--json]

Opens (or fetches) the pre-hire direct-message thread for a proposal — idempotent get-or-create, employer side only. Returns the conversationId to use with messages send.

Wraps POST /api/public/v1/proposals/{proposalId}/conversation.

Terminal window
opentrain contracts list [--job-id <id>] [--status active|ended] [--json]

Lists contracts (hired AI trainers) with milestones, the masked freelancer identity (first name + last initial), and the post-hire job DM conversationId.

Wraps GET /api/public/v1/contracts.

Terminal window
opentrain contracts get --contract-id <id> [--json]

Reads one contract in detail. Alias: contract get.

Wraps GET /api/public/v1/contracts/{contractId}.

Terminal window
opentrain contracts end --contract-id <id> [--json]

Ends a contract. With no funded milestones it ends immediately; with funded escrow at stake it returns a pending approval with an approvalUrl a human must confirm.

Wraps POST /api/public/v1/contracts/{contractId}/end.

Terminal window
opentrain admin-balance-milestones create \
--contract-id <id> \
--idempotency-key <key> \
--description <text> \
--amount <usd> \
[--volume <hours-or-labels>] \
[--name <name>] \
[--due-date <iso>] \
--json

Creates and internally funds a later milestone for an eligible OpenTrain platform-admin workflow. For hourly and per-label contracts, provide a positive --volume or omit it to let OpenTrain derive the volume from --amount and the canonical contract rate. A supplied amount, rate, and volume must agree.

This command is not an ordinary employer funding option. The server independently requires the restricted scope, platform-admin status, canonical admin-organization membership, Admin Pay eligibility, matching token organization, and the default-off rollout. The funding step moves $0 and creates no Stripe charge or PaymentIntent. Releasing payment later remains a separate human-authorized action.

Wraps POST /api/public/v1/contracts/{contractId}/admin-balance-milestones.

Terminal window
opentrain admin-balance-milestones fund \
--contract-id <id> \
--milestone-id <id> \
--idempotency-key <key> \
--json

Applies the restricted ADMIN_BALANCE funding marker to one existing eligible NOT_FUNDED milestone in place. It never creates a replacement milestone. Reuse the same idempotency key when retrying an uncertain request; using the key with a different request fails closed.

The command verifies the contract-to-milestone relationship, amount/rate/volume consistency, milestone state, sequencing, payment holds, and every platform-admin authorization gate. Success changes the existing milestone to ACTIVE_FUNDED, moves $0, and creates no Stripe charge or PaymentIntent. Payment release still requires a separate human approval in OpenTrain.

Wraps POST /api/public/v1/contracts/{contractId}/admin-balance-milestones/{milestoneId}/fund.

Terminal window
opentrain milestones create --contract-id <id> --description <text> [--name <name>] [--amount <usd>] [--volume <n>] [--due-date <iso>] [--json]

Adds an unfunded milestone to an active contract — no money moves at creation.

FlagDescription
--contract-id <id>Required. The contract to add to
--description <text>Required. What the milestone delivers
--name <name>Short milestone name
--amount <usd>Milestone amount in USD
--volume <n>Unit volume for per-unit milestones (e.g. label count)
--due-date <iso>Due date (ISO 8601)

Wraps POST /api/public/v1/contracts/{contractId}/milestones.

Terminal window
opentrain milestones fund --milestone-id <id> [--json]

Requests escrow funding. No money moves: the response is a pending approval with an approvalUrl a signed-in human must open and confirm (expires in ~72 h). Track with approvals get or updates poll.

Wraps POST /api/public/v1/milestones/{milestoneId}/fund.

Terminal window
opentrain milestones approve --milestone-id <id> [--json]

Requests release of a funded milestone’s escrow. Same human co-sign pattern as milestones fund.

Wraps POST /api/public/v1/milestones/{milestoneId}/approve.

Terminal window
opentrain approvals get --approval-id <id> [--json]

Checks a pending human co-sign approval: pending, confirmed, declined, or expired, plus the execution result once confirmed. Alias: approval get.

Wraps GET /api/public/v1/approvals/{approvalId}.

Terminal window
opentrain credits show [--json]

Reads the prepaid credit balance — available vs reserved (escrow-held) — plus recent ledger activity. Alias: credits balance.

Wraps GET /api/public/v1/credits.

Terminal window
opentrain credits ledger [--cursor <cursor>] [--limit <n>] [--json]

Pages the full ledger of top-ups, holds, releases, captures, refunds, and adjustments, newest first.

Wraps GET /api/public/v1/credits/ledger.

Terminal window
opentrain credits top-up --amount <usd> [--json]

Starts a Stripe Checkout top-up ($10–$10,000) and returns a checkoutUrl a human must open and pay — no money moves from the command itself.

Wraps POST /api/public/v1/credits/top-ups.

Terminal window
opentrain credits top-up-status --top-up-id <id> [--json]

Checks a top-up: pending (awaiting payment), completed, canceled, or expired.

Wraps GET /api/public/v1/credits/top-ups/{topUpId}.

Terminal window
opentrain updates poll [--cursor <cursor>] [--limit <n>] [--json]

Polls the account delta feed — small ID-only events for new proposals, messages, contracts, milestone changes, and pending payments. Persist the returned nextCursor and pass it as --cursor on the next poll.

Wraps GET /api/public/v1/updates.

Terminal window
opentrain webhooks create --url <url> --events <type,...> [--json]

Subscribes an HTTPS URL to platform events. The response includes the signing secret once — store it and use it to verify the X-OpenTrain-Signature header.

FlagDescription
--url <url>Required. HTTPS delivery endpoint
--events <type,...>Required. Comma-separated event types, e.g. proposal.received,message.received

Wraps POST /api/public/v1/webhooks.

Terminal window
opentrain webhooks list [--json]

Lists subscriptions with status (ACTIVE or DISABLED). Secrets are never included.

Wraps GET /api/public/v1/webhooks.

Terminal window
opentrain webhooks get <webhook-id> [--json]

Reads one subscription, including disable details after sustained delivery failure. The id can also be passed as --webhook-id. Alias: webhook get.

Wraps GET /api/public/v1/webhooks/{webhookId}.

Terminal window
opentrain webhooks delete <webhook-id> [--json]

Deletes a subscription and stops deliveries. Deleting and re-creating is also how a DISABLED subscription is resumed (the new one gets a new secret).

Wraps DELETE /api/public/v1/webhooks/{webhookId}.

Terminal window
opentrain tokens list [--json]

Lists every API token on the account — names, scopes, status, expiry. Secrets are never returned.

Wraps GET /api/public/v1/tokens.

Terminal window
opentrain tokens revoke --token-id <id> [--json]

Revokes a token by id — immediate and irreversible. Revoking the token the CLI is currently using breaks subsequent commands.

Wraps DELETE /api/public/v1/tokens/{tokenId}.

Terminal window
opentrain team show [--json]

Reads the employer team: organization, members with roles, and pending invites.

Wraps GET /api/public/v1/team.

Terminal window
opentrain team invite --email <address> [--json]

Emails a human an invitation to join the team with shared job and inbox access.

Wraps POST /api/public/v1/team/invites.

Terminal window
opentrain payments pending [--json]

Reads pending payment and milestone state visible to the token owner. Read-only — it never releases funds or changes payment settings.

Wraps GET /api/public/v1/payments/pending.

Terminal window
opentrain instructions <subcommand> [...]

Inspect, preview, create, import, upload images, patch, replace, organize, archive, stage a complete tree, apply it atomically, and verify Job Instructions. Every operation is keyed by job ID and addresses the real job tab. Rename commands preflight without writing when --confirm-live is omitted, and bundle plans omit unchanged ordering operations. Version 0.23.0 adds instructions visual sessions, desktop/mobile renders, private artifacts, and short-lived human review links. If an old script references instructions assets, run instructions assets help for the canonical image-upload replacement. See CLI: Job Instructions.

Wraps the Instructions API.