Pi
Start from Tenki's pre-built Pi image and run the open source Pi coding agent inside a per-session isolation boundary.
Tenki's public tenki/pi:stable image starts with the standard sandbox base image and pins Pi, an open source minimal terminal coding harness invoked as the pi command, at version 0.85.1. Pi needs no git repository and no first-run setup, so a non-interactive pi -p runs out of the box. It includes no credentials: you pass a provider API key when you create a session, or sign in with a subscription inside it.
Isolation
Pi ships no permission system of its own and runs with the permissions of whatever launched it. Pi's own documentation recommends running it in a container or sandbox. In a Tenki sandbox, the guest is the entire boundary, and it is enforced per session.
What that boundary does here:
- Inside the guest: Pi runs as the unprivileged
tenkiuser (uid 1000), which has passwordlesssudo. It can read and write within that guest's filesystem, run shell commands, and use the installed toolchain, all as that user, and it can reach root there. In print mode (pi -p) there is no approval prompt, so anything thetenkiuser can do inside the guest, Pi can do. - Outside the guest: Pi cannot reach the host kernel or filesystem, other tenants' sessions, or the Tenki control plane.
- Network: Pi reaches the network only through the sandbox's normal egress path. It gets no special network capability beyond a standard sandbox session.
- Credentials and state: a provider key exists only as session environment, set at creation; a subscription login is stored in
~/.pi/agent/auth.jsoninside that session only. No credential or state is carried from one session to the next, so nothing bleeds between sessions. The image itself contains no credential.
Authenticate with a provider key
Pi is provider-agnostic. It reads a provider API key straight from the session environment, so the API-key path needs no login step. Any of Pi's supported provider variables works, passed at session creation: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, XAI_API_KEY, OPENROUTER_API_KEY, DEEPSEEK_API_KEY, MISTRAL_API_KEY, and around twenty others.
ANTHROPIC_API_KEY is only what the built-in pi-smoke check happens to use; it is not special to the image. To use any other provider, pass that provider's own variable instead.
With at least one provider key set, Pi resolves that provider's default model; no --model is required. Set PI_MODEL to pin a specific model instead of the default.
Pi can also sign in with a subscription instead of an API key; see Sign in with a subscription.
Pass the key only to the session. Do not bake it into a template, snapshot, source file, or image.
Start a session
Export a provider key locally, then pass it only to the session:
export ANTHROPIC_API_KEY=<your-anthropic-api-key>
tenki sandbox create \
--image tenki/pi:stable \
--env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" \
--name pi-demoThe shell history contains the environment variable reference, not the key value. Do not add the key to a template, snapshot, source file, or image.
Run the built-in connectivity check:
tenki sandbox exec --session pi-demo -- pi-smokepi-smoke reads ANTHROPIC_API_KEY, creates a throwaway sample repo, runs a one-shot pi -p, and prints the model's reply. With its default prompt, a successful result prints:
pongTerminate the Tenki session when you finish:
tenki sandbox terminate pi-demoSign in with a subscription
Pi can use a subscription (Claude Pro/Max, ChatGPT Plus/Pro, GitHub Copilot, xAI, Kimi, OpenRouter, Radius) instead of an API key. Pi has no login subcommand; sign in from its interactive mode over SSH. Create the session with no key:
tenki sandbox create --image tenki/pi:stable --name pi-demo
tenki sandbox ssh pi-demo
pi # then run /login and pick a providerHow the login completes depends on the provider:
- Device code: GitHub Copilot, xAI, and Kimi print a URL and a code; for ChatGPT (Codex), choose Device code login (headless). Open the URL on your own machine and enter the code.
- Paste the redirect back: Claude Pro/Max and OpenRouter open a sign-in URL. Complete it on your own machine; the final redirect to
localhostfails because it points at the sandbox, so copy that URL from your browser's address bar and paste it into Pi's prompt.
Pi stores the login in ~/.pi/agent/auth.json and makes that provider's model the default. Confirm it from outside the TUI, then run headlessly with no key:
tenki sandbox exec --session pi-demo -- pi auth check --provider openai-codex # prints: ready
tenki sandbox exec --session pi-demo -- pi -p --model openai-codex/gpt-5.5 "Summarise this project."Pick the provider with --model <provider>/<model>; --provider alone keeps the default model from the last login. pi --list-models <provider> lists the provider's models, but not every one is available to a subscription account; an unsupported model fails with a clear error. Anthropic bills third-party harness usage on Claude Pro/Max as extra usage rather than plan limits, so enable extra usage on the account first.
A stored login takes precedence over a provider environment variable for the same provider. pi-smoke covers the API-key path only and requires ANTHROPIC_API_KEY.
Run a task
Pi needs no git repository and no first-run setup, so you can run a task immediately. Print mode (pi -p) is the headless path: Pi takes a prompt, does the work, and exits.
tenki sandbox exec --session pi-demo -- pi -p "List the files here and summarise what this project does."Print mode runs directly, with no approval prompt, so Pi acts within the guest as the tenki user. It uses the session's provider key or its stored subscription login.
To work on your own code, clone it into the session and run Pi from inside it:
tenki sandbox exec --session pi-demo -c \
'git clone https://github.com/your-org/your-repo.git && cd your-repo && \
pi -p -a "Add a test for the parser and run it."'Pi keeps its settings and session state under ~/.pi/agent, which the image pre-creates. Override the location with PI_CODING_AGENT_DIR.
Project trust
Pi asks before loading a repository's .pi settings, skills, extensions, and system prompt files, so a repository cannot silently reconfigure the agent. The image pins that behaviour to Pi's own default, ask.
Print mode never shows the prompt. A pi -p run therefore skips those project resources unless you pass -a, and it skips them silently — nothing is printed to say so. Pass -a when the repository is yours, and leave it off for code you have not reviewed: project extensions are TypeScript that runs at startup with your provider key in the environment.
An interactive pi started over tenki sandbox ssh prompts as it does anywhere else, and remembers the answer for that directory.
Pin an exact build
stable moves to each newly published build. When a workload has to stay on the exact build it was tested against, resolve the tag once and launch the snapshot reference it returns:
tenki sandbox registry resolve tenki/pi:stable
# image_id : <image-id>
# snapshot_id : <snapshot-id>
tenki sandbox create --image tenki/pi@<snapshot-id>A snapshot reference never moves, so it keeps launching that build after stable advances.