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

# External Agent Plugins

> Build plugins that integrate third-party AI agents with the Entire CLI

External agent plugins are standalone binaries that integrate any AI coding agent with the Entire CLI. The CLI discovers them automatically, with no changes to the main repository required.

<Warning>
  Plugins are arbitrary executables on your `$PATH` that receive repository paths and session data. Only install plugins you trust, as they have the same filesystem access as the CLI itself.
</Warning>

## How It Works

1. You create an executable named `entire-agent-<name>`
2. Place it anywhere on your `$PATH`
3. The CLI discovers it at startup and registers it as a new agent

The plugin communicates with the CLI through **subcommands** that read/write JSON over stdin/stdout. Each invocation is stateless. For working examples — including `entire-agent-kiro` (Amazon's Kiro) — see the [external-agents repository](https://github.com/entireio/external-agents). For a minimal reference implementation, see [roger-roger](https://github.com/entireio/roger-roger).

<Note>
  When you select an external agent during `entire agent add` or `entire enable`, the `external_agents` setting is automatically enabled. If you install a new external agent binary after initial setup, you can enable discovery manually by adding `"external_agents": true` to your `.entire/settings.json` file, or by re-running `entire agent`.
</Note>

## Environment

Every subcommand invocation receives these environment variables:

| Variable                  | Description                              |
| ------------------------- | ---------------------------------------- |
| `ENTIRE_REPO_ROOT`        | Absolute path to the git repository root |
| `ENTIRE_PROTOCOL_VERSION` | Protocol version (currently `1`)         |

The working directory is always set to the repository root.

## Conventions

* **Output:** JSON on stdout (unless noted otherwise)
* **Errors:** Non-zero exit code + message on stderr
* **Stateless:** Each invocation is independent, no persistent connection

## Lifecycle

Understanding when each subcommand is called helps you build a correct integration. Here's the full sequence from the CLI's perspective.

### Phase 1: Discovery (CLI startup)

Every time the CLI starts, it scans `$PATH` for binaries matching `entire-agent-<name>`.

1. **`info`** — Called once per discovered binary. The CLI reads your metadata, validates the protocol version, and registers the agent. If this fails, the agent is silently skipped.

### Phase 2: Enable (`entire enable`)

When a user enables your agent for a repository:

1. **`detect`** — Called to check whether your agent is available in the current environment.
2. **`install-hooks [--local-dev] [--force]`** — Called to install your hooks into the agent (e.g., writing hook config files). Only called if you declare the `hooks` capability.

### Phase 3: Agent session (hooks firing)

Once enabled, your agent's hooks fire during normal usage and the CLI processes them. This phase requires the `hooks` capability — agents that don't declare it won't participate in the hook lifecycle.

Every hook invocation follows this flow:

```
Hook fires → parse-hook → Event dispatched by type
```

1. **`parse-hook --hook <name>`** — Called on every hook invocation with the raw payload on stdin. Return a normalized [Event](#event), or `null` if the hook has no lifecycle significance (the CLI will do nothing).

The CLI then routes the event by type:

#### SessionStart (type 1)

Fired when the agent begins a new session.

1. **`get-session-id`** — Extract the session ID from the hook input (stdin).
2. **`get-session-dir --repo-path <path>`** — Return where sessions are stored.
3. **`resolve-session-file --session-dir <dir> --session-id <id>`** — Resolve the session file path.
4. **`read-session`** — Read existing session data (stdin: [HookInput](#hookinput)).
5. **`write-session`** — Persist updated session data.
6. **`write-hook-response --message <msg>`** — *(optional, if `hook_response_writer` capability)* Write a startup message in your agent's native format.

#### TurnStart (type 2)

Fired when the user submits a new prompt.

1. **`extract-modified-files --path <path> --offset <n>`** — *(if `transcript_analyzer` capability)* Extract files changed since last checkpoint.
2. The CLI creates a git checkpoint of the current state.

#### TurnEnd (type 3)

Fired when the agent finishes responding.

1. **`prepare-transcript --session-ref <path>`** — *(if `transcript_preparer` capability)* Pre-process the transcript.
2. **`read-transcript --session-ref <path>`** — Read the raw transcript bytes.
3. **`chunk-transcript --max-size <n>`** — Split large transcripts into storable chunks.
4. **`get-transcript-position --path <path>`** — *(if `transcript_analyzer` capability)* Get the current byte offset.
5. **`extract-modified-files --path <path> --offset <n>`** — *(if `transcript_analyzer` capability)* Extract newly modified files.
6. **`calculate-tokens --offset <n>`** — *(if `token_calculator` capability)* Calculate token usage.
7. The CLI stores a checkpoint in git history.

#### Compaction (type 4)

Fired when the agent compresses its context window. Follows the same flow as **TurnEnd** (save + reset offset).

#### SessionEnd (type 5)

Fired when the session terminates. The CLI creates a final checkpoint and cleans up session state.

#### SubagentStart / SubagentEnd (types 6–7)

Fired when the agent spawns or completes a subagent. If you declare the `subagent_aware_extractor` capability, the CLI calls:

* **`extract-all-modified-files --offset <n> --subagents-dir <dir>`**
* **`calculate-total-tokens --offset <n> --subagents-dir <dir>`**

### Phase 4: User commands

Some CLI commands invoke your plugin outside the hook flow:

| Command                    | Subcommands called                                                   |
| -------------------------- | -------------------------------------------------------------------- |
| `entire checkpoint rewind` | `read-transcript`, `reassemble-transcript`, `extract-modified-files` |
| `entire status`            | `get-transcript-position`                                            |
| `entire session resume`    | `format-resume-command`                                              |

### Phase 5: Disable (`entire disable --uninstall`)

1. **`uninstall-hooks`** — Called to remove your installed hooks. Only called if you declare the `hooks` capability.

### Error handling

* **Timeout:** Each subcommand has a 30-second default timeout.
* **Output limits:** Stdout and stderr are each capped at 10 MB. Be mindful of this when implementing `read-transcript` for large sessions.
* **No retries:** The CLI does not retry failed subcommand calls. A non-zero exit code with a message on stderr is treated as a failure.
* **Graceful degradation:** If `parse-hook` returns `null`, the CLI takes no action. If the repo has Entire disabled, hooks exit silently.

## Required Subcommands

Every plugin must implement these subcommands.

### `info`

Returns metadata and declares which optional capabilities your plugin supports.

```bash theme={null}
entire-agent-myagent info
```

```json theme={null}
{
  "protocol_version": 1,
  "name": "myagent",
  "type": "MyAgent",
  "description": "MyAgent - AI-powered code editor",
  "is_preview": true,
  "protected_dirs": [".myagent"],
  "hook_names": ["session-start", "session-end", "stop"],
  "capabilities": {
    "hooks": true,
    "transcript_analyzer": true,
    "transcript_preparer": false,
    "token_calculator": false,
    "text_generator": false,
    "hook_response_writer": false,
    "subagent_aware_extractor": false
  }
}
```

| Field              | Description                                                                 |
| ------------------ | --------------------------------------------------------------------------- |
| `protocol_version` | Must match the CLI's expected version (currently `1`)                       |
| `name`             | Registry name (must match the `<name>` in the binary name)                  |
| `type`             | Display name / type identifier                                              |
| `description`      | Human-readable description                                                  |
| `is_preview`       | Whether the agent is in preview                                             |
| `protected_dirs`   | Directories the CLI should not modify (excluded from checkpoints and diffs) |
| `hook_names`       | Agent lifecycle hooks this plugin handles                                   |
| `capabilities`     | Object declaring which optional capabilities are supported                  |

### `detect`

Returns whether the agent is available in the current environment. Return `{"present": false}` if the agent's dependencies are not met — the CLI will skip enabling the agent.

```bash theme={null}
entire-agent-myagent detect
```

```json theme={null}
{"present": true}
```

### `get-session-id`

Extracts a session ID from a hook input event.

**stdin:** [HookInput](#hookinput) JSON

```json theme={null}
{"session_id": "abc123"}
```

### `get-session-dir --repo-path <path>`

Returns where agent sessions are stored.

```json theme={null}
{"session_dir": "/path/to/sessions"}
```

### `resolve-session-file --session-dir <dir> --session-id <id>`

Resolves the session file path from a session directory and ID.

```json theme={null}
{"session_file": "/path/to/session/file.jsonl"}
```

### `read-session`

Reads session data from a hook input event.

**stdin:** [HookInput](#hookinput) JSON

**stdout:** [AgentSession](#agentsession) JSON

### `write-session`

Persists session data to disk. The plugin is responsible for choosing the storage location and format.

**stdin:** [AgentSession](#agentsession) JSON

Exit `0` on success.

### `read-transcript --session-ref <path>`

Reads a transcript file and returns its raw bytes on stdout.

### `chunk-transcript --max-size <n>`

Splits a transcript (raw bytes on stdin) into chunks.

```json theme={null}
{"chunks": ["<base64-encoded-chunk>", "..."]}
```

### `reassemble-transcript`

Reassembles chunks back into a transcript. Called during `entire checkpoint rewind` to reconstruct transcript data from stored chunks.

**stdin:**

```json theme={null}
{"chunks": ["<base64-encoded-chunk>", "..."]}
```

**stdout:** Raw transcript bytes.

### `format-resume-command --session-id <id>`

Returns the command a user would run to resume a session.

```json theme={null}
{"command": "myagent --resume abc123"}
```

## Optional Capabilities

Set capabilities to `true` in your `info` response to enable these. The CLI will never call subcommands for capabilities you don't declare.

### `hooks`

Manage agent lifecycle hooks for Entire integration.

| Subcommand                              | Description                                                                                                                                                    |
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `parse-hook --hook <name>`              | Parse a raw hook payload (stdin) into an [Event](#event). Return `null` if not relevant.                                                                       |
| `install-hooks [--local-dev] [--force]` | Install hooks. `--local-dev` installs hooks pointing to a local development build. `--force` overwrites existing hook files. Returns `{"hooks_installed": 3}`. |
| `uninstall-hooks`                       | Remove installed hooks. Exit `0` on success.                                                                                                                   |
| `are-hooks-installed`                   | Check hook status. Returns `{"installed": true}`.                                                                                                              |

### `transcript_analyzer`

Extract data from agent transcripts.

| Subcommand                                          | Description                                            |
| --------------------------------------------------- | ------------------------------------------------------ |
| `get-transcript-position --path <path>`             | Returns `{"position": 12345}` (byte offset).           |
| `extract-modified-files --path <path> --offset <n>` | Returns `{"files": [...], "current_position": 12345}`. |
| `extract-prompts --session-ref <path> --offset <n>` | Returns `{"prompts": ["prompt text", ...]}`.           |
| `extract-summary --session-ref <path>`              | Returns `{"summary": "...", "has_summary": true}`.     |

### `transcript_preparer`

| Subcommand                                | Description                                         |
| ----------------------------------------- | --------------------------------------------------- |
| `prepare-transcript --session-ref <path>` | Pre-process a transcript file. Exit `0` on success. |

### `token_calculator`

| Subcommand                      | Description                                                                                                                    |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `calculate-tokens --offset <n>` | Calculate token usage from transcript bytes (stdin). `--offset` is the byte offset into the transcript to start counting from. |

Output:

```json theme={null}
{
  "input_tokens": 1500,
  "output_tokens": 500,
  "cache_creation_tokens": 0,
  "cache_read_tokens": 200,
  "api_call_count": 3
}
```

Only `input_tokens` and `output_tokens` are required. Other fields default to `0`.

### `text_generator`

| Subcommand                      | Description                                                     |
| ------------------------------- | --------------------------------------------------------------- |
| `generate-text --model <model>` | Generate text from a prompt (stdin). Returns `{"text": "..."}`. |

### `hook_response_writer`

| Subcommand                            | Description                                                 |
| ------------------------------------- | ----------------------------------------------------------- |
| `write-hook-response --message <msg>` | Write a message in the agent's native hook format (stdout). |

### `subagent_aware_extractor`

For agents that spawn subagents.

| Subcommand                                                      | Description                                                                                                                                                           |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `extract-all-modified-files --offset <n> --subagents-dir <dir>` | Extract modified files from main + subagent transcripts (stdin: main transcript). Returns `{"files": [...]}`.                                                         |
| `calculate-total-tokens --offset <n> --subagents-dir <dir>`     | Calculate total tokens across main + subagent transcripts (stdin: main transcript). Same format as `calculate-tokens`, with optional `subagent_tokens` nested object. |

## Data Types

### HookInput

Passed via stdin to `get-session-id` and `read-session`.

```json theme={null}
{
  "hook_type": "stop",
  "session_id": "abc123",
  "session_ref": "/path/to/transcript.jsonl",
  "timestamp": "2026-01-13T12:00:00Z",
  "user_prompt": "Fix the login bug",
  "tool_name": "Write",
  "tool_use_id": "toolu_abc123",
  "tool_input": {"path": "/src/main.go"},
  "raw_data": {}
}
```

| Field         | Type   | Required | Description                                                                                   |
| ------------- | ------ | -------- | --------------------------------------------------------------------------------------------- |
| `hook_type`   | string | Yes      | `session_start`, `session_end`, `user_prompt_submit`, `stop`, `pre_tool_use`, `post_tool_use` |
| `session_id`  | string | Yes      | Agent session identifier                                                                      |
| `session_ref` | string | Yes      | Agent-specific session reference (typically a file path)                                      |
| `timestamp`   | string | Yes      | RFC 3339 timestamp                                                                            |
| `user_prompt` | string | No       | User's prompt text                                                                            |
| `tool_name`   | string | No       | Tool name (from tool use hooks)                                                               |
| `tool_use_id` | string | No       | Tool invocation ID                                                                            |
| `tool_input`  | object | No       | Raw tool input JSON                                                                           |
| `raw_data`    | object | No       | Agent-specific extension data                                                                 |

### AgentSession

Used as input to `write-session` and output from `read-session`.

```json theme={null}
{
  "session_id": "abc123",
  "agent_name": "myagent",
  "repo_path": "/path/to/repo",
  "session_ref": "/path/to/transcript.jsonl",
  "start_time": "2026-01-13T12:00:00Z",
  "native_data": null,
  "modified_files": ["src/main.go"],
  "new_files": [],
  "deleted_files": []
}
```

| Field            | Type       | Description                                     |
| ---------------- | ---------- | ----------------------------------------------- |
| `session_id`     | string     | Agent session identifier                        |
| `agent_name`     | string     | Agent registry name                             |
| `repo_path`      | string     | Absolute path to the repository                 |
| `session_ref`    | string     | Path to session in agent's storage              |
| `start_time`     | string     | RFC 3339 timestamp                              |
| `native_data`    | bytes/null | Opaque session content in agent's native format |
| `modified_files` | string\[]  | Files modified during the session               |
| `new_files`      | string\[]  | Files created during the session                |
| `deleted_files`  | string\[]  | Files deleted during the session                |

### Event

Returned by `parse-hook`. Represents a normalized lifecycle event.

```json theme={null}
{
  "type": 3,
  "session_id": "abc123",
  "session_ref": "/path/to/transcript.jsonl",
  "prompt": "Fix the login bug",
  "model": "claude-sonnet-4-20250514",
  "timestamp": "2026-01-13T12:00:00Z"
}
```

**Event types:**

| Value | Name          | Description                                               |
| ----- | ------------- | --------------------------------------------------------- |
| 1     | SessionStart  | Agent session has begun                                   |
| 2     | TurnStart     | User submitted a prompt                                   |
| 3     | TurnEnd       | Agent finished responding                                 |
| 4     | Compaction    | Context window compression (triggers save + offset reset) |
| 5     | SessionEnd    | Session terminated                                        |
| 6     | SubagentStart | A subagent was spawned                                    |
| 7     | SubagentEnd   | A subagent completed                                      |

**Optional event fields:** `previous_session_id`, `session_ref`, `prompt`, `model`, `timestamp`, `tool_use_id`, `subagent_id`, `tool_input`, `subagent_type`, `task_description`, `response_message`, `metadata`.

Only `type` and `session_id` are required.
