Goose github.com/block/goose ↗
Open-source general-purpose AI agent from Block (Apache-2.0, now under Linux Foundation's Agentic AI Foundation). Rust core + TypeScript desktop, ships as CLI + Desktop. MCP plugin model (70+ extensions). Config at ~/.config/goose/; sessions in SQLite at ~/.local/share/goose/sessions/sessions.db (v1.10+). No published GHSAs as of writing, but developer extension grants unsandboxed shell + filesystem by default.
Pin Version, Watch Install Channel
The Linux/macOS one-liner pulls the stable tag and writes a self-updating binary. Desktop builds auto-update.
GOOSE_VERSION=v1.29.0 \
curl -fsSL "https://github.com/block/goose/releases/download/$GOOSE_VERSION/download_cli.sh" | bash
cargo install --git https://github.com/block/goose --tag v1.29.0 goose-cliTip: verify shasum from the releases page; subscribe to releases feed; disable Desktop auto-update on managed fleets.
Desktop vs CLI Exposure Surface
CLI opens no listener (outbound HTTPS to provider only). Goose Desktop runs an internal goose-server process and a local OAuth callback (override via GOOSE_OAUTH_CALLBACK_PORT). Both share ~/.config/goose/.
Tip: prefer CLI for headless/CI; on Desktop keep GOOSE_OAUTH_CALLBACK_PORT bound to loopback and firewall it; isolate users via GOOSE_PATH_ROOT=/srv/goose/$USER.
Provider Credentials — Keyring First, secrets.yaml Last
Goose stores keys in OS keyring (Keychain / libsecret / Windows Credential Manager) by default. GOOSE_DISABLE_KEYRING=1 (or headless without keyring) falls back to ~/.config/goose/secrets.yaml plaintext (mode 0o600).
# ~/.config/goose/config.yaml — reference provider, never inline key
GOOSE_PROVIDER: anthropic
GOOSE_MODEL: claude-sonnet-4-5export ANTHROPIC_API_KEY="$(op read op://dev/anthropic/key)"
goose sessionTip: never git add secrets.yaml or config.yaml; on CI inject keys via env vars + GOOSE_DISABLE_KEYRING=1 to tmpfs-only secrets.yaml; rotate after session sharing.
Pick the Right GOOSE_MODE — auto Is the Default
GOOSE_MODE controls per-tool approval. Default auto (no prompts, agent edits/deletes/executes freely). Switch to smart_approve for risk-classified gating, approve to confirm every tool call, chat to disable tools entirely.
GOOSE_MODE: smart_approve # auto | approve | smart_approve | chat
GOOSE_MAX_TURNS: 50 # default 1000 — cap runaway loopsPer-tool decisions persist to ~/.config/goose/permissions/tool_permissions.json + permission.yaml. Mid-session: /mode approve.
Tip: default smart_approve on dev laptops; approve for customer data; chat for text drafting; review permission.yaml after each session.
No Built-in Sandbox — Isolate the Host
The developer built-in extension shells out (shell, text_editor, list_windows) with full user privileges; computercontroller drives the GUI and runs automation_script; memory writes to disk. Block's docs explicitly point at containers/dev containers for isolation.
docker run --rm -it \
-v "$PWD":/work -w /work \
-v goose-config:/root/.config/goose \
--network=bridge --cap-drop=ALL \
-e ANTHROPIC_API_KEY -e GOOSE_MODE=smart_approve \
ghcr.io/block/goose:v1.29.0 goose sessionTip: one container per project, no bind-mount of $HOME or ~/.ssh, separate Docker network from host LAN.
Lock Down Extensions With GOOSE_ALLOWLIST
The Goose Hub and goose configure → Add Extension will install any MCP server (stdio/SSE/npm/uvx). Block ships an allowlist mechanism — point GOOSE_ALLOWLIST at a YAML of approved command: strings and Goose blocks installs that don't match.
# allowlist.yaml served at https://internal/goose-allowlist.yaml
extensions:
- id: github
command: npx -y @modelcontextprotocol/server-github
- id: filesystem
command: npx -y @modelcontextprotocol/server-filesystemexport GOOSE_ALLOWLIST=https://internal.example/goose-allowlist.yamlTip: host allowlist on internal infra (HTTPS + cert pinning at egress); pin extensions by full command (npx -y pkg@1.2.3); disable computercontroller unless someone explicitly needs browser automation.
Prompt Injection — Enable Security Prompt and Adversary Mode
Goose ships two independent defenses, both off by default. SECURITY_PROMPT_ENABLED=true activates a built-in classifier (SECURITY_PROMPT_THRESHOLD, default 0.8). Adversary Mode is a separate, silent reviewer agent that inspects each tool call and returns ALLOW/BLOCK before execution; rules live in user-editable adversary.md.
SECURITY_PROMPT_ENABLED: true
SECURITY_PROMPT_THRESHOLD: 0.7Tip: turn both on; expand Adversary Mode's tools: list to cover any extension that writes/networks; refuse to paste untrusted web content directly — let developer__fetch bring it in so it's reviewable.
Updates, Telemetry, Egress
Goose Desktop auto-updates and emits OpenTelemetry traces. GOOSE_TELEMETRY_ENABLED (default false) governs anonymous events; OTEL_EXPORTER_OTLP_ENDPOINT / LANGFUSE_*_KEY redirect traces.
GOOSE_TELEMETRY_ENABLED: false
otel_exporter_otlp_endpoint: http://otel-collector.internal:4318Tip: confirm telemetry off fleet-wide; allowlist only provider hostnames at egress proxy; tail goose info -v after upgrade to spot new outbound destinations.
Audit — Session DB, Logs, Memory Files
From v1.10, every session writes to ~/.local/share/goose/sessions/sessions.db (SQLite — id, description, working dir, full transcript, every tool call + result). Logs land under ~/.local/state/goose/logs/. The memory extension persists facts to ~/.config/goose/memory/.
sqlite3 ~/.local/share/goose/sessions/sessions.db \
"SELECT id, created_at, working_dir FROM sessions ORDER BY created_at DESC LIMIT 20;"
goose session listTip: back up the session DB off-box; periodically purge memory/ and prompts/; ship ~/.local/state/goose/logs/*.jsonl to your SIEM and alert on GOOSE_MODE=auto + denied-extension events.
Best Practices Recap
- Pin a release tag, disable Desktop auto-update, verify shasums.
- Keep
GOOSE_MODEatsmart_approveorapprove; capGOOSE_MAX_TURNS. - Run the developer / computercontroller extensions in a container — Goose has no built-in sandbox.
- Keys in keyring; never in
config.yaml; treatsecrets.yamlas a fallback only. - Set
GOOSE_ALLOWLIST; disable extensions you don't use. - Enable
SECURITY_PROMPT_ENABLEDand Adversary Mode; reviewadversary.mdrules. - Disable
GOOSE_TELEMETRY_ENABLED, route OTLP traces internally, force HTTPS through egress proxy. - Treat
sessions.dband~/.local/state/goose/logs/as sensitive — back up, purge, ship to SIEM.