CLI reference
tama request
Answers one Tama Desktop request and exits: the JSON body on stdin, NDJSON events on stdout. Tama Desktop runs one tama request process per operation, so no Tama process stays running between two operations and no port is opened.
#Invocation
tama request <operation> [--root <release-path>]
<operation> names one operation from the table below. --root selects the sealed hook release the operation reads; the desktop passes the release bundled into the app. The body is read from stdin to its end before anything runs, and an empty body is {}, so an operation that takes no fields needs no input: tama request coverage < /dev/null.
#Operations
| Operation | Body | Answer |
|---|---|---|
coverage | none | Registry-declared provider coverage, the document Coverage reads |
install/plan | none | The document tama install plan --json prints |
mcp/config | none | The document tama mcp config prints |
enforcement | none | The machine hook selection tama enforcement status --json prints |
enforcement/update | {mode, enabled}: mode is all with no enabled, or only, add or remove with a non-empty array of hook ids. add and remove change the named hooks against the selection as it is when the change is written, as tama enforcement add|remove do. Another mode is a 400, mode must be "all", "only", "add" or "remove"; every refusal of those commands is a 400 with its sentence | The selection after the change |
hooks/warm | {only?}: hook ids; empty or absent warms every hook | The report tama hooks warm --json prints |
policy-bundles | none | Retained inactive source identities |
policy-bundles/import | {sourcePath, replace?} | The same validating transaction as tama policy import; it never enables hooks |
violations/scan | {repo, mode?}: mode is size-only, duplicates, internal-names or time-limits; absent replays the hooks, anything else is a 400 naming the four | A streamed job: tama violations find --repo <repo> --json [--<mode>] |
violations/clean | {repo, maxRounds}: maxRounds is how many repair rounds the run may take, a number above zero; without it the request is a 400, clean requires maxRounds: how many repair rounds the run may take, a number above zero; tama violations clean --max-rounds has no default either | A streamed job: tama violations clean --repo <repo> --max-rounds <maxRounds>; it may modify the repository |
worktrees/list, worktrees/remove | roots: nonempty strings; removal adds optional except strings and apply/force booleans. Omitted optional fields mean preview-only, non-forced behavior with no exclusions. Malformed fields are refused with their decode cause. | The documents tama worktrees prints under --json |
copies/list, copies/remove | {roots}; removal adds {except?, only?, apply?, force?} | The documents tama copies prints under --json |
reviews/list, reviews/show | none; {id} | The listing or record from tama reviews; per-record read failures remain explicit rows, never passing review results. |
builds, builds/record, builds/close | none; {kind, target, reason, revision?, repository?, minutes?, approvalSession?, approvalQuote?}; {kind, target} | The registry and entries tama build reads and writes |
rules/digest, rules/dismiss | none; {id} | The digest tama rules digest prints under --json; {dismissed, detail} |
justifications/cua | none | {kind, registry, authorizations} |
justifications/cua/record | {sessionId, app, actions, quote} or {sessionId, app, actions, quoteMatch}, with actions an array of strings | {kind, registry, sessionId, authorization} |
justifications/cua/remove | {quote} | {kind, registry, removed, count} |
justifications/ssh | none | {kind, registry, authorizations}: every grant block-unauthorized-ssh reads |
justifications/ssh/record | {sessionId, targets, operation, paths, commands, quote} or the same with quoteMatch; targets, paths and commands arrays of strings, exactly one of paths (read, write) or commands (exec, transfer, tunnel, git) non-empty | {kind, registry, sessionId, authorization} |
justifications/ssh/remove | {quote} | {kind, registry, removed, count} |
justifications/record | {kind, file, justification, expiresAt?, trajectoryEvidence?}, where kind is file; trajectoryEvidence is written as trajectory_evidence_justification beside the justification, as tama justify record --trajectory-evidence writes it | {recorded, kind, registry} |
tests/approvals | none | {approved, record}: every approval tama tests list reads |
tests/approve, tests/revoke | {paths}, an array of files or directories; a relative path is read against the home | {changed, action, approved, record}, the same change tama tests approve|revoke makes |
tests/audit | {roots, remove?}: repositories or directories holding them; remove: true deletes every unapproved test file | the document tama tests audit --json prints: {approval_record, repositories_read, approved, unapproved, remaining, repositories, failures} |
The justification operations reuse tama justify validation and registry transactions. They use the process's home and runtime transcript directory; a request cannot choose another home or transcript source. Recording requests reject unknown fields, and none of these operations issues capabilities, enables hooks or starts Cua Driver.
#Output and state
stdout carries only NDJSON events. A bounded operation prints exactly one:
{"type":"response","status":<status>,"json":{…}}
status is 200 for an answer, and json is the document the matching command prints. Any other status is a refusal named in HTTP's vocabulary — 400 a request the operation refuses, 403 an operation disabled on this machine, 404 an unknown operation, 500 a failure while it ran — and its json is {"error": "<one sentence>"}, the product's own refusal, verbatim.
A streamed job (violations/scan, violations/clean) prints its own output as it happens, then one result:
{"type":"log","stream":"stdout"|"stderr","chunk":"…"} (zero or more)
{"type":"result","status":<exit-code>,"json":{…}} (exactly one, last)
The result's status is the exit code the command would have ended with — for a scan, 1 means violations were found, not that the scan failed — and json is its document. A job refused before it starts prints one response instead. The process exits 0 after a 200 response, 1 after any other response, and with the job's own status after a result. Tama keeps no state of its own for a request; the operation writes what the matching command writes, and cleanup may modify the requested repository.
#Refusals and failures
- No operation:
request requires an operation, exit2, nothing on stdout. - A second positional argument:
unexpected request argument: <argument>, exit2. - Any option but
--root:unknown request option: <option>, andmissing value for --rootfor a bare--root; both exit2. - An unknown operation: a
404response,unknown operation: <operation>. - A body that does not parse: a
400response,request body is not valid JSON. - Unreadable stdin:
failed to read the request body from stdin: <reason>on stderr, exit1, nothing on stdout. - A missing
HOMEfor the build and justification operations: a500response,HOME is not set. - Policy import requires a nonempty
sourcePathand a supported bundle. Invalid input returns the core refusal; conflict and rejected results remain structured documents with no partial writes. - A reader that closes stdout ends the process at its next event. Tama Desktop ends the whole process tree when a scan or cleanup is cancelled or the app quits.
Return to the complete CLI command tree.