# Pi (/docs/agents/pi)

<!-- agent-signals: reading_time_min: 4 · est_tokens: 2397 · updated: 2026-07-30 -->
Related: [Amp](/docs/agents/amp.md), [Claude Code](/docs/agents/claude-code.md), [Claude Managed Agents](/docs/agents/claude-managed-agents.md), [Codex](/docs/agents/codex.md), [Crabbox with E2B](/docs/agents/crabbox.md), [Devin](/docs/agents/devin.md)

[Pi](https://pi.dev) is a minimal terminal coding agent that can be extended with TypeScript extensions, skills, prompt templates, and themes. E2B provides a pre-built `pi` template with Pi already installed.

## CLI [#cli]

Create a sandbox with the [E2B CLI](/docs/cli).

```bash
e2b sbx create pi
```

Once inside the sandbox, start Pi.

```bash
pi
```

Use `/login` to authenticate with a supported subscription provider, or provide an API key through an environment variable.

## Run headless [#run-headless]

Use `-p` for non-interactive print mode. Pi does not show permission prompts for its built-in tools, so no auto-approval flag is needed. The sandbox isolates Pi from your host machine, but sandboxes can reach the open internet by default — restrict outbound traffic with [network rules](/docs/network/internet-access).

Pi supports multiple model providers. The examples below use Anthropic through the `ANTHROPIC_API_KEY` environment variable.

<Note>
  Pi can read and modify files and run shell commands directly. E2B contains those operations inside the sandbox, so Pi cannot access your host files or credentials. It can still make outbound network requests — use [outbound network rules](/docs/network/internet-access) to limit access by CIDR or hostname. Hostname rules apply to HTTP(S) traffic only; use CIDR rules for other protocols.
</Note>

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```typescript  
      import { Sandbox } from 'e2b'

      const sandbox = await Sandbox.create('pi', {
        envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
      })

      const result = await sandbox.commands.run(
        `pi -p "Create a hello world HTTP server in Go"`
      )

      console.log(result.stdout)
      await sandbox.kill()
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      import os
      from e2b import Sandbox

      sandbox = Sandbox.create("pi", envs={
          "ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"],
      })

      result = sandbox.commands.run(
          'pi -p "Create a hello world HTTP server in Go"',
      )

      print(result.stdout)
      sandbox.kill()
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

### Example: work on a cloned repository [#example-work-on-a-cloned-repository]

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```typescript  
      import { Sandbox } from 'e2b'

      const sandbox = await Sandbox.create('pi', {
        envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
        timeoutMs: 600_000,
      })

      await sandbox.git.clone('https://github.com/your-org/your-repo.git', {
        path: '/home/user/repo',
        username: 'x-access-token',
        password: process.env.GITHUB_TOKEN,
        depth: 1,
      })

      const result = await sandbox.commands.run(
        `cd /home/user/repo && pi -p "Add error handling to all API endpoints"`,
        { onStdout: (data) => process.stdout.write(data) }
      )

      const diff = await sandbox.commands.run('cd /home/user/repo && git diff')
      console.log(diff.stdout)

      await sandbox.kill()
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      import os
      from e2b import Sandbox

      sandbox = Sandbox.create("pi", envs={
          "ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"],
      }, timeout=600)

      sandbox.git.clone("https://github.com/your-org/your-repo.git",
          path="/home/user/repo",
          username="x-access-token",
          password=os.environ["GITHUB_TOKEN"],
          depth=1,
      )

      result = sandbox.commands.run(
          'cd /home/user/repo && pi -p "Add error handling to all API endpoints"',
          on_stdout=lambda data: print(data, end=""),
      )

      diff = sandbox.commands.run("cd /home/user/repo && git diff")
      print(diff.stdout)

      sandbox.kill()
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

## Build a custom template [#build-a-custom-template]

If you need to customize the environment (e.g. pre-install dependencies, add config files), build your own template on top of the pre-built `pi` template.

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```typescript  
      // template.ts
      import { Template } from 'e2b'

      export const template = Template()
        .fromTemplate('pi')
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      # template.py
      from e2b import Template

      template = (
          Template()
          .from_template("pi")
      )
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```typescript  
      // build.ts
      import { Template, defaultBuildLogger } from 'e2b'
      import { template as piTemplate } from './template'

      await Template.build(piTemplate, 'my-pi', {
        cpuCount: 2,
        memoryMB: 2048,
        onBuildLogs: defaultBuildLogger(),
      })
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      # build.py
      from e2b import Template, default_build_logger
      from template import template as pi_template

      Template.build(pi_template, "my-pi",
          cpu_count=2,
          memory_mb=2048,
          on_build_logs=default_build_logger(),
      )
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

Run the build script to create the template.

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```bash  
      npx tsx build.ts
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```bash  
      python build.py
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

## Related guides [#related-guides]

<CardGroup cols="3">
  <Card title="Sandbox persistence" icon="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; viewBox=&#x22;0 0 24 24&#x22; fill=&#x22;none&#x22;><circle cx=&#x22;12&#x22; cy=&#x22;12&#x22; r=&#x22;10&#x22; stroke=&#x22;currentColor&#x22; stroke-width=&#x22;1.5&#x22;/><path d=&#x22;M12 8V12L14 14&#x22; stroke=&#x22;currentColor&#x22; stroke-linecap=&#x22;round&#x22; stroke-linejoin=&#x22;round&#x22; stroke-width=&#x22;1.5&#x22;/></svg>" href="/docs/sandbox/persistence">
    Auto-pause, resume, and manage sandbox lifecycle
  </Card>

  <Card title="Git integration" icon="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; viewBox=&#x22;0 0 24 24&#x22; fill=&#x22;none&#x22;><path d=&#x22;M16 6.99998L19.0664 9.64296C20.3554 10.7541 21 11.3096 21 12C21 12.6903 20.3555 13.2459 19.0664 14.357L16 17&#x22; stroke=&#x22;currentColor&#x22; stroke-linecap=&#x22;round&#x22; stroke-linejoin=&#x22;round&#x22; stroke-width=&#x22;1.5&#x22;/><path d=&#x22;M8 6.99998L4.93365 9.64296C3.64455 10.7541 3 11.3096 3 12C3 12.6903 3.64455 13.2459 4.93365 14.357L8 17&#x22; stroke=&#x22;currentColor&#x22; stroke-linecap=&#x22;round&#x22; stroke-linejoin=&#x22;round&#x22; stroke-width=&#x22;1.5&#x22;/></svg>" href="/docs/sandbox/git-integration">
    Clone repos, manage branches, and push changes
  </Card>

  <Card title="SSH access" icon="<svg xmlns=&#x22;http://www.w3.org/2000/svg&#x22; viewBox=&#x22;0 0 24 24&#x22; fill=&#x22;none&#x22;><path d=&#x22;M4.00004 17C4.00004 17 9.99999 12.5811 10 11C10 9.41884 4 5 4 5&#x22; stroke=&#x22;currentColor&#x22; stroke-linecap=&#x22;round&#x22; stroke-linejoin=&#x22;round&#x22; stroke-width=&#x22;1.5&#x22;/><path d=&#x22;M12 19H20&#x22; stroke=&#x22;currentColor&#x22; stroke-linecap=&#x22;round&#x22; stroke-linejoin=&#x22;round&#x22; stroke-width=&#x22;1.5&#x22;/></svg>" href="/docs/sandbox/ssh-access">
    Connect to the sandbox via SSH for interactive sessions
  </Card>
</CardGroup>
