How it works
Single-shot vs interactive chat, conversation memory, and tool visibility.
Single-shot vs interactive chat
The whole architecture branches on one question: does the agent get a plain string prompt, or an AsyncGenerator of messages? A string gives you a single-message mode run with no memory. An AsyncGenerator unlocks a stateful, streaming session that remembers every turn.
| Single-shot (wakeup / talk) | Interactive chat (chat) | |
|---|---|---|
| SDK input | a string | an AsyncGenerator of messages |
| Memory | none, each run is isolated | full, remembers the whole session |
| Mode switching | fixed for the run | live via /mode |
| Lifetime | one run, then exits | until you /exit |
How conversation memory works
There's no memory method being called anywhere. Memory is a side effect of how the SDK's query() is invoked: passing a string means no memory; passing an AsyncGenerator means the SDK keeps one session alive and accumulates every turn itself.
- The SDK holds the history, not CodeBrew's own code. The input bridge is a pipe, not a store.
- Memory lasts only while the session is open. Exiting discards it.
- Context isn't infinite. As a conversation grows, the SDK automatically summarizes older turns and emits a compact_boundary message, shown as "Context compacted".
Tool visibility
As the agent works, every streamed message is rendered live: assistant text, each tool call it makes, and the tool's result. Tools available to the agent are Read, Edit, Write, Bash, Glob, Grep, WebSearch, and WebFetch, depending on the active permission mode. Each turn ends with a summary line showing how many turns it took and the running cost in USD.
The turn gate
A chat loop has to do two things at once: stream Claude's replies and read your keyboard input. CodeBrew coordinates the two with a small traffic light called the turn gate. Starting a turn goes red, meaning the input loop waits; when the agent's result message arrives, the gate goes green and you can type again.
