# Sausage You can see how the sausage is made. Sausage is a world of small WASI programs ("plugins") that you grow by talking to it. A plugin is a `.wasm` file with JSON-RPC methods. Each call to a plugin starts a new process. The agent is a plugin too: it writes new plugins in Rust, builds them, tests them, activates them, and can change its own code. ## Start You need [Nix](https://nixos.org/download) with flakes, and an API token for an LLM (OpenAI Responses or Anthropic Messages API). No clone needed: ```sh nix run git+https://gitea.surma.technology/surma/sausage ``` This creates a world in `./world` the first time (it builds the agent: the first build on a machine takes a few minutes, later worlds reuse the compiled crates), then starts it with a console. Later runs start the existing world. The two steps on their own: ```sh nix run git+https://gitea.surma.technology/surma/sausage -- init # creates ./world and builds the agent nix run git+https://gitea.surma.technology/surma/sausage -- run # starts the world and a console ``` `init` asks for the API shape (`openai-responses` or `anthropic-messages`), the base URL, the model, and the token. It reads `SAUSAGE_API`, `SAUSAGE_BASE_URL`, `SAUSAGE_MODEL`, and `SAUSAGE_API_TOKEN` first. The values go to `world/config/agent.json`. Both commands take another folder as an argument, for example `... -- run my-world`. Compiled code is cached outside the world, in `$XDG_CACHE_HOME/sausage/` (`~/.cache/sausage/` without the variable). All worlds share it. `--cache-dir ` changes it for `init` and `run`. To keep a world on the newest version, run it in a loop: ```sh nix run git+https://gitea.surma.technology/surma/sausage#loop # ./world, created if needed nix run git+https://gitea.surma.technology/surma/sausage#loop -- my-world # an existing world ``` When the host crashes or a plugin calls `core.exit`, the loop fetches the newest commit and starts it again. `quit` ends the loop. Set `SAUSAGE_FLAKE` to run another flake URL instead, for example your fork. From a clone (`git clone https://gitea.surma.technology/surma/sausage`), the same commands are `nix run`, `nix run -- init`, `nix run -- run`, and `nix run .#loop`. ### Headless `--headless` (or `SAUSAGE_HEADLESS=1`) turns the console input off. The host runs until SIGTERM or SIGINT (exit code 0) or until a plugin calls `core.exit` (exit code 75, so the loop starts the newest version): ```sh nix run git+https://gitea.surma.technology/surma/sausage#loop -- --headless my-world ``` ## The console | Input | Effect | | --- | --- | | text | a message to the agent (`agent.chat`) | | `. {json}` | a call. The console prints the result. | | `ls [path]`, `cat ` | the filesystem as a process sees it, with `/proc` and `/run` | | `methods ` | the methods of a plugin, with params and docs | | `ps` | the running processes | | `log [plugin or pid] [-n N]` | the journal | | `activate `, `revert ` | activate a new version, or go back | | `stop `, `kill ` | stop a process | | `help`, `quit` | | ## The world folder ```text plugins//plugin.wasm the current version of a plugin plugins//source/ its source state// the state of a plugin, by convention state/core/journal.sqlite the journal: stderr of all processes, and core events config/boot.json the services that start with the world config/agent.json the configuration of the agent ``` Each process also sees `/proc` (the processes and the state of the core), `/self` (its own folder in `/proc`), and `/run` (shared files in memory). To replace a plugin by hand, copy a `.wasm` file to its `plugin.wasm`. That skips the interface checks. `revert ` goes back to the version before the last activation. ## More - [PROTOCOL.md](PROTOCOL.md): calls, processes, the filesystem, locks, interfaces, and `cargo`. Read this to write a plugin in any language. - [DECISIONS.md](DECISIONS.md): why Sausage is the way it is. - [`sdk/`](sdk/): `sausage-plugin`, the SDK for Rust plugins. - [`examples/`](examples/): small plugins. - [AGENTS.md](AGENTS.md): how to work on Sausage itself.