Documentation

Built-in agent

greppy is a pure coding agent. Every task runs in its own temporary copy-on-write worktree and always ends as a pull request: a proposal commit on refs/greppy/agent/<run-id>. As soon as the proposal is saved, greppy removes the worktree again. Your checkout, its HEAD and its Git index stay unchanged.

You start the agent straight from the shell or let it work as a subagent of another agent, one-shot with greppy -p or remote-controlled through greppy agent serve.

How a task runs

Step What happens
Start greppy creates a copy-on-write snapshot of your repository: the pinned commit plus your staged, unstaged and untracked changes. Ignored files such as node_modules, .venv or target stay out. The worktree is indexed before the model takes its first turn.
Work The agent has exactly one tool: greppy. With it, the agent searches, navigates, reads and edits. Shell commands run as bash-smart -- CMD. It writes to the worktree and its scratch directory and nowhere else.
End The changes in the worktree become a commit on refs/greppy/agent/<run-id>. Its parent is your baseline including uncommitted work, so the proposal contains the agent's changes and nothing else. Then greppy deletes the worktree.

The commit message is the agent's final answer and the description of the pull request: a one-line title, Status: (done, partial or blocked), what changed and why (with file:line), how it was verified and what is open. An explicit Title: line becomes the subject, otherwise the line before Status:; the answer is the body.

--keep-worktree keeps the worktree. If a run ends with an error before a proposal exists, the worktree stays for 24 hours for debugging. If a run reaches a limit (exit 5), the proposal is still saved and the worktree removed.

Requirement: a local model gateway

greppy ships no chat model. The agent speaks the Anthropic Messages API over plain HTTP to a local, Anthropic-compatible gateway. The standard gateway is CLIProxyAPI; it translates the common chat formats and providers into this wire format.

export GREPPY_ENDPOINT=http://127.0.0.1:8317   # the default; or --endpoint URL
export GREPPY_MODEL=MODEL                      # a model ID your gateway offers; or --model
export GREPPY_API_KEY=YOUR_GATEWAY_KEY         # only if the gateway requires a key

The client has no TLS stack, so it reaches plain-HTTP endpoints such as a gateway on localhost. The model ID goes to the gateway unchanged. greppy sends the key as x-api-key and as Authorization: Bearer. There is deliberately no key flag: keys do not belong on the command line. greppy -p --help describes the full setup.

One-shot: greppy -p

greppy -p "add tests for clamp_value" --model MODEL
greppy -p "keep going" --continue

greppy -p "TASK" is the headless mode for scripts and for tasks another agent hands off. The first line on stderr reads session: <session_id>.

Usage:
  greppy agent ["INITIAL TASK"]
  greppy agent stdio [--model M] [--endpoint URL]
  greppy -p "TASK" [--model M] [--endpoint URL] [--max-turns N]
                   [--deadline-secs N] [--apply] [--diff] [--keep-worktree]
                   [--no-sandbox] [--skip-selfcheck]
                   [--continue | --resume ID] [--json]
  greppy -p --help
Flag Effect
--model M model ID, passed to the gateway unchanged (or GREPPY_MODEL); greppy agent saves it through /setup
--endpoint URL base URL of the gateway (or GREPPY_ENDPOINT, otherwise http://127.0.0.1:8317)
--max-turns N optional cap on action turns, followed by a report turn without tools; without the flag there is no cap
--deadline-secs N time budget in seconds (or GREPPY_DEADLINE_SECS); the loop stops between turns, and tool calls already started run at most 30 s past the deadline
--apply applies the agent's changes, and nothing else, to the exactly captured baseline; your Git index stays byte-identical
--diff prints the full patch of the proposal after the stat
--keep-worktree keeps the isolated worktree and its private changes
--no-sandbox turns off the write confinement (or GREPPY_NO_SANDBOX=1)
--skip-selfcheck skips the capability self-check at startup (or GREPPY_SKIP_SELFCHECK=1)
--continue, --resume ID continues this project's latest session, or a specific one
--json streams events as JSON, one per line, on stdout (in -p mode)

There are no fixed limits: no default cap on turns and no fixed tool timeouts. The run's deadline bounds both. greppy folds large tool output behind expand agent-output-ID instead of cutting it off.

A leading -p is reserved for the agent. To search for the pattern -p with grep, use greppy -e -p ….

As a subagent

Another agent hands greppy a self-contained task with greppy -p and gets the pull request back. In -p mode, the prompt tells the agent that a person, a script or another agent reads the final answer and the pull request and nothing else. Nobody answers questions, so the agent decides details itself and names them.

External agents find the instructions for this in the AGENTS.md that ships with greppy.

AGENT:
  greppy -p "TASK" [--model M]       isolated coding task, delivered as refs/greppy/agent/<id>

The task does not edit the working checkout. Review with git show <ref>, apply with
git cherry-pick -n <ref>. greppy -p --help describes gateway setup.

For longer collaboration, you host a session with greppy agent serve and control it remotely, see Remote control.

Review and apply the pull request

git show refs/greppy/agent/<run-id>
greppy agent apply refs/greppy/agent/<run-id>

The proposal is built against a captured baseline: the pinned commit plus your visible staged, unstaged and untracked changes. greppy agent apply REF checks exactly this baseline, applies the agent's changes and nothing else, and leaves your Git index byte-identical. --apply on greppy -p does the same at the end of the run. For proposals on uncommitted work, greppy agent apply is the way. External agents that have nothing but Git use git cherry-pick -n REF, as the AGENTS.md describes.

greppy agent apply with a ref that does not exist exits with code 64.

Interactive: greppy agent

greppy agent
greppy agent "TASK" --model MODEL
greppy agent --continue

greppy agent opens a full-screen terminal UI with the same worktree, the same sandbox and the same proposal as greppy -p. The transcript keeps context across several prompts and shows streamed replies, tool activity and token usage. /setup configures the gateway, the model and the remaining settings and saves them.

Key Action
Enter sends the prompt; prompts you send while the agent works land visibly in a queue
Shift+Enter / Alt+Enter newline, when the terminal reports the modifier
PageUp / PageDown, mouse wheel scroll; End follows the tail again
Tab / Shift+Tab, Esc completions and overlay choices; Esc closes the overlay first, then the completions
Ctrl+C cancels a run at a safe tool boundary (never in the middle of an edit); when idle, it exits the UI; pressed twice, it exits after the running tool
Slash command Effect
/help commands and key bindings
/setup all agent settings: gateway, model, language, storage, sandbox, acceleration, self-check, workspace backend
/clear clears the visible transcript
/model picks a model from the gateway
/endpoint sets and checks the gateway URL
/usage the session's token usage
/tools this session's tool calls
/copy copies the agent's last answer
/sessions resumes a saved session
/name TITLE renames the current session
/compact summarizes older messages, keeps newer ones
/exit (also /quit, /q) exits, restores the terminal, publishes the proposal

Sessions

Sessions live as append-only JSONL under the greppy data directory (agent-sessions/<project>/<id>.jsonl; on macOS that is ~/Library/Application Support/greppy). greppy restores a truncated tail up to the last valid entry. Secrets and authorization headers are redacted on screen and in the file. Every session has a copyable handle, greppy://sessions/<id>, that works wherever a session ID is expected.

greppy agent sessions list [--json] [--all-projects]
greppy agent sessions show ID [--json] [--full]
greppy agent sessions tail ID [--json] [--follow] [--lines N]
greppy agent sessions path ID

Without --lines, tail shows the last 40 lines, and --follow polls until SIGINT. These commands never write to the store. IDs can be unique prefixes; an unknown or ambiguous ID exits with code 2.

$ greppy agent sessions list
no sessions for project serde
$ greppy agent sessions show nope
no session nope in project serde

The second command exits with code 2.

JSON events

greppy -p --json streams one JSON event per line on stdout: session, text, tool_start, tool_finish, turn_complete, error and result. result is always the last line. Human-readable diagnostics stay on stderr.

The first SIGINT or SIGTERM cancels at the next safe boundary and still delivers result with status: "cancelled" and exit_code: 130. A second signal exits immediately.

Remote control

greppy agent serve [TASK] hosts a headless session on a per-user Unix socket. An optional TASK is queued as the first task after setup. Every message continues the same task in the same worktree; the controlling agent can send follow-up tasks or interrupt a turn.

agent serve flag Effect
--model M model ID (or GREPPY_MODEL)
--endpoint URL gateway (or GREPPY_ENDPOINT, default http://127.0.0.1:8317)
--continue, --resume SESSION_ID continues the latest or a specific session
--idle-timeout-secs N exits the host after N seconds idle
--no-sandbox, --skip-selfcheck as with greppy -p

greppy agent sessions list --json reports the socket path for each session. Another shell or another agent then controls the session like this:

greppy agent serve --model MODEL
greppy agent status    ID [--json]
greppy agent send      ID TEXT [--wait] [--json] [--source LABEL]
greppy agent attach    ID [--json] [--since-start]
greppy agent interrupt ID [--json]
greppy agent quit      ID [--json]

ID is a session ID, a unique prefix or the handle greppy://sessions/<id>.

Command Effect
status describes the running session
send queues a prompt; TEXT can be - for stdin; --wait streams events until this turn is done; --source sets the turn's label (default remote)
attach streams events of the running session; --since-start first replays the latest log lines
interrupt cancels the running turn
quit asks the host to exit

A session without a live socket exits with code 3 and names the command greppy agent serve --resume ID that restarts it.

ACP hosts: greppy agent stdio

greppy agent stdio --endpoint http://127.0.0.1:8317 --model MODEL

greppy agent stdio speaks the Agent Client Protocol (JSON-RPC, one message per line) on stdin and stdout for a host application; diagnostics go to stderr. The host supplies the working folder when it creates or loads a session, and every tool call waits for the client's approval. In this mode, the agent edits the client's folder directly: it creates no worktree and produces no proposal under refs/greppy/agent/. Its prompt therefore promises neither a worktree nor a pull request. Sessions use the same store as greppy -p and greppy agent.

Speak the Agent Client Protocol on stdin/stdout.

Usage: greppy agent stdio [OPTIONS]

Options:
      --model <MODEL>        Initial model id. `session/set_model` can replace it [env: GREPPY_MODEL=]
      --endpoint <ENDPOINT>  Anthropic-Messages gateway base URL [env: GREPPY_ENDPOINT=] [default: http://127.0.0.1:8317]
      --max-turns <N>        Maximum assistant turns for one prompt [default: 0]
  -h, --help                 Print help

--max-turns 0, the default, means no cap. The agent process reads the gateway key from GREPPY_API_KEY; ACP clients do not send it. You find the supported operations in docs/acp.md.

One prompt, four modes

All modes render their system prompt from the same source. greppy prompt --mode one-shot|interactive|serve|acp|external prints the matching version, and with --json its SHA-256 as well.

$ greppy prompt --mode one-shot | head -2
prompt-sha256: 12bb2db4bce1ab2603279913aeb676f7b68115143a42170091f5842a6cf0d84f
You are greppy, a coding agent. You never work in the user's checkout: every task runs in its own temporary worktree and ends as a pull request.
Mode Version rendered_sha256 (prefix)
one-shot greppy -p edeaa1c109065b42
interactive terminal UI 7cd2ccd0d083eebd
serve greppy agent serve dd480def31ddda46
acp greppy agent stdio 3683b8542fc14de0
external AGENTS.md for external agents 5834ca668bf9025c

The versions differ in one line about the role: with -p, someone reads the answer and the pull request and nothing else; with serve, another agent steers; in the terminal UI, a person can answer questions.

Worktree and sandbox

greppy creates the isolated worktree before the model gets its first request. Ignored files and build caches are not captured. The worktree has a private Git state: it reads the base commit's objects read-only, and its index, its refs, new objects and commits stay private until the verified proposal is imported.

A copy-on-write filesystem adapter (FSKit on macOS) speeds up creation when it is active. Without it, the agent uses ordinary private directories with the same proposal and apply flow.

greppy workspace setup            # optional: install and activate the platform's adapter
greppy workspace doctor --json    # optional: check it
greppy index --agent-worktree     # optional: warm up the agent's worktree and Base ahead of time

Tool processes write to the worktree, a per-run scratch directory (TMPDIR), the worktree's greppy store and ~/.cargo/{registry,git}, and nowhere else. Reads and network stay open. Seatbelt enforces the confinement on macOS, Landlock on Linux. Credential environment variables are stripped from tool processes, and agent runs do not nest. --no-sandbox or GREPPY_NO_SANDBOX=1 turns the confinement off.

The agent rejects repositories with submodules, repositories in the middle of a merge, rebase, cherry-pick, revert or bisect, and repositories with checkout filters such as Git LFS before the model starts (exit 2).

Exit codes

Code Meaning
0 ok: clean, proposal saved or applied
2 no gateway, wrong usage, missing model or unsupported repository
3 agent or loop error; the unsaved worktree is kept for up to 24 hours
4 --apply refused (target not clean) or cherry-pick conflict; the ref stays available
5 incomplete: explicit turn cap or deadline reached; the proposal is saved
130 cancelled

Upgrade from v0.3.3

v0.3.3 has the one-shot greppy -p and nothing else. The terminal UI, sessions, --continue, --resume, --json, greppy agent apply, agent serve, remote control and agent stdio come with 0.4.1. The flags --workspace-backend and --fresh from v0.3.3 no longer exist in 0.4.1.