Skip to content

Client ​

Agents, scripts and Tama talk to a Toki coordinator through one versioned client schema (toki.client, currently version 1.3). Two clients are generated from it:

  • toki client, a command line that prints compact JSON;
  • a TypeScript client, @toki/client, which runs toki client for you.

Because both come from the same schema, they offer the same operations, flags and summaries. The generator checks the schema against the toki.v1 protocol, so an operation or field the protocol does not define is refused at build time.

Configuration ​

Both clients read a client configuration file. toki build init writes one for the operator (client.json). It holds the coordinator URL, TLS server name, CA certificate and a client token. Tokens never appear on the command line.

To give another client its own credential, issue one on the coordinator machine:

sh
toki daemon issue --socket /var/lib/toki/coordinator/admin.sock --role client --subject ci-agent

Operations ​

OperationWhat it does
submitSubmit a whole command against an exact commit or a published Gin snapshot, optionally running a selection manifest. Retrying the same key and body returns the original build.
getRead one build's state. --view full adds output bytes, attempts, the containment record and Gin source counters.
historyList this client's builds, newest first.
workersList connected workers with their OS, architecture and labels.
cancelRevoke a build's execution authority and cancel its native process tree.
sh
toki client submit  --config client.json --request build.json   # or --request - for stdin
toki client get     --config client.json --id req-<identity>
toki client history --config client.json [--limit 10] [--before CURSOR]
toki client workers --config client.json
toki client cancel  --config client.json --id req-<identity>
toki client schema
toki client help

toki client help lists the operations. toki client schema prints the schema version, the protocol and the operations this executable implements.

Summaries and drill-down ids ​

Each command prints one line of compact JSON. By default this is a summary of at most 2048 bytes, sized for an agent's context:

  • empty members are left out;
  • strings are cut to 160 characters, except drill-down ids;
  • a history page shrinks until it fits, and its nextBefore cursor stays exact;
  • a worker list that does not fit reports how many workers it omitted.

Drill-down ids are never cut:

FieldUse it with
build idget --id, cancel --id
nextBefore (when nonzero)history --before
worker subjectthe worker selector of a submit request

Add --view full to print the whole response. The toki build submit|get|history|workers|cancel commands print the same full responses.

Errors and exit codes ​

Errors are one JSON line on stderr:

json
{"error":{"code":"…","message":"…"}}
Exit codeMeaning
0Success.
1The coordinator refused or failed the call, or a summary cannot fit.
2Usage error: the command line or request cannot be used.
125Toki could not be reached or configured.

--schema MAJOR.MINOR makes the executable refuse a caller generated from a schema it does not implement. The TypeScript client always passes it.

Build states ​

get reports one of these states:

StateMeaning
queuedAccepted and waiting for a worker.
runningAn attempt is running.
completedThe command ended. It may still have a nonzero exitCode.
failedExecution or setup failed, or the build was cancelled or expired.
refusedDurably refused, for example required_platform_unavailable. Retrying the same key returns the same refusal; use a new key for new intent.
indeterminateAn attempt's outcome is unknown after a lost session. It is held until the worker's journal can confirm it.
artifact-incompleteThe build succeeded but its retained artefact bundle has expired.

A completed build's receiptId is its evidence identity. Use the build id, not the receipt id, for get and cancel.

Cancelling a started build means the intent was saved; delivery to the worker is best effort and retried after reconnects. The build stays pending until the worker reports how it ended. An unstarted build is cancelled at once.

TypeScript client ​

The TypeScript client is a dependency-free ES module with type declarations, for Node 18 or later. It lives in the Toki repository under clients/typescript and is not published to npm.

ts
import { TokiClient } from "@toki/client";

const toki = new TokiClient({ config: "/path/client.json", command: "toki" });

const build = await toki.submit({
  key: "gate-1",
  worker: "class:build-host",
  timeoutSeconds: 1800,
  command: {
    program: "cargo",
    args: ["test"],
    source: { repository: "https://github.com/your-org/your-repo.git", commit },
  },
});

const page = await toki.history({ limit: 10 });
const result = await toki.get({ id: build.id! }, { view: "full" });

Options ​

OptionMeaning
configPath of the client configuration.
commandThe toki executable; defaults to toki on PATH.
commandArgsArguments placed before client, for a launcher that wraps the executable.
cwd, envWorking directory and environment for the child process.

Request bodies travel on stdin and the token stays in the configuration file, so neither appears in a process's arguments.

Each operation returns a typed summary by default. Passing { view: "full" } returns the typed full response. Operations without a required input take undefined before the options:

ts
const workers = await toki.workers(undefined, { view: "full" });

Errors ​

A failed call rejects with TokiClientError, which carries:

  • operation: the operation name;
  • exitCode: 1 for an RPC error, 2 for usage, 125 when Toki is unavailable;
  • code: the gRPC status code name of an RPC error;
  • stderr: the error output.

Protocol versions ​

New request fields need a newer protocol minor version. The client negotiates the minimum a request needs and refuses older coordinators rather than letting them silently drop a field:

FeatureMinimum protocol
requiredPlatform1.3
Selection manifests1.5
Provisioned toolchain identity1.6
Gin snapshot source1.7

Status

The client surface and the 2048-byte summary limit are a proposal and may still change.

Part of the Tama toolchain.