Quickstart
This quickstart installs the OpenSpine system from source. Lyra is the included assistant package. The governed runtime underneath Lyra keeps credentials and task authority outside the model.
Everything runs on your machine. There is no OpenSpine account, hosted service, or telemetry. The current alpha setup is technical and the first useful workflow is narrow.
Build and prove it works
Section titled “Build and prove it works”git clone https://github.com/George-RD/openspine.gitcd openspinenpm ci # dev tools used by the check scriptcargo build --workspace./scripts/check.sh # runs every test and check used by CIcheck.sh runs formatting, lints, the full test suite, strict OpenSpec validation, and the claims register that ties every documented security claim to a named test or recorded manual justification.
First run (local chat)
Section titled “First run (local chat)”One command turns the built binary into a running, governed install. openspine init writes a configuration and an owner-only key file, binds you as the single trusted owner, and prints the trust ceremony — seed key, approval boundary, and how to test it:
cargo build --workspace --binsexport PATH="$PWD/target/debug:$PATH"openspine --config openspine.local.yaml init --owner <telegram_user_id> --name "Your Name" --model <model_id>openspine --config openspine.local.yaml chat--owner is your Telegram user id — the trusted principal every later approval and audit row is bound to. Message @userinfobot to find it. --model is the model your OpenAI-compatible endpoint serves (default http://127.0.0.1:11434, override with --base-url); without it init asks the endpoint and uses a lone answer, otherwise it stops and asks you to choose. The configuration it writes uses absolute paths, so it works from any directory. This is the fastest path to a governed local reply; the first-run guide explains each step of the ceremony and the capability rungs beyond it. The Docker deployment below adds Telegram and the guarded Gmail draft flow.
Configure a real server
Section titled “Configure a real server”- Copy
.env.exampleto.envand fill in the values. Compose reads this one file and passes it into the kernel container; it does not read theopenspine.envthatinitwrites for the bare-metal path. At minimum you need:DOCKER_GID: the group ID of the Docker socket as the Linux daemon sees it. Don’tstatthe host path: on Docker Desktop and OrbStack that is a symlink into a VM and reports the wrong group. Ask a container instead:This printsTerminal window docker run --rm -v /var/run/docker.sock:/var/run/docker.sock busybox:1.36 \stat -c '%g' /var/run/docker.sock0on OrbStack and thedockergroup ID on Linux.OPENSPINE_TELEGRAM_BOT_TOKEN: get one from @BotFather.OPENSPINE_ARTIFACT_KEY,OPENSPINE_GRANT_HMAC_KEYandOPENSPINE_WEBHOOK_HMAC_KEY: three separate random 32-byte keys, each fromopenssl rand -hex 32. If you already raniniton this data directory, copy these three lines fromopenspine.envinstead.- Your model provider credentials, such as
ANTHROPIC_API_KEY. - Optional:
RUST_LOG. The kernel logs atinfoby default; setRUST_LOG=debug(or a narrower filter) for more detail.
- Copy
openspine.docker.example.yamltoopenspine.yaml. Setowner.telegram_user_idto your Telegram user ID. Message @userinfobot to find it. - To use
/draft, follow the Gmail setup guide:- fill
OPENSPINE_GMAIL_CLIENT_SECRETandOPENSPINE_GMAIL_REFRESH_TOKENin.env; - add the
gmail:block toopenspine.yaml, including yourmailbox_address.
- fill
- Build the contained task-worker image expected by the Docker configuration, then start the kernel:
docker build --file Dockerfile.shell --tag openspine-shell:latest .docker compose up --buildCompose mounts the Lyra package read-only and retains runtime state in ./data. The kernel’s lifetime lock and terminal-erasure ledger live in ./control (OPENSPINE_CONTROL_DIR, set by compose.yaml), so recreating the container keeps them with ./data; back up and restore the two directories together. A deployment that ran before this directory existed has its ledger only inside the old container: migrate it before the first docker compose up with the new compose.yaml, or the kernel refuses to start with terminal-erasure continuity is missing. Stop the old kernel first so the ledger cannot change mid-copy: docker compose stop kernel, mkdir -p control, find the name with docker cp "$(docker compose ps -aq kernel)":/app - | tar -t | grep -m1 openspine-control (lists names only; nothing from ./data is written to disk), copy it with docker cp "$(docker compose ps -aq kernel)":/app/.openspine-control-<hash> ./control/ (docker cp works on a stopped container), then docker compose rm -f kernel so the old copy can never be restarted, and finally docker compose up -d. A one-shot initializer fixes that directory’s ownership before the non-root kernel starts, so existing Compose data is preserved across upgrades. Docker is the supported path for the Gmail workflow. The bare-metal process driver is a development shortcut and refuses /draft unless unsafe_allow_uncontained_private_data: true is set in an isolated development config.
Full setup guides:
Talk to Lyra
Section titled “Talk to Lyra”Send a direct message to your bot from the configured owner account:
/statuschecks whether the system is up and holding its invariants./draft <thread_id>reads only the selected Gmail thread and prepares a reply. Telegram shows the exact text for approval before Gmail receives a draft. Email sending remains denied./propose <kind>followed by YAML proposes a new rule, route, or policy. It stays inactive until you approve the exact text.
openspine init collapses local first-run into one command (issue #118); the remaining Docker/Telegram/Gmail setup and the intended package-level install and run flow are tracked in issue #117.