afdata CLI reference

A naming convention that lets AI agents understand your data without being told what it means, plus a CLI and library for reading Markdown structure and safely editing structured JSON, TOML, YAML, dotenv, and INI documents.

afdata is compiled from a closed cli-spec-v1 registry: one source for argv parsing, typed invocation values, which parameter combinations are legal, output contracts, and help. An invocation runs only when it matches exactly one registered combination.

Global arguments

AFDATA registers these itself, so the syntax in Commands leaves them out.

ArgumentWhereWhat it does
--helpevery commandEvery legal shape of that command, complete, plus its subcommands. JSON by default; --output plain for a terminal.
--versionafdata onlyName, version, and build identity as one protocol result.
--docsafdata onlyThis document, rendered from the registry.
--output <FORMAT>per output contractRender as json, yaml, plain (default json).
--output-to <DESTINATION>per output contractRoute results and diagnostics to split, stdout, stderr (default split).
--stdout-file <PATH>, --stderr-file <PATH>per output contractAppend that stream to a file instead.

Success output is protocol events, on those terms, unless a command’s own Output line says otherwise.

A shape is one legal set of arguments that may appear together, under a stable id. Where a command has more than one, each id is a heading below. --help returns them all at once, so discovering a command costs one call; there is no recursive mode across commands, and this document is that view.

Commands

afdata add

Add an element to a keyed list

afdata add <FILE> <KEY> <SLUG> [<FIELD=VALUE>...] --slug-field <FIELD> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>]
ArgumentMeaning
FILEDocument file to mutate
KEYDot-path to the keyed list
SLUGNew element slug
FIELD=VALUEAdditional string fields
--slug-fieldField that identifies each list element
--input-formatDocument format override

afdata emit error

Emit a terminal error event

afdata emit error <CODE> <MESSAGE> [--hint <HINT>] [--retryable]
ArgumentMeaning
CODEStable error code
MESSAGEError message
--hintSuggested corrective action
--retryableMark the failure safe to retry

afdata emit log

Emit a diagnostic log event

afdata emit log <debug|info|warn|error> <MESSAGE>
ArgumentMeaning
LEVELdebug, info, warn, or error
MESSAGEHuman-readable message

afdata emit result

Emit a terminal result event

afdata emit result <MESSAGE>
ArgumentMeaning
MESSAGEResult message

afdata get

Read a document or one value as an AFDATA result

get-document — Read the entire document

afdata get <FILE> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--secret-name <FIELD>...]

get-value — Read one value at KEY

afdata get <FILE> <KEY> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--slug-field <FIELD>] [--secret-name <FIELD>...]

Arguments across every shape above:

ArgumentMeaning
FILEDocument file, or - for stdin
KEYOptional dot-path
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path
--secret-nameExtra exact field name to redact

afdata guard

Validate a value against a destructive-verb operand type and print its normalized absolute path as raw stdout bytes

afdata guard <path|tmp_path|cwd_path> <VALUE> [--under <ROOT>]

Output: raw bytes on success; rejects --output and --output-to; redirect with --stdout-file or --stderr-file. Failures are still strict JSON on stderr.

ArgumentMeaning
TYPEpath: no containment beyond the shared reject set; tmp_path: must sit strictly under the system temp area; cwd_path: must sit strictly under the current directory
VALUEValue to validate, e.g. the contents of a shell variable
--underAdditional containment root VALUE must sit strictly under, for a target anchored to a directory the caller knows and the TYPE vocabulary cannot name

afdata keys

List child names as raw lines, without their parent path

keys-root — List the document root’s immediate children

afdata keys <FILE> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--null]

keys-container — List one addressed container’s immediate children

afdata keys <FILE> <KEY> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--slug-field <FIELD>] [--missing-ok] [--null]

Output: raw bytes on success; rejects --output and --output-to; redirect with --stdout-file or --stderr-file. Failures are still strict JSON on stderr.

Arguments across every shape above:

ArgumentMeaning
FILEDocument file, or - for stdin
KEYOptional container dot-path
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path
--missing-okSucceed with no output when KEY is absent
--nullUse NUL separators

afdata lint

Lint structured data for deterministic AFDATA issues

afdata lint <INPUT> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>] [--min-severity <warning|error>]
ArgumentMeaning
INPUTInput file, or - for stdin
--input-formatDocument format override
--min-severityLowest severity to report; error drops the heuristic checks

afdata paths

List each child’s full dot-path as raw lines

paths-root — List the document root’s immediate children

afdata paths <FILE> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--null]

paths-container — List one addressed container’s immediate children

afdata paths <FILE> <KEY> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--slug-field <FIELD>] [--missing-ok] [--null]

Output: raw bytes on success; rejects --output and --output-to; redirect with --stdout-file or --stderr-file. Failures are still strict JSON on stderr.

Arguments across every shape above:

ArgumentMeaning
FILEDocument file, or - for stdin
KEYOptional container dot-path
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path
--missing-okSucceed with no output when KEY is absent
--nullUse NUL separators

afdata remove

Remove a keyed-list element by slug

afdata remove <FILE> <KEY> <SLUG> --slug-field <FIELD> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>]
ArgumentMeaning
FILEDocument file to mutate
KEYDot-path to the keyed list
SLUGElement slug
--slug-fieldField that identifies each list element
--input-formatDocument format override

afdata render

Render JSON or JSONL through AFDATA redaction and formatting

afdata render <INPUT> [--secret-name <FIELD>...]
ArgumentMeaning
INPUTInput file, or - for stdin
--secret-nameExtra exact field name to redact

afdata set

Set a value at a dot-path, creating missing object parents

set-value — Set one typed scalar or JSON value

afdata set <FILE> <KEY> <VALUE> [--value-type <string|number|bool|json>] [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>] [--slug-field <FIELD>]

set-null — Set the key to null; takes no VALUE

afdata set <FILE> <KEY> --value-type null [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>] [--slug-field <FIELD>]

set-secret — Set the key from a secret source, never from argv

afdata set <FILE> <KEY> --secret-from <SOURCE> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>] [--slug-field <FIELD>]

Arguments across every shape above:

ArgumentMeaning
FILEDocument file to mutate
KEYDot-path to set
VALUEValue to write
--value-typeExact VALUE type
--secret-fromRead a secret string from stdin, prompt, fd:N, or env:VAR
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path

afdata shell bash

Print the sourceable Bash authoring kit

afdata shell bash

Output: raw bytes on success; rejects --output and --output-to; redirect with --stdout-file or --stderr-file. Failures are still strict JSON on stderr.

afdata skill install

Install the bundled Agent Skill

skill-install-all — Install into every agent that supports the scope

afdata skill install [--agent all] [--scope <personal|workspace>] [--force]

skill-install-agent — Install into one named agent; only this shape accepts –skills-dir

afdata skill install --agent <codex|claude-code|opencode|hermes> [--scope <personal|workspace>] [--skills-dir <PATH>] [--force]

Arguments across every shape above:

ArgumentMeaning
--agentTarget agent
--scopeSkill scope
--skills-dirExplicit directory; only valid with one concrete agent
--forceOverwrite or remove an unmanaged skill

afdata skill status

Report whether the bundled Agent Skill is installed and current

skill-status-all — Report on every agent that supports the scope

afdata skill status [--agent all] [--scope <personal|workspace>]

skill-status-agent — Report on one named agent; only this shape accepts –skills-dir

afdata skill status --agent <codex|claude-code|opencode|hermes> [--scope <personal|workspace>] [--skills-dir <PATH>]

Arguments across every shape above:

ArgumentMeaning
--agentTarget agent
--scopeSkill scope
--skills-dirExplicit directory; only valid with one concrete agent

afdata skill uninstall

Remove an afdata-managed Agent Skill

skill-uninstall-all — Remove from every agent that supports the scope

afdata skill uninstall [--agent all] [--scope <personal|workspace>] [--force]

skill-uninstall-agent — Remove from one named agent; only this shape accepts –skills-dir

afdata skill uninstall --agent <codex|claude-code|opencode|hermes> [--scope <personal|workspace>] [--skills-dir <PATH>] [--force]

Arguments across every shape above:

ArgumentMeaning
--agentTarget agent
--scopeSkill scope
--skills-dirExplicit directory; only valid with one concrete agent
--forceOverwrite or remove an unmanaged skill

afdata skill validate

Validate an Agent Skill

afdata skill validate <INPUT>
ArgumentMeaning
INPUTSKILL.md file, directory, or - for stdin

afdata unset

Remove one document entry

afdata unset <FILE> <KEY> [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter>] [--slug-field <FIELD>]
ArgumentMeaning
FILEDocument file to mutate
KEYDot-path to remove
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path

afdata validate

Validate protocol-v1 events or a finite event stream

afdata validate <INPUT> [--strict] [--per-event]
ArgumentMeaning
INPUTInput file, or - for stdin
--strictEnforce the strict protocol profile
--per-eventValidate values independently without stream lifecycle rules

afdata value

Read one scalar as raw stdout bytes

afdata value <FILE> <KEY> [--reveal-secret] [--default <VALUE>] [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--slug-field <FIELD>] [--secret-name <FIELD>...]

Output: raw bytes on success; rejects --output and --output-to; redirect with --stdout-file or --stderr-file. Failures are still strict JSON on stderr.

ArgumentMeaning
FILEDocument file, or - for stdin
KEYDot-path to one scalar
--reveal-secretAllow a secret-named leaf
--defaultFallback for missing or null
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path
--secret-nameExtra exact field name to redact

afdata values

Read many scalars as raw lines, from one parse of the document

afdata values <FILE> <KEY>... [--reveal-secret] [--default <VALUE>] [--input-format <json|toml|yaml|yml|dotenv|env|ini|toml-frontmatter|yaml-frontmatter|markdown>] [--slug-field <FIELD>] [--secret-name <FIELD>...]

Output: raw bytes on success; rejects --output and --output-to; redirect with --stdout-file or --stderr-file. Failures are still strict JSON on stderr.

ArgumentMeaning
FILEDocument file, or - for stdin
KEYDot-path to one scalar; repeat for each value wanted
--reveal-secretAllow a secret-named leaf
--defaultFallback for missing or null
--input-formatDocument format override
--slug-fieldField naming each element of an array on the path
--secret-nameExtra exact field name to redact

Exit codes

CodeMeaning
0The command ran and succeeded.
1The command ran and failed. The event carries a domain error.code.
2The invocation was rejected before anything ran. error.code is one of the cli_* codes below.

The split is the useful one for a caller: exit 2 means the call was never made, so retrying it unchanged cannot help, while exit 1 means it was.

CLI errors

Every structural failure emits one strict JSON kind:"error" event on stderr, leaves stdout empty, and exits 2. The code names the failure — cli_unknown_argument for an unknown spelling, cli_unregistered_combination for registered arguments in a mixture that is not, and one each for cli_unknown_command, cli_missing_argument_value, cli_invalid_argument_value, cli_duplicate_argument, cli_unexpected_positional, and cli_invalid_utf8. message identifies a safe argument spelling or the failure category and hint gives the command to run next; neither ever quotes a raw value, including secrets. These are decided before any config, secret source, filesystem, network, or domain I/O.

Two exit-1 codes describe the tool itself rather than the call: cli_invocation_invalid means the program misread its own resolved invocation — an unknown action id, or an argument id the selected combination cannot produce — and output_setup_failed means an output sink (--stdout-file, --stderr-file, stream redirection) could not be established. Both are defects to report, not inputs to correct; retrying the same command cannot help.

Domain failures (exit 1) carry their own stable error.code instead, drawn from whatever this tool defines rather than from the cli_* set. Error events are routinely logged, so a message never quotes a value that came from an argument able to carry a credential — a header, a cookie, a token, a password, a proxy URL, an environment value, a form field. Such an error names the argument and the shape that was wrong, and stops there. A value that cannot be a secret — a path, a dot-path, a session name — is quoted, because an error that cannot say which one it means is not worth logging either.