Skip to content

Settings ​

Route /settings, or Ctrl/⌘ ,.

Settings

Providers ​

The table lists all 11 chat vendors the core knows, with whether each one is configured. Configure opens a dialog for that vendor's fields — an API key, a base URL, a default model, depending on the vendor.

Vendors that support more than a key get a button per flow they actually offer, because the flows are not interchangeable:

ButtonVendorWhat happens
Sign in with a device codeOpenAIA short code to type at the vendor's page; signs in a ChatGPT/Codex subscription
Sign in in the browserOpenRouterOAuth in your browser, back to the app when it is done
Sign in with Google (gcloud)GeminiRuns gcloud auth application-default login. It needs the Google Cloud CLI installed; Google keeps the refresh token, snowpea stores only which method you used

A dialog follows the flow and shows the code, the page to open, and how it ended.

OAuth access token is not one of these. It is a token you obtained elsewhere — the case for a headless or remote machine — and it is pasted in the Configure dialog, for the vendors that accept one (OpenAI and Gemini). Saving one also records auth_method, which is what makes the daemon prefer the token over any API key on file.

Secrets are one-way. Reading the settings back gives *** rather than the value, and the Configure dialog always starts blank, so a mask can never be saved over a real credential.

Local / OpenAI-compatible servers ​

A model you run yourself is a vendor too. Any server that speaks the OpenAI protocol — vLLM, Ollama, LM Studio, or something else entirely — gets a name here, and that name is what its models are referenced by: a server called hon2 serving flash-next-mtp is hon2:flash-next-mtp everywhere a model can be named.

The card under the vendor table lists each one with its address, its default model and a dot saying whether anything answered. The dot is the point: a local box is the one vendor that is routinely switched off, and Check asks all of them again. A dark dot means nothing answered just now, not that the server is misconfigured.

Add server… walks through it in order:

  1. Name — one word. It becomes the vendor id, so it may not contain a colon and may not be one of the core's own vendors.
  2. Type — vLLM, Ollama, LM Studio, or another OpenAI-compatible endpoint. Picking one fills in the port that server usually listens on.
  3. Base URL — editable, because the whole point of naming a server is that it is not the default one.
  4. API key — optional, and usually blank; most local servers want none.
  5. Probe — this saves the server first, then asks it for /v1/models. The core reads the address from settings to know where to ask, so there is no way to probe an unsaved one.
  6. Default model — picked from what the server reported. If nothing answered, the server is still saved: start it and Retry, finish without a default model, or Remove it.

The same flow is on the setup wizard's provider step, where the server joins the vendor list under its own name and is picked straight away.

Remove asks twice, then deletes the server's settings block — which is the whole vendor, since a named local server is nothing but that block.

Project defaults ​

These are the defaults for sessions in one project, stored in that project's own .snowpea/settings.json.

  • Project directory picks which project you are editing. Load reads its settings.
  • Default mode is the permission mode new threads start in: plan, accept or auto.
  • Execution backend is where tools actually run — the local machine, or a sandbox, depending on what the core supports.

Each section saves on its own button; nothing here is applied as you type.

Models ​

Which provider and model anything runs on. The panel has a Global and a Project tab: the project document is <project>/.snowpea/settings.json, and each key in it merges over the global one. The Project tab is available once a project directory is loaded under Project defaults.

  • Profiles name a provider-and-model pair: fast → openai / gpt-4.1-mini. The provider list comes from the vendors the core knows, so a profile cannot point at a vendor that does not exist.
  • Default is the profile used when nothing above it decides.
  • Per-agent pins one agent to a profile, which is how the executor runs on something cheap while the architect runs on something strong.

What decides ​

Five rules can each answer "which model?", and the ladder at the top of the panel shows which one actually won — the deciding rung is lit and the values it overrules are struck through. Highest first:

RungSet by
Call overrideagent.spawn({ model }) — one run only
Agent assignmentPer-agent above; project's models.agents over global's agents.models
Agent definitionThe model: field in the agent's own file
Thread pinThe model picker in a thread header, or /model
Project defaultThe project's models.default
Global defaultThe global models.default

Type an agent's name into for agent to see the chain for that agent rather than for a plain session.

Every model picker — the thread header, the Agents screen, the project settings sheet — lists the profiles first, then one heading per vendor that reports models. A named local server appears under its own heading, which is what keeps hon2:flash-next-mtp legible on a machine running four servers.

A reference can be a profile id, vendor:model, or a bare vendor name meaning that vendor's own default. A bare vendor is easy to create by accident — a typo'd profile id becomes one — so the panel says when a reference resolves that way. inherit decides nothing and passes the question down.

Removing a profile that the default pointed at also clears the default, so nothing is left pointing at a name that no longer resolves.

Effort ​

How hard the model is asked to think: low, medium, high, max. The same model at the two ends behaves like two different assistants, which is why it is a setting of its own rather than something buried in a vendor's block.

Default effort writes agent.effort. auto writes nothing at all — it removes the key, which is how "let the vendor decide" is stored.

Overrides are keyed the way a model reference is written. A bare vendor (openai) covers every model from that vendor; a vendor:model key (openai:gpt-5) covers one model and beats the vendor rule.

The full ladder, highest first:

RungSet by
Thread pinThe effort chip in a thread header, or /effort
Per-model overrideAn openai:gpt-5 key here
Per-vendor overrideAn openai key here
Defaultagent.effort

Nothing matching is a real answer too: the vendor's own default applies, and the IDE says so rather than naming a level it cannot know.

Most local servers ignore the parameter. Their threads show the effort chip greyed out with the reason, and the setting is still stored — it simply changes nothing for that server.

Allowlist ​

Shell commands the agent may run without asking, as regular expressions over the whole command — ^git status.*$ is a typical entry. Scope chooses whether the pattern applies globally or to the current project.

An allowlist entry is a standing approval. A pattern like ^git .*$ is broader than it looks, and .* defeats the mechanism entirely.

Tools ​

The language servers. The core starts one the first time the agent touches a file it serves, and from then on every write comes back with that file's diagnostics attached — the same errors and warnings an editor shows the moment you save.

The card's first line says what is actually running: how many servers are ready, how many are still starting, and how many are broken. A broken server is worth reading as silence rather than noise, because a server that failed to start simply produces no diagnostics for its language.

Enabled off takes the seven lsp_* tools out of the tool list and stops the Diagnostics block being appended to a write. Nothing else changes.

Install missing servers is off by default, and deliberately so: a server that is not on your PATH produces no diagnostics, and nothing is ever downloaded unless you ask here. Turned on, snowpea installs one with npm, pip or go into $SNOWPEA_HOME/lsp.

Idle timeout is how many seconds a server may sit unused before it is shut down. Zero keeps every started server alive for as long as the core runs, which trades memory for never waiting on a restart.

The server list ​

One row per server: its id, its state, and either the project roots it is running in or the file types it serves. The list is the core's own registry — every server it knows how to start, not only the ones that have started — so a core that adds a server shows it here without the app being updated.

It opens showing only the servers that mean something on this machine: ones the core has started, ones you configured, ones you switched off. The rest is mostly about languages you do not use. Show all opens it, and the filter searches the whole registry either way.

Switching a server off leaves it alone entirely: it is not started, and no diagnostics come from it. That is the setting to reach for when a linter is noisy on a particular project rather than wrong.

Two states are not your doing. off by default means the core ships that server switched off — ty and ruff are the current examples — and its toggle is inert, because there is nothing in your settings to remove; turning one on takes an lsp.servers override in the settings document. An install tag means the server is not on your PATH; hover it for the command that puts it there, or turn on Install missing servers above.

A server the core does not ship is listed too, once you have declared it under lsp.servers in the settings document.

MCP servers ​

An MCP server is a separate program that hands the agent a set of tools — GitHub issues, a headless browser, a documentation index. This card lists every one the core knows about for the project you have open, and lets you add, test, disable and remove them without editing JSON by hand.

Servers come from four places, and the scope chip says which:

scopefileeditable here
projectthe project's own .mcp.jsonyes
global$SNOWPEA_HOME/.mcp.jsonyes
plugina plugin's own fileno — remove the plugin instead
settingsthe older mcp.servers block in settingsno

A read-only row offers View and says where it came from. The others offer Edit, Test, Disable and Remove. Disabling keeps the entry and never starts it, which is the difference between "not now" and "gone".

The state dot follows the server live: starting while it comes up, ready once it has answered, error with the reason in the tooltip. Nothing is polled — the core says when a server changes.

Adding one ​

Add server opens a form with three tabs. Command is a program the core runs (npx, -y @modelcontextprotocol/server-github); URL is a server that is already running somewhere; Catalog is a short list of known servers that fills the form in for you and names the environment variables each needs.

The arguments field is split the way a shell would split it, quotes included, but no shell runs it. The server is started from that list directly, so && and | in the line are arguments and not commands.

Test starts the server, asks it what it can do, and shuts it down again. "Connected — 12 tools" comes back with the list, each with a checkbox: untick the ones you do not want and only the rest are registered. A server that fails to start is not saved at all unless you tick Save anyway, which writes the entry and leaves it stopped.

Two other things can hold the save, and each asks separately. A name already taken in that scope offers to replace what is there. A configuration the safety check objects to — a shell interpreter that also reaches the network, an entry that writes to a login profile — prints what it found and needs a second, explicit confirmation.

Secrets ​

Environment variables and HTTP headers are written to the config file and never read back. A saved server shows its variables by name with ••• for a value, and a value you do not retype is left exactly as it is. That is why the table can say GITHUB_TOKEN=••• and nothing more.

Audio ​

Which speech backends to use, which voice, and whether replies are spoken without being asked. See Voice for what each field does and what happens when a backend is missing.

Voice in and Voice out are lists rather than dropdowns, one row per engine, because a row has to do more than name itself.

A direction is in one of two states, and the line above its list says which:

  • Not set — voice input is off; install or pick an engine. Nothing is chosen, so that half of voice does nothing at all. The microphone button and Read aloud are disabled and say the same thing. There is no "automatic": the daemon does not pick for you.
  • Pinned: Supertonic, with Reset to not set beside it. Resetting turns that half of voice off again.

While nothing is set, the engine snowpea recommends is offered above the list with an Install button that already has the keyboard focus. Both recommendations — SenseVoiceSmall for input, Supertonic for output — run on the processor, so they need neither a graphics card nor a key.

Installing and selecting are separate. Install fetches the engine and changes no setting; when it finishes the row becomes usable, takes the focus and says installed — select it to use it. Selecting is what pins it. A button labelled Install never changes what your next turn runs on.

Every row leads somewhere. What it offers depends on what the engine needs:

RowWhat it offers
An engine snowpea can fetchInstall, with the output as a Log you can open beside the row
A system package (eSpeak NG)The command for your package manager, with Copy, Run in terminal — which types it into the integrated terminal without running it — and Re-check once you have installed it
Custom commandThe command template, checked for {path} (input) or {text} and {out} (output), with a Test. It cannot be pinned until it could actually run
A hosted service (OpenAI)The API key, masked and never read back
OffTurns the direction off, which is the same as not set

While an install runs the row shows what it is doing, not only that it is doing something: the stage and which step of how many, a bar that fills when the daemon can say how far along it is, 12 MB / 480 MB when it knows the sizes, the newest line of output, and the full log behind a toggle. A daemon that reports only lines gets a bar that moves without claiming a position, because a bar that guesses can be wrong and one that admits it does not know cannot.

The language you speak ​

Under a pinned voice-in engine is Which language will you speak? — Auto-detect, 한국어, English, 日本語, 中文, or Other… for any BCP-47 tag. Auto-detect is the recommendation and is right for most people; it is wrong for the ones who switch languages mid-sentence, because a recognition engine deciding between "네" and "nay" on a one-word utterance has very little to go on. An engine with a model per language shows which model each one needs, with an Install beside it.

A voice for each language ​

Under a pinned voice-out engine is a tab per language — Korean, English, your own reply language, then Every other language — and under each tab that engine's voices. An engine like Supertonic ships a model per language, so a person who writes two languages can have a voice for each rather than one accent reading both.

Installed voices come first. One that is not downloaded shows its size and an Install button with the same staged progress; as with engines, installing does not choose it. Preview speaks a sentence in that tab's own language through the voice, which is the only way to find out whether you like it.

Engine default clears the language rather than pinning what the engine happens to prefer today, and a language with no entry of its own falls back to Every other language — the picker says when it is doing that.

Engines that belong to another platform are not listed at all: macOS say on Linux is not "unavailable", it is impossible, and a row that can never be acted on is worse than no row. The platform is the daemon's, which on a remote core is a different machine from this one.

Test under Voice in records two seconds and prints what it heard; Test under the voice speaks a sentence. Both check the whole path rather than the setting, which is the point: an engine can be installed, selected, and still hear nothing.

Choosing an engine is saved with the rest of the card, on Save. Nothing is written by installing.

Providers that want a browser login rather than an API key have a Log in button; Signing in to a provider walks through that dialog.

Appearance ​

The appearance panel is mounted on this screen rather than linked from it: theme, density and text size, described in Themes.

About ​

Versions, and the update controls. See Updating.

Run setup wizard ​

At the bottom, Run setup wizard reopens the first-run wizard with everything you already configured in place.

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