Skip to main content
Use toloka to sign in, select a project, move dataset rows, and automate both products. For Data Labeling, it reconciles typed pipeline source and operates pipeline runs. For Train, it creates Training drafts, calculates estimates, controls Training Runs, and downloads Model Versions. The pipeline authoring SDK authors Data Labeling pipeline source only. To drive either product directly over HTTP, use the HTTP API.
Use the latest CLI release. If a Data Labeling project imports @toloka-platform/sdk, use its latest release too. CLI and SDK releases share a version, while installation and updates remain separate; both can change between minor 0.x releases.

Shared setup

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.
  • A Toloka account on a team. toloka login signs you in through your browser. Only automation that runs without a browser needs an API key; generate one 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

With 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. For SDK development, use Bun as the runtime and package manager and add the SDK to each project that imports it:
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

Rerun the installer with its original mode and overrides for an immediate manual update to the latest release:
The CLI checks for eligible updates at most daily, after a release is at least 24 hours old. Run toloka config set auto-update false to turn that off. TOLOKA_SKIP_AUTO_UPDATE=1 skips the check for one command, and CI never checks unless TOLOKA_AUTO_UPDATE=1 is set. Both installs can coexist. To pick one, put its directory first on PATH, refresh the shell cache (hash -r in Bash, rehash in Zsh), then run toloka version --json to confirm which one answers: the channel is native for the standalone executable or global-registry for the Bun global package. Credentials, settings, and project dependencies stay unchanged.

Sign in

Run toloka login and choose browser sign-in. Complete the Google or Microsoft sign-in flow, creating a Toloka account first if needed. The CLI saves the session only after the platform accepts the account. If TOLOKA_API_KEY is set, login stores that key without prompting; the flags below also skip the chooser. On success:
The session is created under $TOLOKA_CLI_CREDENTIALS_DIR (default ~/.toloka/cli/credentials/) with mode 0600 in directories with mode 0700. The platform choice and your project aliases go to $XDG_CONFIG_HOME/toloka/credentials.json (default ~/.config/toloka/credentials.json). If that path has no file, the CLI still reads the older ~/.toloka/credentials.json. The session renews itself for up to 14 days after signing in. When it expires, run toloka login again. The first sign-in on a machine also asks you to allow the Toloka CLI once. toloka login --browser skips the question and goes straight to the browser flow; coding agents and scripts that sign the user in should use it. toloka login --no-browser does the same but prints the link instead of opening a browser. An API key is the alternative for scripts, CI, and coding agents: it does not expire until you delete it in the Business Console. Choose Use an API key in toloka login to type one at a masked prompt, or without a terminal pipe it: 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. An agent session without a terminal opens the chooser page in your browser on its own. toloka logout removes local credentials and attempts to sign out stored browser sessions. Check its output to confirm that sign-out succeeded. It does not revoke an API 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 login. 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 stored login 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.

Verify the connection

Check what the CLI will use. The call needs a login and does not change the project:
whoami is an alias of auth-status. A working login prints the platform URL, a Login: line for the browser session (or a masked API key), the selected project, Reachable: N project(s) visible., and an Account: line with your email. Pass --show-token only when you need the full key or access token on this terminal. It prints the value unmasked, so it can land in scrollback, logs, or a screenshot. Exit code 1 means the CLI could not confirm a working login or encountered a local error. Use the reported message in Troubleshooting. Then list the projects the key can see:
Each row is the project id, name, and, for the selected project, its local alias. The selected project is marked *; other rows show -. An empty account prints No projects visible.

Initialize agent guidance

The Toloka agent bootstrap routes a coding agent to the Data Labeling, fine-tuning, or gisting runbook and its packaged skill. For a Data Labeling project, create a directory, install the TypeScript SDK, and initialize the agent entry points:
The agent can then author the pipeline source, validate it, show the plan, and apply approved changes. project create, import, or explicit project identity on init writes toloka.json; do not edit it by hand. Train workflows do not need the SDK dependency. Run toloka init in the project’s bound checkout to install the bundled agent guidance. In an unbound directory, pass toloka --project-id <id> init.

Select a project

Commands that access project data need a selected project. Highest wins:
  1. --project-id
  2. TOLOKA_PROJECT_ID
  3. projectId in toloka.json in the discovered checkout
  4. the current alias in the credentials file
If none of those resolve, the command fails with No project selected. Run toloka project create for a new project, toloka project add for an existing project, or cd into a checkout. or Missing project ID. Pass --project-id, set TOLOKA_PROJECT_ID, use a bound toloka.json, run toloka project create for a new project, or run toloka project add for an existing project. 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. To bind the directory when running init, pass --project-id, set TOLOKA_PROJECT_ID, or use an existing toloka.json binding. Selecting a project with project switch alone does not bind init. Register and import an existing project, then initialize this directory:
project add with no arguments prompts for alias and id. The new alias becomes the local alias 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:
Creating 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 read-only teams (read-only). 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. After a project is selected, toloka status prints its team ID. A directory already bound to another project keeps that binding, which takes precedence over project switch. 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:
project 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 API key stored by toloka login --api-key-stdin, then the browser session stored by toloka login. With none of those, the platform is https://platform.toloka.ai. The platform URL may include a path, for a gateway that serves the platform under a prefix. Requests keep that path: with TOLOKA_BASE_URL=https://gateway.example/ss/pp.1, the CLI calls https://gateway.example/ss/pp.1/api/v2-beta/..., with or without a trailing slash. Set only the origin when you talk to the platform directly.

Manage shared datasets

Rows are not source. Append a JSON array, JSONL, or CSV file:
The 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:
The 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 fields add <name> <field>... (or --all) turns top-level fields of the uploaded rows into dataset fields, so filters, --balance-by, and split columns can read their values; later uploads fill them too. 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.

Data Labeling

Adopt a live project

To edit an existing project, import its pipelines as TypeScript source. 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.
Omit 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 pipeline authoring SDK and return here for validate, plan, and apply.

Reconcile pipeline source

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.
check 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. check also reports platform-rules warnings for the rules the platform enforces when it writes a graph. Each warning names the node and the setting path that breaks the rule. The rules cover:
  • node names
  • quality criteria
  • Human QA review time
  • price
  • data collection media
  • exam limits
  • onboarding course structure and block contents
  • the 150,000-character limit on one node setting
These warnings do not fail check, but apply reruns the checks before resolving credentials or writing platform state and refuses to write a pipeline that violates a rule. Onboarding content is checked locally, except whether worked examples run against the labeling interface; the platform’s own node checks cover that. validate posts each bound graph and prints valid, invalid with issue details, checks-pending while the platform’s own node checks have not finished, or skipped when the pipeline or its dataset is not on the platform yet. Only invalid exits 1. It does not write the graph. Those platform node checks are tracked separately from toloka check. 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:
  • toloka check reports a failed or missing required check, or a checker that could not run.
  • a new or changed pipeline violates a rule reported by platform-rules — The platform would reject these pipelines:, followed by one - <directory>, node <node>, <setting>: <reason> line per issue.
  • a pipeline in toloka.json is absent from source — Refusing to delete pipelines absent from source: <directories>.
  • a dataset in toloka.json is 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.
If the platform rejects a graph, the CLI prints the 400 body, starting with Pipeline graph validation failed (<n> errors):. Each following line names one node and setting path, for example - node <name>, <setting path>: <reason>. After a failed apply, run toloka plan, inspect the changes, fix the reported errors, and rerun toloka apply. For a new pipeline, a rejected graph creates no dataset fields. Earlier successful pipeline imports remain, and retrying binds their datasets. For an existing pipeline, fields added before a rejected graph write remain and cannot be changed or deleted. On success it prints No changes. or Applied N planned changes with M platform 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.

Set pipeline secrets

Put secret names in node settings and keep values out of source:
The 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 pipeline run

Starting a pipeline run can charge your team’s balance. A single pipeline run launches at most 10,000 items. Forecast Expected and Maximum totals first; a pipeline with no billed nodes may show no charge.
--item-limit on cost is a forecast override. It does not change the pipeline. When a node has a warning, cost prints a Warnings section with one line per node. See Pipeline pricing for how branching affects Expected and Maximum totals. 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; use the ID when names are duplicated. If you omit the argument: 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: A run can remain in progress beyond the wait timeout. Use toloka pipeline status <name> to check it again; toloka 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. By default, cancellation waits for items in Human QA to finish review. Add --accept-without-review to accept waiting items without review now. With either choice, you pay for work recorded before each canceled item ends on its node; the unused reserved amount returns to your balance. See Items that wait for Human QA for the 14-day timeout, items already under review, and where accepted answers appear. 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 uses the same lint gate as the web app. Unfinished built-in lints, configuration errors, and failed checks block the deploy.

Train

Train uses the shared sign-in, project selection, and dataset commands above, but it does not use the TypeScript pipeline-authoring SDK. A Training draft, Training Run, Model, and Model Version are Train resources in the selected project. Create a Training with --dataset <name-or-id> or --slice <id>. --dataset prepares the dataset’s split column and freezes a slice; a dataset with no split column gets an 80% train, 10% validation, 10% test split. --slice reuses a ready slice that freezes a split column. Use --split-column <name-or-id> when there is more than one split column and --parts <names> to select comma-separated train parts. Validation comes from parts with the validate role, and test rows stay out of learning. If the slice supplies no validation rows, the platform holds out 10% of the selected train rows. See Training dataset selections for freezing a new slice after adding data, and Slices and split columns for toloka dataset split, toloka dataset columns, and toloka dataset slice. Use these command families for the Train lifecycle:
Starting a Training Run places a hold for the estimate’s maximum charge on the team balance. Review Training cost before you run it; pipeline Expected and Maximum forecasts do not describe Training settlement.
Follow Train your first model for the first end-to-end CLI workflow. Use Fine-tune a model or Compress a prompt with gisting for method-specific commands and settings.

Command reference

The CLI reference lists every public command, with its arguments, options, defaults, and inherited global flags. It also covers environment variables and exit codes. Output is colored on a terminal. Set NO_COLOR=1 or TERM=dumb to turn color off, or FORCE_COLOR=1 to keep it when piping.

Shared CLI behavior

Usage data

By default, the CLI sends usage reports and reports exceptions from failed commands. Running an authenticated command links reports to your Toloka account. Reports include the command type, duration, exit code, outcome or error code, HTTP status and request ID when available, and SDK and Bun versions. Exception reports use a generated error summary; invalid commands and flags do not produce exception reports. These reports exclude raw arguments, flag values, environment variables, API keys, secret names, platform addresses, local paths, project IDs, original error messages and stack traces, response bodies, and source context. 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. toloka report <report.md> is separate: it previews the file and, after you confirm, sends its full text to Toloka. It needs usage reporting on. With it off, the command stops with Issue reporting is disabled. Re-run with TOLOKA_TELEMETRY=1.

Sharp edges

  • Dataset columns are immutable. plan reports a schema conflict and apply refuses 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.json but absent from source is reported and refused, not dropped. Restore its source or binding, or run toloka project untrack pipeline <name> or toloka project untrack dataset <name> to stop reconciling it while leaving it live. The UI’s Hide action does not delete a resource or remove its local tracking, so hiding does not resolve this error. There is no toloka destroy. import refuses an existing pipelines/ directory unless you pass --force.
  • toloka.json records exactly one projectId. A second project needs a second checkout, or --project-id with state files kept apart.
  • Reusing an upload filename is allowed. Uploads append rows without deduplicating them, even when the filename is unchanged.
  • When an upload fails, the CLI cancels the pending upload itself. If that cancel fails too, later uploads return Another upload is already in progress. Complete or cancel it before starting a new one., and there is no manual cancel. Load into a new dataset and report the dataset id.
  • pipeline run can fail with 500 Internal error. Check toloka pipeline runs <name> before retrying; a run may already have been created.
  • When the dataset export behind dataset load fails, the command stops with Dataset export <exportId> succeeded without a download URL. and a hint to report a defect. The message does not include the export’s error. Read it with GET /exports/:exportId in the HTTP API: a failed export has status failed and an error with code and message. Correct the cause before retrying. Use a longer --timeout only when the export is still running.
  • Layout (canvas positions) is not authored. Existing layout is preserved; new nodes get server defaults.

Permissions

API keys inherit their owner’s team permissions; see HTTP API permissions for 403 and 404 responses. 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

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

Match the exact text the CLI prints: For every other platform message, search Errors and how to fix them.