Skip to content

Threads ​

Route /, the screen the app opens on. This is where you talk to the agent.

Threads

Three panes: navigation on the left, the conversation in the middle, the Inspector on the right. The Inspector starts folded to a thin rail that still shows the waiting-approval and subagent counts; open it from the rail, with Ctrl/⌘ J, or by double-clicking the divider — the choice is remembered.

Opening a project ​

A thread always belongs to a working directory, so the first thing to do on a fresh install is Open project… — in the left pane if you already have one, or the centre pane's own "Add a project to get started" if you have none yet — which opens your platform's folder picker.

Selecting a project opens a thread in it straight away, so what you get is the ordinary conversation screen — mode buttons, model picker, attachments, mic, / commands and all — with a short guide where the transcript will be: the project's name and path, and three chips (/init, summarizing the repository, delegating to an agent) that fill the composer rather than sending themselves, so you can edit one before pressing Enter. The guide disappears with the first message.

Selecting the same project again, or pressing + New thread in a thread you have not used yet, returns to that thread instead of stacking another empty one behind it. An unused thread stays out of the list on the left until it has something in it.

The left pane ​

Exactly one project is open at a time here, reached through the switcher at the top: it names the current project (folder name, then its path in a smaller mono line) and opens a menu of every project, pinned first then most recently opened, plus All projects — a merged view of every project's threads, each row wearing a small badge naming which project it belongs to — and + Add project. A dot next to a project in that menu means it has a thread running right now.

Below the switcher is search: type to filter the list by title, first prompt, session id, or (for a thread this window has already opened) its visible messages; all / running / done / pinned narrow it further. ⌘K (or Ctrl K) focuses the search field from anywhere in the pane.

Under the switcher, a chip names the team this project runs with — click it to pick from the teams already created, or None for no team at all; see Assigning a team to a project.

+ New thread starts a thread in the project currently in view.

The thread list ​

Threads — live ones and closed ones you can still resume — sit together in one list, grouped Pinned · Today · Yesterday · Last 7 days · Older; every group but Pinned and Today starts collapsed, showing just its count, and a thread with a turn running always sorts first inside its group.

Each row is two lines: its title (the first prompt it was sent, or "New thread" before one arrives) on top, and underneath its short session id, how long ago it was last active, and its token count when known. Clicking a live row opens it and replays its whole history, even if this window has never seen a single event of it; clicking a closed one resumes it — the core restores the session from its store and it becomes an ordinary thread again.

The row's ⋯ menu offers:

  • Pin — moves it to the Pinned group, ahead of every date bucket.
  • Rename — gives it a name of your own, in place of the first-prompt title.
  • Open in terminal — opens the Terminal screen at this thread's project.
  • Archive — moves it under the Archive group. Not a delete: an archived thread is still there, still resumable, just out of your way.
  • Delete — removes the stored transcript entirely, after asking. It can no longer be resumed by this app, the TUI, or anything else; this one is not reversible.

Sending a prompt ​

The composer is at the bottom of the middle pane.

KeysAction
EnterSend
Shift+EnterNewline
/ in an empty composerOpen the command palette
Ctrl/⌘ KOpen the command palette from anywhere
Ctrl/⌘ .Interrupt the running turn
Ctrl/⌘ VAttach a clipboard image, or paste text when there is none

Delegating in one line ​

A prompt that starts with $ and an agent name is a short delegation: it hands the rest of the line to that agent as a subagent instead of sending it to the model.

$reviewer look at the diff and tell me what is risky

A chip appears next to Send naming the agent as soon as the line parses, so you can see where it is about to go.

The line is sent as an ordinary prompt: the core recognises the $ prefix itself and runs it as /delegate, which is why the main agent answers with the outcome once the delegate finishes rather than leaving the thread silent. The run also shows up in the Inspector's Subagents tab. An unknown name is refused by the core and the refusal is shown — nothing is silently sent to the model instead. Every client does this the same way, because the parsing happens in the core and not in any one of them.

Completing the name ​

You do not have to remember the name. Typing $ opens a list of every agent this project has — the builtin roles, anything your skills or project team add, and your own named agents — filtered as you type. ↑ and ↓ move through it, Tab or Enter accepts the highlighted one and leaves a space for the task, and Esc dismisses it for that $ if you meant a dollar sign after all.

A $ in the middle of a word — USD$5 — is a dollar sign and opens nothing. If the name matches no agent the list says so and gets out of the way: Enter sends as usual, and the core is still the one that refuses the unknown name.

The same list is in the command palette. Type /delegate or /agent spawn and the palette switches from commands to agents, each with its one-line description and the model it would run on. Enter there completes the name rather than running the command, because the command still needs a task; the list hands itself back to the commands as soon as the name is accepted.

Sending while the agent is busy ​

A prompt sent during a running turn is not refused: the core queues it and runs it when the current turn ends. A queued (N) pill next to Send says how many are waiting. Interrupting the turn (Ctrl/⌘ . or Interrupt) drops the queue along with the turn.

The row under the composer also holds 📎 and the microphone. See Attachments for sending files with a prompt and Voice for dictating.

The answer streams in as it is generated. Tool calls appear as cards with their arguments and, when they finish, their output. The status next to the thread id reads running, then complete — or denied if you refused an approval.

Watching the agent work ​

The transcript follows the newest message while you are at the bottom of it, and stops following the moment you scroll up to read something. Where you scrolled to is remembered per thread: leaving for another screen and coming back, or switching threads and returning, puts you where you were rather than at the top.

If the daemon is restarted while a turn is running, that turn is closed as interrupted the next time the thread is read rather than left counting upward forever.

If this window stops hearing about a running turn for ten minutes, it asks the daemon rather than assuming: when the daemon has gone further than the window has seen, the connection had stalled and the thread catches up silently. Only when the daemon has nothing new either does the bar say "Still working? — the daemon has been quiet for N min", counted from the last thing actually heard.

While a turn is running, a bar sits between the transcript and the composer and says what the agent is doing right now. A hairline sweeps its top edge for as long as the turn lasts.

The phrase on the left changes with what is happening:

What you seeWhat it means
Thinking…The model is working and has produced nothing yet
A rotating verb — Pondering…, Brewing…Words are streaming in; the verb changes every eight seconds
Thinking (2.4k chars)…The model is reasoning privately, and that reasoning is not in the transcript
Running shell npm test…, Reading sessions.ts…One tool call is in flight, and what it is working on
Delegating to reviewer…, 3 agents working…Subagents are doing the work
Compacting…, Compacting automatically…The context window is being rewritten — because you asked, or because it filled up
Waiting for approvalThe turn is stopped until you answer the modal — the spinner stops too

To the right of the phrase are the seconds this turn has taken, when anything was last heard from the daemon, and the turn's token count: ↑ sent, ↓ received. Prompts parked behind the turn show as N queued.

The token counts come from the daemon once per provider call, after the call returns — so on a slow model they would otherwise stand still for a minute at a time. While a call is streaming, ↓ is shown as an estimate instead, with a tilde: ↓ ~1.9k. It is worked out from the text and reasoning streamed since the last exact figure, and it snaps to the real number the moment that figure arrives. ↑ is never estimated, because nothing streams that could estimate it.

last activity 12s ago is the same clock the quiet warning uses, shown without the warning: it is the one thing on the bar that is visibly recent while a long call produces nothing else to see.

When the turn ends the bar steps down to one line — Done in 12s · 4.9k tokens, or Stopped after 3s if you interrupted it — and clears itself a few seconds later.

What it chose, in order ​

Activity N on the right of the bar opens the turn's steps as a numbered list: the tool, what it worked on, and how long it took, oldest first. A running step spins, a finished one gets a tick, a failed one a cross. The same list is always visible in the Inspector's Info tab, under activity.

Each tool card in the transcript carries the same state. A card spins while its call is in flight and shows the clock running; when the result lands it becomes a tick (or a cross) with the final duration and a summary of what came back — 128 lines · 4.2 KB, or +12 −3 for a patch. Open the card for the full arguments and output.

Watching a command as it runs ​

A shell command prints into its card while it runs: the last two hundred lines, scrolled to the newest, with anything the command sent to standard error in the danger colour. A command that prints a great deal is cut off partway with Output truncated — the whole output is still there in the card's result once the call finishes.

A delegation does not get a console. It shows the child agent's newest line under the card head instead, so a fan-out reads as progress rather than as a wall of someone else's prose. The Subagents tab has the same runs with their own clocks.

Opening the app puts you back where you were: the project you were last in, and the thread you were last reading in it. Switching projects does the same — each one remembers its own thread, so moving between two projects moves between two conversations rather than opening two empty ones. When the remembered thread is gone, the project's most recent conversation takes its place; when the project has none at all, a new thread is made. + New thread is still the way to start something fresh.

Generated files ​

A turn that produces files says so under the reply that ends it.

Images appear inline. A render, a chart, a screenshot the agent just made is drawn in the transcript at a readable size with its name and pixel size underneath. Clicking one opens the lightbox: the picture at its natural size on a dark backdrop, Esc or a click outside to close, ← and → to walk through the turn's other images, and buttons to Open in Files or Copy path.

Every file gets a card. Not only the images: each detected file appears as a small card showing a picture of itself, so you can tell at a glance whether it is the file you wanted.

  • JSON is pretty-printed first, then clipped to its first lines — a generated .json usually arrives as one very long line.
  • HTML is a shrunken sandboxed render of the page itself, with scripts off. A document over 512 KB shows its source instead.
  • Markdown is rendered; text, code and logs show their first lines.
  • CSV, TSV and spreadsheets show the top-left corner of the grid, six rows by six columns, the first sheet of a workbook.
  • Short audio gets a small play control.
  • PDF, Word documents and video are named and measured rather than drawn: neither has a preview worth the megabytes it would cost.

Only files the turn actually produced are shown. A tool that wrote one said so; a file the reply merely refers to — "the output.png from earlier is still there" — is checked against the moment the turn began, and one that predates it is listed by name under Also mentioned rather than drawn as something this turn made.

A turn that produced more than four files, or more than two images, shows a single line instead — "9 files generated", with Open in Files and Show previews — because a dozen cards bury the reply they belong to and each one costs a read. Show previews draws them for that turn only. The limit is ide.previews.inlineMax in the settings document.

Preview ↗ in a card's header — or a click anywhere on the card — opens the same viewer the Files screen uses, over the thread rather than instead of it. The folder button jumps to Files with that file selected. Cards read their file only once they are scrolled into view, and read at most 256 KB of it.

The files are found three ways, in this order: the tools that write files name their path outright; a shell command has its command line and its output scanned for anything that looks like a file worth showing; and the reply's own text is read for paths it mentions — which is what catches a python script that wrote output/chart.png and a reply that says so in a sentence. A path relative to the thread's working directory is resolved against it.

Only the last two are guesses, and a guess is checked before it is drawn: the file has to really exist, and it has to be inside a folder you opened. A filename the agent merely talked about leaves nothing behind. At most twelve files are shown per turn.

Scheduled runs and subagent sessions ​

Not every session is a thread you typed into. Asking for something later — "in three minutes, search the news and tell me" — schedules a job, and when it fires the core runs it in a session of its own. Delegating to an agent does the same. Those sessions are real and have real transcripts, but they belong to the thread that caused them, and the list says so rather than showing them as unrelated conversations.

A scheduled run sits under the thread that asked for it, behind a ⏰ 1 scheduled run line that opens to show them, newest first. Each is titled by the time it ran, because every run of the same job repeats the same task and the time is what tells them apart. When the thread that scheduled it is not in view — a different project, or a filter — the run is listed on its own with the ⏰ badge rather than hidden.

A subagent session is not in the list at all. It belongs to the turn that spawned it and is shown in the Inspector's Subagents tab. Search still finds it: type its id or a word from it and it appears with a ↳ badge, because a search that hides sessions is a search that lies.

A named agent's own session is listed as a peer with a ◆ badge.

When a scheduled run finishes, the thread that asked for it says so in its transcript: ⏰ Scheduled run finished, the first line of what the run produced, and a link to the session holding the rest. A run that failed or ran out of time says that instead.

Opening one of these sessions shows a line under the thread header naming what it is — Scheduled run of s-850623 · job j-1 — with open parent next to it. The Inspector's Info tab carries the same facts as rows.

The model ​

Next to the thread's name is its model. Left alone it reads inherit, meaning the thread follows the configured routing; picking a profile or a vendor's model pins this thread to it, and its subagents inherit the pin.

It is a session-level choice and writes nothing to any settings document. To change what an agent runs on everywhere, use Settings → Models, which also explains which rule wins when several could apply.

The picker groups what it offers: the configured profiles first, then one heading per vendor. A local server you added appears under its own name, so hon2:flash-next-mtp is legible even on a machine running several.

Effort ​

Beside the model is effort — how hard the model is asked to think. The same model at low and at max behaves like two different assistants, so it is a choice worth making per thread: Auto, low, medium, high, max.

Auto is not a fifth level. It is the absence of a pin, which is why the chip reads Auto · high rather than plain Auto — it names what the next turn will actually use and where that came from. With nothing configured anywhere it reads plain Auto, meaning the vendor's own default applies, which snowpea cannot name for you.

Picking a level pins it to this thread the way the model pin works, and Auto clears it again. The defaults it falls back to live in Settings → Models, which has the same ladder: this thread's pin, then a per-model override, then a per-vendor one, then agent.effort.

Most servers you run yourself ignore the reasoning parameter entirely. For those the chip is greyed out and says which server ignores it, rather than offering a control that would do nothing.

Permission modes ​

The three buttons at the right of the composer, just before Send, switch what the agent may do without asking. They sit there rather than in the header because the mode governs the prompt you are about to send, and that is the last thing you look at before sending it. Shift+Tab in the composer cycles them.

ModeMeaning
planRead-only: no writes, no shell
acceptWrites allowed, running commands asks first
autoEverything runs without asking

The mode is a property of the session, so changing it here changes it for every client looking at the same session. New threads start in accept unless the project's own settings say otherwise.

Hearing replies ​

Replies are read aloud when you ask for them to be. There are two ways:

  • Read replies aloud in the ⋯ menu speaks every finished reply from then on. It is remembered, so it stays on across restarts until you turn it off.
  • Read aloud appears on an assistant message when you point at it, and speaks just that one.

While something is playing, a 🔊 speaking · stop pill sits above the composer. Both are unavailable, with the reason, when the core has no voice configured — see Voice.

Questions from the agent ​

Sometimes the agent needs an answer before it can carry on — which scope a memory belongs in, which of three approaches to take. It asks, and a dialog opens over the thread with the question and its options. The turn is stopped until you answer, the same way it stops for an approval, and the bar above the composer says "Waiting for your answer".

The recommended answer comes first and is already taken, so Enter is usually the whole interaction. Every list in the app — questions, approvals, the skill and MCP forms, the first-run wizard — answers to the same keys:

KeyWhat it does
↑ ↓Move between options
SpaceToggle an option, when more than one may be picked
EnterTake the option and move on; on the last tab, send the batch
1–9Jump straight to that option. It never sends
← → · TabPrevious and next question
EscDecline

A question that allows it also has an Other… row for an answer that is not on the list: Enter opens the field, Enter again sends, and Esc leaves the field without leaving the question. A question with no options at all is just that field.

When the agent asks for a credential — /setup and /login can ask for an API key from inside a thread — the field is masked and carries an eye to show what you typed while you check it. The Review tab prints •••• in its place, so the key is never on screen twice. What the agent receives is the value exactly as you typed it; the mask is about who can read your screen, not about what is sent.

When the agent asks several things at once they arrive as tabs, marked with where each one stands — ✓ answered, ▸ the one you are on, · still to do — and a Review tab at the end listing every answer, with (not answered) against anything still missing. Answer them in any order, go back and change one, and Submit sends them together.

Decline — or Escape — answers nothing and lets the agent continue without you. That is a real answer, not an error: the agent is told the question went unanswered and decides what to do. If the question is answered somewhere else first, in the TUI say, the dialog closes on its own.

Approvals ​

In accept mode, a command the agent wants to run stops the turn and opens a modal naming the tool and its arguments, with five answers in one list and the same keys every other list uses:

AnswerWhat it covers
DenyThis one call is refused
Deny with a reasonThe same, and the agent is told why, in your words
Allow onceThis one call
Allow for this sessionEvery call like it in this thread
Allow for this projectEvery call like it in this folder

Deny leads and starts chosen, so Enter is the safe answer and Esc denies outright. A reason is worth giving when the refusal is about this case rather than the tool: the agent reads it as the refusal itself and can act on it instead of trying the same thing again.

Some calls carry an extra warning from the core above the arguments. The one worth stopping for is modifies snowpea configuration, shown in the danger colour: allowing it lets the agent rewrite snowpea's own settings — providers, credentials, the allowlist — rather than anything in your project. Read the arguments before allowing one, especially with a scope wider than once.

An approval you are not looking at is not lost. The Inspector's Approvals tab lists everything waiting, and so does the Gateway screen, which is where an approval goes when it has to be answered from chat.

The Inspector ​

The right pane has four tabs.

  • Info — the thread's own vitals in a label/value grid: its id and working directory (click either to copy), model (and whether it is pinned or inheriting), mode, token counts, context reading, when it was created and last active — plus every action the row's ⋯ menu offers (Pin, Rename, Archive, Delete) alongside Review/Open in terminal/Interrupt. This is also where Compact lives when the context meter offers it. Under it, activity lists the current turn's tool calls in the order the agent chose them.
  • Subagents — the tree of runs this thread delegated. Nodes appear as they are spawned and change state as they finish, so a fan-out is visible while it is happening rather than afterwards. A running node spins and carries its own clock.
  • Approvals — the shared queue described above.
  • Files — the project on disk, rooted at the thread's working directory. It is a read-only viewer, which is the point: a file the agent just wrote can be read without leaving the conversation.

The thread header ​

The header is two lines and carries only what identifies the thread.

The first line is the thread's name, its model, Interrupt and the ⋯ menu. The name starts as the project's folder name; click it to rename this thread, Enter to save, Escape to leave it alone. Clearing the field puts the project's name back rather than leaving the thread nameless. As the pane narrows, Review and Open in terminal fold into ⋯ rather than pushing past the edge.

The second line is the thread's address — 📁 /home/you/work/snowpea · s-0222212c64a9. A long path is cut in the middle rather than at the end, since the folder it names is the half worth keeping; hover either part to see it in full, and click either to copy it.

The composer's instruments ​

Everything that says what a prompt will cost and how it will run sits on the row under the composer, with the prompt itself:

ControlWhat it is for
📎Attach files to this prompt
plan accept autoWhat the agent may do without asking
🎤Dictate into the composer — press it again, or Esc, to stop
SendSend the prompt

At narrow widths the row wraps: the mode buttons, the mic and Send drop to a second line under the rest. Nothing is hidden — every control here changes what the next prompt does, so none of it folds into a menu.

How full the context window is shows in the status bar at the bottom of the window and in the Inspector's Info tab. Past 85% a notice appears above the composer with a Compact button — the same /compact the ⋯ menu and the palette run.

Resizing the panes ​

The Projects pane on the left and the Inspector on the right can both be dragged narrower or wider from the thin divider on their inner edge — the cursor turns into a resize arrow over it. ←/→ on a focused divider nudge it in 16px steps. Each pane remembers the width you leave it at and restores it the next time you open the app.

A double-click on the Projects divider resets that pane to its default width.

Hiding the Inspector ​

The Inspector folds away to a narrow rail: press Ctrl/⌘ J, use the chevron at the right of its tab strip, or double-click its divider. The rail keeps the button that brings it back, and badges anything inside worth reopening it for — approvals waiting for an answer, subagents still running. The centre pane takes the width back, so the thread header shows more of its controls while the Inspector is hidden.

The app remembers whether you left it open.

Leaving the thread ​

Two buttons in the header lead out of it, both carrying the thread with them.

  • Review changes opens Diff review for this thread; the count next to it is how many files it changed.
  • Open in terminal opens the Terminal screen on this thread's project, focusing the shell that is already there if one is running.

MIT licensed. The manual is generated from the product repositories — see the banner on each page.