Manage git-backed recipe sources listed in pack-sources.yaml
(add/list/update/remove tracked repos), separately from the prompt packs
themselves (loaded by the standard discovery pipeline).
sonny tracks recipe repositories listed in pack-sources.yaml under
$XDG_CONFIG_HOME/sonny. Use these subcommands to add, list, update, or remove
tracked repos. Cloned repos live under $XDG_CACHE_HOME/sonny/pack-repos and
are loaded by the standard recipe discovery pipeline on startup.
Usage:
sonny recipe [command]
Aliases:
recipe, pack
pack is an alias, so sonny pack list and sonny recipe list are the same
command. The help output prints the primary name recipe.
All subcommands accept the global flags .
Subcommands
| Subcommand | Purpose |
|---|---|
add | Register and clone a new recipe source |
approve-routing | Trust a recipe source’s model routing (endpoints and credential env var names) |
artifact | Inspect captured tool results without putting them in model context |
default | Show, set, or clear the persisted default prompt recipe |
eval | Run a recipe’s eval suite through the configured provider |
evidence | Score two per-case ledgers into one paired evidence record and decide promotion |
inspect | Show resolved scope, sub-scopes, validation, and provenance for a recipe |
list | List tracked recipe sources (or --recipes to list prompt recipes) |
migrate | Rewrite a v1 prompt recipe as v2 (in-place by default) |
optimize | Evolve a recipe’s system prompt against its eval suite |
pin | Pin a model-pack variant for a session, or as a pack-wide standing default |
qualify | Assemble and freeze a model-variant campaign’s qualification document |
reload | Force-refetch one or all tracked recipe sources |
remove | Drop a recipe source and delete its cache directory |
replay | Reproduce a pinned variant decision from a lock and a snapshot |
resolve | Emit the fully-resolved, tool-aware compiled subject for a recipe |
search | BM25-rank loaded prompt recipes against a query |
snapshot | Write a replayable variant-resolution snapshot for one logical recipe |
update | Fetch + reset tracked sources to their upstream branch tip |
validate | Statically validate a recipe YAML file |
variant | Operate on one model recipe variant envelope file |
variants | List the model-pack variants discovery found for one logical recipe |
recipe add
sonny recipe add <git-url|dir>[@<ref>]
Register and clone a new recipe source from git-url. A local directory (.,
./dir, ~/dir or an absolute path) works too: a git repository is cloned on
its checked-out branch, and any other directory is snapshotted into the cache and
re-read on every sync or reload (the directory itself is never modified). Append
@<ref> to the URL (e.g. https://example.com/packs.git@v1.2.3) to pin the
source to a specific semver tag or to @latest for the newest available tag.
Pinned sources are frozen: sonny will not auto-update them on startup; use
sonny recipe reload <name> to refresh.
| Flag | Type | Description |
|---|---|---|
--approve-mcp | — | after cloning, record your approval of the MCP servers every pack from this source declares (inherited ones included), as sonny mcp approve pack does for each: a pack-source server launches only on such an approval |
--approve-routing | — | after cloning, trust the source’s model routing (endpoints and credential env var names its catalogs declare) by copying it into <config-dir>/models.d/pack-<name>-routing.yaml; see sonny recipe approve-routing |
--branch | string | branch to track (default “main”) |
--default-recipe | string | override this source’s repository default primary pack; an explicitly empty value disables its default |
-h, --help | — | help for add |
--mcp-auto-approve | — | connect this source’s MCP servers without a prompt for the packs that name them, once sonny mcp approve registry <name> records your approval of their unchanged definitions; false writes mcp_auto_approve: false, so they get the stricter explicit-approval pinning (unset: on only for a source with --mcp-d) (default true) |
--mcp-d | stringArray | mcp.yaml-style directory relative to the clone root whose *.yaml servers load for the packs whose mcp.allowed names them, overriding same-name mcp.yaml servers (repeat for multiple dirs) |
--mcp-env-allow | strings | host environment variable NAME this source’s MCP servers may read, e.g. the credentials its packs’ servers reference (repeat, or comma-separate; persists mcp_env_allow in pack-sources.yaml) |
--model-catalog | stringArray | model-catalog YAML path relative to the clone root (repeat for multiple files); replaces the default model-registry/models.yaml |
--models-d | stringArray | models.d-style directory relative to the clone root whose *.yaml drop-ins override same-id local sources (repeat for multiple dirs) |
--name | string | override the directory name (defaults to repo basename) |
--no-model-catalog | — | do not load the source’s default model-registry/models.yaml (persists models_auto: false) |
--pin | string | lock this source to a specific version: a semver tag (e.g. v1.2.3) or “latest” to resolve and record the current highest tag; may also be set inline as <url>@<ref>. Pinned sources are not auto-updated on startup; use “sonny recipe reload <name>” to refresh. |
--skip-unresolved | — | with --approve-mcp: silently skip servers whose binary is not installed on this host |
--subdir | string | subdir of the repo containing pack YAML files |
--update-policy | string | update policy (on_startup|manual) (default “on_startup”) |
--write-config | — | with --approve-mcp: also merge approved server definitions into <config-dir>/mcp.yaml so they are available globally |
--write-untrusted-references | — | with --write-config: also write $VAR references, refused env keys and egress policy beyond the server’s own url host from servers of packs that are not verified-signed into mcp.yaml, where references expand against your environment |
recipe list
Usage:
sonny recipe list [flags]
| Flag | Type | Description |
|---|---|---|
--detail | string | short|full (only with –packs) (default “short”) |
--format | string | deprecated alias for --json (text|json); use --json (default “text”) |
-h, --help | — | help for list |
--json | — | emit the machine-readable envelope instead of the listing |
--recipes | — | list loaded recipes instead of sources |
--tags | strings | filter to packs carrying ALL listed tags (only with –packs) |
The --detail and --tags descriptions are quoted verbatim from the help
output; the flag that switches the listing from sources to loaded recipes
is --recipes.
recipe default
sonny recipe default [recipe-id]
| Flag | Type | Description |
|---|---|---|
--clear | — | remove the persisted default |
-h, --help | — | help for default |
--show | — | print the current default pack (if any) |
recipe update, reload and remove
sonny recipe update fetches and resets tracked sources to their upstream
branch tip:
| Flag | Type | Description |
|---|---|---|
-h, --help | — | help for update |
--name | string | limit update to one source (empty = update all on_startup sources) |
sonny recipe reload [name] performs an unconditional git fetch+reset for the
named source, or every source when name is omitted. It ignores UpdatePolicy
so a manual-policy source still pulls down a new tip on demand. It takes no
flags beyond -h/--help.
sonny recipe remove <name> drops a recipe source and deletes its cache
directory. It takes no flags beyond -h/--help.
recipe search
sonny recipe search <query> BM25-ranks loaded prompt recipes against a query.
| Flag | Type | Description |
|---|---|---|
--detail | string | short|full (default “short”) |
--format | string | text|json (default “text”) |
-h, --help | — | help for search |
--tags | strings | filter to packs carrying ALL listed tags before ranking |
recipe validate
sonny recipe validate <file> statically validates a recipe YAML file.
| Flag | Type | Description |
|---|---|---|
-h, --help | — | help for validate |
--output | string | output format: text | jsonl (default “text”) |
Selecting a pack at run time
sonny recipe manages the sources; a session selects a pack with
sonny run
flags — --dir/-d and
--file/-f to load packs, --recipe to select an already-discovered pack by
id, and --pick-recipe to force the picker.