GooseCode logoGooseCodeCLIBack to home
// cli reference

Goose Code CLI Guide

A coding agent from your terminal. The CLI runs on the same core (runOpenAiAgent) as the desktop app: the same loop, the same tool set, the same skills and subagents, the same session files. Only the shell differs - a terminal instead of a window.

The command is called goosecode (short alias - goose). The standalone binary (goose-windows-x64.exe / goose-linux-x64 / goose-macos-arm64) runs without Node/Bun - rename it to whatever suits you. The examples below use goose. From source (dev): bun run cli <args> or bun src/cli/index.ts <args>.

Quick start#

The general form: a command (defaults to run), any options, and an optional prompt. Give a prompt to run one task; omit it to open the interactive REPL.

goose [command] [options] ["<prompt>"]
terminal
# Interactive session in the current folder (full-screen UI)
goose

# One-off task: streams the answer and exits
goose "add a dark-mode toggle to the settings page"

# Headless (for scripts/CI): -p / --print
goose -p "explain what src/cli/index.ts does" > notes.md

# Context via stdin
cat build.log | goose -p "why did this build fail?"

# Continue the previous session
goose -c "now write tests for that change"

With no prompt and a terminal attached, an interactive session starts (the full-screen UI by default, or the line-based REPL with --no-ink). With a prompt (an argument and/or stdin) a single non-interactive turn runs instead. See Interactive vs non-interactive for the full breakdown.

Exit codes: 0 - success; 1 - agent error, unknown flag, missing prompt, or missing key. This is what to rely on in CI.

Interactive vs non-interactive#

The CLI picks one of two modes from the way you launch it, and they behave very differently: one keeps a conversation open, the other runs a single task and exits.

InteractiveNon-interactive (headless)
Starts whenNo prompt and a terminal (TTY) is attached - just goose.A prompt is given (argument and/or stdin), or -p is passed.
What happensOpens a session you talk to turn after turn; it stays open until you leave.Runs a single turn, streams the answer to stdout, then exits.
InterfaceFull-screen terminal UI by default; --no-ink switches to the plain line-based REPL.No UI - just the streamed output (colors auto-off outside a TTY).
Slash commandsYes - /help, /new, /model, and the rest.No - it is one shot.
OutputAlways the human-readable view.Pick with --output-format: text, json, or stream-json.
Best forCoding by hand in the terminal.Scripts, pipes and CI.
terminal
# Interactive: the full-screen UI (default)
goose

# Interactive: the classic line-based REPL instead of the full-screen UI
goose --no-ink

# Non-interactive: one task, streamed to stdout, then exit
goose -p "explain what src/cli/index.ts does"

# Non-interactive is also implied by any prompt (even without -p)
goose "add a dark-mode toggle to the settings page"

The -p / --print flag forces non-interactive mode even with no prompt in the arguments - useful when all the input arrives on a pipe.

Authentication and keys#

The CLI is account-only - the same as the desktop app.

A Goose Code key

A gsk_live_… key is created in your account - on the goosecode.org website or in the desktop app (Settings → API Keys). It authenticates your account, usage bills against your subscription (just like in the app), and it's what unlocks the server-mediated tools - web search, page fetching, image analysis and generation (see Which tools are available).

bash
export GOOSE_API_KEY=gsk_live_XXXXXXXXXXXXXXXXXXXX
goose -p "fix the failing test in src/auth"

# or once, as a flag
goose --api-key gsk_live_XXXX -p "explain this repo"

Precedence: --api-key <token>GOOSE_API_KEY (env). A value beginning with gsk_live_ always goes to the Goose Code proxy.

Your own provider keys don't work in a public build. This is deliberate: inference goes through the account only, like the desktop. Bring-your-own OpenAI / OpenRouter keys are enabled only in an eval build (meant for sandbox evals where the harness measures the model on its own credentials). In a normal user build OPENAI_API_KEY / OPENROUTER_API_KEY are ignored.

The run command - the agent#

Runs the agent on a prompt. run is the default command, so goose "prompt" is equivalent to goose run "prompt". The prompt may be an argument, piped in on stdin, or both.

goose [run] [options] ["<prompt>"]

Options:

OptionPurpose
-p, --printHeadless (non-interactive): stream the answer and exit. The prompt can be piped in.
-m, --model <id>Model: goose-ai (default) · auto · goose-local.
-d, --dir <path>Working directory (defaults to the current one).
-c, --continueContinue the most recent session.
-r, --resume <id>Resume a session by id.
--max-effortForce the strongest tier and highest reasoning effort.
--verboseShow the agent's thinking.
--output-format <fmt>text (default) · json · stream-json.
--max-turns <n>Cap the number of agent turns (only with -p).
--api-key <token>A Goose Code account key (or a provider key in an eval build).
-f, --file <path>Attach a file to the prompt. Repeatable.
-s, --skill <name>Load a skill by name before the turn. Repeatable.
--no-code-indexDon't build the semantic code index for this run.
--no-session-persistenceRun in memory - the session isn't saved and can't be resumed.
--no-inkInteractive only: use the plain line-based REPL instead of the default full-screen UI.

Models

  • goose-ai (default) - the family via account/proxy. The main path.
  • auto - the OpenAI tier chain. A provider path, so in a public build it needs an account (a BYO OpenAI key works only in an eval build).
  • goose-local - an offline mock agent. No key needed, deterministic output. Good for checking the pipeline, scripts and tests.
bash
# Strongest tier + highest reasoning on a hard refactor
goose -p -m auto --max-effort "refactor the auth module to remove the callback hell"

# Offline check that the CLI works at all
goose -p -m goose-local "hello"

Attach files

--file puts a file into the message context. The core detects the type itself - text, PDF, DOCX, XLSX, an image (images need an account key). A missing path or a directory is an error at startup (better to fail than to silently answer about a file the agent never saw).

bash
goose -p -f error.log -f src/server.ts "why does the server 500 on startup?"
goose -p --file spec.pdf "summarise the API contract in this spec"

An attachment is spent on the first turn (like the app's composer), not glued onto every subsequent one.

Load a skill

--skill loads a skill by name before the turn begins. See the available ones with goose skills.

bash
goose -p -s code-review "review my staged changes"
goose -s react-app "scaffold a settings page with a dark-mode toggle"

A one-off run that leaves no trace

bash
# Writes nothing to the data directory; cannot be resumed
goose -p --no-session-persistence "one-off question - don't save it"

Interrupt

Ctrl-C stops the current turn (the session is kept). A second Ctrl-C at an idle REPL prompt exits.

Interactive session#

Starts when there is no prompt and a terminal is attached: just goose. By default it is a full-screen terminal UI - a composer, live streaming, and a status line. Prefer a classic line-based prompt? Add --no-ink. Both accept the same slash commands:

slash commands
/help              show help
/new               start a new session
/sessions          list recent sessions
/rm [id]           delete a session (default: the current one)
/model <id>        switch model (auto | goose-ai | goose-local)
/effort            toggle max-effort
/clear             clear the screen
/exit, /quit       leave

Any other /name is treated as a skill invocation of that name (the same as goose skills). For example /code-review inside the REPL runs the code-review skill.

To an agent question (AskUserQuestion) in the REPL you reply with the option number or your own text.

Output formats and automation#

--output-format controls what goes to stdout.

text (default)

A human-readable rendering: assistant text, tool cards, diffs.

json - a single final object

When the turn finishes, exactly one object is printed - the answer and the totals. Handy for a script that wants the result, not a play-by-play.

bash
goose -p -m auto --output-format json "what does src/cli/index.ts export?" | jq -r .result

Object shape:

json
{
  "type": "result",
  "is_error": false,
  "session_id": "…",
  "num_turns": 3,
  "result": "…answer text…",
  "usage": { "turns": 3, "inputTokens": 1200, "outputTokens": 340, "…": "…" }
}

The usage and error fields are present only when there's something to show (the offline goose-local model, for instance, has no usage). The keys type, is_error, session_id, num_turns, result are always present.

stream-json - an NDJSON stream

A line-by-line stream of events as they happen - one JSON object per line. This is the programmatic contract the eval harness parses.

bash
goose -p -m auto --output-format stream-json "fix the bug" \
  | jq -c 'select(.kind=="block")'

Event kinds (the kind field): message-start, block, usage, error, message-end.

The --json flag is a legacy alias for --output-format stream-json (hidden from --help, but still working; existing scripts and the harness depend on it).

Cap the number of turns

bash
# Don't let an unattended run "keep going until it decides to stop"
goose -p --max-turns 8 "investigate and fix the flaky test"

--max-turns counts main-loop turns (not subagent calls) and only applies in headless mode.

Fail a CI step on an agent error

bash
# is_error → a non-zero exit code
goose -p --output-format json "run the tests and fix any failure" \
  | jq -e '.is_error | not' > /dev/null || exit 1

Sessions#

Lists and deletes saved sessions, which are shared with the app (the same data directory).

goose sessions [list | rm <id…>]

list (the default, can be omitted) prints recent sessions; rm <id…> deletes one or more by id. To reopen a session, use -c (latest) or -r <id> on run.

bash
# List (list is the default command, can be omitted)
goose sessions
goose sessions list

# Delete one or more by id
goose sessions rm 8d4e82c9-801d-4110-ad5c-15094f2291cd
goose sessions rm <id1> <id2> <id3>

# Continue the latest / resume a specific one
goose -c "and add a test as well"
goose -r 8d4e82c9-801d-4110-ad5c-15094f2291cd "finish this PR"

Deleting an unknown id is an error (exit 1), not a silent success.

Skills#

Skills are instruction packs, compatible with the Claude Code format. The CLI sees them from several layers (built-ins + ~/.claude/skills/ + <data-dir>/skills/ + <cwd>/.claude/skills/ + <cwd>/.goose/skills/).

goose skills [--json]

Lists the skills visible from the current folder; --json prints them machine-readably. Load one for a run with -s <name>.

bash
# What's available from this folder
goose skills

# Machine-readable
goose skills --json

# Use one in a run
goose -p -s code-review "review the diff on this branch"

In the REPL a skill is invoked as /skill-name [args].

Utility commands#

CommandWhat it does
goose index [-d dir] [--json]Build the code index and print stats.
goose doctorCheck the environment: runtime, ripgrep, tree-sitter, data dir, flags.
goose open [-d dir]Launch the desktop app (needs Electron; not in the standalone binary).
No search / files / parse subcommands. Code search and shell parsing are the agent's internal tools (Grep/Glob and the Run-command analyzer), not a CLI utility belt. Claude Code and Codex are built the same way. If you want a raw grep, you already have rg.

Examples:

bash
# Build the code index and print stats
goose index
goose index -d src --json

# Check the environment (runtime, ripgrep, tree-sitter, data-dir, flags)
goose doctor

# Launch the desktop app (needs Electron; not available in the standalone exe)
goose open -d ./my-project

Example doctor output:

goose doctor
✓ runtime        bun 1.3.14
✓ electron       …/node_modules/electron/dist/electron.exe
✓ ripgrep        …/@vscode/ripgrep-…/rg.exe
✓ ts runtime     …/web-tree-sitter/tree-sitter.wasm
✓ bash grammar   …/tree-sitter-bash/tree-sitter-bash.wasm
✓ shell parser   tree-sitter
✓ dist build     …/dist
✓ data dir       …/goose-code
✓ workspace      /path/to/project (main)
flags: devtools, telemetry, shell-analysis, context-search, code-index, eval

Environment variables#

Keys and access (public build)

VariableEffect
GOOSE_API_KEYA Goose Code account key (gsk_live_…). The only key that works in a public build.
GOOSE_PROXY_TOKEN_FILEPath to an account-token file; re-read on every request (a long run never sends a stale token).
GOOSE_PROXY_TOKENA static account token.
GOOSE_PROXY_BASE_URLInference proxy base (default https://api.goosecode.org/v1).
GOOSE_PROXY_TOOLS_URL / GOOSE_TOOLS_BASE_URLWeb-tools base (default https://api.goosecode.org/tools).

BYO provider keys - eval build only

Effective only if the build carries the eval flag (bun run eval:binary). Ignored in a public build.

VariableEffect
OPENROUTER_API_KEYOpenRouter key for goose-ai (eval).
OPENAI_API_KEYOpenAI key for auto (eval).
OPENROUTER_BASE_URL / OPENAI_BASE_URLAlternate provider endpoints.

Behavior and output

VariableEffect
NO_COLORDisable ANSI colors (also auto-off when stdout is not a TTY).
GOOSE_MODEL_FAMILYModel family: deepseek → DeepSeek; otherwise MiMo (default).
GOOSE_NO_PLAN=1Disable the planning pass and the parallel subagent fan-out.
GOOSE_PROMPTBase-prompt A/B arm: opencode / goose; otherwise v2 (production).
GOOSE_WASM_DIRExplicit tree-sitter grammar directory (for container runs).

Where things live#

The data directory is shared with the app:

  • Windows: %APPDATA%\goose-code
  • macOS: ~/Library/Application Support/goose-code
  • Linux: $XDG_CONFIG_HOME/goose-code (usually ~/.config/goose-code)

Inside: sessions/ (one file per session), settings.json (shared settings), code-index/ (index cache), skills/ (global skills). The exact path is shown by goose doctor (the data dir line).

Which tools are available in the CLI#

The agent sees the same tool set as the app, minus those that physically cannot run in the current process. Only workable tools are offered to the model - so it doesn't spend a turn on a call that's bound to fail.

ToolsWhen available
Read, Write, Edit, Bash, PowerShell, Grep, Glob, Skill, Agent, TodoWrite, AskUserQuestion, documents (pdf/xlsx/docx)Always
outline, symbols, deps (code index)Index enabled (no --no-code-index, build ships the grammars)
WebSearch, WebFetch, analyze_image, generate_imageAccount credentials present (a gsk_live_… key)
verify_webDesktop app only (needs a browser)

Practical upshot: on a Goose Code key everything is available except verify_web. (In an eval build on a BYO provider key, web/vision drop out - they need an account - but the full coding tool set stays.)

Docker / CI#

Use a glibc base image (e.g. debian) - bun-linux-x64 is not built for musl (Alpine).

bash
docker run --rm \
  -e GOOSE_API_KEY \
  -v "$PWD:/work" -w /work \
  debian:stable-slim \
  ./goose-linux-x64 -p "fix the failing test"

The binary extracts its embedded ripgrep into the data directory on first run - no external ripgrep is needed in the container.

An example CI step that fails on an agent error:

bash
goose -p --max-turns 12 --output-format json "make the test suite pass" \
  | tee result.json | jq -e '.is_error | not' > /dev/null

Troubleshooting#

No credentials for model "…"
no account key is set. Create one on the goosecode.org website or in the desktop app (Settings → API Keys) and export GOOSE_API_KEY=gsk_live_…, or pass --api-key. Quick check without a key: -m goose-local. A raw OpenAI/OpenRouter key won't do in a public build - only in an eval build.
Web search / images don't work
this needs an account key (gsk_live_…).
index disabled - use Grep/Glob/Read
the code index is off (--no-code-index, or a build without grammars). The agent works fully via Grep/Glob/Read.
Colors clutter CI logs
NO_COLOR=1 (or just write to a pipe/file - colors turn off automatically outside a TTY).
goose open says Electron is missing
the command only works next to an installed app; it's absent from the standalone binary.
// get the binary

Ready to run it in your terminal?

Grab the standalone binary or the desktop app - no API keys required.

Download