Goose is an AI agent that runs tasks on your machine, and its history makes it worth studying: it started at Block, the payments company, as an engineer’s coding and operations assistant, and it now lives with the Agentic AI Foundation under the Linux Foundation as the aaif-goose/goose repository. The pitch is breadth with control: the README says it works with 15+ providers including Anthropic, OpenAI, Google, Ollama, OpenRouter, Azure, and Bedrock, it can use your existing Claude, ChatGPT, or Gemini subscriptions through the ACP protocol, and it connects to 70+ extensions through the Model Context Protocol. The whole thing is Apache-2.0 Rust, organized as a workspace of crates you can read end to end.
What makes the codebase interesting is that it treats automation as a first-class product, not an afterthought. Beyond the interactive CLI and the desktop app, there is a recipe format for parameterized repeatable runs, a scheduler for timed jobs, session storage you can list, resume, and export as markdown, JSON, or YAML, and hooks, hints, and skills for tailoring behavior per project. The agent core in the goose crate powers all the surfaces, so the CLI, the desktop app, and the SDK build on the same loop rather than three divergent implementations.
As always in this series, this is an educational tour of published source code. Goose reads your files, runs commands, and drives other tools with model guidance, and the project pairs that power with a permission engine, security checks, and confirmation routing for a reason. Run it on projects you own, read the approval prompts it shows you, and treat its guardrails as part of the lesson, because a Rust agent that wants to be embedded everywhere has to earn that trust in its design.
Goose at a glance: CLI, desktop, and SDK surfaces converge on one core crate, which runs an agent loop over MCP extensions, provider backends, and the ACP bridge, under a permission gate.
Reading the overview from left to right:
- The binary starts at crates/goose-cli/src/main.rs, with argument parsing in crates/goose-cli/src/cli.rs.
- The desktop application lives under ui/desktop, and the embeddable library ships as crates/goose-sdk.
- All three surfaces drive the core crate whose entry is crates/goose/src/lib.rs.
- The agent loop itself is organized under crates/goose/src/agents, the heart of the system.
- Capabilities arrive as MCP extensions from crates/goose-mcp, and model calls route through crates/goose-providers.
- Subscription-based providers connect via the ACP bridge at crates/goose/src/acp.
- Automation comes from the recipe engine at crates/goose/src/recipe and timed jobs in crates/goose/src/scheduler.
- Every conversation is persisted in the session store at crates/goose/src/session, and tool calls pass the permission engine at crates/goose/src/permission.
Why You Need This
The first reason is provider freedom in both directions. Most agent tools lock you into one vendor’s API key, and the ones that escape that trap usually stop at APIs. Goose supports the usual cloud providers, local models through Ollama, and, more distinctively, subscription logins through ACP, so a Claude, ChatGPT, or Gemini plan you already pay for can drive the agent. The provider implementations live in plain sight under crates/goose-providers, which means you can read exactly how requests, retries, and streaming differ between vendors, a comparison most projects keep behind their walls.
The second reason is the extension story. Goose speaks MCP, the open standard for connecting agents to external tools, and it treats extensions as the primary way to grow. The repository bundles several in crates/goose-mcp, including a computer controller, a memory extension, and others, and anything else attaches at runtime through the same protocol. Because the agent core talks to bundled and external capabilities through one client abstraction, you can add a server on Friday and the agent treats it like it shipped with the product. If you want a reference implementation for how to make an agent extensible without forking it, this is it.
The third reason is operational maturity. Recipes give you parameterized, repeatable runs you can share; the scheduler runs jobs on a schedule without external cron plumbing; sessions persist to disk and export to markdown, JSON, or YAML for review or archiving; hooks and hints let a repository describe how the agent should behave inside it. That combination is what turns a demo into infrastructure, and the fact that all of it is one Rust workspace means you can trace a single task from CLI argument to provider request without leaving the repo.
How It Works
Inside Goose: the CLI package, agent internals with their helper managers, bundled extensions and providers, the control stack around every tool call, and the session, scheduler, and recipe machinery.
Understanding the Architecture
A CLI that stays thin. The goose-cli crate starts at main.rs and hands off to cli.rs for argument parsing, then to the command modules under crates/goose-cli/src/commands. Interactive sessions, scripted runs, configuration, and session management each get their own module, with dedicated subcommands for sessions in crates/goose-cli/src/session and recipes in crates/goose-cli/src/recipes. The CLI orchestrates and displays; it does not implement agent behavior itself, which is why the desktop app and SDK can match it feature for feature.
One agent loop, many helpers. The runtime in crates/goose/src/agents/agent.rs owns the conversation turn: it assembles prompts through prompt_manager.rs, picks and routes models through provider_manager.rs, connects to extension servers through mcp_client.rs, and executes tool calls through tool_execution.rs. A subagent_handler.rs supports delegation for heavier work, and a tool_confirmation_router.rs intercepts risky calls so a human can approve them. A builtin_extension.rs presents the agent’s own native capabilities through the same interface as external MCP servers, keeping the tool surface uniform.
Bundled extensions and a wide provider bench. The goose-mcp crate ships ready-to-use extension servers, including the computer controller in crates/goose-mcp/src/computercontroller for system interactions and the memory extension in crates/goose-mcp/src/memory for cross-session recall. On the model side, crates/goose-providers implements each vendor separately, with anthropic.rs and ollama.rs as readable examples of how hosted and local backends differ. The ACP support in crates/goose/src/acp bridges subscription plans, which is why the README can promise your existing Claude or ChatGPT login works.
Control wrapped around every call. The permission engine at crates/goose/src/permission applies rules about which tools may run and when, backed by security checks in crates/goose/src/security, and the confirmation router turns uncertain cases into explicit approvals. Context shaping gets its own machinery: the hints loader in crates/goose/src/hints reads project-level .goosehints instructions, skills in crates/goose/src/skills load packaged expertise, hooks in crates/goose/src/hooks expose lifecycle events, and context management in crates/goose/src/context_mgmt keeps long sessions within limits. None of these are bolt-ons; the agent loop calls into each of them per turn.
State that outlives the process. Session storage in crates/goose/src/session/session_manager.rs persists every conversation so you can resume or export it later, and the scheduler in crates/goose/src/scheduler triggers agent runs on a timer. The recipe engine at crates/goose/src/recipe loads parameterized run definitions, and the repository’s workflow_recipes directory collects community-contributed templates to start from. The desktop app under ui/desktop embeds its own ACP server, ui/goose-acp, so the GUI drives the same agent runtime the CLI uses.
Advantages
- Provider flexibility with subscriptions. 15+ providers, local models via Ollama, and ACP logins for Claude, ChatGPT, or Gemini plans mean you are never locked into one billing model.
- MCP-native extensibility. 70+ extensions connect through the Model Context Protocol, and bundled examples in goose-mcp show exactly how to write your own.
- True multi-surface architecture. CLI, desktop app, and SDK share one agent core, so behavior is consistent no matter where you drive it from.
- Automation built in. Recipes parameterize repeatable runs and the scheduler triggers them on time, with no external glue required.
- Durable, exportable sessions. Conversations persist to disk and export to markdown, JSON, or YAML, which makes audits and handoffs straightforward.
- Honest safety layering. Permission rules, security checks, and confirmation routing are separate modules you can read and tighten.
Benefits
- Readable Rust workspace. Crates split by responsibility, so you can study the agent loop, a provider, or an extension server in isolation.
- Foundation governance. As an Agentic AI Foundation project, the roadmap and contributions are community-driven rather than tied to one company’s product cycle.
- Project-aware behavior. .goosehints files, skills, and hooks let a repository teach the agent its conventions without code changes.
- Cross-session memory. The bundled memory extension gives the agent recall between sessions, a practical pattern for long-running collaborations.
- Scriptable end to end. Output formats for scripted runs, exportable sessions, and parameterized recipes make the agent a component in larger automation, not just a chat window.
- License and transparency. Apache-2.0 code with no hidden server component means what you read is what you run.
Usage
Install the CLI with the script from the README:
curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | bash
Check the install and run first-time setup, which walks through provider and extension configuration:
goose --version
goose configure
Start an interactive session in your project directory:
goose session
Give the agent a one-shot instruction, or point it at a full instruction file for bigger jobs:
goose run -t "Summarize the TODO items in this repository and open an issue for each"
goose run -i instructions.txt
Run a parameterized recipe, resume an earlier conversation, or export a session for review:
goose run --recipe my_recipe.yaml --params target=src/
goose session --resume
goose session list
goose session export --format markdown
Inspect your setup or update the binary when a new release lands:
goose info
goose update
Conclusion
Goose earns its place in this series by showing what an agent looks like when extensibility and automation are the product instead of features bolted on later. One Rust agent core serves a terminal, a desktop app, and an SDK; MCP makes the capability surface unbounded; recipes, the scheduler, and exportable sessions make it dependable enough to put in a workflow; and the permission and confirmation layers keep the leash attached even when the model is clever. Read it for the provider abstraction, the extension client, or the recipe format, and you will leave with patterns worth stealing for any agent you build.
Links:
Enjoyed this post? Never miss out on future posts by following us