diff --git a/Environment-Variables.md b/Environment-Variables.md
index e3ef5c2..5de5c45 100644
--- a/Environment-Variables.md
+++ b/Environment-Variables.md
@@ -120,5 +120,5 @@ can also pass the `--disable-log-colors` flag as well.
# Miscellaneous Variables
| Environment Variable | Description | Default Value |
|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
-| `AUTO_CONFIRM` | Bypass all `guard_*` checks in the bash prompt helpers; useful for agent composition and routing. Can also be enabled for a single invocation by passing `--dangerously-skip-permissions` (Coyote sets `AUTO_CONFIRM=true` for the process and all spawned tools/agents). | |
+| `AUTO_CONFIRM` | Bypass all `guard_*` checks in the bash prompt helpers; useful for agent composition and routing. Set automatically when passing `--dangerously-skip-permissions`, `--headless`, or `--acp-server` (Coyote sets `AUTO_CONFIRM=true` for the process and all spawned tools/agents). See [Unattended Mode](Unattended-Mode). | |
| `LLM_TOOL_DATA_FILE` | Set automatically by Coyote on Windows. Points to a temporary file containing the JSON tool call data.
Tool scripts (`run-tool.sh`, `run-agent.sh`, etc.) read from this file instead of command-line args
to avoid JSON escaping issues when data passes through `cmd.exe` → bash. **Not intended to be set by users.** | |
diff --git a/Unattended-Mode.md b/Unattended-Mode.md
new file mode 100644
index 0000000..647d526
--- /dev/null
+++ b/Unattended-Mode.md
@@ -0,0 +1,184 @@
+Coyote supports two unattended operation modes for scripting and programmatic use:
+
+- **`--headless`** suppresses all interactive prompts and runs as a non-interactive CLI process.
+- **`--acp-server`** exposes a full agent server over stdio using JSON-RPC 2.0, suitable for host-side orchestration.
+ It implies `--headless`.
+
+---
+
+# `--headless`
+
+The `--headless` flag runs Coyote in fully unattended mode. It is designed for use in scripts, CI pipelines, and
+sandboxed environments where no user is present to respond to prompts.
+
+When `--headless` is active:
+
+- All interactive prompts (confirmations, selections, free-text inputs) return structured JSON instead of blocking.
+- `AUTO_CONFIRM=true` is set for the process and all spawned tools.
+- REPL mode is not supported; a prompt must be provided via `-f ` or as an inline argument.
+
+```shell
+coyote --headless -f prompt.txt
+coyote --headless "Summarize this project for me"
+```
+
+User-interaction tool calls (e.g. `user__confirm`, `user__select`) return a structured JSON object instead of prompting.
+The response shape matches the tool's normal output, so agents handle it transparently.
+
+---
+
+# ACP Agent Server (`--acp-server`)
+
+`--acp-server` starts Coyote as an ACP agent server over stdio. It is designed for host applications that need to drive
+Coyote programmatically — the host sends JSON-RPC requests over stdin and reads JSON-RPC responses from stdout.
+
+Every byte on stdout is a valid JSON-RPC 2.0 frame. Diagnostic logs go to stderr (or to the log file if `COYOTE_LOG_FILE`
+is configured). The flag implies `--headless`.
+
+```shell
+coyote --acp-server
+```
+
+All normal context flags work alongside `--acp-server` and are applied before the server starts listening:
+
+```shell
+coyote --acp-server --role diagnose
+coyote --acp-server --agent sisyphus
+coyote --acp-server --rag my-index --no-memory
+coyote --acp-server --model gpt-4o
+```
+
+The server then inherits the fully-configured context — the client manages sessions via `session/new` / `session/load`
+as normal.
+
+## Protocol
+
+Each request and response is a single JSON object on one line, terminated by `\n`. Send requests line-by-line; the
+server processes them sequentially and writes a response (or nothing, for notifications) before reading the next line.
+
+**Request:**
+```json
+{"jsonrpc": "2.0", "id": 1, "method": "method/name", "params": {...}}
+```
+
+**Success response:**
+```json
+{"jsonrpc": "2.0", "id": 1, "result": {...}}
+```
+
+**Error response:**
+```json
+{"jsonrpc": "2.0", "id": 1, "error": {"code": -32601, "message": "Method not found: ..."}}
+```
+
+## Methods
+
+| Method | Params | Result | Notes |
+|------------------|-------------------------|---------------------------------------------|-------------------------------------------------------------------------------------|
+| `initialize` | none | `{name, version, protocolVersion}` | Returns server identity. Call this first. |
+| `session/new` | none | `{sessionId: "default"}` | Starts a new temporary session. Only one session per process. |
+| `session/load` | `{sessionId: ""}` | `{sessionId: ""}` | Loads a previously saved session by name (as shown in `coyote --list-sessions`). |
+| `session/prompt` | `{text: ""}` | `{output, stopReason}` | Runs one conversation turn. Requires an active session. |
+| `session/cancel` | none (notification) | `{}` if an `id` was given, else no response | Sets the abort flag for the next call. See [Known Limitations](#known-limitations). |
+
+## Outbound Notifications
+
+The server may emit notifications (messages without an `id`) between a request and its response.
+
+| Notification | Params | When |
+|------------------------------|-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
+| `session/request_permission` | `{action, question, options}` | Emitted when a tool triggers a user-interaction call (e.g. `user__confirm`, `user__select`). Sent before the turn's final response. |
+
+## Error Codes
+
+| Code | Meaning |
+|----------|--------------------------------------------------------------------|
+| `-32700` | Parse error — request line was not valid JSON |
+| `-32601` | Method not found |
+| `-32602` | Invalid params — a required field is missing |
+| `-32600` | Invalid request — e.g. `session/prompt` before `session/new` |
+| `-32000` | Application error — e.g. no active session, session already active |
+
+## Smoke Testing
+
+Build the binary first (`cargo build`), then use a heredoc to send multiple requests:
+
+**Structural test (no LLM required):**
+
+```shell
+./target/debug/coyote --acp-server << 'EOF'
+{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
+{"jsonrpc":"2.0","id":2,"method":"unknown/method","params":{}}
+EOF
+```
+
+Expected: initialize succeeds, then `-32601` method-not-found.
+
+**Parse error recovery:**
+
+```shell
+./target/debug/coyote --acp-server << 'EOF'
+not valid json
+{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
+EOF
+```
+
+Expected: `-32700` for the bad line, then a valid initialize response. The server continues processing after a parse
+error.
+
+**Full session (requires a configured model):**
+
+```shell
+coyote --acp-server << 'EOF'
+{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
+{"jsonrpc":"2.0","id":2,"method":"session/new","params":{}}
+{"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{"text":"Reply with the single word: pong"}}
+EOF
+```
+
+**Multi-turn context:**
+
+```shell
+coyote --acp-server << 'EOF'
+{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
+{"jsonrpc":"2.0","id":2,"method":"session/new","params":{}}
+{"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{"text":"Count to 3 and stop."}}
+{"jsonrpc":"2.0","id":4,"method":"session/prompt","params":{"text":"What was the last number you said?"}}
+EOF
+```
+
+id=4 should answer "3", confirming session history threads across turns.
+
+**Load a saved session:**
+
+```shell
+coyote --acp-server << 'EOF'
+{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
+{"jsonrpc":"2.0","id":2,"method":"session/load","params":{"sessionId":"my-saved-session"}}
+{"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{"text":"Summarize what we've discussed."}}
+EOF
+```
+
+## Known Limitations
+
+**`session/cancel` cannot interrupt a running `session/prompt`.** The server processes requests sequentially. While a
+`session/prompt` turn is executing, the server is not reading stdin. `session/cancel` sets an abort flag that takes
+effect on the *next* invocation.
+
+**`session/request_permission` notifications are post-turn.** They are emitted immediately before the turn's final
+response, not mid-stream. A real-time permission bridge would require a concurrent server design.
+
+---
+
+# Sbx-Kit Headless Profile
+
+The embedded sbx kit ships a `headless` profile for running Coyote in unattended mode inside a sandbox. Set
+`COYOTE_PROMPT_FILE` to the path of a prompt file before launching:
+
+```shell
+export COYOTE_PROMPT_FILE=/path/to/prompt.txt
+sbx run coyote --profile headless
+```
+
+The headless profile passes `--headless -f "${COYOTE_PROMPT_FILE}"` to Coyote and sets `COYOTE_LOG_LEVEL=WARN` to
+reduce noise on stderr. For ACP use inside a sandbox, override the entrypoint directly via `sbx run --entrypoint`.
diff --git a/_Sidebar.md b/_Sidebar.md
index 5d10053..e52d82b 100644
--- a/_Sidebar.md
+++ b/_Sidebar.md
@@ -11,6 +11,9 @@
- [Shell Integrations](Shell-Integrations)
- [Bash Prompt Helpers](Bash-Prompt-Helpers)
- [Sessions](Sessions)
+- [Unattended Mode](Unattended-Mode)
+ - [--headless](Unattended-Mode#--headless)
+ - [ACP Agent Server](Unattended-Mode#acp-agent-server---acp-server)
## Model Providers
- [Clients](Clients)