Skip to content
capcom docs

JSON and KV output

Every capcom command prints plain text by default. For agents and scripts there are two machine-readable formats: --json, which every command takes, and --kv, which some commands take. Both are stable: a script written against them keeps working as capcom grows.

With --json, a command prints exactly one JSON object on one line, the envelope:

Terminal window
$ capcom show session-refresh --json
{"schema":1,"kind":"issue","data":[{"id":"session-refresh","path":".capcom/issues/login-flow/session-refresh.md","parent":"login-flow","title":"Refresh the session token","status":"open","category":"todo","type":"task","priority":2,"labels":[],"deps":["db-schema"],"aliases":[],"created":"2026-10-13T18:54:28Z","etag":"e07aed565d368a66","body":"","related":[],"ready":true,"dependents":[]}],"elsewhere":[],"warnings":[]}
Member Always present Value
schema yes The envelope’s version, currently 1.
kind yes What data holds: issue, issue-write, close, ready, prime, check, version, …, or error.
data no The command’s result. Left out when a command fails before it has one. null when capcom next finds nothing Ready (kind next, exit code 4).
error no Present only when the command failed; see Errors below.
elsewhere yes Issue changes on other branches, [] when there are none or the command does not scan.
warnings yes Warning messages, [] when there are none.

An Issue in data (show, list, ready, prime, dep list) carries "standing": true when it is a Standing Parent; the member is left out otherwise. Such an Issue always has "ready": false, and its standing member is what holds it back.

--json is a global flag, so it may stand before or after the command name.

schema changes only when an existing field changes its meaning or disappears. New fields can appear in data at any time without a change of schema, so a parser should ignore members it does not know. Check schema once, and treat any value other than the one you were written for as a reason to stop.

A warning never fails a command. In --json it goes into warnings, beside a normal result:

Terminal window
$ capcom create --id audit-log2 --title "Log failed logins" --json
{"schema":1,"kind":"issue-write","data":{"etag":"58756f0fb416f617","id":"audit-log2","path":".capcom/issues/audit-log2.md"},"elsewhere":[],"warnings":["audit-log2 has no body: state what, why and a \"## Acceptance\" section with capcom update audit-log2 --body-append-file <file>"]}

A file capcom cannot read (a bad issue file, say) is reported as a warning by every command that reads the store, until it is fixed; the rest of the store stays usable. How each problem with a file is worded and located is described under Errors in the file format reference.

A command that fails sets error, with a code, a message and, when a file is to blame, its path and line:

Terminal window
$ capcom dep add login-flow write-docs --json
{"schema":1,"kind":"error","error":{"code":"invalid","message":"login-flow cannot depend on write-docs: that would create the cycle login-flow -> write-docs -> login-flow","path":".capcom/issues/login-flow.md"},"elsewhere":[],"warnings":[]}

A command that fails on part of its work keeps its own kind and sets both data and error:

Terminal window
$ capcom close nosuch --reason x --json
{"schema":1,"kind":"close","data":[{"id":"nosuch","outcome":"not_found","now_ready":[]}],"error":{"code":"not_found","message":"id \"nosuch\" not found"},"elsewhere":[],"warnings":[]}

A refusal of a status rule is invalid; closing or claiming a Standing Parent, say:

Terminal window
$ capcom update feature-requests --status active --json
{"schema":1,"kind":"error","error":{"code":"invalid","message":"the issue is standing: it only groups its children and is never claimed or closed; run capcom update feature-requests --no-standing first","path":".capcom/issues/feature-requests.md"},"elsewhere":[],"warnings":[]}

A mistyped command or subcommand also sets suggestion, the path below capcom of the closest valid one; it is left out when none is close:

Terminal window
$ capcom know shwo x --json
{"schema":1,"kind":"error","error":{"code":"invalid","message":"unknown command \"shwo\" for \"capcom know\"","suggestion":"know show"},"elsewhere":[],"warnings":[]}

A mistyped long flag sets it to the closest flag of that command, its own or one it inherits such as --json; an unknown shorthand such as -z gets none:

Terminal window
$ capcom update x --statsu active --json
{"schema":1,"kind":"error","error":{"code":"invalid","message":"unknown flag: --statsu","suggestion":"--status"},"elsewhere":[],"warnings":[]}

code is one of a closed set:

Code Meaning Exit code
not_found No Issue, Note or lock matches. 3
locked Another session holds the Tree lock. 3
exists The id or alias is already taken. 1
invalid The input or a file is not valid. 1 (2 for a usage error)
conflict The file changed under you: its etag no longer matches --if-match, or it changed while the command ran. 1
not_initialized There is no capcom store here; run capcom init. 1
Exit code Meaning
0 Success. Warnings may still have been reported.
1 An error.
2 A usage error: an unknown command or flag, a flag that holds one value given more than once, or a wrong number of arguments.
3 Not found, or locked.
4 Nothing is Ready: capcom next found no Issue to print. Used for nothing else.

capcom check and capcom fmt --check exit 1 when they find something to report, and capcom prime always exits 0.

--kv prints KEY=VALUE lines, one per field, and ends each record with a STATUS= line: ok, an outcome such as closed, or an error code. It is meant for shell scripts, which can read a value with a sed or a grep instead of a JSON parser:

Terminal window
$ capcom create --id audit-log --title "Log failed logins" --kv
WARNING=audit-log has no body: state what, why and a "## Acceptance" section with capcom update audit-log --body-append-file <file>
ID=audit-log
PATH=.capcom/issues/audit-log.md
ETAG=58756f0fb416f617
STATUS=ok

A command that acts on several ids prints one record per id:

Terminal window
$ capcom close audit-log audit-log2 --reason "not needed" --status dropped --kv
ID=audit-log
STATUS=closed
ID=audit-log2
STATUS=closed

A failure is a record too, with a MESSAGE= line and the error code as its status:

Terminal window
$ capcom show nosuch --kv
ID=nosuch
MESSAGE=id "nosuch" not found
STATUS=not_found

A failure that carries a suggestion in --json adds it as a SUGGESTION= line just before its STATUS= line:

Terminal window
$ capcom shwo nosuch --kv
MESSAGE=unknown command "shwo" for "capcom"
SUGGESTION=show
STATUS=invalid

Unlike --json, --kv is offered only by some commands, it goes after the command name, and it leaves out the Elsewhere report. Which commands take it, and where its WARNING= lines go relative to STATUS=, are listed in the paragraph on output in the README’s What it does section.