> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beacon.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Pi

> Beacon support details for Pi endpoint telemetry

## Runtime overview

Beacon supports [Pi](https://pi.dev/) through a managed local extension.

<Note>
  Looking for [Oh My Pi](/runtimes/oh-my-pi) (`omp`), [Prime Agent](/runtimes/prime-agent), or [Senpi](/runtimes/senpi) (`omo`, the standalone edition of oh-my-openagent)? All three are forks of Pi, supported separately and recorded under their own harness names. Unlike Pi, Oh My Pi reports operator approval decisions.
</Note>

Pi fits neither of Beacon's two usual live integration shapes. It has no hooks configuration file to merge a managed hook block into, and no OpenTelemetry support to point at the local collector. Its documented observation surface is the TypeScript extension API, so the live integration is extension-shaped: one Beacon-owned extension file forwards runtime events to `beacon-hooks`, the same shape as the OpenCode and Cline plugins.

```bash theme={null}
beacon endpoint hooks install --harness pi
```

Beacon can also read Pi's committed JSONL session store after the fact:

```bash theme={null}
beacon endpoint pi sync
```

That poll path is local and offline, checkpointed by file and line number, and marks every event `harness.collection_method=poll`. It complements the extension rather than replacing it: the extension sees live events as Pi runs, while the poll path can backfill sessions that happened before the extension was installed or sessions where the extension was not loaded.

## Prerequisites

Before enabling Pi telemetry, make sure:

* Pi is installed and available as the `pi` executable, or has a local state directory at `~/.pi/agent`.
* `beacon endpoint install` has run so shared endpoint config and runtime log paths exist.
* Pi is restarted after install or removal so new sessions load the updated extension.

## Collection path

Beacon's managed Pi extension is a single TypeScript file at one of two documented extension locations:

| Level   | Extension path                     |
| ------- | ---------------------------------- |
| User    | `~/.pi/agent/extensions/beacon.ts` |
| Project | `./.pi/extensions/beacon.ts`       |

User level is the default. A project-level extension is subject to Pi's project-trust prompt, and `beacon endpoint discover` reports on the user path only, so a project-level extension does not appear in discovery output.

Beacon identifies its own extension file by the marker `beacon-managed-pi-extension:v1`. The version suffix is part of the contract with the extension source: it is what lets a repair recognize a stale file instead of leaving it in place. A `beacon.ts` without the marker belongs to somebody else, so install will not overwrite it and discovery does not report it as Beacon telemetry.

Pi has no OpenTelemetry export for Beacon to configure, so there is no OTLP path for this runtime. The poll path reads JSONL transcripts from `~/.pi/agent/sessions`; if `PI_CODING_AGENT_DIR` is set, Beacon reads `sessions` below that directory, matching Pi's user-level agent directory override. The cursor lives in Beacon state, not in Pi's directory.

## Discovery and status

Beacon detects Pi through the `pi` executable, and treats the `~/.pi/agent` state directory as an additional signal. Pi installed through npm, pnpm, or bun is often missing from the `PATH` the endpoint process inherited, because a shell alias, a version manager, or a per-project install can all hide it while the state directory is still present. The OpenCode, Cursor, and Hermes probes use the same fallback.

```bash title="Show Pi discovery state" theme={null}
beacon endpoint discover --all --json
```

Pi reports as the `pi_cli` harness with capability `plugin`:

| Telemetry status | Meaning                                                                                                    |
| ---------------- | ---------------------------------------------------------------------------------------------------------- |
| `missing`        | No extension file at the user-level managed path                                                           |
| `disabled`       | A `beacon.ts` exists but carries no Beacon marker, so it is somebody else's extension sharing the filename |
| `enabled`        | Beacon's managed extension is in place                                                                     |

An unmarked extension file reports `disabled` rather than `enabled`, because reporting it as enabled would show the runtime as covered while no events arrive.

## Install or configuration support

`beacon endpoint install` prepares shared endpoint config and runtime log paths. The extension is installed separately, because Pi loads it from the user's own profile rather than from a machine-wide location:

```bash theme={null}
beacon endpoint hooks install --harness pi            # user level (default)
beacon endpoint hooks install --harness pi --level project
beacon endpoint hooks status --harness pi
beacon endpoint hooks uninstall --harness pi
```

Install writes one file and refuses to touch a `beacon.ts` it did not write, so an extension of your own that happens to share the filename is left alone and the install fails loudly rather than replacing it.

`status` reports `installed=false` when the extension exists but points at a hook binary that is no longer there, which happens after a Beacon uninstall, a partly applied update, or a home directory restored onto a different machine. In each case Pi loads an extension that spawns nothing.

## Telemetry coverage

| Area                                             | Support                                                                                                                                         |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Runtime discovery                                | Supported through executable and `~/.pi/agent` detection, managed extension path, and telemetry status                                          |
| Harness attribution                              | Supported. `pi`, `pi.dev`, `pi_cli`, `pi-cli`, `pi_agent`, `pi-agent`, and `pi agent` all normalize to `pi_cli`                                 |
| Extension install, status, uninstall, and repair | Supported                                                                                                                                       |
| Session-store sync                               | Supported through `beacon endpoint pi sync`, with `--print`, `--watch`, and `--sessions-dir`                                                    |
| Session lifecycle                                | Supported. `session.started` and `session.ended`, carrying why the session started or stopped                                                   |
| Prompts                                          | Supported. `prompt.submitted`, with whether the input was typed, delivered over RPC, or injected by another extension                           |
| Tool use                                         | Supported. `tool.invoked` before execution, then `tool.completed` or `tool.failed`                                                              |
| Commands                                         | Supported. `command.executed` for the agent's `bash` tool and for commands you run with Pi's `!` prefix, which are marked as operator-initiated |
| File activity                                    | Supported. `file.read`, `file.created`, and `file.modified`, with the unified patch on an edit                                                  |
| Agent reasoning                                  | Supported. `agent.reasoning` from an assistant message's thinking parts, in the OTel GenAI reasoning-part shape                                 |
| Token usage and cost                             | Supported. `token.usage` normalized into `gen_ai.usage`, including cache and reasoning tokens and runtime-reported cost                         |
| Approval decisions                               | Not available. Pi exposes no operator approval decision to observe. See [Known gaps](#known-gaps)                                               |
| Local JSONL and dashboard                        | Supported                                                                                                                                       |
| MDM deployment                                   | Supported for the endpoint agent. The Pi extension installs separately in the logged-in user's context                                          |

Harness names are matched against a closed set of spellings rather than by substring, because `pi` is two characters and appears inside names belonging to other runtimes. `copilot` contains it, so a substring rule would attribute every GitHub Copilot and VS Code Copilot session to Pi.

## Data handling

Pi content is handled like every other runtime. Prompts, tool arguments, commands, paths, diffs, and reasoning text are retained in local or customer-controlled logs, with local secret redaction and per-string limits applied before writing, and a hash and byte count on each content-bearing event. Events over the 64 KiB limit drop raw and retained content, preserve stable metadata, and set `field_truncated`.

The extension itself sends nothing over the network. It spawns the local `beacon-hooks` binary with a fixed argv and writes the event to its stdin. A send that has not completed in two seconds is abandoned so Beacon cannot stall Pi's agent loop, and a failure to spawn costs the event rather than the run.

## Known gaps

* **No approval telemetry.** Pi's `tool_call` event lets an extension block a call, but that is an extension deciding rather than an operator being asked. Pi exposes no operator approval decision through the extension API, so Beacon records these as tool activity and writes no approval events for Pi. Cline works the same way for the same reason. Detections in `rules/approval-abuse/` do not fire on Pi activity.
* **No enforcement.** As with every other runtime, enforcement stays behind the optional, off-by-default policy provider seam (`BEACON_POLICY_PROVIDER`), which is not wired to Pi. Pi's blocking `tool_call` handler makes it a viable target for that seam later.
* **Streaming events are not collected.** The extension subscribes to seven of Pi's event types and ignores the rest, which are provider-request and TUI-rendering internals. Assistant output is recorded once when a message finalizes rather than token by token, so Beacon stays out of the streaming path.
* **Poll sync is after-the-fact.** `beacon endpoint pi sync` can recover committed prompts, assistant messages and reasoning, tool calls and results, bash execution records, errors, compactions, skill-load records, and token usage from Pi's JSONL store. It cannot block or delay anything, and it does not have every live extension context field. Use it as backfill or scheduled catch-up, not as an enforcement surface.
* **Project-level installs need Pi's trust prompt.** A `.pi/extensions/beacon.ts` is subject to Pi's project-trust prompt, so a user-level install is the one that works without further interaction.

## Deployment notes

The extension is loaded when Pi starts, so an install taken while Pi is running takes effect on the next launch.

Confirm discovery sees the runtime, then generate one Pi event and check the log:

```bash theme={null}
/opt/beacon/bin/beacon endpoint discover --all --json
/opt/beacon/bin/beacon endpoint hooks status --harness pi
/opt/beacon/bin/beacon endpoint doctor --system
grep '"name":"pi_cli"' ~/.beacon/endpoint/logs/runtime.jsonl | tail -3
```

## Related

<Columns cols={2}>
  <Card title="Supported agent harnesses" icon="list-check" href="/runtimes">
    Return to the runtime support overview.
  </Card>

  <Card title="Agent harness integration model" icon="plug" href="/runtimes/integration-model">
    See how Beacon discovers and configures each runtime.
  </Card>
</Columns>
