# Run Sausage Use the web UI for conversations, passkeys, approvals, and secret entry. The host serves only JSON through `/api/`. **TL;DR:** Start a separate v3 world, create the SSH tunnel below, and open http://localhost:8080. The Nix package supplies the userland bundle, source tree, and enabled chat service. Keep the complete world folder between starts. ## Build and start Run host commands from a checkout of the repository. Use Nix with flakes and the `pipe-operators` experimental feature. The package supplies the native Rust builder and its tools. `nix build` builds the host and userland through separate Crane pipelines. The userland pipeline targets `wasm32-wasip2`. Separate Go derivations build awk and esbuild for WASI preview1. QuickJS builds from its vendored C sources with WASI clang. Nix assembles the final bundle without the development bundle script. Use `sausage run --no-builder-sandbox WORLD` only when the host must run the builder without namespace isolation. The package entry point is: ```sh nix run . -- init "$HOME/sausage-v3" nix run . -- run "$HOME/sausage-v3" .md`. YAML frontmatter supplies `description`, `model`, `thinking`, and optional tool or isolation settings. The body supplies the role prompt. The filename supplies the name. Project definitions use `/.sausage/roster/*.md`. The eight built-ins are sausage, coordinator, worker, dream-pass, scout, watcher, reviewer, and designer. Every agent receives the global `prompt` before its role prompt. The shared prompt explains how agents inspect their own model and the live harness state. Run `sausage init`. Set `providers..api_key` in the config, then run `sausage run`. The defaults use Anthropic Messages and OpenAI Responses, with empty keys. The config also shows a commented OpenAI-compatible Chat Completions endpoint. Each provider has `type`, `base_url`, `api_key`, and `models`. References use `/`. An optional `catalog` selects the models.dev provider ID. It defaults to the configured provider's name. The host refreshes models.dev metadata at startup and caches it in `host/models-dev.json`. If the refresh fails, the host uses that cache or the packaged snapshot. Model objects can override `context_window`, `max_tokens`, `reasoning`, and `cost`. Cost fields are `input`, `output`, `cache_read`, and `cache_write`, in USD per million tokens. An unknown model needs all metadata fields. Its error names the missing fields and config path. Pi-ai stores estimated call costs in assistant usage. The host and chat start with empty keys. A model request with missing settings names the config file. Provider API keys in the config are intentionally visible to agents. Do not print or commit them. Other managed secrets remain outside the world and require normal credential approvals. Edit `main_agent_name` to select a definition. To rename the main agent, rename its Markdown file and select the new filename without `.md`. The same conversation adopts the new name, model, and role prompt. The default is `sausage`, with `anthropic/claude-opus-5-5` and `high` thinking. Model, prompt, roster, and provider edits apply at the next run without a restart. Sources: [`credentials.rs`](../host/src/harness/credentials.rs), [`main.ts`](../host/js/main.ts), and [`models`](../extensions/models/README.md). ## Change extensions The platform source is `/src/sausage`. Each extension lives at `extensions/NAME/server.ts`. Save extension edits directly. No Git commit or restart is required. The VFS watcher waits for a short quiet period, then hashes the extension files. Unchanged contents do not reload. The loader copies the files under `/run/sausage/extensions/HASH`. It validates the entire candidate before it replaces the live registry. A broken candidate leaves the previous good set active. An active tool call retains its implementation. The next call uses the new implementation. Read `/proc/extensions` through the agent's file tools to inspect `current`, `good`, and `error`. Use `undo` to restore earlier files. The normal file watch reloads them. At startup, the loader hashes the current files, including edits made while the host was offline. If they fail, it loads the last good copy from `host/harness.sqlite` and shows the error. The fallback does not change editable files. Source: [`extensions`](../extensions/README.md) and [`extensions.ts`](../host/js/extensions.ts). ## Everyday tools inside the world These are world programs, not console commands. Ask the agent to run them. | Tool | Use and limits | | --- | --- | | `cargo` | Build, run, and test Rust programs. The host copies the workspace through the VFS, fetches dependencies, then builds offline in namespaces. It publishes WASI artifacts into the world. Other targets are unsupported. | | `undo` | Inspect tags and restore filesystem changes. Later edits can conflict. Network effects and native builds are not reversible. Retention is seven days or 4 GiB of unique content. | | `systemctl` | Control world init services, not the host machine's systemd. Persistent units live under `/etc/systemd/system`. Init observes edits without daemon reload. | | `journalctl` | Read world service logs under `/var/log/journal`. Each unit retains a 1 MiB log and one rotated file. | | `git` | Manage world repositories. HTTPS credential rules can inject authorization through the host HTTP hook. SSH remotes use host signing. | | `ssh` | Execute a remote command without a PTY. Public identities and signatures come from the host. Private keys never enter the world. Host keys live in the world's known_hosts file. | Init starts when the host starts the runtime, if `/bin/init.wasm` exists. Transient units under `/run/systemd/transient` disappear after restart. A missing credential grant causes a pending host request, not an automatic approval. A changed SSH host key fails even with the accept-new policy. Command reference and implementation evidence: [`builder`](../host/src/builder/README.md), [`undo`](../userland/undo/README.md), [`init`](../userland/init/README.md), [`git`](../userland/git/README.md), and [`ssh`](../userland/ssh/README.md). ## Build a world UI with the host API World programs call **`http://host.sausage`** through standard WASI HTTP. The world web server forwards `/api/PATH` to `http://host.sausage/PATH` through WASI HTTP. It streams response chunks instead of buffering the entire NDJSON body. The bootstrap page polls `entries?after=` once per second rather than using a persistent stream. Use the credential views in the web UI. They call only `/api/cred/...` JSON routes. | Method and route | Result or request | | --- | --- | | `GET /harness/conversations` | Conversation records and `main_agent: {name, conversationId}` for the default selection. | | `GET /harness/conversations/ID/entries?after=0` | `{entries:[...]}` in ascending order. | | `GET /harness/conversations/ID/stream?after=0` | NDJSON entries, replay first, then live commits. | | `POST /harness/conversations/ID/submit` | `{content:"text",requestId:"stable-id"}` returns 202 and a submission ID. Reuse the request ID for retries. | | `POST /harness/conversations/ID/stop` | Stops active turns and owned work. Queued input remains. | | `GET /harness/events?after=0` | NDJSON events, replay first, then live commits. | | `POST /harness/extensions/NAME/actions/ACTION` | `{args:{...},conversationId?:number}` invokes an exported user action. | | `GET /harness/models` | Public model catalog without authentication data. | | `GET /harness/extensions` | Loaded extension status. | | `GET /harness/credential-requests` | Pending conversation requests with `/#approve/ID` links. | The `after` cursor is exclusive. Reconnect with the last record ID. Streams close when the client disconnects or the harness stops. Do not render a stream as one JSON response. An unavailable harness returns 503. Invalid input returns 400. Missing resources return 404. Source: [`host API contract`](../host/src/api/README.md), [`harness-api.ts`](../host/js/harness-api.ts), and [`harness/http.rs`](../host/src/harness/http.rs). ## Known gaps before cutover - Laptop access, passkey ceremonies, secret entry, and browser approval remain **to check with Surma**. - Startup checks use fake provider credentials. They do not verify a real model session or external credential injection. - The bootstrap chat is deliberately plain. There is no item editor or credential dashboard. - The console has no shell commands, transcript navigation, or special quit command. - `sausage sh` requires `-c`. Its interactive shell is not implemented. A successful local start does not verify external services or the production passkey origin.