Chat
anyy chat sends a single prompt through the running Anyy gateway
and prints the reply. It is the non-interactive counterpart to the
interactive app: no TUI, no prompt loop — one prompt in, one
answer out. That makes it the building block for scripts, cron jobs, CI steps,
and any place you want an Anyy answer without a terminal session.
Because the work is served by the resident daemon, the gateway must already be
running (see Gateway). chat is a thin RPC client: it creates
or reuses a session, sends your text, and renders the assistant's final
message. For the full command surface see the CLI overview.
anyy chat [--home PATH] [--socket PATH] [--role ROLE] [--session ID] [--json] [--yes] PROMPT
The prompt is everything after the flags; multiple arguments are joined with spaces, so quoting is optional but recommended:
anyy chat "summarize my unread mail and list anything that needs a reply"
One-shot Prompt
A one-shot prompt creates a fresh session, runs a single turn, and prints the
assistant's text to standard output. Nothing else is written to stdout, so
the output is safe to capture:
reply=$(anyy chat "what's on my calendar tomorrow?")
echo "$reply"
Each invocation without --session starts a new session titled from the first
60 characters of your prompt. To continue an existing conversation instead, see
Session Selection.
Diagnostics (errors, warnings, continuation notices) always go to stderr, and
the assistant reply goes to stdout. This split lets you redirect them
independently:
anyy chat "draft a reply to the latest support email" \
>reply.txt 2>chat.log
Role Selection
--role ROLE selects the Role used when a new session is created. Roles
bundle a system prompt, default model, and tool policy (see
Sessions for how Roles and sessions relate):
anyy chat --role researcher "find three recent papers on local-first sync"
The global form anyy --role ROLE chat "..." is equivalent; the
command-level --role takes precedence when both are present.
--role only applies while creating a session, so it cannot be combined
with --session (which targets an already-created session). Passing both is a
usage error and exits 2:
✗ Cannot combine --role and --session
Reason:
--role only applies when creating a new session
Next:
omit --role, or start a new chat without --session
Session Selection
--session ID sends the prompt into an existing session instead of creating a
new one, so the turn sees that session's prior history, memory, and Role:
# First turn creates a session; capture its id from JSON output.
sid=$(anyy chat --json "start a trip plan for Kyoto" | jq -r .session_id)
# Continue the same conversation.
anyy chat --session "$sid" "add a day for day trips to Nara"
Session ids are stable. Capture one from anyy chat --json output (the
session_id field), or resume a session from the interactive app;
see Sessions for how sessions persist. Targeting a session
keeps multi-step scripts in a single coherent thread.
Approvals
When a turn wants to perform a state-changing or root-capable action, Anyy
raises an approval instead of acting silently. The interactive app prompts
you; anyy chat is non-interactive, so it applies a deterministic policy:
-
Default (no
--yes): deny. Any pending approvals are denied, the reply (if any) is still printed, and the command exits3:✗ Approval requiredReason:Anyy opened 1 pending approval(s), and noninteractive chat denies approvals by defaultNext:rerun with --yes to approve supported pending approvals -
--yes: approve supported approvals. Each pending approval is approved with reasonapproved by anyy chat --yes, thenchatwaits up to 10 seconds for the turn to continue and prints the final reply:anyy chat --yes "move yesterday's screenshots into ~/Archive/2026-06"
This makes --yes the explicit opt-in for unattended automation. Use it only
when you trust the prompt and the Role's tool policy, since it auto-approves the
actions a human would otherwise confirm. ChangePlan, approval, and audit
records are still written by the gateway regardless of how the decision is made.
If --yes approves everything but no new assistant text arrives within the
continuation window, chat prints a timeout notice to stderr and returns the
text it already had:
⚠ Continuation wait timed out
Reason:
no new assistant text arrived within 10s
Next:
open Anyy to inspect the session, or rerun anyy chat
Streaming Output
anyy chat is not a streaming client: it waits for the turn to finish
and then prints the assistant's final message in one block. There is no
token-by-token output and no --stream flag. For live, incremental output use
the interactive app.
In the default (human) mode only the assistant text is written, followed by a
trailing newline. If the turn produces no assistant text (for example, it only
denied an approval), nothing is printed to stdout and the exit code carries
the result.
JSON Mode
--json replaces the human reply with a single pretty-printed JSON object
describing the turn — ideal for scripting and for inspecting approvals or the
stop reason. The object is the only thing on stdout:
anyy chat --json "what timezone am I in?"
{
"session_id": "ses_01J9Z8...",
"turn_id": "trn_01J9Z8...",
"stop_reason": "completed",
"assistant_text": "You're in Asia/Shanghai (UTC+8).",
"approvals": []
}
Field shape:
| Field | Type | Meaning |
|---|---|---|
session_id | string | Session the turn ran in (new or the one from --session). |
turn_id | string | Identifier for this turn; empty if the turn never started. |
stop_reason | string | Why the turn ended, e.g. completed, max_iterations, output_limit. |
assistant_text | string | The assistant's final text (empty if none was produced). |
approvals | array | Approvals still open after the policy ran; empty when none remain. |
Each entry in approvals has this shape:
| Field | Type | Meaning |
|---|---|---|
id | string | Approval id. |
kind | string | Approval category (the action class). |
title | string | Short human-readable title. |
risk | string | Risk level reported for the action. |
summary | string | Longer description of what was requested. |
With --json and the default deny policy, denied approvals still appear in the
emitted object before the command exits 3, so a script can record exactly
what was refused:
anyy chat --json "delete every file in /tmp" \
| jq '.approvals[] | {id, kind, risk}'
Combine --json with --session to capture the id once and reuse it:
out=$(anyy chat --json "begin a standup summary")
sid=$(echo "$out" | jq -r .session_id)
anyy chat --json --session "$sid" "now add yesterday's blockers" \
| jq -r .assistant_text
Exit Codes
anyy chat uses exit codes so scripts can branch without parsing text:
| Code | Meaning | Typical cause |
|---|---|---|
0 | Success | The turn completed (and any approvals were approved). |
1 | Runtime error | Gateway not running / socket unreachable, or an RPC call failed. |
2 | Usage error | Missing prompt, unparseable flags, or --role combined with --session. |
3 | Approval denied | Pending approvals were denied by the default non-interactive policy. |
With --json, an exit of 3 is still accompanied by the JSON object (including
the denied approvals); exit codes 1 and 2 print only the error block on
stderr.
A runtime failure when the gateway is not running looks like this:
✗ Could not create chat session
Reason:
dial unix ~/.anyy/anyy.sock: connect: no such file or directory
Next:
start Anyy gateway, then run anyy chat again
Start the daemon first (anyy gateway start, see
Gateway) and retry. A scripting pattern that distinguishes the
"needs approval" case from a hard failure:
if anyy chat --yes "tidy my downloads folder"; then
echo "done"
else
case $? in
3) echo "blocked: an action needed approval the policy would not grant" ;;
2) echo "usage error — check the command" ;;
*) echo "gateway/runtime error — is the gateway up?" ;;
esac
fi
Selecting the gateway
By default chat finds the gateway socket from the active profile and home
directory. Override either when you run more than one Anyy, or in scripts
that target a specific instance:
--home PATH— use a specific Anyy home (also settable viaANYY_HOME); the socket is derived from it.--socket PATH— connect to an explicit gateway Unix socket, bypassing profile/home resolution.
anyy chat --socket ~/.anyy/anyy.sock "ping"
See Sessions for how sessions and Roles persist across calls, and the CLI overview for the rest of the command set.