install & first run

Getting started

What you need to build Thetis, how to start it, how to run it against a scriptable stand-in instead of a paid API, and what the chat surface gives you on the first turn.

Requirements

Rust 1.82 or newer, and the wasm32-wasip2 target. Thetis was developed against Rust 1.95.

That target is the only unusual requirement. It is what lets plain cargo build emit a WebAssembly component, which is why Thetis needs no cargo-component or similar tooling.

rustup target add wasm32-wasip2

On Linux, install Rust from rustup and add the target in one pass:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
rustup target add wasm32-wasip2

On a minimal image you also need a C linker, so install build essentials:

# Debian / Ubuntu
sudo apt-get install -y build-essential pkg-config

# Fedora / RHEL
sudo dnf install -y gcc make

On Windows, install Rust from rustup.rs using the rustup-init.exe installer. It offers to install the MSVC build tools if they are missing; accept, because the linker is required. Then, in PowerShell:

rustup target add wasm32-wasip2

Check both are present. You should see wasm32-wasip2 in the list.

rustc --version
rustup target list --installed

You also want an OpenRouter API key from openrouter.ai/keys. Thetis talks to OpenAI-compatible endpoints, so any OpenRouter-supported model works. You can point it at a local server instead — llama.cpp, vLLM, Ollama, LM Studio — or alongside OpenRouter, so local and hosted models sit side by side in the model picker; add a [[providers]] entry to thetis.toml, where the section documents itself. A local model must support tool calling, and llama.cpp's server needs --jinja for that to work at all.

Install and first launch

Get the code and build the orchestrator.

git clone https://github.com/biscuitWizard/thetis.ai.git thetis
cd thetis
cargo build --release

The first build compiles wasmtime and takes several minutes. Later builds are seconds.

This builds only the orchestrator. The agent, the chat gateway and any tools are guest components, and the orchestrator compiles those itself on first run.

Give it a key and start it. The key can live in the config file or in the environment, and the environment wins, so you can keep one in a file and override it per run.

OPENROUTER_API_KEY=sk-... cargo run --release -p thetis

On Windows PowerShell, set the variable first — for the current session, or permanently:

$env:OPENROUTER_API_KEY = "sk-or-v1-..."
setx OPENROUTER_API_KEY "sk-or-v1-..."
export OPENROUTER_API_KEY="sk-or-v1-..."
# or add it to ~/.bashrc / ~/.zshrc to persist

Prefer a key that version control ignores over one in thetis.toml. Copy the file, set api_key under [llm], and point Thetis at the copy.

cp thetis.toml thetis.local.toml
api_key = "sk-or-v1-..."
THETIS_CONFIG=thetis.local.toml cargo run --release
$env:THETIS_CONFIG = "thetis.local.toml"; cargo run --release

Guests are built automatically on boot. On the first start you watch each one compile and load:

INFO starting thetis root=/path/to/thetis
INFO building aspect=gateway/web
INFO building aspect=agent
INFO hot reload active
INFO thetis listening addr=127.0.0.1:7777

Open http://127.0.0.1:7777. Subsequent starts serve components straight from the build cache — no compile needed — and come up in well under a second.

You can also run the built binary directly instead of through cargo:

./target/release/thetis
.\target\release\thetis.exe

Running without an API key

A scriptable stand-in speaks enough of the streaming protocol to exercise the whole system — token deltas, tool calls, usage accounting — at no cost. It is useful for development, and for confirming the setup works before spending anything.

Run it in one terminal:

cargo run --release --bin mock-llm

And Thetis in another, pointed at it:

OPENROUTER_API_KEY=test OPENROUTER_BASE_URL=http://127.0.0.1:7788 THETIS_MODEL=mock/echo cargo run --release -p thetis
$env:OPENROUTER_API_KEY = "test"
$env:OPENROUTER_BASE_URL = "http://127.0.0.1:7788"
$env:THETIS_MODEL = "mock/echo"
cargo run --release

The mock picks its reply from keywords in your message. Try remember something, make a new tool, or please be slow about this to exercise different paths.

To go back to the real API, unset those three variables — they override the config file — and restart.

unset OPENROUTER_BASE_URL THETIS_MODEL
Remove-Item Env:OPENROUTER_BASE_URL, Env:THETIS_MODEL -ErrorAction SilentlyContinue

Your first conversation

The web UI is an ES-module app with no build step, embedded in the gateway component. Four controls carry most of what you do on the first turn.

Modes

Each conversation has a mode, Agent by default. Plan withholds every tool that would change something, and refuses them at dispatch too, so a model that remembers a tool from earlier in the conversation still cannot call it. Switch modes per conversation from the mode picker.

Models

The model picker is a per-conversation override, chosen from THETIS_MODELS. Leave it empty and the conversation uses the grip default. The mode and model selectors are both instances of the same Picker.

Skills

Skills are named instruction sets, one markdown file each in skills/, with a short frontmatter block for the title and description and the body as the instructions. Attach them per conversation from the Skills panel; attached skills are appended to the system prompt. Editing a file takes effect on the next turn — nothing to restart, nothing to register.

---
name: Concise replies
description: Answer in as few words as the question needs.
---

Lead with the answer. Do not restate the question.

The tools panel

The tools panel shows exactly what the model is offered for this conversation, asked of the agent itself rather than reconstructed, so it cannot drift from reality. Each tool lists its arguments, whether it is built in or a hot-loaded component, and whether it changes anything — which is also why the list shrinks in Plan mode.

Attachments and titles

Images can be pasted, dropped, or picked from the file browser. They travel base64-encoded from the browser through the event log to the model's image_url content parts, so nothing re-encodes on the way and a reopened conversation still shows its pictures.

A conversation is named from its opening message, trimmed to one line and cut on a word boundary, or named after the file when the message is only an attachment. Once a title exists, nothing renames it but you.

Troubleshooting

error: failed to run custom build command or linker errors on Linux. Install build essentials, as above.

the 'wasm32-wasip2' target may not be installed. Run rustup target add wasm32-wasip2.

no API key: set llm.api_key in thetis.toml, or OPENROUTER_API_KEY in the environment. The key is missing or blank. An empty setting counts as absent.

Thetis refuses to start naming a config key. The config file is parsed strictly, so a typo is an error rather than a setting that silently does nothing. The message names the offending key.

Address already in use on startup. Another copy is running. Thetis retries the bind for 15 seconds to allow for restarts, then gives up. Find and stop it, or change server.bind in thetis.toml.

pkill thetis
Get-Process thetis | Stop-Process -Force

aspect failed to start aspect=tool/delete-tool. A leftover half-written tool that does not compile. It is harmless — the orchestrator logs it and carries on — but you can delete tools/delete-tool/ to quiet it.

The page says "the chat gateway is unavailable". The gateway component failed to build or load. The page is host-rendered and links to /admin, where you can reset the branch to a commit that built green.

Wiping state. data/ holds conversations and the event log; artifacts/ is the build cache. Deleting both resets Thetis to a clean install — though conversation branches live in git and survive until pruned. Stop it first.