TEHAS

Bootstrap a host

bootstrap.sh prepares a fresh machine with everything tehas and pi-rukas need, at the versions in host/versions.env. It is in the top of the platform repository, next to install.sh. It installs tools only: credentials, the clones and tehas itself come after it, on the new project page.

What the machine needs

Run it

git clone <the platform repository> ~/tehas/platform
cd ~/tehas/platform
sudo ./bootstrap.sh root boss     # 1. as root, naming the tehas user
# log out and in again, so the docker group applies
./bootstrap.sh user               # 2. as the tehas user
./bootstrap.sh check              # 3. one line per tool

If the platform repository is private, the clone needs the deploy key from the credentials section first; create that key by hand and come back.

1. root <user>

Installs from Ubuntu's packages: Docker with compose and buildx, git, jq, curl, openssl, rsync, shellcheck, unzip and the build tools that compiling two of the tools needs. Adds the user to the docker group, enables lingering for it (so the dispatcher timer runs without a login) and enables the Docker service.

System packages are not pinned. You get what the distribution offers.

2. user

Installs under the user's home, each tool in its own place:

Tool Where From
Node and npm ~/tehas/tools/node Release archive, checksum
gh ~/tehas/bin/gh Release archive, checksum
Deno ~/.deno/bin Release archive, checksum
Bun ~/.bun/bin Release archive, checksum
Pi, ctx7, parallel-cli ~/.local (npm prefix) npm, exact versions
Rust, then vipune and oo ~/.rustup, ~/.cargo rustup, then cargo install
codebase-memory-mcp ~/.local/bin Its installer, pinned release
pi-rukas ~/tehas/repos/pi-rukas, one commit Its repository, then its install.sh

Every release archive is checked against a SHA-256 in versions.env before it is unpacked. The last step runs pi-rukas's own installer, which links its extension and skills into ~/.pi/agent/ and pulls its sandbox base image.

Compiling vipune and oo takes a few minutes. The rest is quick.

3. check

Changes nothing. Prints each tool with the version found and the one expected, then the system tools, Docker without sudo, and lingering. Exit 1 if anything is missing or at another version. ./install.sh --check runs it as its Dependencies line.

Running it again

It is safe to run again. A tool already at its version is skipped. A tool it owns that is at another version is replaced with the pinned one. To change a version, edit host/versions.env (the version and, for an archive, its checksum), run ./bootstrap.sh user, rebuild the sandbox image and rerun the contract test before a cycle uses it.

A tool of the same name installed elsewhere by someone else is left alone. The pinned one comes first on the PATH that env.sh sets.

Two traps the script handles

Both were found installing the example host by hand. The script deals with them; they are here so the error is recognisable if it comes back.

Credentials

Not created by the script. All of them go in ~/.config/tehas/, mode 600, never in git.

The bot token. A token of a GitHub machine account with write access to the product repository, in ~/.config/tehas/env as GH_TOKEN=.... What it is used for: reading the queue and label events, relabelling and commenting, pushing the cycle's branch, opening the pull request.

The deploy key. For a private platform repository, a read-only deploy key:

ssh-keygen -q -t ed25519 -N "" -f ~/.config/tehas/deploy_key
git -C ~/tehas/platform config core.sshCommand \
  "ssh -i ~/.config/tehas/deploy_key -o IdentitiesOnly=yes"

Add deploy_key.pub to the repository's deploy keys without write access.

The bot's git identity. git config --global user.name and user.email for the tehas user. tehas-work refuses to start a cycle without them.

What is proven

bootstrap.sh was written from a hand install of the example host, recorded step by step in docs/bringup/2026-10-08-tehas-tehas-log.md. On that host check passes and a second user run changes nothing. A run from scratch on a fresh machine has not been done. Expect to fix something the first time.