CLI commands

arizukoreference › CLI commands

Every subcommand of the arizuko binary, grouped by concern. Each entry shows the exact signature, the flags flag.NewFlagSet registers, what state changes where, and a source link pointing at the dispatch site. Ground truth is cmd/arizuko/main.go; the dispatch map sits at main.go:54.

The CLI uses Go's standard flag package plus a hand-rolled positional dispatcher — no cobra. Top-level verb is os.Args[1]; subcommand verb (where applicable) is args[1] after the instance name. <instance> is the data-dir suffix; resolved via $ARIZUKO_DATA_DIR/arizuko_<name> or ${PREFIX:-/srv}/data/arizuko_<name> (main.go:146).

Index

Instance lifecycle

arizuko create <name> [--product <product>]

Seed an instance data dir, write .env with a generated CHANNEL_SECRET, open store/, insert the default main group, set up its group folder, and seed default tasks. If --product is given, reads ant/examples/<product>/PRODUCT.md, prints the env checklist, and copies the product's skills/facts into the new group.

FlagTypeDefaultEffect
--productstring""Product template name; looked up under $HostAppDir/ant/examples/<product>/PRODUCT.md. On miss, prints known products and exits non-zero.

State touched: creates ${PREFIX:-/srv}/data/arizuko_<name>/, writes .env (mode 0600), opens store/messages.db, inserts main group, calls container.SetupGroup for folder skeleton, seeds default tasks. Idempotent on .env (only written when missing).

arizuko create solo
arizuko create launch --product strategy

Source: cmd/arizuko/main.go:161

arizuko generate <instance>

Generate docker-compose.yml in the instance dir from compose.Generate. Atomic write via tempfile + rename; mode 0644.

State touched: writes <data-dir>/docker-compose.yml only.

arizuko generate krons

Source: cmd/arizuko/main.go:100

arizuko run <instance>

Generate the compose file (same path as generate), then docker compose -f <compose> up --remove-orphans. Foreground process; SIGINT propagates to the compose stack.

State touched: writes the compose file, then leaves long-lived docker state under control of docker.

arizuko run krons

Source: cmd/arizuko/main.go:89

arizuko status <instance>

docker compose ps against the instance compose file, then GET http://localhost:<APIPort>/v1/channels on the router with a 10s timeout. Prints registered channel name → URL pairs, or a "router API unreachable" / "no channels registered" line.

State touched: read-only. Requires docker-compose.yml to exist (will die with a "run 'arizuko generate' first" hint).

arizuko status krons

Source: cmd/arizuko/main.go:721

arizuko pair <instance> <service> [args...]

Run a one-shot pairing/admin shell against a compose service: docker compose -f <compose> run --rm <service> [args...]. Used for interactive setup of channel adapters (e.g. whapd QR pairing).

State touched: whatever the chosen service does. --rm removes the container on exit.

arizuko pair krons whapd
arizuko pair krons mastd login --instance mas.to

Source: cmd/arizuko/main.go:699

Config manifests

The cold-tier config of an instance — groups, acl, routes, web_routes, secrets, scheduled tasks, network rules, onboarding gates, proxyd routes — reads and writes as one YAML document. The same resreg engine that serves these resources over REST, MCP, and /openapi.json also drives export and apply, so the YAML shape matches the schema exactly. Spec specs/5/36-yaml-manifests.md.

arizuko export <instance> [output.yaml]

Dump the instance's cold-tier resources as one YAML document. Keys sort deterministically — config_version first, then resources by name — so re-exporting an unchanged store yields byte-identical output, which makes the file diffable in git. Writes to the named file if given; otherwise to stdout (the byte-count line goes to stderr so a redirect captures only YAML).

State touched: read-only.

arizuko export krons > krons-config.yaml
arizuko export krons krons-config.yaml

Source: cmd/arizuko/apply.go:69

arizuko apply <instance> <manifest.yaml> [--force]

Replace the instance's cold-tier resources with the manifest's. For each resource named in the file, the engine runs DELETE FROM <table> then re-inserts the manifest rows — all in one transaction. A resource absent from the manifest is left untouched; a resource present but empty is cleared. The manifest's config_version must match the store's, or apply exits 2 and tells you to re-export and re-apply — this is the guard against overwriting a change made since you exported. Validation runs before the DB is touched, so a malformed file changes nothing. On success the config_version bumps by one.

FlagTypeDefaultEffect
--forceboolfalseSkip the config_version match check and apply anyway. The version still advances. Use when you intend to overwrite concurrent edits.

State touched: rewrites every table named in the manifest, in one transaction. Deleting a group cascades to its web_routes and route_tokens (declared FKs, migrations 0068/0069) — the URL routes pinned to a removed group go with it.

arizuko export krons > krons.yaml
# edit krons.yaml
arizuko apply krons krons.yaml
arizuko apply krons krons.yaml --force

Source: cmd/arizuko/apply.go:29

Operator chat & messaging

arizuko chat <instance>

Launch claude (Claude Code CLI) wired via socat to the instance's root MCP socket at <data-dir>/ipc/main/gated.sock. Writes a temporary mcpServers config pointing at socat STDIO UNIX-CONNECT:<sock> and execs claude --mcp-config <tmp>. Local-operator only — socket-fs access is the auth.

State touched: none on disk beyond a deleted-on-exit tempfile. Anything the agent does via MCP tools mutates the store as usual.

Prereqs: instance running (socket exists), claude and socat on $PATH.

arizuko chat krons

Source: cmd/arizuko/main.go:657

arizuko send <instance> <folder> [<message>] [--wait | --stream] [--stdin] [--topic <t>]

POST a message to a group's chat endpoint, optionally blocking until the agent's turn finishes. Resolves a web:<folder> token from route_tokens and reads WEB_HOST from .env; scheme is http for localhost/127.0.0.1, otherwise https. See specs/5/W-webhook-routes.md for the token model.

FlagTypeDefaultEffect
--waitboolfalseAfter POST, poll /chat/<token>/<turn_id>?after=<seq> at 1s cadence, print frames, exit 0 on success / 1 on failed.
--streamboolfalseSame as --wait but subscribes to .../sse instead of polling. Exit codes: 0 success, 1 failed, 2 transport error.
--stdinboolfalseRead message body from stdin (trimmed) instead of the positional arg.
--topicstringauto-genConversation thread id. Reuse the same value across calls to keep the agent in the same context.

State touched: opens the instance store read-only to look up the chat token; everything else happens server-side via the /chat/<token>/ endpoint.

arizuko send krons main "hello from cli"
arizuko send krons main "what's the status?" --stream
echo "long body" | arizuko send krons main --stdin --wait

Source: cmd/arizuko/send.go:29

Groups & grants

All group verbs share the same store and dispatch under cmd/arizuko/main.go:256.

arizuko group <instance> list

List all groups as tab-separated folder\tname.

State touched: read-only.

arizuko group krons list

Source: cmd/arizuko/main.go:268

arizuko group <instance> add <jid> <folder> [--product <name>]

Create a group bound to a channel JID. Folder is validated via groupfolder.IsValidFolder. Calls container.SetupGroup for the folder skeleton (optionally seeded from a product template under $HostAppDir/ant/examples/<product>/), seeds default tasks, inserts the group row, then adds a route room=<JidRoom(jid)> -> <folder>. For Discord guild channels (jid prefix discord: but not discord:dm/) the route is scoped to verb=mention so only mentions fire; other messages fall through to a catch-all #observe row.

FlagTypeDefaultEffect
--productstring""Product template applied to this group (same set as arizuko create --product). On miss, errors with the expected PRODUCT.md path.

State touched: filesystem (group skeleton), groups, routes, default-task seed.

arizuko group krons add whatsapp:120363042@g.us standup
arizuko group krons add "discord:guild/123/456" eng --product developer

Source: cmd/arizuko/main.go:275 (v0.40.6 added --product)

arizuko group <instance> rm <folder>

Delete the group row by folder via store.DeleteGroup. Does not remove the on-disk group directory or routes pointing at it; clean those up manually if needed.

State touched: groups table.

arizuko group krons rm standup

Source: cmd/arizuko/main.go:313

arizuko group <instance> grant <sub> <pattern>

Authorize sub on a scope. The literal pattern ** writes acl_membership(sub, role:operator) (the operator role's permissions live on the role, not duplicated per user); any other pattern writes an acl(principal=sub, action=admin, scope=pattern, effect=allow) row. Idempotent. See grants reference for syntax.

State touched: acl_membership (for **) or acl table.

arizuko group krons grant google:alice@example.com 'solo/**'
arizuko group krons grant telegram:42 'corp/eng/sre'
arizuko group krons grant google:operator@example.com '**'   # operator role

Source: cmd/arizuko/main.go:347

arizuko group <instance> ungrant <sub> <pattern>

Reverse of grant. ** removes the operator-role membership edge; any other pattern deletes the matching acl row.

State touched: acl_membership (for **) or acl table.

arizuko group krons ungrant google:alice@example.com 'solo/**'

Source: cmd/arizuko/main.go:327

arizuko group <instance> grants [<sub>]

List grants. With no sub, lists all grants. With a sub, filters to that subject. Tab-separated SUB | PATTERN | GRANTED_AT.

State touched: read-only.

arizuko group krons grants
arizuko group krons grants google:alice@example.com

Source: cmd/arizuko/main.go:333

Identities

Identities unify multiple subject IDs (google:, telegram:, github:…) under one logical user. Dispatcher at main.go:550.

arizuko identity <instance> list

List all identities and the subs claimed by each. Columns: ID | NAME | CREATED_AT | SUBS (comma-joined).

State touched: read-only.

arizuko identity krons list

Source: cmd/arizuko/main.go:562

Bind sub to an identity. With no --id, creates a new identity (display name is --name or, if empty, sub) and adds sub as its first claim. With --id, attaches sub to that existing identity.

FlagTypeDefaultEffect
--namestring""Display name when creating a new identity. Ignored if --id is set.
--idstring""Existing identity ID to attach sub to; bypasses creation.

State touched: identities, identity_subs.

arizuko identity krons link google:alice@example.com --name Alice
arizuko identity krons link telegram:42 --id id_a1b2c3

Source: cmd/arizuko/main.go:566

Remove the claim row for sub. Prints "no claim to remove" if there was none.

State touched: identity_subs.

arizuko identity krons unlink telegram:42

Source: cmd/arizuko/main.go:577

Invites

Onboarding tokens consumed by onbod's invite landing. Dispatcher at main.go:473.

arizuko invite <instance> create <target_glob> [--max-uses N] [--expires DURATION]

Mint an invite token whose redemption grants the user the given target_glob pattern. Prints token, target, max-uses, optional expiry.

FlagTypeDefaultEffect
--max-usesint1Maximum redemptions. Rejected if < 1.
--expiresduration0 (no expiry)Time-from-now after which the token is dead. Parsed by time.ParseDuration (24h, 72h30m, …).

State touched: invites table; issued_by_sub is set to the literal "cli".

arizuko invite krons create 'solo/**' --max-uses 1 --expires 72h
arizuko invite krons create 'corp/eng/**' --max-uses 5

Source: cmd/arizuko/main.go:485

arizuko invite <instance> list [--issued-by SUB]

List invites. Columns: TOKEN | TARGET_GLOB | ISSUED_BY | ISSUED_AT | EXPIRES_AT | USED (where USED is used_count/max_uses).

FlagTypeDefaultEffect
--issued-bystring""Filter to invites issued by a specific subject. Empty = all.

State touched: read-only.

arizuko invite krons list
arizuko invite krons list --issued-by cli

Source: cmd/arizuko/main.go:512

arizuko invite <instance> revoke <token>

Revoke a token by ID. Future redemption attempts fail.

State touched: invites row marked revoked.

arizuko invite krons revoke inv_abc123

Source: cmd/arizuko/main.go:538

Gates (rate limits)

Per-spec daily limits enforced inside gated. Dispatcher at main.go:402.

arizuko gate <instance> list

List gates as GATE | LIMIT/DAY | ENABLED. Prints no gates if empty.

State touched: read-only.

arizuko gate krons list

Source: cmd/arizuko/main.go:414

arizuko gate <instance> add <spec> <N>/day

Upsert a gate at the given daily limit. Limit string accepts an optional /day suffix (stripped); must parse as a positive integer.

State touched: gates table.

arizuko gate krons add solo/inbox 200/day
arizuko gate krons add 'corp/eng/**' 1000

Source: cmd/arizuko/main.go:434

arizuko gate <instance> rm <spec>

Delete a gate row by spec.

State touched: gates table.

arizuko gate krons rm solo/inbox

Source: cmd/arizuko/main.go:447

arizuko gate <instance> enable <spec>

Flip enabled to true on the row.

State touched: gates table.

arizuko gate krons enable solo/inbox

Source: cmd/arizuko/main.go:454

arizuko gate <instance> disable <spec>

Flip enabled to false on the row. The row stays so the spec/limit survives re-enable.

State touched: gates table.

arizuko gate krons disable solo/inbox

Source: cmd/arizuko/main.go:461

Budget (cost caps)

Per-folder and per-user daily spend caps in cents. The pre-spawn gate in gateway/ refuses to spawn when today's spend exceeds the lower of (folder cap, user cap). Caps live on groups.cost_cap_cents_per_day and auth_users.cost_cap_cents_per_day; spend is summed from cost_log. Spec 5/34. Dispatcher at budget.go:18.

arizuko budget <instance> set <folder|user> <name|sub> --daily N

Set a daily cap (in cents) on a folder or user. --daily 0 removes the cap (uncapped). Negative values are rejected.

FlagTypeDefaultEffect
--dailyintrequiredDaily cap in cents. 0 = uncapped (cap row removed).

State touched: groups.cost_cap_cents_per_day (folder scope) or auth_users.cost_cap_cents_per_day (user scope).

arizuko budget krons set folder corp/eng --daily 5000
arizuko budget krons set user google:alice@example.com --daily 1000
arizuko budget krons set folder solo/inbox --daily 0   # uncapped

Source: cmd/arizuko/budget.go:30

arizuko budget <instance> show <folder|user> <name|sub>

Print the cap, today's spend, remaining budget, and a status line (ok, WARN at ≥80%, EXHAUSTED when turns will be refused). Tab-aligned key/value table.

State touched: read-only.

arizuko budget krons show folder corp/eng
arizuko budget krons show user google:alice@example.com

Source: cmd/arizuko/budget.go:43

Network allowlist

Per-folder egress rules consumed by the crackbox proxy. Walks the folder ancestry on resolve. Dispatcher at network.go:12.

arizuko network <instance> allow <folder> <target>

Add an allow rule binding a folder to a hostname (or other target form supported by store.AddNetworkRule). created_by is set to the literal "cli".

State touched: network_rules table.

arizuko network krons allow main api.github.com
arizuko network krons allow corp/eng api.openai.com

Source: cmd/arizuko/network.go:24

arizuko network <instance> deny <folder> <target>

Remove a previously-added allow rule. Naming preserves the operator-mental-model (allow + deny as paired verbs); under the hood it's a row delete via store.RemoveNetworkRule.

State touched: network_rules table.

arizuko network krons deny main api.github.com

Source: cmd/arizuko/network.go:32

arizuko network <instance> list [<folder>]

List rules. Without <folder>, lists all. With a folder, lists that folder's own rows (not inherited ones — use resolve for that). Columns: FOLDER | TARGET | CREATED_AT | CREATED_BY (root rows render as (root)).

State touched: read-only.

arizuko network krons list
arizuko network krons list corp/eng

Source: cmd/arizuko/network.go:40

arizuko network <instance> resolve <folder>

Print the fully resolved allowlist for a folder — walks ancestry, dedupes, includes default seeds (anthropic.com, api.anthropic.com from migration 0037). One target per line. Useful for verifying what crackbox will accept for a given folder.

State touched: read-only.

arizuko network krons resolve corp/eng/sre

Source: cmd/arizuko/network.go:66

Secrets (folder & user)

Folder-scoped and user-scoped secrets backing the secret-broker model (see specs/9/11-crackbox-secrets.md). Keys must match ^[A-Z][A-Z0-9_]*$ (validated by keyValid at secret.go:132).

Status: cmd/arizuko/secret.go is currently uncommitted on the working branch. The feature ships under spec 9/11 (folder + user scopes, REST + MCP surface). Commands documented here reflect the in-flight implementation; signatures will land in the next tag.

arizuko secret <instance> set <folder> KEY --value V

Store a folder-scoped secret. --value is required; empty values rejected. Key is validated against the uppercase ENV-style pattern.

FlagTypeDefaultEffect
--valuestring""Secret value. Required, must be non-empty.

State touched: secrets table, scope_kind = folder.

arizuko secret krons set corp/eng GITHUB_TOKEN --value ghp_xxxxxxxxxxxx
arizuko secret krons set main OPENAI_API_KEY --value sk-xxxxxxxx

Source: cmd/arizuko/secret.go:28

arizuko secret <instance> list <folder>

List keys (not values) for a folder. Columns: KEY | CREATED_AT. Prints no secrets if empty.

State touched: read-only.

arizuko secret krons list corp/eng

Source: cmd/arizuko/secret.go:38

arizuko secret <instance> delete <folder> KEY

Delete one folder-scoped key.

State touched: secrets table row delete.

arizuko secret krons delete corp/eng GITHUB_TOKEN

Source: cmd/arizuko/secret.go:43

arizuko user-secret <instance> set <user_sub> KEY --value V

Operator fallback for setting a user-scoped secret on behalf of a user who hasn't logged in via /dash/me/secrets yet. Same key validation as secret set.

FlagTypeDefaultEffect
--valuestring""Secret value. Required, must be non-empty.

State touched: secrets table, scope_kind = user.

arizuko user-secret krons set google:alice@example.com GITHUB_TOKEN --value ghp_xxx

Source: cmd/arizuko/secret.go:67

arizuko user-secret <instance> list <user_sub>

List keys for one user sub. Columns: KEY | CREATED_AT.

State touched: read-only.

arizuko user-secret krons list google:alice@example.com

Source: cmd/arizuko/secret.go:77

arizuko user-secret <instance> delete <user_sub> KEY

Delete one user-scoped key.

State touched: secrets table row delete.

arizuko user-secret krons delete google:alice@example.com GITHUB_TOKEN

Source: cmd/arizuko/secret.go:82

See also