The Entire CLI supports external agent plugins — standalone binaries that implement the Agent interface via a subcommand-based protocol over stdin/stdout. This allows third-party agents to integrate with the CLI without modifying the main repository.
The CLI discovers external agents by scanning $PATH for executables matching the pattern entire-agent-<name>. For example, entire-agent-cursor would register as the "cursor" agent.
Two rules bound that scan, both because discovery executes what it finds (it calls each binary's info subcommand):
-
It is off unless
external_agentsis set in an untracked.entire/settings.local.json. The committed.entire/settings.jsoncannot grant it — see Whyexternal_agentsis local-only. Interactive setup flows scan regardless, so you can still pick a plugin before the setting exists. Commands that name one agent (entire enable --agent <name>,entire agent add <name>,entire agent remove <name>) resolve only that binary, also regardless of the setting;entire agent listnames none, so it scans only when the setting is on. -
Only absolute
$PATHentries are scanned. A relative entry resolves against the working directory, which for a git hook is whatever repository invoked it. -
Binaries whose
<name>conflicts with an already-registered built-in agent are skipped. -
Discovery runs once during CLI initialization (before building the hooks command tree).
-
The binary must be executable and respond to the
infosubcommand.
Every subcommand invocation except generate-text sets:
| Variable | Description |
|---|---|
ENTIRE_REPO_ROOT |
Absolute path to the git repository root |
ENTIRE_PROTOCOL_VERSION |
Protocol version (1) |
The working directory is set to the repository root.
generate-text is the exception. Its stdin is a summary prompt carrying
untrusted transcript content, so it runs from a fresh empty temporary
directory, without ENTIRE_REPO_ROOT and without GIT_* variables, the same
isolation Entire gives its built-in summary generators. A plugin should not
need the repository to generate text; if its model has tools, it should run
them with none enabled, as the built-in generators do where their CLI allows.
- Subcommand-based: Each Agent interface method maps to a CLI subcommand.
- JSON over stdin/stdout: Structured data uses JSON. Transcripts use raw bytes.
- Stateless: Each invocation is independent — no persistent connection.
- Exit codes:
0= success, non-zero = error. Error messages go to stderr.
Returns agent metadata and declared capabilities.
Arguments: None
Output (stdout): JSON
{
"protocol_version": 1,
"name": "cursor",
"type": "Cursor",
"description": "Cursor - AI-powered code editor",
"protected_dirs": [".cursor"],
"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
}
}The capabilities object determines which optional subcommands the CLI will call. If a capability is false or missing, the CLI will never invoke the corresponding subcommands.
Optional: "caller_env_vars": ["MYAGENT_SESSION_ID"] lists environment variables the agent sets for the commands it runs (uppercase names only). entire review uses them to recognise the agent as the caller, so it refuses to approve reviews of someone else's code on the user's behalf and names the agent when one passes --trust-target. Agents that set the cross-tool AI_AGENT variable are recognised without declaring it.
Checks whether the agent is present/usable in the current environment.
Arguments: None
Output (stdout): JSON
{"present": true}Extracts the session ID from a hook input event.
Input (stdin): JSON — the HookInput object
Output (stdout): JSON
{"session_id": "abc123"}Returns the directory where agent sessions are stored.
Arguments:
--repo-path— Absolute path to the repository
Output (stdout): JSON
{"session_dir": "/path/to/sessions"}Resolves the session file path from a session directory and ID.
Arguments:
--session-dir— Session directory path--session-id— Session identifier
Output (stdout): JSON
{"session_file": "/path/to/session/file.jsonl"}Reads session data from a hook input event.
Input (stdin): JSON — the HookInput object
Output (stdout): JSON — AgentSession object
{
"session_id": "abc123",
"agent_name": "cursor",
"repo_path": "/path/to/repo",
"session_ref": "/path/to/file.jsonl",
"start_time": "2026-01-13T12:00:00Z",
"native_data": null,
"modified_files": ["src/main.go"],
"new_files": [],
"deleted_files": []
}Writes/updates session data.
Input (stdin): JSON — the AgentSession object
Output: Exit 0 on success.
Reads a transcript file and returns its raw bytes.
Arguments:
--session-ref— Path to the transcript file
Output (stdout): Raw transcript bytes.
Splits a transcript into chunks for storage.
Input (stdin): Raw transcript bytes.
Arguments:
--max-size— Maximum chunk size in bytes
Output (stdout): JSON
{"chunks": ["<base64-encoded-chunk>", "..."]}Reassembles transcript chunks back into a full transcript.
Input (stdin): JSON
{"chunks": ["<base64-encoded-chunk>", "..."]}Output (stdout): Raw transcript bytes.
Returns the command a user can run to resume a session.
Arguments:
--session-id— Session identifier
Output (stdout): JSON
{"command": "cursor --resume abc123"}These subcommands are required when capabilities.hooks is true.
Parses a raw agent hook payload into a structured event.
Arguments:
--hook— Hook name (e.g., "stop", "session-start")
Input (stdin): Raw agent hook payload bytes.
Output (stdout): JSON — the parsed Event object, or null if the payload is not relevant.
Installs agent hooks for Entire integration.
Arguments:
--force— Overwrite existing hooks (optional)
--local-dev was removed: it asked the agent to point hooks at a build inside
the working tree, which meant installed hooks ran whatever the checked-out
branch contained. The CLI never sends it. Agents that still accept the flag
should treat it as a no-op; hook commands must name the entire binary.
Output (stdout): JSON
{"hooks_installed": 3}Removes installed agent hooks.
Arguments: None
Output: Exit 0 on success.
Only your binary can remove your hooks, so entire disable --uninstall cannot
finish without you. A non-zero exit fails the whole uninstall: the command
exits non-zero, reports that Entire was not fully removed, and prints the exact
command line the user can run to invoke this subcommand by hand. Write anything
the user needs in order to act to stderr — the CLI captures it and shows it
verbatim.
Checks whether hooks are currently installed.
Arguments: None
Output (stdout): JSON
{"installed": true}A non-zero exit or unparseable stdout is not read as "no hooks" — it means the
state is unknown, which the CLI must treat as "hooks may still be installed".
entire disable --uninstall then exits non-zero and hands the user the manual
uninstall-hooks command rather than claiming Entire was fully removed. Report
"installed": false when you know there are none; fail only when you genuinely
could not find out.
Required when capabilities.transcript_analyzer is true.
Returns the current byte position/size of a transcript file.
Arguments:
--path— Path to the transcript file
Output (stdout): JSON
{"position": 12345}Extracts the list of files modified by the agent from a transcript.
Arguments:
--path— Path to the transcript file--offset— Byte offset to start reading from
Output (stdout): JSON
{"files": ["path/to/file1.go", "path/to/file2.go"], "current_position": 12345}The current_position field returns the transcript position after extraction, allowing the caller to resume from that point on subsequent calls.
Extracts user prompts from a transcript.
Arguments:
--session-ref— Path to the transcript file--offset— Byte offset to start reading from
Output (stdout): JSON
{"prompts": ["first prompt text", "second prompt text"]}Required when capabilities.transcript_preparer is true.
Prepares/processes a transcript file (e.g., converting from raw format).
Arguments:
--session-ref— Path to the transcript file
Output: Exit 0 on success.
Required when capabilities.compact_transcript is true.
Converts a native transcript into Entire Transcript Format (the transcript.jsonl stored next to full.jsonl in each checkpoint).
Arguments:
--session-ref— Path to a transcript file in the agent's native format. It may be a CLI temp file outside the agent's session store, so accept any regular file here.
Output (stdout): JSON
{"transcript": "<base64-encoded transcript.jsonl>", "assets": [{"name": "img-001.png", "media_type": "image/png", "data": "<base64>"}]}assets is optional. The CLI calls this on each checkpoint write with a temp file of the already-redacted transcript, and redacts the result again. It also compacts the lines before the checkpoint's start to scope the checkpoint: only leading output lines identical in both runs count as earlier checkpoints' content, so a line that changes once later input arrives (for example a tool call that absorbs its result) stays in this checkpoint. Each run has a 5 second limit, and stdout may be up to the base64 size of a 50 MB transcript. On failure, timeout, empty output, or assets, the CLI uses its built-in compactor instead. entire explain also uses it for summaries.
Required when capabilities.token_calculator is true.
Calculates token usage from a transcript.
Input (stdin): Raw transcript bytes.
Arguments:
--offset— Byte offset to start calculating from
Output (stdout): JSON
{
"input_tokens": 1500,
"cache_creation_tokens": 0,
"cache_read_tokens": 200,
"output_tokens": 500,
"api_call_count": 3,
"subagent_tokens": null
}Only input_tokens and output_tokens are required. The optional fields (cache_creation_tokens, cache_read_tokens, api_call_count) default to 0 if omitted. subagent_tokens is an optional nested object with the same structure, for agents that spawn subagents.
Required when capabilities.text_generator is true.
External agents that declare capabilities.text_generator: true can be used as
summary providers for entire explain --generate and checkpoint auto-summarize.
Configure them with:
entire configure --summarize-provider <agent-name> [--summarize-model <model>]The provider name is derived from the executable name entire-agent-<agent-name>.
The CLI passes Entire's summary prompt on stdin to generate-text --model <model>
and expects {"text":"..."} on stdout.
Generates text using the agent's underlying LLM.
Input (stdin): Prompt text.
Arguments:
--model— Model to use for generation
Output (stdout): JSON
{"text": "Generated response text"}Required when capabilities.hook_response_writer is true.
Writes a message in the agent's native hook response format.
Arguments:
--message— Message to write
Output (stdout): Agent-native format bytes (e.g., JSONL for Claude Code).
Required when capabilities.subagent_aware_extractor is true.
Extracts modified files from both the main transcript and any subagent transcripts.
Input (stdin): Raw main transcript bytes.
Arguments:
--offset— Byte offset for the main transcript--subagents-dir— Directory containing subagent transcripts
Output (stdout): JSON
{"files": ["file1.go", "file2.go"]}Calculates total token usage across main transcript and subagent transcripts.
Input (stdin): Raw main transcript bytes.
Arguments:
--offset— Byte offset for the main transcript--subagents-dir— Directory containing subagent transcripts
Output (stdout): JSON
{
"input_tokens": 5000,
"cache_creation_tokens": 0,
"cache_read_tokens": 1000,
"output_tokens": 2000,
"api_call_count": 8,
"subagent_tokens": {
"input_tokens": 2000,
"output_tokens": 800
}
}Same token usage format as calculate-tokens. The subagent_tokens field aggregates usage from all subagents.
The HookInput object is passed via stdin to get-session-id and read-session.
{
"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": {"custom_field": "value"}
}| Field | Type | Description |
|---|---|---|
hook_type |
string | Hook type: session_start, session_end, user_prompt_submit, stop, pre_tool_use, post_tool_use |
session_id |
string | Agent session identifier |
session_ref |
string | Agent-specific session reference (typically a file path) |
timestamp |
string | RFC 3339 timestamp |
user_prompt |
string | User's prompt text (from user_prompt_submit hooks). Optional. |
tool_name |
string | Tool name (from pre_tool_use/post_tool_use hooks). Optional. |
tool_use_id |
string | Tool invocation ID. Optional. |
tool_input |
object | Raw tool input JSON. Optional. |
raw_data |
object | Agent-specific data for extension. Optional. |
Used as input to write-session and output from read-session.
{
"session_id": "abc123",
"agent_name": "cursor",
"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": ["src/new_file.go"],
"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/reference to session in agent's storage. Constrained — see session_ref constraints |
start_time |
string | RFC 3339 timestamp of session start |
native_data |
bytes/null | Session content in agent's native format (opaque to CLI) |
modified_files |
string[] | Files modified during the session |
new_files |
string[] | Files created during the session |
deleted_files |
string[] | Files deleted during the session |
session_ref stays agent-defined: a plugin backed by a database may return an opaque key rather than a path, and the CLI forwards such a value to write-session unchanged. Which checks apply depends on the shape of the value, and one of them also depends on whether repo_path was supplied.
A reference that is absolute, or that carries a volume name (/home/u/.agentx/sessions/abc.jsonl, C:\Users\u\...) is treated as a filesystem path. It must contain no . or .. component — always, whether or not repo_path is set. When repo_path IS set, it must additionally resolve inside the directory the plugin itself reported from get-session-dir; without repo_path there is no session directory to resolve against, so that containment check does not run and the reference is forwarded.
Any other reference is treated as an agent-defined key. It must not be rooted, and once cleaned it must not escape its own base, so ../outside.jsonl and nested/../../outside.jsonl are refused. A key that merely contains a dot segment without escaping, such as tenant/../session-key, is forwarded as given. Note that the rooted check is reachable only on Windows: on Unix a leading separator makes the reference absolute, so it takes the filesystem branch above.
This is a preflight, not a sandbox. The plugin runs as its own process and can write wherever its own permissions allow; the check exists so the CLI does not hand it a reference that leaves the store the plugin named.
Returned by parse-hook. Represents a normalized lifecycle event.
{
"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"
}| Field | Type | Description |
|---|---|---|
type |
int | Required. Event type (see table below) |
session_id |
string | Required. Agent session identifier |
previous_session_id |
string | Non-empty when this event represents a session continuation/handoff. Optional. |
session_ref |
string | Agent-specific transcript reference. Optional. |
prompt |
string | User's prompt text (on TurnStart events). Optional. |
model |
string | LLM model identifier. Optional. |
timestamp |
string | RFC 3339 timestamp. Optional. |
tool_use_id |
string | Tool invocation ID (for SubagentStart/SubagentEnd). Optional. |
subagent_id |
string | Subagent instance ID (for SubagentEnd). Optional. |
tool_input |
object | Raw tool input JSON (for subagent type/description extraction). Optional. |
subagent_type |
string | Kind of subagent (for SubagentStart/SubagentEnd). Optional. |
task_description |
string | Subagent task description. Optional. |
response_message |
string | Message to display to the user via the agent. Optional. |
metadata |
object | Agent-specific state preserved across events. Optional. |
Event types:
| Value | Name | Description |
|---|---|---|
| 1 | SessionStart | Agent session has begun |
| 2 | TurnStart | User submitted a prompt, agent is about to work |
| 3 | TurnEnd | Agent finished responding to a prompt |
| 4 | Compaction | Agent is compressing its context window (triggers save + offset reset) |
| 5 | SessionEnd | Session has been terminated |
| 6 | SubagentStart | A subagent (task) has been spawned |
| 7 | SubagentEnd | A subagent (task) has completed |
- Exit code
0indicates success. - Any non-zero exit code indicates an error.
- Error messages should be written to stderr.
- The CLI captures stderr and wraps it in a Go error.
- If the binary is not found in PATH, the agent is simply not registered.
- If
infofails or returns invalid JSON, the binary is skipped during discovery.
The protocol version is declared in the info response (protocol_version field) and set via ENTIRE_PROTOCOL_VERSION environment variable. The CLI checks that the binary's protocol version matches its expected version before registering the agent.
Future protocol versions may add new subcommands or capabilities. Existing subcommands will maintain backwards compatibility within a major version.