This guide is the deep reference for administrators, platform engineers, and developers who deploy, operate, secure, extend, or embed goose — the open source on-machine AI agent. It covers the system architecture, the full configuration surface, security model, deployment topologies (including remote goosed and Docker), operations, and a source-level internals tour of the Rust workspace and TypeScript desktop app.
For end-user installation and usage, see the companion User Guide.
Table of Contents
- Executive Summary
- System Architecture
- Repository & Workspace Layout
- The Agent Engine (crates/goose)
- The goosed Server & Desktop App
- System Requirements
- Configuration Mastery
- Environment Variable Reference
- Security
- Deployment
- Operations
- Observability
- Developer Internals
- Embedding goose (SDKs)
- Testing Strategy
- Troubleshooting (Operational)
- Potential Improvements
- Quick Reference
1. Executive Summary
goose is a Rust-core, polyglot AI agent distributed as a CLI and a desktop application. Its job is to take a natural-language request, plan with an LLM, and execute real work through tools exposed by Model Context Protocol (MCP) extensions — running commands, editing files, calling APIs — while keeping the operator in control.
What an administrator needs to know up front:
| Concern | Summary |
|---|---|
| Language & license | Rust (edition 2021, MSRV 1.91.1), TypeScript desktop; Apache-2.0. Workspace version 1.37.0. |
| Runtime model | Local-first. The agent runs on the user's machine. No central server is required. |
| Two surfaces, one engine | CLI binary (goose) and Desktop (Electron) both drive the same crates/goose engine. The Desktop spawns a local server, goosed, and talks to it over HTTP/WebSocket. |
| Model-agnostic | 40+ LLM providers via a pluggable provider layer; nothing about the model is hard-coded. |
| Extensibility | Capabilities come from MCP servers (bundled + third-party + custom). |
| Autonomy | Autonomous by default — with the Developer extension goose runs commands and edits files. Governed by GOOSE_MODE, tool permissions, .gooseignore, and an extension allowlist. |
| Secrets | System keyring by default; secrets.yaml fallback for headless/container environments. |
| Observability | OpenTelemetry (traces/metrics/logs), optional Langfuse, opt-in PostHog telemetry. |
| Interop | Implements Agent Client Protocol (ACP) as both server (editors drive goose) and client (goose delegates to Claude Code / Codex). |
Important
The single most important operational fact: goose executes on the host as the invoking user, with that user's privileges, autonomously by default. Treat the autonomy mode, the extension allowlist, and
.gooseignoreas your primary control plane (see Security).
2. System Architecture
2.1 Component Model
goose has three logical components, regardless of interface:
- Interface — collects input and renders output (Desktop app, CLI, TUI, or an ACP editor).
- Agent — the core loop (in
crates/goose) that orchestrates the model and tools. - Extensions — MCP servers exposing tools; bundled, third-party, or custom.
┌──────────────────────────────────────────────────────────────────────┐
│ INTERFACES │
│ │
│ goose CLI goose Desktop goose TUI ACP editors │
│ (goose-cli) (ui/desktop, Electron) (ui/text) (Zed/JetBrains)│
│ │ │ spawns │ ACP │ ACP │
│ │ in-proc ▼ + HTTP/WS │ stdio ▼ │
│ │ ┌───────────────┐ │ ┌────────────┐ │
│ │ │ goosed │◀─────────────┘ │ goose acp/ │ │
│ │ │ (goose-server) │ HTTP+WS (X-Secret) │ serve │ │
│ │ └──────┬─────────┘ └─────┬──────┘ │
└──────┼───────────────────┼─────────────────────────────────────┼──────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────────────────┐
│ AGENT ENGINE (crates/goose) │
│ │
│ Agent loop ── Providers ── Conversation/Context mgmt ── Sessions │
│ Recipes ── Scheduler ── Permissions ── Security ── Hooks ── Skills │
└───────────────┬───────────────────────────────────┬──────────────────┘
│ MCP (rmcp) │ Provider HTTP (reqwest/rustls)
▼ ▼
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ EXTENSIONS (MCP servers) │ │ LLM PROVIDERS │
│ bundled (goose-mcp): │ │ Anthropic / OpenAI / Gemini │
│ developer, memory, │ │ Bedrock / Databricks / Groq │
│ computercontroller, ... │ │ Ollama / LM Studio (local) │
│ + any 3rd-party / custom │ │ + 40 more │
└──────────────────────────────┘ └──────────────────────────────┘
2.2 The Agent Loop
A single turn (implemented in crates/goose/src/agents):
- Request — user input enters via the interface.
- Provider chat — the agent sends the request plus the catalogue of available tools to the configured LLM provider.
- Tool call — the model may return a tool call (JSON). The model describes the action; goose executes it.
- Execute — the agent dispatches the call to the owning MCP extension and collects the result.
- Feed back — results return to the model; tool steps repeat as needed.
- Context revision — old/irrelevant content is dropped, verbose output summarized, to manage tokens and cost.
- Response — the model's final answer is rendered; the loop restarts on the next message.
Resilient error handling: invalid JSON, missing tools, and command failures are returned to the model as tool results (becoming "prompts" that let it self-correct) rather than aborting the session.
2.3 Key Protocols & Foundations
| Concern | Mechanism | Crate/dep |
|---|---|---|
| Tool interop | Model Context Protocol (MCP) | rmcp 1.4 |
| Editor/agent interop | Agent Client Protocol (ACP) | agent-client-protocol 0.11 |
HTTP server (goosed) |
Axum (HTTP/1, HTTP/2, WS) | axum 0.8 |
| Provider HTTP | reqwest + Rustls (aws-lc-rs) | reqwest 0.13, rustls 0.23 |
| CLI parsing | clap derive | clap 4 |
| Async runtime | Tokio | tokio 1.48 |
| Local inference | candle + llama.cpp (GGUF) | candle-core 0.10, llama-cpp-2 |
| Code intelligence | tree-sitter (Go/Java/JS/TS/Py/Ruby/Rust/Swift/Kotlin) | tree-sitter 0.26 |
| Code Mode (JS exec) | Vendored V8 | vendor/v8 (patched) |
| Secret storage | OS keyring | keyring 3.6 |
| Telemetry | OpenTelemetry | opentelemetry 0.32 |
3. Repository & Workspace Layout
The repository is a Cargo workspace (crates/*) plus separately-built TypeScript apps under ui/, a Docusaurus docs site, and supporting tooling.
3.1 Rust Crates (layered by responsibility)
| Layer | Crate | Responsibility |
|---|---|---|
| Core engine | crates/goose |
The agent: loop, providers, MCP client, recipes, sessions, scheduler, config, security, permissions, context management, local inference, ACP, gateways, skills, hooks. The heart of the system. |
| Interfaces | crates/goose-cli |
The goose binary — clap CLI, interactive session UX, terminal integration, review, local-model management. |
crates/goose-server |
goosed — the Axum HTTP/WebSocket server the Desktop talks to, and the ACP HTTP server. |
|
| Tools | crates/goose-mcp |
Bundled MCP servers: Developer, Computer Controller, Memory, Tutorial, Auto Visualiser, and more. |
| SDK / embedding | crates/goose-sdk |
Rust SDK for embedding goose (incl. UniFFI bindings for other languages). |
crates/goose-sdk-types |
Shared SDK type definitions. | |
| Support | crates/goose-acp-macros |
Proc-macros for the ACP integration. |
crates/goose-test, crates/goose-test-support |
Test harness, MCP test servers, fixtures. |
Note
A
*-macros/proc-macro crate (goose-acp-macros) plus a thin facade (goose-sdkovergoose) is the classic Rust workspace shape: the macro crate enforces compile-time guarantees for the protocol layer, and the SDK re-exports the engine for embedders. Read each member'sCargo.tomlfor its exactdescriptionand target-specific dependencies.
3.2 Non-Crate Components
| Path | Stack | Purpose |
|---|---|---|
ui/desktop |
Electron + React + TypeScript | The Desktop app. Thin shell that spawns goosed and renders the chat UI. |
ui/text |
TypeScript (npm: @aaif/goose) |
The terminal UI (goose tui). |
ui/sdk |
TypeScript | Generated TS client for the goosed API. |
documentation/ |
Docusaurus | The docs site (the canonical user docs and extension catalog). |
examples/ |
mixed | Example extensions, plugins, MCP servers. |
evals/ |
Python | Benchmark/eval harnesses (harbor, open-model-gym). |
services/ask-ai-bot |
TypeScript | A Discord support bot. |
oidc-proxy/ |
JavaScript | OIDC proxy helper. |
recipe-scanner/, workflow_recipes/ |
mixed | Recipe tooling and CI workflow recipes. |
scripts/ |
Python/shell | Build, benchmark, and release tooling. |
vendor/v8 |
vendored | V8 engine for Code Mode JavaScript execution. |
3.3 Build Tooling
Justfile— task runner (just generate-manpages, build helpers, etc.).Dockerfile,BUILDING_DOCKER.md,BUILDING_LINUX.md— container & Linux builds.CUSTOM_DISTROS.md— building custom/branded goose distributions.flake.nix— Nix dev environment.rust-toolchain.toml— pins the Rust toolchain (MSRV 1.91.1).
4. The Agent Engine (crates/goose)
crates/goose/src is the system's core. Key modules (an operator/extender's map):
| Module | Responsibility |
|---|---|
agents/ |
The agent loop, tool dispatch, platform extensions, subagent execution |
providers/ |
LLM provider implementations (one per provider) + declarative/ JSON model catalogs + local_inference/ (llama.cpp/GGUF) |
config/ |
Config loading, paths, provider config, signup flows (OpenRouter/Tetrate/NanoGPT) |
recipe/ |
Recipe parsing, templating, building, deeplinks |
session/ |
Session lifecycle, persistence, import/export formats |
scheduler.rs, scheduler_trait.rs |
Built-in cron scheduler for recipes |
context_mgmt/, conversation/ |
Token management, context revision, compaction |
permission/ |
Tool permission levels and decisions |
security/ |
Prompt-injection detection, package malware scanning |
acp/ |
Agent Client Protocol server + transport |
gateway/ |
Platform gateways (e.g. Telegram) |
skills/, plugins/, hooks/ |
Skills, git-backed plugins, lifecycle hooks |
oauth/ |
OAuth flows for providers and MCP servers |
mcp_utils.rs, subprocess.rs |
MCP client helpers; subprocess management for stdio extensions |
model.rs, token_counter.rs |
Model abstraction, context limits, token counting |
otel/, tracing/, posthog.rs, logging.rs |
Observability and telemetry |
doctor.rs, checks/ |
goose doctor health checks |
4.1 The Extension/Tool Contract
Extensions implement a Rust Extension trait (for bundled extensions) or speak MCP over stdio/Streamable HTTP (for external ones). The trait:
#[async_trait]
pub trait Extension: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn instructions(&self) -> &str;
fn tools(&self) -> &[Tool];
async fn status(&self) -> AnyhowResult<HashMap<String, Value>>;
async fn call_tool(&self, tool_name: &str,
parameters: HashMap<String, Value>) -> ToolResult<Value>;
}
Each tool is async, takes a JSON Value, and returns a ToolResult<Value>. Errors come in two flavors: ErrorData (tool-execution errors that are surfaced back to the model as prompts) and anyhow::Error (general extension errors). This split is deliberate — tool errors become part of the conversation so the model can recover.
Tip
When building a bundled extension, return specific
ErrorDatamessages — they become prompts the model reads. Vague errors waste a turn; precise ones ("file not found at /x; did you mean /y?") let the model self-correct immediately.
5. The goosed Server & Desktop App
5.1 What goosed Is
goosed (built from crates/goose-server) is an Axum HTTP + WebSocket server that exposes the agent engine as an API. The Desktop app spawns goosed as a local subprocess and drives it over HTTP/WebSocket. goosed is also what goose serve runs for ACP-over-HTTP.
5.2 The goosed API Surface
Routes live in crates/goose-server/src/routes/. They are not a public, unauthenticated API — every request requires the shared secret in the X-Secret-Key header (see below). Route groups:
| Route module | Purpose |
|---|---|
agent.rs |
Create/configure agents, run the loop |
reply.rs, session.rs, session_events.rs |
Send messages; manage sessions; stream events (SSE) |
recipe.rs, recipe_utils.rs |
Recipe execution and utilities |
schedule.rs |
Scheduled-job management |
config_management.rs, setup.rs |
Read/write config; first-run setup |
status.rs, features.rs |
Health/status; feature flags |
prompts.rs, sampling.rs |
Prompt templates; MCP sampling |
local_inference.rs |
Local GGUF model management |
gateway.rs, tunnel.rs |
Gateways; remote tunneling |
dictation.rs |
Voice dictation |
action_required.rs |
Approval/elicitation prompts |
mcp_app_proxy.rs, mcp_ui_proxy.rs |
Proxies for MCP Apps / MCP UI |
telemetry.rs |
Telemetry endpoints |
5.3 Securing goosed
Every client request must carry the shared secret:
| Variable | Purpose | Default |
|---|---|---|
GOOSE_HOST |
Interface to bind. 127.0.0.1 = local only; 0.0.0.0 = network-reachable |
127.0.0.1 |
GOOSE_PORT |
TCP port | 3000 |
GOOSE_TLS |
Enable TLS with a self-signed cert (required for remote Desktop connections) | true |
GOOSE_SERVER__SECRET_KEY |
Shared secret required in the X-Secret-Key header on all requests |
random (auto-generated) |
# A network-reachable goosed over TLS with a fixed secret
export GOOSE_HOST=0.0.0.0
export GOOSE_PORT=3000
export GOOSE_TLS=true
export GOOSE_SERVER__SECRET_KEY='a-long-random-secret'
goosed agent
Caution
Binding
goosedto0.0.0.0exposes an agent that can execute commands on the host to the network. Always keep TLS on, set a strongGOOSE_SERVER__SECRET_KEY, and restrict access at the network layer (firewall/VPN). On startup with TLS,goosedprintsGOOSED_CERT_FINGERPRINT=...; clients need it to verify the self-signed cert. See Remote goose Server.
5.4 The Desktop App
ui/desktop is an Electron + React (TypeScript) app. It:
- Locates and spawns the
goosedbinary (GOOSED_BINARY,GOOSE_EXTERNAL_BACKEND,GOOSE_PORT). - Talks to
goosedover the local HTTP/WS API. - Handles desktop concerns: auto-update (
autoUpdater.ts,githubUpdater.ts), proxy settings (HTTP_PROXY/HTTPS_PROXY/NO_PROXY), deep links (goose://), localization, and platform shims (WindowswinShims.ts). - Shares all core config with the CLI via the same
config.yamland keyring, so settings made in one surface apply to the other.
6. System Requirements
| Requirement | Detail |
|---|---|
| OS | macOS, Linux (Debian/Ubuntu DEB provided), Windows 10/11 (native via Git Bash/MSYS2/PowerShell, or WSL) |
| An LLM | A provider API key, a subscription (ChatGPT/Copilot/Tetrate), or a local model. Tool-calling support is required for full functionality. |
| Package runners (for external extensions) | Node.js (npx) and/or uv (uvx); optionally jbang (Java/Kotlin, Linux/macOS only), Docker |
| Network | Outbound HTTPS to your provider (unless fully local). Proxy-aware. |
| Disk | Modest for goose itself; local GGUF models can be large |
| Build-from-source | Rust toolchain pinned by rust-toolchain.toml (MSRV 1.91.1), plus Node for the desktop/TUI |
Note
goose stores data per-platform: macOS
~/Library/Application Support/Block/goose/, Linux~/.local/share/goose/, Windows%APPDATA%\Block\goose\. Config lives in~/.config/goose/(macOS/Linux) or%APPDATA%\Block\goose\config\(Windows). Override the root withGOOSE_PATH_ROOT.
7. Configuration Mastery
7.1 Configuration Files
| File | Purpose |
|---|---|
config.yaml |
Provider, model, extensions, and general settings |
permission.yaml |
Tool permission levels (managed via goose configure) |
secrets.yaml |
API keys/secrets (only when file-based storage is in use) |
permissions/tool_permissions.json |
Runtime permission decisions (auto-managed) |
prompts/ |
Customized prompt templates |
custom_providers/*.json |
Custom provider definitions |
Locations: ~/.config/goose/ (macOS/Linux) or %APPDATA%\Block\goose\config\ (Windows).
7.2 Configuration Precedence
1. Environment variables (highest priority)
2. config.yaml settings
3. Built-in defaults (lowest priority)
7.3 A Complete config.yaml
# --- Model Configuration ---
GOOSE_PROVIDER: "anthropic"
GOOSE_MODEL: "claude-4.5-sonnet"
GOOSE_TEMPERATURE: 0.7
# --- Planning (optional separate model) ---
GOOSE_PLANNER_PROVIDER: "openai"
GOOSE_PLANNER_MODEL: "gpt-4"
# --- Tool / autonomy behavior ---
GOOSE_MODE: "smart_approve" # auto | approve | smart_approve | chat
GOOSE_TOOLSHIM: true
GOOSE_CLI_MIN_PRIORITY: 0.2
# --- Recipes ---
GOOSE_RECIPE_GITHUB_REPO: "aaif-goose/goose-recipes"
# --- Extension command search path ---
GOOSE_SEARCH_PATHS:
- "/usr/local/bin"
- "~/custom/tools"
- "/opt/homebrew/bin"
# --- Security ---
SECURITY_PROMPT_ENABLED: true
# --- Observability ---
otel_exporter_otlp_endpoint: "http://localhost:4318"
otel_exporter_otlp_timeout: 20000
# --- Custom slash commands that run recipes ---
slash_commands:
- command: "run-tests"
recipe_path: "/path/to/recipe.yaml"
# --- Extensions ---
extensions:
developer:
bundled: true
enabled: true
name: developer
timeout: 300
type: builtin
memory:
bundled: true
enabled: true
name: memory
timeout: 300
type: builtin
github:
name: GitHub
type: stdio
cmd: npx
args: [-y @modelcontextprotocol/server-github]
enabled: true
timeout: 300
envs: { "GITHUB_PERSONAL_ACCESS_TOKEN": "<TOKEN>" }
available_tools: [] # empty = all tools; or restrict to specific tool names
7.4 Global Settings (root of config.yaml)
| Setting | Values | Default | Required |
|---|---|---|---|
GOOSE_PROVIDER |
provider name | — | Yes |
GOOSE_MODEL |
model name | — | Yes |
GOOSE_TEMPERATURE |
0.0–1.0 | model-specific | No |
GOOSE_MAX_TOKENS |
positive int | model-specific | No |
GOOSE_MODE |
auto/approve/chat/smart_approve |
auto* |
No |
GOOSE_MAX_TURNS |
int | 1000 | No |
GOOSE_PLANNER_PROVIDER / GOOSE_PLANNER_MODEL |
provider/model | falls back to main | No |
GOOSE_TOOLSHIM / GOOSE_TOOLSHIM_OLLAMA_MODEL |
bool / model | false / system | No |
GOOSE_CLI_MIN_PRIORITY |
0.0–1.0 | 0.0 | No |
GOOSE_CLI_THEME |
light/dark/ansi |
dark |
No |
GOOSE_CLI_SHOW_COST |
bool | false | No |
GOOSE_ALLOWLIST |
URL | — | No |
GOOSE_RECIPE_GITHUB_REPO |
org/repo |
— | No |
GOOSE_AUTO_COMPACT_THRESHOLD |
0.0–1.0 | 0.8 | No |
SECURITY_PROMPT_ENABLED |
bool | false | No |
SECURITY_PROMPT_THRESHOLD |
0.01–1.0 | 0.8 | No |
GOOSE_TELEMETRY_ENABLED |
bool | false | No |
* The default mode is smart_approve at runtime; config.yaml documents auto as the file default. Set it explicitly to avoid ambiguity.
7.5 Extension Configuration Schema
extensions:
<name>:
bundled: true|false # included with goose
display_name: "Name" # human-readable (optional)
enabled: true|false # active?
name: "<name>" # internal name
timeout: 300 # per-tool-call timeout (seconds)
type: "builtin"|"stdio"|"streamable_http"
available_tools: [] # [] = all tools; or a whitelist of tool names
# stdio extensions only:
cmd: "command"
args: ["arg1", "arg2"]
description: "text"
env_keys: []
envs: {}
Tip
Tool filtering via
available_toolsis an under-used token optimization: load only the tools you need from a big extension to cut prompt overhead. Empty means all tools.
7.6 Verifying Configuration
goose info -v # all active settings and current values
goose info --check # test the provider connection
goose doctor # end-to-end health check
Note
Direct edits to config files usually require restarting goose for existing sessions. Provider credential changes made through Desktop Settings refresh the provider inventory without a restart, but currently-active chat sessions keep the provider instance they started with.
8. Environment Variable Reference
Environment variables override config.yaml. Grouped by function.
8.1 Model & Provider
| Variable | Purpose | Default |
|---|---|---|
GOOSE_PROVIDER / GOOSE_MODEL |
Provider / model | must configure |
GOOSE_FAST_MODEL |
Model for auxiliary calls (tool-selection, classification, titles) | provider default |
GOOSE_TEMPERATURE / GOOSE_MAX_TOKENS |
Temperature / response cap | model default |
GOOSE_PROVIDER__TYPE / __HOST / __API_KEY |
Provider implementation / endpoint / key | derived/none |
GOOSE_PREDEFINED_MODELS |
JSON array defining custom models (name, provider, context_limit, request_params) |
— |
GOOSE_CONTEXT_LIMIT / GOOSE_INPUT_LIMIT / GOOSE_PLANNER_CONTEXT_LIMIT |
Context-window overrides (main / ollama num_ctx / planner) |
model default |
CLAUDE_THINKING_TYPE / CLAUDE_THINKING_BUDGET |
Claude reasoning mode / token budget (Anthropic, Databricks) | adaptive (4.6+) / 16000 |
GEMINI3_THINKING_LEVEL |
Gemini 3 thinking level (low/high) |
low |
GOOSE_PLANNER_PROVIDER / GOOSE_PLANNER_MODEL |
Planning-mode provider/model | falls back to main |
BEDROCK_* / DATABRICKS_* retries |
Provider retry tuning (max retries, intervals, backoff) | per-provider |
8.2 Session & Context
| Variable | Purpose | Default |
|---|---|---|
GOOSE_CONTEXT_STRATEGY |
On context overflow: summarize/truncate/clear/prompt |
prompt (interactive), summarize (headless) |
GOOSE_MAX_TURNS |
Max turns without user input | 1000 |
GOOSE_GATEWAY_MAX_TURNS |
Turn cap for gateway sessions only | falls back to GOOSE_MAX_TURNS, then 5 |
GOOSE_SUBAGENT_MAX_TURNS |
Max turns per subagent | 25 |
GOOSE_MAX_BACKGROUND_TASKS |
Concurrent subagents | 5 |
GOOSE_AUTO_COMPACT_THRESHOLD |
Auto-summarize at this context fraction (0 disables) | 0.8 |
GOOSE_TOOL_CALL_CUTOFF |
Tool calls kept in full before summarizing older ones | 10 |
CONTEXT_FILE_NAMES |
Custom hint/context filenames (JSON array) | [".goosehints"] |
GOOSE_DISABLE_SESSION_NAMING |
Skip AI session naming | false |
GOOSE_DISABLE_TOOL_CALL_SUMMARY |
Skip per-tool AI title | false |
GOOSE_PROMPT_EDITOR |
External editor for composing prompts | unset |
GOOSE_CLI_THEME / _LIGHT_THEME / _DARK_THEME |
CLI markdown + syntax themes | dark / GitHub / zenburn |
GOOSE_CLI_SHOW_THINKING / GOOSE_CLI_SHOW_COST |
Show reasoning / cost in CLI | off |
GOOSE_MAX_CODE_BLOCK_LINES / GOOSE_TRUNCATED_SHOW_LINES / GOOSE_NO_CODE_TRUNCATION |
CLI code-block truncation controls | 50 / 20 / off |
GOOSE_MOIM_MESSAGE_TEXT / GOOSE_MOIM_MESSAGE_FILE |
Inject persistent text into working memory every turn (≤64 KB file) | unset |
8.3 Tools & Execution
| Variable | Purpose | Default |
|---|---|---|
GOOSE_MODE |
Tool execution behavior | smart_approve |
GOOSE_TOOLSHIM / GOOSE_TOOLSHIM_OLLAMA_MODEL |
Tool-call interpretation for non-tool-calling models | false |
GOOSE_CLI_MIN_PRIORITY |
Tool output verbosity (0.0–1.0) | 0.0 |
GOOSE_DEBUG |
Full tool params, no truncation | false |
GOOSE_SEARCH_PATHS |
Extra dirs prepended to PATH for extension commands (JSON array) | system PATH |
GOOSE_MAX_TOOL_RESPONSE_SIZE |
Char cap before a tool response is spilled to a temp file | 200000 |
GOOSE_SHELL |
Shell for Developer extension commands | /bin/bash (Unix), cmd (Windows) |
GOOSE_EDITOR_API_KEY / _HOST / _MODEL |
Enhanced code editing model (all three required) | none |
8.4 Security & Privacy
| Variable | Purpose | Default |
|---|---|---|
GOOSE_ALLOWLIST |
URL listing allowed extensions | unset |
GOOSE_DISABLE_KEYRING |
Force file-based secret storage (set to any value) | unset (keyring on) |
SECURITY_PROMPT_ENABLED / SECURITY_PROMPT_THRESHOLD |
Prompt-injection detection / sensitivity | false / 0.8 |
SECURITY_PROMPT_CLASSIFIER_ENABLED / _ENDPOINT / _TOKEN |
ML-based injection detection | false |
GOOSE_TELEMETRY_ENABLED |
Anonymous usage data collection | false |
GOOSE_SANDBOX |
macOS Desktop sandbox (sandbox-exec) |
false |
8.5 Network, Server & OAuth
| Variable | Purpose | Default |
|---|---|---|
HTTP_PROXY / HTTPS_PROXY / NO_PROXY |
Proxy config (HTTPS wins over HTTP) | none |
GOOSE_OAUTH_CALLBACK_PORT |
Fixed OAuth callback port (for IdPs requiring exact redirect_uri) |
random |
GOOSE_HOST / GOOSE_PORT / GOOSE_TLS / GOOSE_SERVER__SECRET_KEY |
goosed bind/port/TLS/secret |
127.0.0.1 / 3000 / true / random |
8.6 Observability
| Variable | Purpose |
|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT |
Base OTLP endpoint (/v1/traces, etc.) |
OTEL_EXPORTER_OTLP_{SIGNAL}_ENDPOINT |
Per-signal endpoint override |
OTEL_{SIGNAL}_EXPORTER |
otlp/console/none per signal |
OTEL_SDK_DISABLED |
Disable all OTel export |
LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY / LANGFUSE_URL |
Langfuse integration |
8.7 Recipes & Internal
| Variable | Purpose |
|---|---|
GOOSE_RECIPE_PATH |
Extra recipe directories (OS path-separated) |
GOOSE_RECIPE_GITHUB_REPO |
GitHub recipe repo (owner/repo) |
GOOSE_RECIPE_RETRY_TIMEOUT_SECONDS / _ON_FAILURE_TIMEOUT_SECONDS |
Recipe command timeouts |
GOOSE_PATH_ROOT |
Override root for all config/data/state |
GOOSE_VERSION |
Pin CLI version (CI/CD reproducibility) |
GOOSE_TERMINAL / AGENT / AGENT_SESSION_ID |
Set by goose so shells/tools/extensions can detect agent execution and isolate work by session |
Important
Enterprise rollout: For consistent governance, pre-set provider endpoints (
GOOSE_PROVIDER__HOST), proxy variables,GOOSE_ALLOWLIST, and security toggles via your configuration management, and prefer the keyring or env vars over committing secrets tosecrets.yaml.
9. Security
goose's threat model is unusual: it is an agent that executes arbitrary actions on the host as the user, directed by an LLM that may be influenced by untrusted content (web pages, file contents, tool output). The controls below form the defense.
9.1 The Autonomy Control Plane
| Control | What it limits | How |
|---|---|---|
GOOSE_MODE |
Whether/when goose executes tools | chat (no execution) → approve (ask every time) → smart_approve (ask on risky) → auto (full) |
| Tool permissions | Per-tool allow/deny | permission.yaml via goose configure; runtime decisions in permissions/tool_permissions.json |
.gooseignore |
Files/paths goose may touch | Glob patterns, like .gitignore |
| Extension allowlist | Which extensions may load | GOOSE_ALLOWLIST URL |
| Recipe trust | Running unfamiliar recipes | Desktop "New Recipe Warning" — review then Trust and Execute |
Caution
Default mode is
smart_approve, not read-only. For shared, CI, or high-privilege hosts, setGOOSE_MODE=approveorchatand scope.gooseignoreto keep goose away from secrets, infra config, and credential stores.
9.2 Extension Malware Scanning
Locally-executed external extensions installed via uvx (PyPI) or npx (NPM) are checked against the OSV malware database before activation. A hit is blocked:
Blocked malicious package: package-name@1.0.0 (npm). OSV MAL advisories: MAL-2024-1234
If the OSV service is unreachable, extensions still install (fail-open) — so the allowlist remains your hard control. Only install extensions from trusted sources.
9.3 Prompt-Injection Detection
goose can scan for prompt-injection attempts (malicious instructions hidden in content goose reads):
export SECURITY_PROMPT_ENABLED=true
export SECURITY_PROMPT_THRESHOLD=0.9 # stricter
# Optional ML-based classifier:
export SECURITY_PROMPT_CLASSIFIER_ENABLED=true
export SECURITY_PROMPT_CLASSIFIER_ENDPOINT="https://your-endpoint/classify"
export SECURITY_PROMPT_CLASSIFIER_TOKEN="..."
9.4 Secret Storage
- Default: OS keyring (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux) via the
keyringcrate. - Fallback:
secrets.yaml(plaintext) when no keyring is available (headless, containers, CI) or when disabled withGOOSE_DISABLE_KEYRING.
GOOSE_DISABLE_KEYRING=1 goose configure
Warning
secrets.yamlstores keys in plaintext. In CI/containers prefer injecting provider keys as environment variables and answering No to "save to keyring," rather than persistingsecrets.yaml.
9.5 macOS Desktop Sandbox
The Desktop app supports an optional macOS sandbox using Apple's sandbox-exec to restrict file access, network connections, and process execution:
export GOOSE_SANDBOX=true
9.6 goosed Network Exposure
See §5.3. The combination that matters: TLS on + strong GOOSE_SERVER__SECRET_KEY + network-layer restriction whenever GOOSE_HOST is not 127.0.0.1.
9.7 Reporting
Security issues are handled per SECURITY.md in the repository. Do not file public issues for vulnerabilities.
10. Deployment
10.1 Desktop Deployment
Distribute the platform build (macOS app, Linux DEB, Windows package) or via package managers (brew install --cask block-goose). The Desktop self-updates; ENABLE_DEV_UPDATES/GOOSE_VERSION control update channels for testing.
10.2 CLI Deployment (incl. CI/CD)
curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash
For reproducible, non-interactive installs (CI/CD), pin the version to avoid 404s when the stable tag lacks assets:
export GOOSE_VERSION=1.37.0
A headless CI run:
export GOOSE_PROVIDER=anthropic GOOSE_MODEL=claude-sonnet-4-5
export ANTHROPIC_API_KEY=... # via secret store, not secrets.yaml
export GOOSE_DISABLE_KEYRING=1
export GOOSE_MODE=auto
goose run --no-session --recipe ci-check.yaml --output-format json
10.3 Remote goosed Server
Run goosed on a remote/more-powerful host and connect the Desktop to it:
# On the remote host
export GOOSE_HOST=0.0.0.0 GOOSE_PORT=3000 GOOSE_TLS=true
export GOOSE_SERVER__SECRET_KEY='a-long-random-secret'
goosed agent
# Note the printed GOOSED_CERT_FINGERPRINT=... — the client needs it
The Desktop then connects with the host, port, secret, and cert fingerprint. Restrict access with a firewall/VPN.
10.4 Docker / DevContainers
goose can run inside containers, and can run extensions inside a container via --container <id> (for devcontainer workflows). See BUILDING_DOCKER.md and the in-repo Dockerfile. In containers, the keyring is typically unavailable — set GOOSE_DISABLE_KEYRING=1 and inject keys via env vars.
10.5 Custom Distributions
CUSTOM_DISTROS.md documents building branded/customized goose builds — useful for enterprises that need to bake in proxy config, an allowlist, custom shims for airgapped networks, or a pre-pinned provider.
10.6 Linux Packaging & Manpages
Distribution packagers can generate Unix manpages from the CLI definitions:
just generate-manpages # ROFF output in target/man/ (goose.1, goose-session.1, ...)
Install them to /usr/share/man/man1/ for offline man goose. See BUILDING_LINUX.md.
11. Operations
11.1 Health & Diagnostics
goose doctor # full health check
goose info -v # active config
goose info --check # provider connectivity
goose session diagnostics --name <session> -o diag.zip # support bundle
11.2 Logs & Data Locations
| Platform | Config | Data/sessions | Logs |
|---|---|---|---|
| macOS | ~/.config/goose |
~/Library/Application Support/goose |
~/.config/goose |
| Linux | ~/.config/goose/ |
~/.local/share/goose/ |
~/.local/state/goose/ |
| Windows | %APPDATA%\Block\goose\ |
%APPDATA%\Block\goose\ |
%LOCALAPPDATA%\Block\goose\ |
11.3 Scheduled Jobs
The built-in scheduler runs recipes on cron (no external service):
goose schedule add --schedule-id nightly --cron "0 2 * * *" --recipe-source ~/recipes/maint.yaml
goose schedule list
goose schedule run-now --schedule-id nightly
goose schedule remove --schedule-id nightly
11.4 Backup & Migration
Back up ~/.config/goose/ (config + recipes + prompts) and the data directory (sessions). Secrets live in the OS keyring (or secrets.yaml if file-based). Use GOOSE_PATH_ROOT to relocate or isolate an entire environment.
11.5 Uninstall / Reset
Stop all goose processes, delete the "goose" credential from the keychain/credential manager, then remove the data/config/state directories for your platform (see Known Issues → Uninstall).
12. Observability
goose emits OpenTelemetry signals (traces, metrics, logs) to any OTLP-compatible collector, has a Langfuse integration, and an opt-in PostHog telemetry channel.
# Export everything to a local collector
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
# Traces only; console debug; sample 10% in prod
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"
Or in config.yaml:
otel_exporter_otlp_endpoint: "http://localhost:4318"
otel_exporter_otlp_timeout: 20000
Built-in metrics include session counters, durations, token usage, and recipe runs (emitted as monotonic_counter.goose.* tracing events). Anonymous product telemetry is off by default (GOOSE_TELEMETRY_ENABLED=false).
Tip
For per-session LLM tracing (prompts, tool calls, costs), use the Langfuse integration (
LANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEY) — the most operator-friendly view of what the agent actually did.
13. Developer Internals
13.1 Architecture Layers (recap, for extenders)
goose-cli / ui/desktop / ui/text / ACP editors ← interfaces
│
crates/goose-server (goosed, Axum) ← API surface (Desktop/ACP-HTTP)
│
crates/goose ← engine (loop, providers, MCP, recipes,
│ sessions, scheduler, security, permissions)
├── MCP (rmcp) → goose-mcp + 3rd-party ← tools
└── provider HTTP → LLM providers ← models
crates/goose-sdk(+types), goose-acp-macros ← embedding & protocol support
13.2 Provider Layer
Providers live in crates/goose/src/providers/, one module per provider, plus:
declarative/*.json— model catalogs (e.g.groq.json,novita.json,routstr.json) listing model names and context limits. This is where the "supported models per provider" data lives.local_inference/— GGUF inference viallama-cpp-2(with allamacpp/backend) andcandle.formats/,canonical/— request/response formatting and a canonical message representation that normalizes across providers.
To add a provider, implement the provider trait, add a declarative model catalog if applicable, and register it. Prompt caching for Claude is applied automatically for Anthropic/Bedrock/Databricks/OpenRouter/LiteLLM.
13.3 Recipes & Scheduler
recipe/parses and templates recipe YAML (Jinja-style includes, parameters, sub-recipes) and builds deeplinks (recipe_deeplink.rs).scheduler.rs+scheduler_trait.rsimplement the embedded cron scheduler (no external broker).
13.4 Context Management
context_mgmt/ and conversation/ implement the context-revision strategy: token counting (token_counter.rs), automatic compaction (GOOSE_AUTO_COMPACT_THRESHOLD), tool-output summarization (GOOSE_TOOL_CALL_CUTOFF), and find-and-replace-over-rewrite editing. This is the cost-control core.
13.5 Code Mode & V8
The Code Mode platform extension executes JavaScript for tool discovery/calling. It relies on a vendored V8 (vendor/v8, pinned via [patch.crates-io]) — a notable build dependency. Known interaction bug: MCP Apps may fail to render when Code Execution is enabled (#9598).
13.6 Contributing
See CONTRIBUTING.md, CONTRIBUTING_RECIPES.md, AGENTS.md (agent-oriented contribution guidance), GOVERNANCE.md, MAINTAINERS.md, and RELEASE.md/RELEASE_CHECKLIST.md. The project moved to the AAIF organization (aaif-goose/goose); authorship is AAIF <[email removed]>, license Apache-2.0.
14. Embedding goose (SDKs)
Two SDK surfaces let you embed goose:
- Rust SDK —
crates/goose-sdk(types incrates/goose-sdk-types), including UniFFI bindings (examples/uniffi) so the agent can be driven from other languages. - TypeScript SDK —
ui/sdk, a generated client (src/generated/) for thegoosedHTTP API. This is what custom front-ends or integrations target.
Embedders typically run goosed (or link the engine) and drive sessions/recipes through these clients, supplying provider config and extensions programmatically.
15. Testing Strategy
| Layer | Where |
|---|---|
| Unit & integration (Rust) | Per-crate tests/ and #[cfg(test)] modules |
| MCP/agent harness | crates/goose-test, crates/goose-test-support (test MCP servers, ACP fixtures, recorded provider responses under scenario_tests/recordings/<provider>) |
| Desktop (TS) | ui/desktop/tests/ (unit, integration, Playwright e2e) |
| Evals/benchmarks | evals/ (harbor, open-model-gym) — measures model/agent performance on task suites |
| Self-test | goose-self-test.yaml — a recipe that exercises goose end-to-end |
| Lint/deps | clippy.toml, deny.toml (cargo-deny), cargo-machete (the vendor/v8 workspace member exists partly to satisfy it) |
Extensions should be tested at three levels: unit tests per tool, integration tests for extension behavior, and property tests for tool invariants.
16. Troubleshooting (Operational)
16.1 Keyring Unavailable (containers / headless / CI)
Symptom: Failed to access keyring / org.freedesktop.secrets was not provided.
Cause: No desktop keyring (Secret Service over DBus) in the environment.
Fix: Force file storage or use env vars:
GOOSE_DISABLE_KEYRING=1 goose configure
goose may auto-fall-back to secrets.yaml for the current process; new sessions retry the keyring. Force file storage to make it persistent.
16.2 Airgapped / Restricted Networks
Symptom: Extensions fail with hermit:fatal or "Could not run extension command."
Cause: goose's packaged npx/uvx shims try to download runtimes via Hermit, which restricted networks block.
Fix: Create alternatively-named runners (not npx/uvx/jbang) so goose passes them through unchanged, and reference those in config:
ln -s /usr/local/bin/uvx /usr/local/bin/runuv
ln -s /usr/local/bin/npx /usr/local/bin/runnpx
extensions:
example:
cmd: runuv # bypasses goose's shim
args: [mcp-server-example]
For deeper constraints (TLS interception, proxies), build a custom distribution (CUSTOM_DISTROS.md) with the right shims/config baked in.
16.3 Clean Uninstall / Reset
Stop all goose processes, delete the "goose" keychain/credential, then:
# macOS
rm -rf ~/.config/goose ~/Library/Application\ Support/goose
# Linux
rm -rf ~/.local/share/goose/ ~/.local/state/goose/ ~/.config/goose/
# Windows (cmd)
rmdir /s /q "%APPDATA%\Block\goose"
rmdir /s /q "%LOCALAPPDATA%\Block\goose"
16.4 Corporate Proxy
export HTTPS_PROXY="http://proxy.company.com:8080"
export NO_PROXY="localhost,127.0.0.1,.internal"
Restart goose. Env vars take precedence over OS proxy settings.
16.5 OAuth Behind a Strict IdP
If your identity provider requires an exact redirect_uri (no wildcard ports), pin the callback port:
export GOOSE_OAUTH_CALLBACK_PORT=8080
Register http://127.0.0.1:8080/oauth_callback (MCP OAuth) or http://localhost:8080 (Databricks OAuth).
16.6 Node.js Extensions Fail on Windows
goose expects Node at C:\Program Files\nodejs\. If installed elsewhere, symlink it (Admin PowerShell): mklink /D "C:\Program Files\nodejs" "D:\Program Files\nodejs".
16.7 Known Bugs (from the issue tracker)
| Issue | Status | Note |
|---|---|---|
| MCP Apps fail to render when Code Execution extension enabled (#9598) | Open | Disable Code Mode when using MCP Apps |
Desktop ignores GOOSE_MODEL from config.yaml (#9451) |
Closed | Set model via Settings |
shell tool returns empty stdout/stderr on Windows in ACP stdio mode (#9582) |
Open | Affects ACP subprocess launches |
Empty "New Chat" sessions created on reconnection when goosed unreachable (#9608) |
Open | Ensure goosed reachable |
| Tool request/response timestamp ordering breaks Claude API message order (#9461) | Open | Provider-specific ordering issue |
17. Potential Improvements
Observations for maintainers and operators planning hardening or contributions:
- Default mode clarity.
config.yamldocumentsGOOSE_MODEdefault asautowhile runtime default issmart_approve. Aligning the documented and effective defaults would reduce operator surprise on high-privilege hosts. secrets.yamlplaintext. File-based fallback stores secrets unencrypted. An at-rest encryption option (or first-class env-injection mode) would help container/CI deployments that can't use a keyring.- Fail-open malware scan. If OSV is unreachable, extension installs proceed. Environments with a strict posture should treat the allowlist as the authoritative control and consider a fail-closed option.
goosedexposure footguns. Binding to0.0.0.0exposes a command-executing agent; a startup warning whenGOOSE_HOST != 127.0.0.1without a strong secret would reduce risk.- Code Mode / MCP Apps interaction (#9598). A documented, enforced mutual exclusion (or a fix) would remove a sharp edge.
- Windows ACP
shellstdout (#9582). Empty stdout/stderr under ACP stdio is a correctness gap for Windows automation. - Tree-sitter breadth. Code intelligence covers 10 languages; extending the grammar set would broaden Code Mode/analysis coverage.
18. Quick Reference
18.1 Operator Commands
goose doctor # health check
goose info -v # full config
goose info --check # provider connectivity
goosed agent # run the server (Desktop backend / remote)
goose serve --port 3284 # ACP over HTTP/WS
goose schedule list # scheduled jobs
just generate-manpages # packager manpages
18.2 Critical Security Settings
| Setting | Hardened value |
|---|---|
GOOSE_MODE |
approve or chat on shared/CI/high-privilege hosts |
GOOSE_ALLOWLIST |
URL of approved extensions |
.gooseignore |
exclude secrets, infra config, credential stores |
GOOSE_SERVER__SECRET_KEY |
strong random; required if GOOSE_HOST != 127.0.0.1 |
GOOSE_TLS |
true for any non-local goosed |
SECURITY_PROMPT_ENABLED |
true when reading untrusted content |
GOOSE_DISABLE_KEYRING |
1 in containers (+ env-var keys, avoid secrets.yaml) |
18.3 Workspace Crate Map
| Crate | Role |
|---|---|
goose |
Agent engine (core) |
goose-cli |
goose binary / CLI |
goose-server |
goosed HTTP/WS + ACP-HTTP server |
goose-mcp |
Bundled MCP extensions |
goose-sdk / goose-sdk-types |
Embedding SDK |
goose-acp-macros |
ACP proc-macros |
goose-test / goose-test-support |
Test harness & fixtures |
18.4 Facts Sheet
| Fact | Value |
|---|---|
| Workspace version | 1.37.0 |
| Rust edition / MSRV | 2021 / 1.91.1 |
| License | Apache-2.0 |
| MCP library | rmcp 1.4 |
| ACP library | agent-client-protocol 0.11 |
| Server framework | Axum 0.8 (goosed) |
Default goosed bind/port |
127.0.0.1:3000, TLS on |
Default ACP HTTP port (goose serve) |
3284 |
Default GOOSE_MODE |
smart_approve |
Default GOOSE_MAX_TURNS |
1000 |
| Bundled MCP servers | developer, computercontroller, memory, tutorial, autovisualiser |