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.mod pins go 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
No `-v` flag
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:

  1. /clear, /compact, /goal, and /undo are handled by the chat engine.
  2. Anything in the command palette (/help, /models, /pack, /login, …) is handled there.
  3. A recipe id offered at startup switches to that recipe.
  4. A sub-pack directive of your active recipe is sent to the model, because that is part of the recipe’s own contract.
  5. 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.db under your data directory, which is what lets --continue and --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-trace or SONNY_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 nextWhy
CLI ReferenceEvery command, flag, and exit code
RecipesAuthor recipes beyond the one-file example
Distributed MeshRun sessions on machines other than this one
MCP ServersGive Sonny tools hosted by other processes
Client AppsDesktop, VS Code, and Neovim

Source of truth

  • Makefile (install, install-dirs, uninstall, go-install, build-windows)
  • packaging/debian/postinst, .goreleaser.yaml
  • cmd/sonny/cli (version, init, config path)
  • cmd/sonny/cli/run.go (--prompt, --simple, --new, --pack)
  • cmd/sonny/ui/slash.go (directive and command precedence)