Getting Started
This page takes you from a machine with nothing installed to a working Sonny chat session. Sonny is commercial software; use the distribution and access provided for your organization. See Licensing and access .
Requirements
- Building from source needs Go 1.27.1 or newer;
go.modpinsgo 1.27.1. - The Linux release binary and the deb/rpm/apk packages are built with cgo enabled (for the mesh identity resolvers), so they need a glibc-compatible Linux system. The macOS and Windows binaries are cgo-free.
- No recipes are preinstalled. The binary ships with one embedded recipe,
sonny-base; everything else you add yourself.
Install
Pre-built binaries
Every tagged release publishes an archive per OS and architecture:
sonny_<version>_<os>_<arch>.tar.gz # linux, darwin
sonny_<version>_windows_<arch>.zip # windows
Download the archive for your platform, extract it, put sonny on your PATH,
then confirm:
sonny version
sonny -v does not work — there is no short flag for version. Use
sonny --version or sonny version.Debian and Ubuntu
curl -fsSL https://apt.codepros.org/codepros-keyring.gpg \
| sudo tee /usr/share/keyrings/codepros-archive-keyring.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/codepros-archive-keyring.gpg] https://apt.codepros.org stable main" \
| sudo tee /etc/apt/sources.list.d/codepros.list
sudo apt update
sudo apt install sonny
Fedora, RHEL, Rocky, Alma
sudo rpm --import https://rpm.codepros.org/RPM-GPG-KEY-codepros
sudo dnf config-manager --add-repo https://rpm.codepros.org/codepros.repo
sudo dnf install sonny
The repository serves x86_64 and aarch64 packages and its metadata is signed
with the same key as the apt repository.
The desktop package
sonny-desktop is a separate native package for graphical workstations. It
depends on the exact same version of sonny, so installing or upgrading the
desktop can never pair it with a different client-protocol build.
sudo apt install sonny-desktop # or: sudo dnf install sonny-desktop
The desktop does not run sessions itself. It connects to one user-scoped local
service, sonny supervisor serve, which it starts on first launch and which the
editor integrations share. Closing the window stops only that window’s
connection; sessions and scheduled work carry on. When you need a fresh service
— after changing a credential the service reads at startup, or after an upgrade
— stop it with Quit Sonny and stop daemon… in the tray menu or with
sonny supervisor stop.
Authorized source access
Source builds require access granted by CodePros. Follow the build instructions in your authorized checkout; source access does not grant an open-source license.
First run
sonny init
sonny config path
sonny init creates your config, data, and cache directories and seeds
models.yaml with an example model-category catalog — but only if models.yaml
does not already exist. It also creates models.d/ in the config directory for
drop-in catalog fragments. Running it again is safe; it will not overwrite a
models.yaml you have edited unless you pass --force.
sonny config path prints every standard path Sonny uses: the config directory
(models.yaml, pack-sources.yaml), the data directory (sessions.db, your
recipes), the cache directory (cloned recipe repositories), and the state directory.
Point Sonny at an LLM endpoint
Sonny talks to LLM providers over plain HTTP. For the openai:// scheme — and
anything OpenAI-compatible — two environment variables are enough:
export OPENAI_BASE_URL="https://api.openai.com/v1" # or any OpenAI-compatible endpoint
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
Nothing else about your recipe changes when you switch providers. The URI scheme decides the transport; see Providers and models .
Your first recipe
A recipe is a YAML file. An llm_profiles entry says which model to call, and a
main prompt supplies the system instructions and the tools the model may use.
Save this as hello.yaml:
version: 2
pack:
id: hello
kind: primary
llm_profiles:
- id: default
uri: "openai://gpt-4o?temp=0.2"
default_llm_profile_id: default
prompts:
- id: main
type: main
title: Hello
system: |
You are a concise assistant. Answer in one sentence.
tools:
allowed: [read_file, find]
Validate it before running anything:
sonny recipe validate hello.yaml
Run one turn headless
--prompt runs exactly one turn and exits. It implies --simple (plain-text
chat, no TUI) automatically, which makes it the right shape for smoke-testing a
recipe, scripting, or invoking Sonny as a one-shot sub-agent.
sonny run --file hello.yaml --prompt "say hello" --new --isolation-mode off
--new starts a fresh session instead of resuming your last one, which keeps a
one-shot call repeatable.
Simple mode is a plain-text REPL, not the TUI. The engine directives /clear,
/compact, and /goal work there as they do in the TUI (/goal <text> starts
work on the objective immediately); /undo reports that the REPL cannot rewind a
turn. The REPL has a few commands of its own and /help lists them. A headless
run has no operator to answer a permission prompt, so what it may run without one
is governed by the permission and isolation settings described in the
CLI reference
.
Open the TUI
Drop --prompt to get the full interactive TUI:
sonny run --file hello.yaml
Bare sonny with no subcommand is the same as sonny run. With no
--file/--pack and no persisted default recipe, it shows a picker over every
recipe Sonny discovered; passing --file, --pack <id>, or setting a default with
sonny recipe default skips the picker and goes straight into the chat.
The rough shape of the screen:
┌ sonny — pack: hello model: openai://gpt-4o ─────────────────┐
│ │
│ You [1]: say hello │
│ ─────────────────────────────────────────────────────────── │
│ Assistant [Turn 1] │
│ ─────────────────────────────────────────────────────────── │
│ Hello! How can I help you today? │
│ │
├───────────────────────────────────────────────────────────── │
│ > _ │
├───────────────────────────────────────────────────────────── │
│ ctrl+p palette f1 help /help commands ctrl+c exit │
└───────────────────────────────────────────────────────────── ┘
Two keys orient you fast: ctrl+p opens the command palette, which lists every
registered /command and is searchable; f1 opens in-app help. Typing /help
in the message box does the same thing as f1.
Typing / resolves in a fixed order, and only the last step ever reaches the
model:
/clear,/compact,/goal, and/undoare handled by the chat engine.- Anything in the command palette (
/help,/models,/pack,/login, …) is handled there. - A recipe id offered at startup switches to that recipe.
- A sub-pack directive of your active recipe is sent to the model, because that is part of the recipe’s own contract.
- Anything else that is still directive-shaped — including a typo like
/mispelled— is consumed locally with an “unknown command” status. A typo never burns a turn.
Text that merely contains a / partway through a message, or a path like
/usr/bin/env, is not directive-shaped and goes straight to the model.
Where things landed
sonny config path
test -f "$XDG_DATA_HOME/sonny/sessions.db"
- Every chat session is recorded in
sessions.dbunder your data directory, which is what lets--continueand--session <uuid>resume it later. - Conversation traces are written under the data directory’s
traces/directory by default. Turn tracing off for a run with--no-traceorSONNY_TRACE=0.
Verifying the install
sonny version --license | head -3
sonny version also takes --sbom (CycloneDX 1.5 JSON) and
--third-party-licenses (a CSV of module, source URL, and SPDX licence id) for
compliance review.
Upgrading and uninstalling
Re-run whichever install method you used the first time. A fresh make install
or package upgrade overwrites the binary in place; your config, recipes, and
sessions live outside the install path, so upgrading never touches them.
make uninstall # honors the same PREFIX/DESTDIR you installed with
That removes the installed binaries only. Config, data, and cache directories —
and, for a package install, the sonny system user plus /etc/sonny,
/var/lib/sonny and friends — are left in place.
Next steps
| Read next | Why |
|---|---|
| CLI Reference | Every command, flag, and exit code |
| Recipes | Author recipes beyond the one-file example |
| Distributed Mesh | Run sessions on machines other than this one |
| MCP Servers | Give Sonny tools hosted by other processes |
| Client Apps | Desktop, VS Code, and Neovim |
Source of truth
Makefile(install,install-dirs,uninstall,go-install,build-windows)packaging/debian/postinst,.goreleaser.yamlcmd/sonny/cli(version,init,config path)cmd/sonny/cli/run.go(--prompt,--simple,--new,--pack)cmd/sonny/ui/slash.go(directive and command precedence)