# marvin-turnstone Local turnstone deployment as a [boco](https://git.nubo.sh/hulthe/boco) **container-VM**. host podman build ──> boco build qcow2 ──> boco boot │ QEMU/KVM (virtio, user-net) ┌─────────────────────┴───────────────────┐ │ VM (Arch) │ │ /boco/init → start-turnstone.sh (root) │ │ ├─ sshd (ops channel) │ │ └─ setpriv marvin │ │ └─ turnstone-server :8080 PID 1 │ └─────────────────────────────────────────┘ host :8080 ──hostfwd──> web UI host :2222 ──> guest sshd :22 ## Prerequisites - `podman`, `qemu-base`, `virtiofsd`, `boco` ## Build ```sh scripts/build.sh ``` Creates `configs/ssh/id_ed25519` (ops keypair, once), builds the podman image, then packs it as `boco` qcow2 into the boco registry. ## Run ```sh scripts/run.sh ``` This exposes the turnstone console on `:8080`, and ssh on `:2222` ### LLM backend Set up `configs/turnstone/config.toml` with an OpenAI-compatible endpoint. ## Shares (virtiofs, survives reboots) | Host path | Guest path | Purpose | |------------------------|--------------------------------|--------------------------| | `configs/turnstone/` | `/home/marvin/.config/turnstone` | turnstone config.toml | | `data/` | `/var/lib/turnstone` | SQLite database | | `work/` | `/home/marvin/work` | agent workspace | Note that virtiofsd runs under `podman unshare`, which means that files written by the guest-VM will be owned by a subuid-range. ## Configuration Edit `configs/turnstone/config.toml` (see `config.toml.example`): - `[models.]` - LLM provider; `api_key` must be set. - `[auth] jwt_secret` - required, generate once. - `[database] path` - SQLite on the `data/` share. - `[tools]` - `workspace_dir` surfaced to the model. ### Personas Turnstone offers a few built-in personas (Engineer, Writer, Researcher, Scribe, Manager, Executive), which are seeded by turnstone's migration. This deployment adds a custom default persona `marvin` (VM-specific: persistence rules, Gitea remotes, podman) via `scripts/persona.py` - the prompt text is versioned there and re-applied after a DB reset: ```sh python3 scripts/persona.py # --db data/turnstone.db default ``` (Without a console deployment, persona CRUD is a direct SQLite write; with `turnstone-console` running, use its admin API/Personas tab.) ### Skills Skills are checked in under `skills` in the `SKILL.md format.` These are imported into turnstone's DB-backed catalog via `scripts/import_skills.py`. The script runs inside the VM. ```sh scp -O -i configs/ssh/id_ed25519 -P 2222 -r skills scripts/import_skills.py \ marvin@localhost:/tmp/ ssh -i configs/ssh/id_ed25519 -p 2222 marvin@localhost \ /opt/turnstone/bin/python /tmp/import_skills.py --dir /tmp/skills ``` Idempotent (`--update` re-imports + appends version rows). **Reboot the VM after importing** - the running server holds a stale WAL snapshot and won't see new rows until restart.