Chat
subs chat is an agent session in your terminal. It is a channel, like
Slack: a line you type becomes a client message, and the event
stream becomes text.
subs chat assistantassistant
model claude-sonnet-5
llm claude (anthropic)
session 01a02417-7d46-7441-8090-23b20d0f980f
> what is the capital of Portugal?
The capital of Portugal is Lisbon.
> how far is it from Madrid?
About 500 km.
>subs run sends one message and exits, so a second message needs --session
and a second process. Chat holds the session, so the next question can depend on
the last one.
Where the turn runs
The file decides, as it does for every other command. A file that names no
[remote] describes an engine here, so chat starts one in the process and the
session lands in this machine's database. A file that names one describes a
deployment, so chat streams the turn from there.
subs chat assistant # the file decides
subs chat assistant --url http://localhost:8080 # a deployment, for this chat--url also points at a subs serve you are running, which is how to chat with
the engine that answers your Slack workspace.
See CLI.
The session
A chat with no --session opens a new one and prints its ID. Ctrl-D ends the
chat and prints the command to pick it back up.
continue this session with:
subs chat assistant --session 01a02417-7d46-7441-8090-23b20d0f980fThe session is durable and outlives the process. subs sessions list shows it,
subs run --session adds a turn to it, and a Slack thread on the same engine is
the same kind of thing. See Conversations.
Editing and history
↑ walks the lines you have typed, in this chat and in earlier ones. The
history file is beside your credentials, at ~/.config/subs/chat_history.
A line ending in \ is not finished, so Enter opens the next one and the
message carries the newline. Alt-Enter and Ctrl-J do the same.
> summarise this: \
the first point \
the second pointProgress while a turn runs
A turn is quiet between the model call and its first token, and again while a tool runs. A line below the transcript names the step in progress and counts the time it takes.
⠙ fetch_url (7s)It names one call, counts a batch of them (2 tools), and counts the attempts
when the engine tries the same call again. The line is drawn on stderr and
erased before anything else is written, so subs run piped into another program
still writes only the turn.
A call is written to the transcript once, when it is answered.
● get_current_time (180ms)
2026-08-22T09:50:33.010Z
↻ fetch_url {"url":"https://example.com"} (attempt 1, 2.1s)
503 Service Unavailable
● fetch_url {"url":"https://example.com"} (attempt 2, 1.4s)
{"status":"ok"}A call on a connection is named by the server and the tool, as each of them names itself.
● deepwiki Ask a question {"q":"login page"} (1.2s)A call that took less than a moment shows no time. A result that is only text reads as that text. A result longer than the screen is cut short, and the rest is counted.
… +182 linesMarkdown rendering
Chat renders the answer as CommonMark. Headings, code, bold, lists,
quotes, and links carry their styling rather than their markers.
An agent whose system prompt asks for Slack mrkdwn reads differently here than
it does in Slack, because Slack's *bold* is CommonMark's italic.
Interrupt prompts
A turn that stops to ask something renders the question where you are, and your answer resumes it. You do not type an interrupt ID.
An interrupt whose metadata.options names answers renders them as a picker,
the same list Slack draws as buttons. ↑ and ↓ pick, Enter answers, and the
turn carries on in the same chat.
? Run `issues__delete_issue`?
```
{
"id": "7"
}
``` ›
❯ Run it
DeclineAn interrupt that offers no options takes typed text, delivered whole as the resolution payload.
A question waits in the session, not in the process. Ctrl-C at a question ends
the chat and leaves the question open, and a chat that opens that session with
--session asks the question first, before reading a line.
What chat resolves is stamped channel: "cli", so the session records which
channel answered and which option was picked, the same way Slack's does. See
Interrupts.
Limitations
Chat has no slash commands, and it cannot send a message while a turn is running.
Ctrl-C during a turn stops watching it and prints how to pick the session back
up. It does not stop the turn. The turn runs to its end, and the next chat on
that session reads what it wrote.
Chat cannot settle a client-side tool call, so it says so and stops.
⧗ get_weather is waiting on a client-side result, which this chat cannot settle.Use subs run <agent> --input '{"type":"tool.result",…}' for those. See
Client tools.
Related
no-code-chat: a chat agent that is one file.- Slack: the same session, in a thread.
- CLI: every command and flag.