# Pi (https://tenki.cloud/docs/sandbox/pi)

> For the complete documentation index, see [llms.txt](https://tenki.cloud/llms.txt)

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](https://tenki.cloud/docs/sandbox/base-image.md) 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 `tenki` user (uid 1000), which has passwordless `sudo`. 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 the `tenki` user 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.json` inside 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](#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:

```bash
export ANTHROPIC_API_KEY=<your-anthropic-api-key>

tenki sandbox create \
  --image tenki/pi:stable \
  --env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" \
  --name pi-demo
```

The 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:

```bash
tenki sandbox exec --session pi-demo -- pi-smoke
```

`pi-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:

```text
pong
```

Terminate the Tenki session when you finish:

```bash
tenki sandbox terminate pi-demo
```

## Sign 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:

```bash
tenki sandbox create --image tenki/pi:stable --name pi-demo
tenki sandbox ssh pi-demo
pi        # then run /login and pick a provider
```

How the login completes depends on the provider:

* **Device code**: GitHub Copilot, xAI, and Kimi print a URL and a code; for ChatGPT (Codex), choose &#x2A;*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 `localhost` fails 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:

```bash
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.

```bash
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:

```bash
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:

```bash
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.