CLI
Install and use the toloka command-line interface to authenticate, select projects, and reconcile local source with the platform.
Use toloka to sign in, select a project, inspect differences, apply source, move dataset rows, manage secrets, and run pipelines.
Pipeline source is authored with the TypeScript SDK. To drive the same workflow directly over HTTP, use Programmatic access (API).
Before you start
Section titled “Before you start”You need:
- macOS or Linux on ARM64/x64. The installer uses compatible Bun or downloads a standalone executable; native downloads require glibc Linux,
curl,tar,mktemp, and SHA-256 tooling. No separate runtime installation is required for the native path. Native Windows packages are not provided. - An API key. Generate it in the Business Console: open your company, switch to API keys, and click Generate API key. The same tab lists and deletes keys. See Manage your team and balance.
Install
Section titled “Install”curl -fsSL https://platform.toloka.ai/cli/install.sh | shWith stable Bun 1.4.0 or newer matching the host architecture, the installer uses Bun’s global SDK package. Otherwise it installs a checksum-verified standalone executable into ~/.local/bin, without changing Bun. Add the printed directory to PATH if prompted.
Force a mode with curl -fsSL https://platform.toloka.ai/cli/install.sh | sh -s -- --native or --bun. Forced Bun fails when incompatible; a failed Bun package install never silently switches to native.
The default installer follows latest; stable 0.2.0 includes Training commands. For SDK development, use Bun as the runtime and package manager and add the SDK to each project that imports it:
bun add @toloka-platform/sdk@latestRun bun add @toloka-platform/sdk@0.2.0 to pin the project dependency. CLI-only workflows, including Training, do not need that dependency. Projects that import SDK authoring or testing APIs do.
TOLOKA_CLI_INSTALL_DIR overrides the native directory and requires --native when Bun is present. TOLOKA_CLI_CHANNEL selects the release channel; TOLOKA_CLI_PACKAGE overrides the selected mode’s SDK or native package. TOLOKA_CLI_REGISTRY selects the installer registry. Use an explicit mode with custom packages. Automatic updates always use the public npm registry.
Updates and migration from Bun global installs
Section titled “Updates and migration from Bun global installs”Rerun the installer with its original mode and overrides for an immediate manual update. For an exact native version on macOS ARM64:
curl -fsSL https://platform.toloka.ai/cli/install.sh \ | TOLOKA_CLI_PACKAGE=@toloka-platform/cli-darwin-arm64@0.2.1 sh -s -- --nativeThe CLI checks for eligible updates at most daily, after a release is at least 24 hours old. A version pin does not disable updates; run toloka config set auto-update false to stay pinned.
If both versions are installed, put your chosen binary directory first on PATH, refresh the shell cache (hash -r in Bash or rehash in Zsh), and run toloka version --json. The channel is native for standalone or global-registry for Bun-global. Credentials, settings, and project dependencies stay unchanged.
Sign in
Section titled “Sign in”toloka loginlogin prints where to generate a key for https://platform.toloka.ai, prompts for it without echoing, and verifies it by listing projects. A key that does not authenticate is never written to disk. On success:
Authenticated against https://platform.toloka.ai: 12 project(s) visible.Saved credentials to /Users/you/.config/toloka/credentials.json.
toloka reads them automatically. --api-key and TOLOKA_API_KEY still win when set.The file is created at $XDG_CONFIG_HOME/toloka/credentials.json (default ~/.config/toloka/credentials.json) with mode 0600. If the parent directory does not exist, it is created with mode 0700. If that path has no file, the CLI still reads the older ~/.toloka/credentials.json.
Without a terminal — an agent session, a container, a CI step that must store credentials — there is no prompt. Pipe the key instead: toloka login --api-key-stdin < key.txt. The key never enters shell history or the process list, which --api-key <key> and TOLOKA_API_KEY cannot promise.
toloka logout deletes the stored file. It does not revoke the key. Delete the key in the Business Console.
CI does not need login for plan, apply, validate, status, dataset, pipeline, and secret commands. Set TOLOKA_API_KEY to override the stored key. The stored platform URL and selected project still apply unless you also set --base-url / TOLOKA_BASE_URL and --project-id / TOLOKA_PROJECT_ID. project add, project create, project switch, and project remove still need the credentials file from login.
Earlier releases named these variables POTATO_API_KEY, POTATO_BASE_URL, and POTATO_PROJECT_ID. The CLI still reads each legacy name when its TOLOKA_* counterpart is unset, prefers the TOLOKA_* value when both are set, and prints POTATO_API_KEY is deprecated and will stop being read; set TOLOKA_API_KEY instead. (and the same line for the other two) on stderr once per command. The aliases remain supported for compatibility; rename them to silence the warning and use the current names in new automation.
Your first call
Section titled “Your first call”Check what the CLI will use. The call needs a key and does not change the project:
toloka whoamiwhoami is an alias of auth-status. A working key prints the platform URL, a masked key, the selected project, and Reachable: N project(s) visible. Pass --show-token only when you need the full key on this terminal: it prints the key unmasked, so it can land in scrollback, logs, or a screenshot. Exit code 1 on this command means no key is in effect, the platform rejected the key (Rejected: …, run toloka login), the platform did not answer (Not reachable: …, a network problem — the key was not evaluated), or the platform failed (Platform error: …, retry later); other local errors also exit 1 and print on stderr.
Then list the projects the key can see:
toloka project listEach row is the project id, name, and team id. The selected project is marked *. An empty account prints No projects visible.
Initialize a project for your agent
Section titled “Initialize a project for your agent”For a guided first run, open a fresh coding-agent session and ask it to follow the Toloka agent bootstrap. It routes to the data-labeling agent guide, fine-tuning, or gisting workflow and the matching packaged skill.
Create a project directory, install the TypeScript SDK, and initialize the agent entry points:
mkdir cat-labeling && cd cat-labelingbun add @toloka-platform/sdk@latesttoloka initOpen your coding agent in this directory and describe the pipeline you want. The agent authors the TypeScript source, validates it, shows the plan, and applies approved changes. project create, import, or explicit project identity on init writes toloka.json; do not edit it by hand.
How the CLI finds a project
Section titled “How the CLI finds a project”Commands that access project data need a selected project. Highest wins:
--project-idTOLOKA_PROJECT_IDprojectIdintoloka.jsonin the discovered checkout- the
currentalias in the credentials file
If none of those resolve, the command fails with No project selected. Run toloka project add, or cd into a checkout. or Missing project ID. Pass --project-id, set TOLOKA_PROJECT_ID, set projectId in toloka.json, or run toloka project add.
A directory is a checkout when it contains toloka.json. Commands walk up from the working directory until they find that file, and print Using project root <path> (found from <cwd>). on stderr when that path is not the working directory. --source-root disables discovery. init always uses the working directory or --source-root; it installs agent entry points without requiring a selected platform project. It writes toloka.json only when project identity comes from --project-id, TOLOKA_PROJECT_ID, or an existing checkout binding. It does not bind from the machine registry’s current alias.
Register and import an existing project, then initialize this directory:
toloka project add cats pp.019ffa5f-29a7-74de-a76c-7ba5ceedf37ftoloka import pp.019ffa5f-29a7-74de-a76c-7ba5ceedf37ftoloka initproject add with no arguments prompts for alias and id. The new alias becomes the machine registry’s current value. import binds this directory by writing toloka.json with the project, pipeline, and dataset IDs before init writes the agent entry points.
Create a live project and select it in one step, in a directory that has no toloka.json yet:
toloka project create cats --team-id <teamId> --delivery-order-id <orderId>toloka initCreating a project requires a team. Without --team-id, the CLI uses the only team where your key has write access; toloka whoami lists your teams on a Teams: line and marks them (internal) and (read-only) where that applies. When several teams are writable the command refuses with Missing team id. Pass --team-id. This account can create projects in several teams: <ids>.; when none is writable it refuses with This account has no writable team, so it cannot create a project. A project owned by a team marked (internal) also needs a Sunday delivery order: run toloka delivery-order list and pass --delivery-order-id; the account-level Internal: line does not decide this. The flag and the command are available to every user; the platform answers deliveryOrderId is required for internal teams or deliveryOrderId can only be set for internal teams when the order does not match the team. After a project is selected, toloka status prints its team id. If this directory is already bound to another project, that checkout stays selected and overrides the new registry current.
project switch, project current, and project remove only change the local alias registry. remove does not delete the live project.
To stop reconciling one tracked pipeline or dataset without deleting it from the platform, run toloka project untrack pipeline <name> or toloka project untrack dataset <name>. The command changes only toloka.json; it previews the binding in a terminal and requires --confirm outside a terminal.
Print the selected project’s browser-ready URL for an agent or script:
toloka project urlproject url uses the same project and platform precedence as other commands, fetches the live project to resolve its team, and writes only the URL to stdout.
Credentials and the platform URL resolve separately, highest first: --api-key / --base-url, then TOLOKA_API_KEY / TOLOKA_BASE_URL, then the credentials file. With none of those, the platform is https://platform.toloka.ai.
Adopt a live project
Section titled “Adopt a live project”Adoption is the shorter first path: you get source that already matches the platform. Every pipeline in the project must already bind a dataset, or import stops with Every imported pipeline must have a bound dataset. Two pipelines that bind different datasets with the same name also stop import: Project has multiple referenced datasets named "<name>". Rename one live dataset first.
toloka importtoloka planOmit the id to import the selected project, or pass pp.… to import that id and bind it. import records live ids in toloka.json. Do not hand-edit those ids. If pipelines/ already exists, import exits with Folder already exists: <path>. Pass --force to replace it. Pass -f or --force to replace it. A freshly imported project prints No changes. If plan prints anything else, the source and the platform disagree — read the diff before you edit.
To author a project from scratch, start with the TypeScript SDK and return here for validate, plan, and apply.
The reconcile loop
Section titled “The reconcile loop”TypeScript source is the desired state. plan reads source and live state and prints the difference. apply makes the platform match, until a pipeline has a run whose deploy did not fail. After that, a graph write returns 409 and later edits need a clone. Run plan again and require No changes.
toloka checktoloka validatetoloka plantoloka applytoloka plancheck is credential-free. It runs project TypeScript, automatic labeling-interface typechecking, Vitest, and required typed test.code, test.ui, and test.pipeline coverage. Exit 1 means source, types, tests, or required coverage failed. Exit 2 means a required checker could not run. apply runs the same gate again before resolving credentials or writing platform state.
validate posts each bound graph and prints valid, invalid with issue details, or skipped when the pipeline or its dataset is not on the platform yet. It does not write the graph. Remote Node Check state remains separate from the local gate.
plan is read-only. Matching source prints No changes. Otherwise it prints Plan: N changes and one line per change (+ added, ~ changed, - removed, ! missing).
apply refuses before any write when:
- the Local Check Gate reports a failed or missing required check, or a checker infrastructure error.
- a pipeline in
toloka.jsonis absent from source —Refusing to delete pipelines absent from source: <directories>. - a dataset in
toloka.jsonis named by no pipeline —Refusing to delete datasets absent from source: <names>. Dataset items are never deleted. - a code node names a secret the project does not have —
Required secrets are missing: <names>. Run toloka secret set <name> before apply. - a declared field exists with a different JSON Schema —
Dataset field schemas conflict with source: <dataset>.<field>. Existing fields are never rewritten.
On success it prints No changes. or Applied N writes to project <projectId>.
toloka status (no pipeline prefix) is project health: id, name, team, live pipeline / dataset / secret counts, and either Source has no pending changes. or Source has N pending change(s). That last line is the same test as plan, not a claim that every live resource is declared in source.
Load rows and set secrets
Section titled “Load rows and set secrets”Rows are not source. Append a JSON array, JSONL, or CSV file:
toloka dataset upload cat-images ./data/cat_images.jsonlThe CLI infers .json, .jsonl, or .csv from the filename and uploads the original bytes. JSON contains an array of row objects; JSONL contains one object per non-empty line; CSV uses its header row as field names and ingests every value as a string. Upload is additive. If the dataset does not exist yet and a pipeline in source declares it with at least one column, upload creates the dataset with those columns. Otherwise create it first:
toloka dataset create cat-imagesThe rows of a dataset created this way are stored whole; the first upload infers its columns. Field schemas are immutable after creation: you can add a column, never alter or remove one. See Create and manage datasets.
dataset list prints live name and id. dataset fields <name> prints inferred field() TypeScript, or Dataset <name> has no inferred fields yet. Inference runs on the file-upload path; rows added another way can leave this empty even when the dataset holds items.
dataset load <name> --out ./data/rows.jsonl starts a platform export, waits (default 60 seconds), downloads the JSON array, and writes JSONL. Pass --timeout in milliseconds, for example --timeout 120000. --limit slices after that download; it still waits for the full export. Failed downloads leave --out untouched.
Duplicate live names must be addressed by id.
Put secret names in node settings and keep values out of source:
toloka secret set OPENAI_API_KEY --from-env OPENAI_API_KEYThe value is read from that environment variable, or from stdin if you omit --from-env. Node settings reference the name; they never carry the value.
Price and start a run
Section titled “Price and start a run”toloka pipeline cost cat-labelingtoloka pipeline cost cat-labeling --item-limit 10toloka pipeline run cat-labeling--item-limit on cost is a forecast override. It does not change the pipeline.
pipeline run starts a run of the live pipeline — the same operation as the API’s start-run call. It does not wait. Exit code 0 means the platform accepted the run, not that labeling finished. A follow-up line tells you to poll toloka pipeline status or re-run with --wait.
Pass the live pipeline name or id. Duplicate names must be addressed by id. There is no implicit “the only pipeline.” On a terminal, omitting the name opens a picker only when the project has more than one pipeline. One pipeline, or no terminal, still requires the name. Zero pipelines prints This project has no pipelines. Several pipelines without a terminal print This project tracks several pipelines, so name one: …
With --wait, the CLI polls until the run succeeds or fails, or until the wait window closes (default 60 seconds; pass --timeout in milliseconds). Exit codes:
| Code | Meaning |
|---|---|
| 0 | The run succeeded, or --wait was omitted and the run was accepted. |
| 1 | The run failed. |
| 2 | The wait window closed while the run was still going. |
A queue with no one working it stays in progress, so bound the wait. After a timeout, pipeline status <name> reports the latest run; pipeline results <runId> --failed lists failed items.
pipeline cancel <runId> requests cancellation. Already-completed items are unaffected. Cancellation is asynchronous — poll pipeline status until the run settles. After cancel, the run reports failed with the error Run canceled. Cancel works only once the run is deployed. Canceling during deploy, canceling twice, or canceling while the run is being finalized returns 409. See Resume or cancel a run.
A second pipeline run on the same live pipeline returns 409 with Cannot create run for pipeline <pipelineId> because it already has an active run. After a successful run, apply that would write a new graph also returns 409 with Cannot create a new checkpoint for pipeline <pipelineId> because it has an active run. Clone the pipeline in the platform, then import or re-point. A failed deploy is the exception: it frees the same pipeline. See One pipeline, one run.
Starting a run through the CLI skips the lint gate that blocks a UI deploy when a built-in check has not completed — missing or still running. Configuration errors and failed checks still block.
Commands
Section titled “Commands”| Command | What it does |
|---|---|
version [--json] | Print semver, or structured build and install provenance with --json. |
login / logout / whoami | Store, remove, or inspect machine credentials. |
config / config get / config set | Read or write machine CLI settings. auto-update defaults to on. |
project list / add / switch / current / url / remove / create | Select the current project or print its platform UI URL. create takes --delivery-order-id for projects owned by internal teams. |
init | Initialize this project directory and install the agent bootstrap. |
import [projectId] | Generate TypeScript from a live project. |
check [pipeline] [--node <node>] [--json] [--watch] | Run source, type, test, and required local coverage checks without credentials. |
validate / plan / apply | Validate remotely, preview changes, and reconcile source; apply reruns the local gate before writes. |
status | Project health and pending source changes. |
secret set <name> | Set a secret value without writing it to disk. |
delivery-order list | List Sunday delivery orders this key can attach on project create; the platform answers only for internal accounts. |
dataset list / create / fields / load / upload | Catalog and rows. |
base-model list / get | Inspect the catalog of models you can train from. |
training create / update / get / cost / run / status / logs / resume / cancel | Create a Training draft, calculate cost, and run one Training Run. See Fine-tune a model and Compress a prompt with gisting. |
model get / versions / version download | Inspect and download a published Model Version. |
pipeline list / run / status / runs / cost / cancel / results | Operate on one live pipeline. |
Global flags, before any command: --source-root, --api-key, --base-url, --project-id.
Usage data
Section titled “Usage data”Unless you opt out, toloka sends command events so we can see which commands run and which error classes they hit. Every failed command with an exception also emits a sanitized PostHog Error Tracking $exception; usage errors such as unknown commands or invalid flags do not. While resolving credentials for an authenticated command, the CLI asks the platform who you are and aliases a locally stored random id onto your user id without setting person properties. Command events contain only an allowlisted command classifier, duration, exit code, outcome or error code, optional HTTP status and server request ID, SDK and Bun versions, actor, and channel. Error Tracking receives the same bounded metadata plus a synthetic exception; raw arguments, flag values, environment variables, API keys, secret names, base URLs and hosts, local paths, project ids, error messages, stack traces, response bodies, and source context are not sent. GeoIP enrichment is disabled.
Set TOLOKA_TELEMETRY=0 or DO_NOT_TRACK=1 to turn this off. TOLOKA_TELEMETRY=1 turns it on even when DO_NOT_TRACK=1 is set. CI is off unless you set TOLOKA_TELEMETRY=1. Accepted values for on: 1, true, yes, on. For off: 0, false, no, off.
Sharp edges
Section titled “Sharp edges”- Dataset columns are immutable.
planreports a schema conflict andapplyrefuses rather than rewriting data. Declare a new column, or bind the pipeline to a new dataset. - No live platform resource is deleted implicitly. A pipeline or dataset tracked in
toloka.jsonbut absent from source is reported and refused, not dropped. There is notoloka destroy. Remove live resources in the platform UI, or useproject untrackto stop reconciling a resource while leaving it live.importrefuses an existingpipelines/directory unless you pass--force. toloka.jsonrecords exactly oneprojectId. A second project needs a second checkout, or--project-idwith state files kept apart.- Uploading a file whose basename already exists in that dataset can fail with
500Internal error. Use a distinct filename per upload. - A failed upload can leave a pending upload row. Later uploads then return
Another upload is already in progress. Complete or cancel it before starting a new one., and the CLI has no cancel. Load into a new dataset and report the dataset id. pipeline runcan fail with500Internal error. Checktoloka pipeline runs <name>before retrying; a run may already have been created.- A dataset export that fails currently stays
running.dataset loadtimes out rather than waiting forever; raise--timeout. - Layout (canvas positions) is not authored. Existing layout is preserved; new nodes get server defaults.
Permissions
Section titled “Permissions”An API key acts as the user it belongs to, the same as Programmatic access (API). A key whose every team is read-only gets 403 on a write. Otherwise a write against a read-only or foreign team is masked as 404, except project create --team-id naming a team the user is not on, which answers 403. pipeline results on a read-only key withholds failure details: Failure details are withheld because this API key has read access only. A key with write access on the project sees them.
project add, project switch, project remove, and project create refuse --api-key / --base-url / TOLOKA_API_KEY / TOLOKA_BASE_URL when those would select a different key or platform than the stored file.
Errors and hints
Section titled “Errors and hints”A failing command prints its message to stderr and exits 1. Most messages are followed by a Hint: … line naming the next command to run, for example Hint: Run toloka training list and pass the training id (trg.…).; messages that already spell out the remedy carry no hint. Platform failures print the API status and body first, followed by a hint chosen by status: 401/403 point at toloka whoami and toloka login, 404 at the selected project and the matching list command, 429 asks you to wait, and 5xx asks you to retry and then file a report with toloka report <report.md>. Every platform error also carries its request id; quote it when you report a problem.
Troubleshooting
Section titled “Troubleshooting”Match the exact text the CLI prints:
| Response | Cause | What to do |
|---|---|---|
Missing API key. Run toloka login once to store credentials for this machine: | No flag, env, or credentials file. | Run toloka login, or set TOLOKA_API_KEY. |
Could not authenticate against <url>: … / Nothing was saved. | The login probe failed. The second line says which: a rejected key, a platform that did not answer, or a platform error. | Rejected: copy the key whole from the console that serves that URL. Did not answer: fix network access and retry. |
error: unknown command '<name>' / toloka <version> does not have it. | The installed CLI does not define that command; --help does not change this and the root help is not printed. Exit code 1. | Run the default installer again, confirm toloka --version reports 0.2.0 or a newer stable version, then use toloka --help to see its commands. |
Rejected: … / Not reachable: … / Platform error: … (from whoami) | The platform rejected the key (401/403); the platform did not answer (DNS, connection, proxy); the platform failed. Exit code 1 in all three. | Rejected: toloka login with a working key. Not reachable: fix network access; the key was not evaluated. Platform error: retry later. |
No project selected. Run toloka project add, or cd into a checkout. | No project id in flag, env, or toloka.json, or the credentials-file alias is for a different platform than the URL in effect. | toloka project add, cd into a checkout, or pass --project-id. |
Missing team id. Pass --team-id. … | Your key can write in several teams, or the platform did not report your teams. | Pick a team from toloka whoami and pass --team-id. |
Dataset field schemas conflict with source: <dataset>.<field>. Existing fields are never rewritten. | Source declares a different JSON Schema than the live column. | Declare a new column name, or bind a new dataset. |
Required secrets are missing: <names>. Run toloka secret set <name> before apply. | A code node names a secret the project does not have. | toloka secret set <name> --from-env <variable>, then plan again. |
Refusing to delete pipelines absent from source: <directories>. | Live pipelines in toloka.json have no matching source. | Restore the source, remove the live pipeline in the UI, or run project untrack pipeline <name>. |
Refusing to delete datasets absent from source: <names>. Dataset items are never deleted. | Tracked datasets are named by no pipeline. | Restore the source binding, keep the dataset tracked, or run project untrack dataset <name>. |
Another upload is already in progress. Complete or cancel it before starting a new one. | A previous upload to that dataset is still pending. The CLI has no cancel. | Load into a new dataset and report the dataset id. |
Pass a pipeline name. This project has: <name> (<id>). | pipeline was invoked without a name, there is exactly one live pipeline, and no picker ran. | Pass the name or id. Several pipelines without a terminal print This project tracks several pipelines, so name one: … |
Stopped waiting for run <id>; it has not reached a terminal state yet and may still be running. | --wait hit --timeout (default 60 seconds). | toloka pipeline status <name>; raise --timeout. |
401 Unauthenticated | The key is missing or invalid. | Send a working key; see Programmatic access (API). |
Cannot create run for pipeline <pipelineId> because it already has an active run. | The pipeline already has a run whose deploy did not fail. | Clone the pipeline in the platform, then import or re-point. |
Cannot create a new checkpoint for pipeline <pipelineId> because it has an active run. | apply tried to write a graph after a run whose deploy did not fail. | Clone the pipeline, then import or re-point. |
For every other platform message, search Errors and how to fix them.
Related
Section titled “Related”- TypeScript SDK — define pipelines, fields, nodes, and connections in source
- Programmatic access (API) — the same loop over HTTP, without TypeScript source
- Training — the concept page behind the training, base-model, and model commands
- Fine-tune a model — supervised fine-tuning from labeled conversations
- Compress a prompt with gisting — gisting from examples and a prompt file
- Create and manage datasets — the data contract uploads follow
- Label a large dataset in batches — the per-run cap and clone cycle
- Pricing and billing — how a run is priced
- Errors and how to fix them — every customer-visible platform error, quoted verbatim