Skip Navigation

Scott Spence

Setting Up Codename Goose in WSL

10 min read

Ok, so, I’ve heard about this CLI tool that allows you to use your preferred LLM provider, Goose, from Block (Square, payment thingy) which I think is officially called codename goose, but we all know everyone is going to refer to it as Goose. Anyway, Goose will allow you to run commands and interact with your computer and also use Model Context Protocol (MCP) tools.

So, super quick pre-amble there but essentially getting set up with Goose (as a WSL user) wasn’t as straight forward as I hoped.

Install Goose

These instructions will be going through the install on a fresh Ubuntu 24.04 install on WSL.

The installation for goose is essentially Linux, there’s Windows instructions but it’s to use WSL.

I want to make sure I’m all up to date first:

sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y

I’ll open a new WSL terminal without sudo permissions applied and keep the sudo terminal open for the next steps.

I’ll run the install script.

curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | bash

This will attempt to install the CLI but there’s a missing dependency, here’s the output.

$ curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | bash
Downloading stable release: goose-x86_64-unknown-linux-gnu.tar.bz2...
Extracting goose-x86_64-unknown-linux-gnu.tar.bz2...
tar (child): bzip2: Cannot exec: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now

So, there’s a missing dependency bzip2 I’ll install the missing dependency now in the terminal with sudo permissions:

sudo apt install bzip2

I’m now allowed to continue with the CLI setup!

$ curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | bash
Downloading stable release: goose-x86_64-unknown-linux-gnu.tar.bz2...
Extracting goose-x86_64-unknown-linux-gnu.tar.bz2...
Creating directory: /home/username/.local/bin
Moving goose to /home/username/.local/bin/goose

Configuring Goose


Welcome to goose! Let's get you set up with a provider.
  you can rerun this command later to update your configuration

┌   goose-configure
│
◆  Which model provider should we use?
│  ○ Anthropic
│  ○ Azure OpenAI
│  ○ Databricks
│  ○ Google Gemini
│  ○ Groq
│  ○ Ollama
│  ○ OpenAI
│  ● OpenRouter (Router for many model providers)

I’m going to go with OpenRouter for now as I can pick which model I want to use, I’ll be using anthropic/claude-3.5-sonnet for now.

So, now I’m prompted to add my OpenRouter API key.

Configuring Goose


Welcome to goose! Let's get you set up with a provider.
  you can rerun this command later to update your configuration

┌   goose-configure
│
◇  Which model provider should we use?
│  OpenRouter
│
◆  Provider OpenRouter requires OPENROUTER_API_KEY, please enter a value
│
└

Paste in my OpenRouter API key, hit enter and get this:

  Error Failed to access secure storage (keyring): Platform secure storage failure: DBus error: The name org.freedesktop.secrets was not provided by any .service files
  Please check your system keychain and run 'goose configure' again.
  If your system is unable to use the keyring, please try setting secret key(s) via environment variables.

Warning: Goose installed, but /home/username/.local/bin is not in your PATH.
Add it to your PATH by editing ~/.bashrc, ~/.zshrc, or similar:
    export PATH="/home/username/.local/bin:$PATH"
Then reload your shell (e.g. 'source ~/.bashrc', 'source ~/.zshrc') to apply changes.

So keyring (what’s in the failure message) is part of Gnome, that’s present in the full Ubuntu GUI install, it’s not part of the WSL install.

I’m going to need to do this via environment variables!

API Key Management

Ok, so… remember my post about speeding up my zsh shell? Probably not I only posted it the other day, but it has some swish bits in there for loading the SSH agent! I’m using that same approach for managing API keys securely.

You don’t have to follow this! Add your keys directly into your shell config if you like, I’m writing this for future Scott essentially!

All the keys I want to use in Goose I’ll add to a ~/.goose_keys file, this could alternately go into a ~/.config/api-keys file but I like things in home so I can poke around in there without having to go digging elsewhere.

touch ~/.goose_keys
chmod 600 ~/.goose_keys

Then add in my key and the environment-specific configuration:

# Make sure to chmod 600 this file after creation

# OpenRouter API configuration
export OPENROUTER_API_KEY="secret-key-here"

Great! I’ll update my current .zshrc config to load the keys:

# Lazy load API keys and sensitive configurations
function _load_api_keys() {
    if [ -f ~/.goose_keys ]; then
        if [ "$(stat -c %a ~/.goose_keys)" != "600" ]; then
            echo "Warning: ~/.goose_keys has incorrect permissions. Run: chmod 600 ~/.goose_keys"
        else
            source ~/.goose_keys
        fi
    fi
}

autoload -U add-zsh-hook
add-zsh-hook precmd _load_api_keys

Now if I try the goose configure command I get this:

$ goose configure

Welcome to goose! Let's get you set up with a provider.
  you can rerun this command later to update your configuration

┌   goose-configure
│
◇  Which model provider should we use?
│  OpenRouter
│
●  OPENROUTER_API_KEY is set via environment variable
│
◆  Would you like to save this value to your keyring?
│  ○ Yes  / ● No
└

I’ll pick No, because there’s no keyring! Then I’m prompted for the model I want to use, the default is listed.

$ goose configure

Welcome to goose! Let's get you set up with a provider.
  you can rerun this command later to update your configuration

┌   goose-configure
│
◇  Which model provider should we use?
│  OpenRouter
│
●  OPENROUTER_API_KEY is set via environment variable
│
◇  Would you like to save this value to your keyring?
│  No
│
◆  Enter a model from that provider:
│  anthropic/claude-3.5-sonnet (default)

I’ll hit enter to accept the default.

Then a last little confirmation:

◐  Checking your configuration...
└  Configuration saved successfully

Looks like I’m all set!

To start a Goose session it’s goose session then I’m set to start using it!

$ goose session
starting session | provider: openrouter model: anthropic/claude-3.5-sonnet
    logging to /home/username/.config/goose/sessions/iNy1kNmS.jsonl

Goose is running! Enter your instructions, or try asking what goose can do.

( O)>

Sweet! One last thing now is to check out what’s been configured, you may have seen references to where the config is: /home/scott/.config/goose/config.yaml

I’ll pop that open now to check out what’s in there:

GOOSE_MODEL: anthropic/claude-3.5-sonnet
GOOSE_PROVIDER: openrouter
extensions:
  developer:
    enabled: true
    name: developer
    type: builtin

And right now, that’s not much!

What comes in the box? 📦

Ok, so Goose comes with some built-in extensions:

  1. Developer: Your basic dev tools - this one’s on by default
  2. Computer Controller: For web scraping and automation stuff
  3. Memory: Helps Goose remember your preferences
  4. JetBrains: For those IDE fans out there
  5. Google Drive: File management with Google Drive

The Developer extension is enabled by default, I want to enable the Computer Controller and Memory now using the goose configure command:

$ goose configure

This will update your existing config file
  if you prefer, you can edit it directly at /home/scott/.config/goose/config.yaml

┌   goose-configure
│
◆  What would you like to configure?
│  ○ Configure Providers
│  ○ Toggle Extensions (Enable or disable connected extensions)
│  ● Add Extension
└

Goose configure you’d think to enable existing extensions it’d be toggle extensions but it’s not add extension, then built in extension.

┌   goose-configure
│
◇  What would you like to configure?
│  Add Extension
│
◆  What type of extension would you like to add?
│  ● Built-in Extension (Use an extension that comes with Goose)
│  ○ Command-line Extension
│  ○ Remote Extension
└

Now, instead of allowing me to select individual extensions to enable, all I can do is select one at a time then go through the config again for the next one! So, I’ll select the Computer Controller extension first:

┌   goose-configure
│
◇  What would you like to configure?
│  Add Extension
│
◇  What type of extension would you like to add?
│  Built-in Extension
│
◆  Which built-in extension would you like to enable?
│  ○ Developer Tools
│  ● Computer Controller (controls for webscraping, file caching, and automations)
│  ○ Google Drive
│  ○ Memory
│  ○ JetBrains
└

the CLI confirms it’s enabled then I’m back in the terminal!

If you know which extensions you want it’s quicker to edit the /home/username/.config/goose/config.yaml file directly!

This is for me next time so I can copy and paste the config from this post!

GOOSE_PROVIDER: openrouter
GOOSE_MODEL: anthropic/claude-3.5-sonnet
extensions:
  computercontroller:
    enabled: true
    name: computercontroller
    type: builtin
  developer:
    enabled: true
    name: developer
    type: builtin
  memory:
    enabled: true
    name: memory
    type: builtin

You can check out the Goose extensions page where you can see some of the built in extensions and how to install other extensions.

The thing that got me excited about using Goose was the possibility to use your own extensions (MCP tools!) I’ve made some of my own MCP tools, you can see them on my GitHub or read about using them with Claude Desktop in my Using MCP Tools with Claude and Cline post.

Adding in my own MCP tools

So, I have a few MCP tools I’ve built that I like to use (you can see them here on GitHub if you like) the thing is, the config I’m used to for Claude Desktop and Cline is JSON but the config for Goose is YAML.

You can add in a MCP tool via the Goose CLI or just add them directly to the config file. There’s an example of the config on the Goose docs

I’ll follow that format and add them directly to the config file:

GOOSE_PROVIDER: openrouter
GOOSE_MODEL: anthropic/claude-3.5-sonnet
extensions:
  computercontroller:
    enabled: true
    name: computercontroller
    type: builtin
  developer:
    enabled: true
    name: developer
    type: builtin
  memory:
    enabled: true
    name: memory
    type: builtin
  mcp-tavily-search:
    name: mcp-tavily-search
    cmd: npx
    args: [-y, mcp-tavily-search]
    enabled: true
    envs: { 'TAVILY_API_KEY': 'key-here' }
    type: stdio
  mcp-perplexity-search:
    name: mcp-perplexity-search
    cmd: npx
    args: [-y, mcp-perplexity-search]
    enabled: true
    envs: { 'PERPLEXITY_API_KEY': 'key-here' }
    type: stdio
  mcp-jinaai-search:
    name: mcp-jinaai-search
    cmd: npx
    args: [-y, mcp-jinaai-search]
    enabled: true
    envs: { 'JINAAI_API_KEY': 'key-here' }
    type: stdio
  mcp-jinaai-grounding:
    name: mcp-jinaai-grounding
    cmd: npx
    args: [-y, mcp-jinaai-grounding]
    enabled: true
    envs: { 'JINAAI_API_KEY': 'key-here' }
    type: stdio
  mcp-jinaai-reader:
    name: mcp-jinaai-reader
    cmd: npx
    args: [-y, mcp-jinaai-reader]
    enabled: true
    envs: { 'JINAAI_API_KEY': 'key-here' }
    type: stdio
  mcp-svelte-docs:
    name: mcp-svelte-docs
    cmd: npx
    args: [-y, mcp-svelte-docs]
    enabled: true
    type: stdio
  mcp-brave-search:
    name: mcp-brave-search
    cmd: npx
    args: [-y, '@modelcontextprotocol/server-brave-search']
    enabled: true
    envs: { 'BRAVE_API_KEY': 'key-here' }
    type: stdio
  mcp-memory-libsql:
    name: mcp-memory-libsql
    cmd: npx
    args: [-y, mcp-memory-libsql]
    enabled: true
    envs: { 'LIBSQL_URL': 'file:/home/scott/repos/memory-tool.db' }
    type: stdio
  mcp-sequentialthinking-tools:
    name: mcp-sequentialthinking-tools
    cmd: npx
    args: [-y, mcp-sequentialthinking-tools]
    enabled: true
    type: stdio
  mcp-wsl-exec:
    name: mcp-wsl-exec
    cmd: npx
    args: [-y, mcp-wsl-exec]
    enabled: true
    type: stdio

Ok, I’m now set up with the built-in extensions and my own MCP tools!

I’m still exploring Goose’s features and practical use, so, still early days, from what I can glean from interactions is that it’s claude desktop in the terminal 😂

The specific Goose features I’m still trying out, like iterating on something in the terminal and a code editor.

What’s Next? 🚀

Ollama, I’ve downloaded DeepSeek model and tried that out with Goose but it’s not compatible there appears to be people working on deepseek-goose-models so I’ll be taking a look at that at some point.

That’s it! I’mm going to give this a good crack now and try incorporate it into my workflow!

Quick Reference

This is for me when I need to come back to this!!

  • Config location: ~/.config/goose/config.yaml
  • API keys: ~/.goose_keys
  • Permissions:
    • Key files: chmod 600

List of Goose commands:

# Session Management
goose session                         # Start a new chat session
goose session -r                      # Resume the last session
goose session -n test                 # Start a new session named "test"
goose session -r -n test              # Resume a specific session named "test"

# Extension Management
goose session --with-builtin name     # Add a builtin extension by name
goose session --with-extension 'cmd'  # Add a custom extension using command

# Configuration
goose configure                       # Configure Goose settings

# Other Commands
goose agents                          # List available agent versions
goose run                             # Execute commands from instruction file/stdin
goose help                            # Show help message
goose help <command>                  # Show help for specific command

# Version
goose -v                              # Show version information

This reference covers the main commands available in Goose. Each command also has additional options that can be viewed using goose <command> --help for more detailed information.

That’s it! Hope this helps if you’re setting up Goose on WSL!

There's a reactions leaderboard you can check out too.

Copyright © 2017 - 2025 - All rights reserved Scott Spence