CLI & contract reference
Product version 1.3.2 · contract version 4.7.0.
Every toryo app exposes a subcommand CLI as its integration contract. Invoke it
directly as toryo-<app> <command>, or through the umbrella binary as
toryo <app> <command> (which dispatches to the sibling CLI). --help on any app
prints its generated usage; toryo-<app> version --json reports the product +
contract version a script can assert against.
This page is generated from the frozen contract, so it cannot drift from the CLIs.
Commands by app#
toryo#
setup, provision ~/.toryo (dirs, host tools, config, DB, migrations, services)[--runtime docker|pglite] [--no-services] [--dry-run] [--rc <path>][--database-mode local-docker|local-pglite|external] [--database-url <url>][--ollama-mode local|external] [--ollama-host <url>][--yes] accept every install offer; [--no-input] never prompt or install[--install tmux,ollama,ollama-models,playwright-browser,gh|none] pre-answer the tool offers[--answers @<path>|<json>] answer every catalog question up front (for GUI callers); exit 64 on a missing or unknown id[--keep-targets] answer the database and Ollama targets from config.json; exit 1 when it records no database or cannot be read[--questions --json] print the question catalog for this host and exit, changing nothing[--report-json] print a setup-report JSON line as the last line of stdout
uninstall, remove toryo: services, binaries, shell PATH, skills, MCP registration[--purge] also delete ~/.toryo and the docker volume (every database)[--dry-run] [--yes] [--rc <path>]
update, self-update: rebuild from source, or swap released binaries[--check] [--notify] (with --check: send one messaging notice, apply nothing)[--quiescence [--json]] report what an update would interrupt; exit 68 when busy[--force] update even with jobs, runs or worker sessions in flight
supervisor, operate the foreman watch supervisor (the LaunchAgent that keeps services up)<status | stop | start | restart>
doctor, host preflight checklist (alias for foreman doctor)license, start a trial, activate, inspect, refresh, or manage this machine’s licenses<trial --email <email> [--replace-unreadable]| activate --email <email> [--replace-unreadable] <key>| add --email <email> [--replace-unreadable] <key> | list [--json] [--out <path>] | remove <tenantId>| status [--json] [--out <path>] | refresh [--tolerate-offline] | deactivate| adopt [--dry-run] [--move] [--map <slug>=<target> ...]>
knowledge, point this install at a team-hosted Postgres knowledge plane (shared brain)<configure --url <url> | --clear | --brain-endpoint <url> | --clear-brain-endpoint| provision | status [--json]| export --out <dir> [--from <context>] [--projects <slugs>] [--memories <ids>] [--documents <ids>]| import --in <dir> [--to <context>] [--map <slug>=<target> ...] [--move]| restamp --context <ctx> (--project <id> [--to-project <id>] | --from-context <ctx>) [--dry-run]| move-runtime --to docker|pglite [--dry-run]| move-hosting --context <tenantId> [--dry-run] [--tolerate-pending] [--quiet-wait <minutes>]>
llm, point this install at a team-hosted llm-service (shared embedding + judge), or warm the embedder<configure --endpoint <url> | --clear | status [--json] | warm>
browser, point a worker’s browser MCP at your real logged-in Chrome via CDP<configure --cdp-endpoint <url> | --clear | status [--json]>
skills, install the toryo operator /-commands into the harness skills roots<install [--dry-run] | uninstall | list [--json]>
mcp, the umbrella MCP server, knowledge + control plane over stdio<serve [--scope worker|operator|knowledge|local|local-worktree]>
settings, install-wide settings, persisted to ~/.toryo/config.json<describe | get | set [--database-mode MODE] [--database-url URL] [--ollama-mode MODE] [--ollama-host URL] [--telemetry true|false] [--force]>
runtime, keep the Node setup unpacked for the research browser on the pinned version<refresh [--dry-run]> reinstall a stale toryo-owned Node; an operator-owned one is left alone
toryo-brain#
search, unified search across the four sources--query Q [--project UUID] [--root PATH] [--home PATH][--sources memory,library,code-index,directives] [--k N] [--worktree PATH]
mcp, stdio MCP server (spawned by the worker)[--tools all|knowledge|local] [--context <tenant id|license name>]context: --context, then TORYO_CONTEXT, then the default license
serve, HTTP MCP gateway: knowledge tools over /mcp, seat-gated (WS-C)[--http-port 9800] [--auth-disabled]
cleanup-project, lift + clear a removed project's knowledge (memory/library/code-index); --apply acts only on a removed tombstone--project UUID [--apply | --counts]--apply: a refusal is also sent as a messaging alert--counts: prints each source's row count for the project, writing nothing; a source it could not read has count null and an error
cleanup-orphans, sweep + clean knowledge of every removed project (safety net), acting only on removed tombstones, which it then purges[--apply]
restamp, move tool-call telemetry to another license context (restamp --context UUID --project UUID|--from-context UUID)[--dry-run]; selection is the AND of the filters, rows already on --context are untouched[--to-project UUID] (requires --project) also re-points the project, whatever the row contextprints {restamped, skippedActive, dryRun}
migrate, bootstrap + apply tool-calls telemetry DB migrations
toryo-code-index#
reindex, index a project tree; prints JSON (--project UUID --root PATH [--full])forget, drop every indexed row for a project (--project UUID)status, index status, one project or all ([--project UUID] [--check])file, one file plus its imports (--project UUID --path RELPATH [--worktree PATH])exporters, files exporting a symbol (--project UUID --symbol N [--worktree PATH])importers, files importing a file (--project UUID --path P [--worktree PATH])search, ranked files matching a name/path substring or full text over symbols and doc comments (--project UUID --query S [--limit N] [--freshness check|off|refresh] [--worktree PATH])map, files ranked by the import graph, grouped by directory, within a character budget (--project UUID [--max-chars N] [--freshness check|off|refresh] [--worktree PATH])graph, the indexed files and resolved import edges the map ranks over (--project UUID)migrate, apply pending DB migrationsrefresh-shared, index a remote context's project from its remote default branch; prints JSON (--context TENANT --project UUID --root PATH [--full] [--tolerate-offline])hashes, stored content hash and parse version per file (--project UUID)stage, stage commit-sourced rows under a batch, payload on stdin (--project UUID --batch UUID --to-sha SHA --stdin)apply, apply a staged batch, advancing the indexed sha by compare-and-swap (--project UUID --from-sha SHA|none --to-sha SHA --stdin)
toryo-completion#
complete, run a subscription-backed structured-output completion; prints JSON--prompt-file PATH --schema-file PATH [--model ID] [--effort LEVEL][--max-attempts N] [--priority N] [--timeout-ms N] [--out PATH]
toryo-db#
up, bring the server up (build + start + wait for ready)down, stop the server (keeps volume)reset, stop + drop volume + restart (DESTROYS all app data)status, JSON: running + connection paramslogs, tail container logspsql, open psql against the running server
toryo-pglite#
up, start the embedded runtime (spawn server, wait for ready)down, stop the embedded runtimestatus, JSON: running + runtime + databases + unreadyserve, run the server in the foreground (used by up)init, initialize one database's data dir in this process, then exit (used by serve)<database> one of the built-in app databases
reset, stop + delete all embedded data + restart (DESTROYS data)
toryo-directives#
received, launch-time directive snapshot for a worker as JSONreceived <job-id>
resolve, full directive stack as JSONresolve <root> [--home PATH] [--project UUID]
search, matching sections as a JSON arraysearch <root> --query Q [--home PATH] [--project UUID]
list, {layer, path, claudeNative} inventory as JSONlist <root> [--home PATH] [--project UUID]
toryo-ideas#
add, register an idea; prints JSON--prompt TEXT [--scope global|project] [--project ref][--kind feature|process|rule-gap] [--impact N] [--effort N][--context UUID] the tenant id to stamp; the default context when absent[--files a.ts,b.ts] (repeatable) repo-relative paths the idea concernseffort is [0, 1]; higher means more work. Both scores stamp source=triage[--no-split] file the prompt verbatim; never close an idea, never ask a modela prompt reporting an earlier idea as fixed closes it and stores the remainder[--provenance JSON] the run or job filing it: {kind, id, prUrl?, ...Attempts?}unusable provenance is warned about on stderr and the idea is filed without it
drain-followups, file a session's recorded follow-ups as ideas; prints JSON<file> [--project ref] [--scope global|project][--receipt F] [--out F] [--fail-open]a receipt beside the artifact keeps a retry from filing anything twice--fail-open reports an unreachable registry as failed entries, not exit 65[--provenance JSON] the run or job filing them: {kind, id, prUrl?, ...Attempts?}[--predicted-paths a,b] (repeatable) the plan predicted these; an entrynaming a file under none of them records unpredictedPath on its originunusable provenance is warned about on stderr and every entry is still filed
list, list ideas; prints JSON array[--scope global|project] [--project ref] [--context UUID][--kind feature|process|rule-gap][--status open|promoted|dismissed|merged] [--include-merged][--has-files | --no-files] partition by whether any file is named[--origin UUID] every idea one sequence run or dispatch job filed[--pinned] only rows on your working set[--cull-proposed] open rows the quality gate proposed closing, not closuresmerged rows are triage tombstones and are hidden unless asked for
get, print one idea as JSON (get <id>)update, change an idea; prints JSON (update <id>)[--prompt T] [--impact N | --clear-impact][--effort N | --clear-effort] effort is [0, 1]; higher means more work[--triage-impact N] [--triage-effort N] machine scores, source=triage;both are [0, 1] and never overwrite an operator-sourced axis[--status open|promoted|dismissed|merged][--promoted-to REF | --clear-promoted-to][--clear-merged-into] reverses a triage merge; needs --status too[--clear-cull] reverses a quality-gate verdict; nulls culled_at and cull_notepair it with --status open to reverse a closure, or use it alone for a proposal
dismiss, set status=dismissed (dismiss <id>)promote, set status=promoted, promoted_to=REF (promote <id> [--task REF])pin, add an idea to your working set (pin <id>); prints JSONoperator-only: the only automated write is a merge carrying the pin overthe pin feeds no ranking, and a status change never moves itnarrow a listing to the set with list --pinned
unpin, take an idea off your working set (unpin <id>); prints JSONoperator-only, as pin is; scores, clocks and status are untouched
forget, drop a project's ideas (forget --project UUID)--project UUID [--context UUID]
restamp, move ideas to another license context (restamp --context UUID --project UUID|--from-context UUID)[--dry-run]; selection is the AND of the filters, rows already on --context are untouched[--to-project UUID] (requires --project) also re-points the project, whatever the row contextprints {restamped, skippedActive, dryRun}
stats, ideas counts by project. JSON: {total, byProject}[--context UUID] [--out F]
subsystems, group ideas by the app or package their files name; prints JSON[--scope global|project] [--project ref][--kind feature|process|rule-gap] [--status S] [--out F]defaults to --status open; no model is asked anythingeach owner splits by drift: unattributed, unchecked, deleted, moved, standingan idea naming files under two owners is filed under the one it names mostids and scores only; join the prompts by id through list
categories, group ideas by the kind of work they are; prints JSON[--scope global|project] [--project ref][--kind feature|process|rule-gap] [--status S] [--out F]defaults to --status open; no model is asked anything and nothing is embeddedtwo reads over an unchanged registry return identical groupingsunclassified means a model found no fit; unruled means nothing has ruled yetstaleness reports the escape-bucket share; nothing re-induces on its ownids and scores only; join the prompts by id through list
induce-categories, propose a taxonomy of work kinds for one partition; prints JSON[--scope global] | [--project ref], exactly one partition[--sample N] [--force] [--dry-run] [--out F]reads a deterministic sample of the partition and asks one capable modelrefuses to write over an existing taxonomy without --force--force resets every category in the partition, then writes the new ones--dry-run still asks the model; the proposal is the previewa failed induction writes nothing and exits non-zero: half an axis is worse
classify, place unruled ideas into their partition taxonomy; prints JSON[--scope global|project] [--project ref] [--kind K][--limit N] [--dry-run] [--out F]fills only rows with no category; an existing verdict is never overwrittena partition with no taxonomy is skipped and named, not guessed atneeds Ollama; batches that did not answer leave their rows unruled and exit 1
category, rename, merge or delete one category (category <slug>)[--scope global] | [--project ref], exactly one partition--rename NAME | --merge-into SLUG | --delete, exactly onerename moves the display name only; the slug is the stored keymerge repoints every idea to the survivor, then removes the loserdelete returns every idea carrying the slug to the classify queue
category-add, add one category by hand, sourced operator; prints JSON--slug S --name N --description D[--scope global] | [--project ref], exactly one partitionthe description is what the classifier reads to decide membershipunclassified and unruled are reserved: the view already emits both
triage, merge near-duplicate ideas and rank what is left; prints JSON[--dry-run] [--scope global|project] [--project ref][--kind feature|process|rule-gap] [--threshold N] [--out F][--rescore-impact] also asks about rows no model has ever scored[--rescore-impact-all] also asks about rows a model already scoredan operator-set score is never touched by either flag[--max-flags N] outstanding flagged rows to allow per scope (default 100)a row is flagged when a file it names changed or is not in the treemerges apply unattended; this pass never closes an idea
verify-dispatch, start an ideas-verify run per scope with flagged ideas; prints JSON[--dry-run] [--max-runs N] [--max-ideas N] [--out F]decides only what gets checked; the sequence does the checking
verify-sweep, start an ideas-verify run for the ideas you name; prints JSON--ids a,b,c (repeatable) [--dry-run] [--max-runs N] [--max-ideas N] [--out F]the triage flag is not consulted; only open ideas are sweptevery id given comes back under a target or in dropped, with a reason
cull, rule on whether each open idea is worth doing at all; prints JSON[--dry-run] [--scope global|project] [--project ref][--kind feature|process|rule-gap] [--max N] [--recheck] [--out F]candidates are open rows with no triage state and no verdict yet[--recheck] also re-judges rows this pass already ruled oncloses only the settled class, whose evidence is a verbatim span of the promptnot-actionable and restates-rule are proposed for the operator, never closed--dry-run still asks the model; the verdicts are the previewreverse any verdict with update <id> --clear-cullneeds Ollama; a pass no batch answered writes nothing and exits 1
backfill-files, lift Affected files lists out of prompts into the column; prints JSON[--dry-run] [--out F]a one-shot maintenance pass over every status, tombstones includedidempotent: a lifted row has no heading left, so a second run updates nonea bullet carrying prose beside the path is left alone and counted unparsed
backfill-impact, lower text-only impacts written before the ceiling; prints JSON[--dry-run] [--out F]a one-shot maintenance pass over every status, tombstones includedidempotent: after one pass no stored impact differs, so a second lowers noneoperator and verified scores are exempt, and updated_at is left alone
migrate, apply pending DB migrations
toryo-janitor#
plan, dry-run preview; deletes nothing (JSON)[--types T,..] [--before ISO]
collect, run a pass; follows persisted dryRun/enabled, --apply overrides both[--apply] [--types T,..] [--before ISO] [--max N]
status, recent audit passes (JSON)[--limit N]
settings, self-describing configdescribe|get|set --<flag> V
migrate, create DB + apply migrations
toryo-library#
add, store an authored document; prints a compact JSON receiptimport, import a docs directory (project or global)seed, write the documents toryo ships, if absent [--force]get, print one document as JSON (get <id|slug>)--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
export, print one document as markdown with frontmatter (export <id>)--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
list, list documents as a JSON array--split-global: set by toryo on a --scope all read outside the personal context; reads it as a project child and a global child--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
search, search documents (fts|semantic|hybrid) [--envelope for {results, degraded}]--split-global: set by toryo on a --scope all read outside the personal context; reads it as a project child and a global child--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
stats, aggregate stats as JSON ({total, byScope, byProject, chunks})--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
update, patch a document; prints a compact receipt, re-embeds body changes (update <id>)remove, soft-delete a document (remove <id> [--if-unchanged <updatedAt>])--if-unchanged: delete only while the row still carries that updatedAt; exit 1 when it has changed since
restore, restore a removed document (restore <id>)reembed, heal vectorless / stale-model documents [--dry-run]migrate, apply pending DB migrationsexport-bundle, one page of live documents for a knowledge bundle; prints {rows, next}[--projects <ids>] [--ids <ids>] [--after <cursor>] [--limit <1..1000, default 200>]--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
import-bundle, write knowledge-bundle documents read on stdin with their vectors; prints {results}--stdin --scope <project|global>
embed-inputs, the section texts a re-embed would embed for stale or named documents; prints {rows, next}--stale [--limit <1..32, default 8>] [--after <cursor>]--ids <id,...>--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id reads as not found
write-vectors, store seat-supplied section vectors for named documents; prints {written, skipped}--ids <id,...> --embeddings-stdin
drain-global, move this context's global documents the caller wrote into the personal library; prints a report[--dry-run] [--batch-size <1..500, default 50>]--split-global: set by toryo outside the personal context; without it there is nothing to drain--global-only: set by toryo on the child that files into the personal context; reads documents on stdin
toryo-memory#
remember, store a memory; prints JSONremember-batch, store one memory per JSONL line; prints a JSON report<file>--scope <value> default scope for a line that names none: global|project--project <value> default project uuid, with --scope project--receipt <value> replay-suppression file, so a retry files nothing twice--out <value> write the JSON report here instead of stdout--fail-open report a pass that could not run at all at exit 0--drop-unknown-fields drop a line's unknown keys and file the rest, rather than refusing the line--pre-approved an operator approved this file; global lines skip the judge--split-global set by toryo outside the personal context: global lines go to a --global-only child--global-only every line must be global; refuses a project line--origin-context <value> set by toryo when it reroutes a --global-only batch--origin-context-name <value> set by toryo with --origin-context
recall, rank memories for a query [--envelope for {results, degraded}]--split-global: set by toryo on a --scope all read outside the personal context; reads it as a project child and a global child
get, print one memory as JSON (get <id>)--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
list, list memories as a JSON array--split-global: set by toryo on a --scope all read outside the personal context; reads it as a project child and a global child--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
count, count memories matching filters--split-global: set by toryo on a --scope all read outside the personal context; reads it as a project child and a global child--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
stats, aggregate memory stats as JSON--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
forget, soft-delete a memory (forget <id> [--if-unchanged <updatedAt>])--if-unchanged: delete only while the row still carries that updatedAt; exit 1 when it has changed since
restore, restore a soft-deleted memory (restore <id>)pin, mark a memory decay-exempt (pin <id>)unpin, clear a memory decay exemption (unpin <id>)rate, record an outcome signal (rate <id> --signal 0..1)[--source <manual|judge>, default manual] [--job <uuid>]--source judge requires --job: set by toryo when a seat-side SessionEnd judge rates a recall
queue, global memories awaiting reviewapprove, admit a pending memory (approve <id>)reject, reject a pending memory (reject <id>)decay, run one decay passreembed, heal vectorless / stale-model memories [--dry-run]rejudge, re-run the global judge over pending memories [--dry-run]judge-session, attribute recall outcomes for a job--split-global: set by toryo outside the personal context; then judges the personal store in a --global-only child--global-only: judge the personal store alone; set by toryo on that child
record-recall, attribute an already-made recall to a job (--job <uuid> --memories <ids> --scores <n,n>)signal-recall, deterministically signal a job's recallspopulate-session, auto-populate memory from a session--on-seat: set by toryo for a gateway-context session; runs here and files through forwarded remember
session-inputs, the recalls and memories a seat-side SessionEnd reads for a job; prints {events, memories, populated}--job <uuid>--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
generalize-project, lift a removed project's durable memories to global, then clear them (--project <id> [--apply])--apply: refused (exit 1) unless the project has a removed tombstone no hosting move or binding names; exit 65 when that cannot be read--no-lift: lift nothing and call no model; every project memory is forgotten under --apply
migrate, apply pending DB migrationsexport-bundle, one page of live memories for a knowledge bundle; prints {rows, next}[--projects <ids>] [--ids <ids>] [--after <cursor>] [--limit <1..1000, default 200>]--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
import-bundle, write knowledge-bundle rows read on stdin with their vectors; prints {results}--stdin --scope <project|global>
embed-inputs, the texts a re-embed would embed for stale or named memories; prints {rows, next}--stale [--limit <1..256, default 64>] [--after <cursor>]--ids <id,...>--exclude-global: set by a gateway, which serves no global rows; reads project rows only, and a global id is answered as a missing one
write-vectors, store seat-supplied vectors for named memories; prints {written, skipped}--ids <id,...> --embeddings-stdin
global-rows, one page of this store's global rows the caller wrote; prints {rows, next, notYours}[--after <cursor>] [--limit <1..500, default 100>]
drain-global, move this context's global rows the caller wrote into the personal review queue; prints a report[--dry-run] [--batch-size <1..500, default 50>]--split-global: set by toryo outside the personal context; without it there is nothing to drain
toryo-messaging#
start, run the daemon (foreground)[--poll-ms N] [--http-port N]
send, enqueue a message; prints id--file P
list, list messages newest-first[--status S] [--source-app A] [--target-kind user|external|app][--limit N]
get, print message JSON (get <id>)ack, acknowledge by id (ack <id> [--response JSON])ack --source-app A --source-ref JSON [--response JSON]ack --ids <id,id,…> [--response JSON], bulk; prints counts, not rows
find-by-source-ref, list messages matching source-ref--source-app A --source-ref JSON
set-payload, overwrite a message payload--id <id> --payload JSON
mark-delivered, mark a pending message delivered (mark-delivered <id>)expire, mark a message expired (expire <id>)health, daemon up? JSON: {running, pid}migrate, apply pending DB migrationssettings, describe | get | set --default-ttl-sec N --notify-window-sec N
toryo-project#
add, register a project; prints JSON--name N --root P [--slug S] [--parent ref] [--no-index] [--docs-glob G][--git-remote URL [--repo-subpath P]]: store this identity instead of detecting it--repo-subpath: the project's directory within the repository, '' or . for its topon a team gateway: --root is refused; --git-remote and --repo-subpath are requiredin a shared store: exits 68 when another live definition has the same remote and subpathexits 68 when another live project already holds --root on this machine (a nested root is allowed)
list, list projects; prints JSON array--removed: list only removed (tombstoned) projects, oldest removal first
get, print one project as JSON (get <id|slug>)resolve, resolve a filesystem dir to its project; prints JSONupdate, change a project; prints JSON (update <id|slug>)[--name N] [--root P] [--slug S] [--parent ref | --clear-parent][--index | --no-index] [--docs-glob G][--git-remote URL [--repo-subpath P] | --clear-git-remote | --detect-git-remote]--git-remote: store this remote, normalized to host/path, with the root's subpath--repo-subpath: store this subpath instead of reading it from the root--detect-git-remote: re-read origin from the root; --clear-git-remote: store nonea shared definition: --clear-git-remote exits 64; a remote and subpath another live definition has exits 68
install-command, read/set the dependency-install argv (install-command <id|slug>)no flags: print the stored argv, resolving through detection when unset-- <argv...>: store this argv --none: store "no install here"--detect: re-run detection against the root and persist the result
verification, read/set the full test command and how often it runs (verification <id|slug>)no flags: print the stored argv, resolving through detection when unset-- <argv...>: store this argv --none: store "no full suite here"--detect: re-run detection against the root and persist the result--full-suite <never|before-review|every-verify|ci>: set the policy (default before-review)--full-suite-check <name>: the forge check that counts as the suite under ci--no-full-suite-check: clear it--timeout-ms <1..3600000>: bound the full test command --default-timeout: back to 10 minutes
sensitive-paths, read/set the glob patterns code-task treats as sensitive (sensitive-paths <id|slug>)no flags: print the registered patterns ([] when none)-- <pattern...>: replace the list --clear: remove every patternpatterns are repo-relative; only * and ** are wildcards; a leading ./ is removeda run copies the list when it is created, so a change never reaches a run in flight
routing, read/set code-task's implement routing table (routing <id|slug>)no flags: print the switch and the stored table (null when none)--table <json>: replace the whole table, e.g. {"mechanical":{"llm":"claude:sonnet"}}--on | --off: switch routing; --off keeps the table, every class runs free--clear: remove the table and switch on, back to the shipped tablea run copies the setting when it is created, so a change never reaches a run in flight
roles, read/set code-task's model and effort per pinned role (roles <id|slug>)no flags: print the stored table (null when none)--table <json>: replace the whole table, e.g. {"review":{"llm":"claude:opus","effort":{"claude":"medium"}}}roles: premiseCheck, plan, review, integrationReview, reflect; row keys: llm, effort (keyed by harness)--clear: remove the table, back to the host setting and then the shipped defaultsa run copies the setting when it is created, so a change never reaches a run in flight
descendants, print id set (self + descendants) as JSONremove, remove a project + clean its knowledge (remove <id|slug> [--yes|--dry-run] [--no-cleanup|--retire] | <uuid> --purge)tombstones the project, recording why: removed, kept with --no-cleanup, or retired with --retirenames what it destroys first and asks [y/N]; with no terminal it exits 64 unless --yes, and a declined prompt exits 1--dry-run: print what the removal would destroy (with per-source counts) as JSON, writing nothinga local removed project's knowledge is cleaned unless --no-cleanup; the cleanup starts in the background and reports by notification--no-cleanup: records kept, which no cleanup or sweep ever acts on; refused for a shared definition--retire: its records now live under another id; nothing is cleaned on its accounta shared definition's knowledge is cleaned and its tombstone purged by the gateway sweep--purge: delete an already tombstoned project (remove <uuid> --purge)prints cleanup: started | not-started | kept | gateway-sweep | none
migrate, apply pending DB migrationsbindings, list where this machine keeps a context's projects; prints JSON--context TENANT: read from the machine-local binding store, never forwarded
bind, record where one of a context's projects lives on this machine; prints JSON--context TENANT --project UUID --root PATH: the root must be an existing directoryexits 67 when this machine does not hold --context; warns when the id is bound in another context--auto --root PATH [--context TENANT] [--project UUID]: match every team context's definitions to the checkout's origin and <toplevel>/<repoSubpath>--auto prints {checkout: {root, gitRemote}, results: [{contextId, projectId, slug, root, outcome, conflicts?}], unbound: [{contextId, projectId, root}]}--auto first drops each binding in the checkout whose answering context no longer lists its id (unbound)--auto outcomes: bound, already-bound (left as is), ambiguous, root-taken, missing-subpath (refusals name the manual bind)--auto exits 0 all bound or already bound, 1 any refusal, 67 nothing matched or no team context
adopt, re-stamp another tenant's projects onto this one, ids kept; prints JSON--from-tenant TENANT [--ids UUID,...] [--dry-run]--dry-run prints {projects: [{id, slug, root, parentId, conflict}], dryRun: true}--dry-run with --ids prints only those ids, and refuses (64, nothing written) exactly as the real run wouldrefuses (64, nothing written) a slug conflict or a parent left behindmoves each adopted project's binding; prints {adopted: [{id, slug}], dryRun: false}
import-definitions, create or restore projects fromlistrows, ids kept, parents first; prints JSON--stdin: a JSON array of rows as list prints thema row the acting tenant holds removed is restored with the incoming definition, refused slug-taken or parent-missing as a create isprints {results: [{id, outcome: created|existing|restored|refused, reason?}]}; exit 1 on any refusalreason: slug-taken | id-taken | invalid-row | parent-missing
share, make a local project a team project, moving its knowledge; prints JSON<id|slug> --to TEAM [--slug S] [--dry-run]: never forwarded; names each child context itselfmerges into the team definition with the same remote and subpath; an owner or admin creates one when none existsmoves memories and documents one way, re-points execution records, binds the checkout, retires the local rowprints {project, team: {tenantId, role}, definition: {id, slug, action}, knowledge: {memories, documents}, moved, records: {byApp}, binding: {root, outcome}, retired, reason, codeIndex, dryRun}exits 0 done or planned, 1 partial (re-run to finish), 64 refused, 67 not found (project, team, or no definition for a member), 68 slug taken
toryo-relay#
send-message, push an inbox message (K: instruction|notification|alert)--job-id J --kind K --body B [--forwarded-from M]
inbox, read inbox, read-only (S: pending|delivered|consumed)<jobId> [--status S]
inbox-consume, list pending + mark delivered (worker poll target)<jobId>
inbox-deliver, mark named messages delivered (SessionStart injection's ack)--job-id J --ids ID[,ID...]
progress, append a progress event--job-id J --message M
progress-log, a job's progress log<jobId>
checkpoint, record a named milestone (X: JSON detail)--job-id J --name N [--detail X]
last-checkpoint, most recent checkpoint<jobId>
ask, ask the operator either/or questions, blocking until answered--job-id J --questions-file F [--timeout-seconds N]
questions, list questions (newest-first)[<jobId>] [--open]
answer, answer an open question (P: JSON number[][])--id Q --picks P
stalls, stall-detector output[--open]
status, daemon liveness + open-stall count (JSON)daemon, stall-detector singleton loop (foreman runs this)health, daemon liveness (JSON)settings, self-describing configdescribe|get|set --<flag> V
migrate, create DB + apply migrations
toryo-dispatch#
start, run the daemon (foreground)[--poll-ms 500] [--event-log-dir P] [--http-port 9790]
enqueue, add a job; prints guid on stdout--file P --caller C [--caller-job-id I][--priority 1-5] [--force] [--socket PATH] [--context UUID]
cancel, cancel a queued/running job (cancel <id>)force, let a queued job skip the slot cap and usage hold (force <id>)still waits on write conflicts, an open circuit and an admission pause
override-conflict, admit a queued job past conflicts held in other worktrees (override-conflict <id>)never a same-worktree conflict, an open circuit or a pause; not the slot cap
status, print job JSON (status <id>)list, list jobs; prints JSON array[--status S[,S]] [--caller C] [--project UUID] [--context UUID] [--limit N] [--summary]
events, print a job's lifecycle event timeline (events <jobId>)logs, print a job's worker event log as JSON (logs <jobId>)[--tail N] [--out P]
crashes, crash/failure projection; prints JSON[--project UUID] [--since ISO] [--summary]
history, bounded terminal outcome and event reliability summary--since ISO [--caller C] [--project UUID] [--out P]
conflicts, active write claims that collide with a candidate scope in <dir>; prints JSON--dir <path> [--scope a,b,c] [--project UUID, to see run claims in other dirs]
claim, take (or re-assert) a sequence run's run-lifetime write claim; prints JSON--run <id> --dir <path> [--project UUID] [--scope a,b,c] [--ttl-ms N] [--dormant] [--out P]
release, drop a sequence run's write claim; prints {runId, released}--run <id> [--out P]
forget, drop a project's jobs + events (forget --project UUID)--project UUID [--context UUID]live jobs are skipped; reported as skippedActive
restamp, move jobs to another license context (restamp --context UUID --project UUID|--from-context UUID)[--dry-run]; selection is the AND of the filters, rows already on --context are untouched[--to-project UUID] (requires --project) also re-points the project, whatever the row contextprints {restamped, skippedActive, dryRun}live jobs are skipped; reported as skippedActive
health, daemon up? JSON: {running, pid}stats, active slots + breakdown JSON (incl. byProject)[--context UUID] narrows byProject only; slots and queue stay machine-wide
circuit, provider circuit breaker state; JSON[reset] close it now, re-allowing claims
pause, stop claiming queued jobs; in-flight jobs finish untouchedcapacity is preserved and the pause survives a restart
resume, claim queued jobs again from the next tickmigrate, apply pending DB migrationssettings, describe | get | set --max-concurrent N
toryo-scheduler#
start, run the daemon (foreground)[--tick-ms 1000] [--http-port 9791]
schedule, create a new schedule; prints JSON--file P --caller C( --at ISO | --cron EXPR [--timezone TZ] | --every DURATION )[--name LABEL] [--caller-job-id ID] [--priority 1-5][--overlap skip|allow] [--misfire skip|fire-once] [--context UUID]
update, edit a schedule in place; prints JSON (update <id> [flags...])(same flags as schedule except --context; only those given change)
list, list schedules; prints JSON array[--status STATUS] [--project UUID] [--context UUID]
status, print one schedule as JSON (status <id>)history, list run history for a schedule (history <id> [--limit N])fire, run a schedule now; prints the run JSON (fire <id>)pause, pause an active schedule (pause <id>)resume, re-activate a paused schedule (resume <id>)disable, suppress a schedule, system rows included (disable <id>)enable, re-activate a disabled schedule (enable <id>)delete, delete a schedule + its runs, refused while a run is live (delete <id>)<id> [--force]
health, daemon up? JSON: {running, pid}forget, drop a project's schedules (forget --project UUID)--project UUID [--context UUID]
restamp, move schedules to another license context (restamp --context UUID --project UUID|--from-context UUID)[--dry-run]; selection is the AND of the filters, rows already on --context are untouched[--to-project UUID] (requires --project) also re-points the project, whatever the row contextprints {restamped, skippedActive, dryRun}
stats, schedules counts by project. JSON: {total, byProject}[--context UUID] [--out F]
migrate, apply pending DB migrations
toryo-session-debugger#
analyze, analyze one transcript; prints JSON[<ref>] positional session|run|file.jsonl[--file PATH] read a transcript file directly[--session ID [--cwd DIR]] locate by session id[--run JOBID] locate via a dispatch job workingDir[--project UUID] attribute to a project (with --file)[--no-capture] dry-run: detect + emit, no DB write[--out PATH] write JSON to a file instead of stdout[--duplicate-read-per-session N] already-covered reads of a path (dflt 1)[--retry-loop-len N] consecutive same-tool fails (dflt 3)[--failed-tool-per-session N] failures of one tool per run (dflt 3)
report, aggregate persisted analyses; prints JSONcaptures rule-gap ideas unless --no-capture[--no-capture] [--out PATH]
forget, drop a project's session analyses (forget --project UUID)--project UUID [--context UUID]
restamp, move session analyses to another license context (restamp --context UUID --project UUID|--from-context UUID)[--dry-run]; selection is the AND of the filters, rows already on --context are untouched[--to-project UUID] (requires --project) also re-points the project, whatever the row contextprints {restamped, skippedActive, dryRun}
stats, session analyses counts by project. JSON: {total, byProject}[--context UUID] [--out F]
migrate, apply pending DB migrations
toryo-foreman#
check, JSON report: green/red per service; exit 0 iff all greenstatus, alias for checkdoctor, host preflight checklist (bun, docker, tmux, claude, …);[--json] exit 0 iff every required check passes
up, bring up whatever is down; waits until greenup [<service>] brings up that service + its deps only
down, stop everything (reverse dependency order)down [<service>] stops that service + its dependents only
restart, bounce a service (and its transitive dependents);no argument restarts every registered servicerestart <service> queues behind a busy supervisor and runs once it drainsa service with in-flight work stops nothing: it defers and exits 75[--force] bounces now, unless dispatch may still be draining live work
models, JSON report: what each installed harness says it can run, vs what toryo offersspawns each harness's own catalog command; claude publishes none, so its row says soexit 0 even when a harness is absent; doctor is what grades reachability
watch, daemon: hold lockfile, poll, restart anything red[--interval-ms 5000]
toryo-usage#
get, cached snapshots; re-polls stale ones (JSON)[--provider id]
poll, force a fresh poll, ignoring the TTL (JSON)[--provider id]
providers, registered providers + enabled state (JSON)settings, self-describing configdescribe | get | set --<flag> V
migrate, create DB + apply migrations
toryo-sequence#
start, run the daemon (foreground)[--tick-ms 500][--tick-concurrency 4][--reconcile-ms 30000][--http-port 9792](env TORYO_SEQUENCE_TICK_CONCURRENCY=<n> sets the same lane cap)(env TORYO_SEQUENCE_WORKER_DEFAULTS=<json>seeds worker payload defaults, e.g.'{"llm":{"provider":"claude","model":"default"}}')
list, available sequences (built-in + declarative)[--project UUID|slug] also load that project’s .toryo/sequences[--all-projects] include every project of one context’s .toryo/sequences[--context ID|name] the license context --all-projects reads (default: TORYO_CONTEXT, the cwd's project, else personal)[--include-system] include system-owned sequences (e.g. ideas-verify)
describe, full spec of one sequence (describe <name>)[--project UUID|slug] also load that project’s .toryo/sequences[--all-projects] include every project of one context’s .toryo/sequences[--context ID|name] the license context --all-projects reads (default: TORYO_CONTEXT, the cwd's project, else personal)
validate, compile + check a declarative sequence file (validate <file.yaml>)[--strict] fail on a step routing to a harness this host disabled[--base-dir D] resolve a sandbox transform's sibling source from D
transform, run one sandboxed transform against JSON (transform <file.yaml> --step <name>)--step NAME the 'use: sandbox' transform step to run[--input X] the threaded input: @file.json, - for stdin, or inline JSON[--state X] run state {run, steps, project}: @file.json, -, or inline JSON[--emit-types] write the sibling <source>.types.ts instead of running
run-acceptance, run a plan's declared acceptance commands and record their exit codes--file F the acceptance-commands.json the plan wrote--out F where the gate evidence is written[--working-dir D] absolute command directory (default cwd)[--timeout-ms N] wall-clock bound on one command (default 600000)[--deadline-ms N] wall-clock bound on the whole list (default 1140000)[--base-branch B --base-checkout-dir D [--base-install-json J]] re-run failures at the merge-base with B[--install-json J] reinstall the worktree with argv J before the commands
apply-edits, apply a JSONL edit list, all or nothing (apply-edits --file F)--file F one {"file","old","new"} object per line; each old must match exactly once[--root D] absolute directory the paths are relative to (default cwd)[--dry-run] compute and report, write nothingprints {applied, files, dryRun, failures}; exit 1 when any line failed (nothing written)exit 64 for bad arguments, 67 when --file or --root cannot be read
proof, prove a claim about HEAD's diff from its merge-base (proof <kind> --base R)<kind> comment-only: every changed file changes only comments--base R the diff runs from the merge-base of R and HEAD to HEAD[--working-dir D] absolute repository directory (default cwd)prints {kind, base, mergeBase, head, proven, files}; exit 1 when not provena git failure is exit 1 with {kind, base, error}; exit 64 for bad arguments
source, raw YAML of a declarative sequence (source <name>)[--project UUID|slug] read that project’s .toryo/sequences[--out F] write the YAML to F instead of stdout
create, write a new declarative sequence (create <name>)[--project UUID|slug] write into that project’s .toryo/sequences[--file F] the source; omit to read stdin
clone, copy a declarative sequence under a new name (clone <name> <newName>)[--project UUID|slug] clone within that project’s .toryo/sequences[--description TEXT] set the copy’s description: instead of inheriting
edit, replace a declarative sequence's source (edit <name>)[--project UUID|slug] edit within that project’s .toryo/sequences[--file F] the new source; omit to read stdin
delete, remove a declarative sequence file (delete <name>)[--project UUID|slug] delete within that project’s .toryo/sequences
import, fetch a remote sequence, review it, then write it (import <source>)<source> owner/name, or a github blob URL, or an http(s) URL[--path F] the file inside an owner/name repo[--ref R] branch, tag or sha to resolve (github sources only)[--project UUID|slug] write into that project’s .toryo/sequences[--yes] accept without the review prompt
install-shipped, write the sequences toryo ships into a sequences directory[--project UUID|slug] install into that project’s .toryo/sequences[--dry-run] report what would change, write nothing[--upgrade-only] upgrade an installed copy; never install an absent onean edited or foreign copy is reported and left alone, never overwritten
run, create a run; prints {runId} (run <name> --input I)[--project UUID][--working-dir PATH] root a project-less run (absolute path)[--title T] [--description D][--depends-on A,C] hold run 'blocked' until those runs succeed[--context UUID] license tenant the run belongs to (default: the default license)[--dry-run] validate input + project, create no run
runs, list runs[--sequence X] [--status S[,S]] [--project REF[,REF|none]] [--context UUID] REF is a UUID or slug[--archived exclude|only] omit for no archive constraint (the default)[--limit N] [--order O] [--summary] [--out F]
history, bounded terminal-run repeat-attempt summary--since ISO [--project UUID] [--out F]
outcomes, finished runs’ outcome rows, newest finish first[--sequence X] [--project UUID] [--status S[,S]] S is succeeded|failed|cancelled[--since ISO] runs that finished at or after[--limit N] default 100, at most 1000[--out F]prints {outcomes: [...]}; exit 64 for bad arguments, 65 for a db failure
tool-usage, per-step MCP tool calls from toolMix over a window--since ISO [--until ISO] [--sequence X] [--project UUID][--tool NAME[,NAME]] default code_search,code_map[--out F]prints {window, tools, groups, totals}; exit 64 for bad arguments, 65 for a db failure
status, run + step history (status <runId>)update, patch a run's identity, or a pre-start run's inputs (update <runId>)[--title T] [--description D] at any status[--depends-on A,C] replace the whole set (pre-start only)[--clear-depends-on] empty the set; the next reconcile promotes the run[--input <json|@file>] revalidated against the run's pinned sequence[--project UUID|slug] [--working-dir PATH][--re-pin] failed run only: re-point at the file on disk[--re-pin --force] also a paused/failed run whose PIN no longer compiles, mid-graph
ack, advance an awaiting-human step (ack <runId>)[--data <json>] [--note ...]
gate-form, a parked gate's form and live preview, read-only (gate-form <runId>)[--values <json>] the form values to preview; omit to preview the defaultsprints {runId, stepRunId, stepName, form, preview}; form and preview are null when undeclareda failing preview is exit 0 with preview.ok falseexit 1 when the pinned sequence no longer resolves, 64 for bad arguments, 65 db, 67 run not found, 68 no awaiting-human step
cancel, cancel a run + open steps (cancel <runId>)retry, re-arm a stuck/failed run's latest step (retry <runId> [--force])--force also re-arms a parked worker step (the only lever an escalated run has)
resume, paused → running (resume <runId>)refuses a run parked on a human step; use ack, or retry --force
archive, mark terminal runs as dealt with (archive <runId>… | archive --status S)ids form: prints {archived, alreadyArchived, notTerminal, notFound}a live run is refused (exit 68); the terminal ids in the same call still landfiltered form: [--status S[,S]] [--project UUID[,UUID|none]] [--sequence X] [--before ISO]at least one narrowing flag is required, and ids do not combine with them--before is measured on createdAt: finishedAt is nullable and would let rows escape
unarchive, clear the archive stamp (unarchive <runId>…)prints {unarchived, notArchived, notFound}; ids only, no filtered form
settings, view/update settings (settings describe|get|set)escalate-after-N, api-retry
forget, drop a project's runs (forget --project UUID)--project UUID [--context UUID]live runs are skipped; reported as skippedActive
restamp, move runs to another license context (restamp --context UUID --project UUID|--from-context UUID)[--dry-run]; selection is the AND of the filters, rows already on --context are untouched[--to-project UUID] (requires --project) also re-points the project, whatever the row contextprints {restamped, skippedActive, dryRun}live runs are skipped; reported as skippedActive
stats, run counts by project. JSON: {total, byProject}[--context UUID] [--out F]
health, daemon up? JSON: {running, pid}migrate, apply pending DB migrations
Exit codes#
The shared convention:
| Code | Meaning |
|---|---|
0 | success |
1 | generalError |
64 | badArgs |
65 | dbError |
66 | noDaemon |
67 | notFound |
68 | conflict |
toryo-completion (documented exception)
| Code | Meaning |
|---|---|
0 | success |
1 | schemaInvalid |
2 | cancelled |
4 | crashed |
64 | badArgs |
65 | dispatchError |
toryo-foreman (documented exception)
| Code | Meaning |
|---|---|
0 | green |
1 | red |
64 | badArgs |
66 | alreadyRunning |
75 | busy |
Environment variables#
Caller-set TORYO_* inputs external consumers may rely on (frozen in the contract):
TORYO_DATABASE_URLTORYO_DATABASE_MODETORYO_PG_HOSTTORYO_PG_PORTTORYO_PG_USERTORYO_PG_PASSWORDTORYO_KNOWLEDGE_DATABASE_URLTORYO_KNOWLEDGE_PG_HOSTTORYO_KNOWLEDGE_PG_PORTTORYO_KNOWLEDGE_PG_USERTORYO_KNOWLEDGE_PG_PASSWORDTORYO_KNOWLEDGE_APP_URLTORYO_KNOWLEDGE_APP_PG_HOSTTORYO_KNOWLEDGE_APP_PG_PORTTORYO_KNOWLEDGE_APP_PG_USERTORYO_KNOWLEDGE_APP_PG_PASSWORDTORYO_LLM_ENDPOINTTORYO_BRAIN_ROOTTORYO_BRAIN_HOMETORYO_BRAIN_JOBTORYO_BRAIN_TENANTTORYO_BRAIN_USERTORYO_CONTEXTTORYO_BRAIN_ENDPOINTTORYO_HOMETORYO_SUPERVISOR_LABELTORYO_REPOTORYO_BIN_DIRTORYO_USE_BINARIESTORYO_UPDATE_CHANNELTORYO_UPDATE_TOKENTORYO_NO_UPDATE_BANNERTORYO_DB_RUNTIMETORYO_OLLAMA_MODETORYO_OLLAMA_HOSTTORYO_LICENSE_ENDPOINTTORYO_GATEWAY_KEYTORYO_GATEWAY_STATE_DIRTORYO_GATEWAY_DB_POOL_SIZETORYO_GATEWAY_PROJECT_DB_POOL_SIZETORYO_INSTALL_IDTORYO_LICENSE_EMAILTORYO_CLAUDE_SKILLS_DIRTORYO_AGENTS_SKILLS_DIRTORYO_EXEC_STRATEGYTORYO_MULTIPLEXERTORYO_DISPATCH_CLITORYO_BROWSER_CDP_ENDPOINTTORYO_NODE_BIN_DIR
SequenceSource (sequence) surface#
The externalized sequence surface is the SequenceDescriptor JSON emitted by toryo-sequence list | describe, plus these dispatch verbs:
run · ack · status · list · describe · cancel · retry · resume · update
Step kinds: worker · transform · human · setup · acceptance.