# Goose AI Coding Assistant: 12 Steps, 70 Min [2026]

> Source: <https://shattered.io/goose-ai-coding-assistant-local-ollama-12-steps-2026/>
> Published: 2026-11-10 23:23:45+00:00

Goose is a free, Apache-2.0 coding agent that now sits under the [Agentic AI Foundation](https://aaif.io/about) at the Linux Foundation, and it can drive a model running on your own laptop with no API bill attached. The foundation launched in December 2025 with three founding projects (MCP, Goose and AGENTS.md) and grew to 10 hosted projects and 305 member organizations by October 22, 2026. That backing makes Goose one of the more durable picks among open-source AI coding assistants, and it explains why searches for the category keep climbing.

The pull toward local setups is easy to explain. In the 2025 Stack Overflow Developer Survey, 84% of respondents said they use or plan to use AI tools. Developers want an agent that edits files and runs tests, but many teams will not ship source code to a third-party API to get one. Running the model locally removes that objection, at the price of some setup work and a hardware budget.

Goose handles that setup well because it treats the model as a swappable part. Point it at Ollama and a local coding model and it reads files, runs shell commands, edits code and re-runs tests inside a terminal session or a desktop window. If you would rather live in a terminal agent with a longer provider list, the [OpenCode and Ollama setup](https://shattered.io/open-source-ai-coding-assistant-opencode-ollama-2026/) covers that route. The twelve steps below build the Goose route from a blank machine to a working Python project, a reusable recipe and a guarded wrapper script.

Don't miss new tech stories on Google

Add Shattered once in the Google app and our stories show up in your news suggestions.

[Add now](https://www.google.com/preferences/source?hl=en&q=https%3A%2F%2Fshattered.io%2F)

## Goose as an Open-Source AI Coding Assistant in November 2026

Goose began as a Block project and moved into the Agentic AI Foundation when the Linux Foundation formed it on December 9, 2025. Its GitHub home is now the aaif-goose organization. It describes itself as an open-source, extensible agent for installing, executing, editing and testing software, and it runs as a desktop application or a command-line tool on macOS, Linux and Windows. Goose is general purpose, so coding is one job among several, but the developer tooling is where most people start.

| Item | State as of November 10, 2026 | Why it matters for this setup | 
|---|---|---|
| License | Apache-2.0, free to use | Model, API and hardware costs are separate from Goose itself | 
| Stewardship | Agentic AI Foundation, Linux Foundation, since December 2025 | Vendor-neutral governance instead of a single company roadmap | 
| Repository | aaif-goose GitHub organization | Update old bookmarks and any scripts that point at the previous org | 
| Latest release | v1.58.0, released November 9, 2026 | Adds an opt-in context-relevance operation, context-window reporting and an AIHubMix provider | 
| Providers | More than 15 model providers, local models included | You can start local and add a hosted fallback later | 
| Local inference | Built-in llama.cpp option described in Linux Foundation material | Runs without Docker, Ollama or an API key | 
| Foundation scale | 10 hosted projects, 305 member organizations (October 22, 2026) | Signals the project has institutional support beyond one maintainer | 

Two version notes keep you out of trouble. First, one current index lists a v1.58.1 dated November 10, 2026, which conflicts with the official release page showing v1.58.0 from November 9. Either build works for everything below, so check `goose --version` and move on. Second, Goose’s blog carries a post titled “goose 2.0 beta – new architecture and clients.” The steps here target the stable 1.x command-line client. If you install the 2.0 beta, menus and screens will differ from the ones described.

Agents are still a minority habit, which is worth remembering before you sell the idea to a team. In the [2025 Stack Overflow Developer Survey](https://stackoverflow.co/company/press/archive/stack-overflow-2025-developer-survey/), “Only 31% of developers reported currently using AI agents, while 38% said they did not plan to use them.” The same survey found that “Among developers who had used AI agents at work, 69% agreed that the agents had increased their productivity.” Those numbers describe 2025 behavior, so treat them as a floor. Analysts expect the curve to keep bending, and [Gartner](https://www.gartner.com/en/newsroom/press-releases/2025-07-01-gartner-identifies-the-top-strategic-trends-in-software-engineering-for-2025-and-beyond) put it this way in 2025: “Gartner predicted that 90% of enterprise software engineers will use AI code assistants by 2028, up from fewer than 14% in early 2024.”

Goose competes with a crowded field. Aider pairs tightly with git and commits each change, which the [Aider local setup guide](https://shattered.io/aider-local-ai-coding-assistant-ollama-git-2026/) walks through. OpenHands runs tasks inside a Docker sandbox, which the [OpenHands local setup](https://shattered.io/openhands-local-setup-agent-canvas-ollama-12-steps-2026/) covers. Goose sits in the middle: a terminal and desktop agent with a plugin model built on MCP, a recipe system for repeatable jobs and a growing set of provider integrations.

## Prerequisites and Versions

Install the pieces below before starting. The versions are the ones current on November 10, 2026. Newer patch releases should behave the same way.

| Component | Version or requirement | Check command | 
|---|---|---|
| Goose CLI | v1.58.0 (stable 1.x line) | `goose --version` | 
| Ollama | v0.40.16 or newer | `ollama --version` | 
| Python | 3.10 or newer | `python3 --version` | 
| Git | Any recent release | `git --version` | 
| pytest | Latest, installed in a virtual environment | `pytest --version` | 
| Operating system | macOS, Linux or Windows (Goose supports all three) | `uname -a` or`winver` | 
| Memory | At least the model’s download size, plus headroom for context | `ollama ps` after loading | 

Memory is the constraint that decides everything else. A model has to fit in GPU memory, or in unified memory on Apple Silicon, with room left for the context window. The download size shown on the model’s page in the Ollama library is your floor. Add a few gigabytes for the conversation, because coding agents stuff file contents and tool schemas into every request. If the model spills into system RAM, Ollama splits it across CPU and GPU and responses slow to a crawl.

Ollama is not the only local runtime, and Goose can also use LM Studio or its own built-in llama.cpp mode. The [comparison of Ollama, LM Studio, llama.cpp and vLLM](https://shattered.io/ollama-vs-lm-studio-vs-llama-cpp-vs-vllm-local-llm-runtimes-2026/) explains when each one makes sense. For a single developer on one machine, Ollama is the simplest because it manages downloads, quantized formats and the HTTP server in one place. Ollama’s own release notes also claim up to 90% faster performance for coding agents on Apple Silicon in version 0.31, measured with the Aider polyglot benchmark, which is a useful tailwind for Mac users.

You also need a terminal you trust and a scratch directory. Everything in this build lives in one folder called `tagcount`, and nothing touches your real repositories until you decide to point Goose at one. Create a fresh git repository for the project in Step 7 so you can always roll back what the agent does.

## Phase 1: Install the Local Model Stack (Steps 1 to 3)

### Step 1: Install Ollama and confirm the server answers

On macOS and Windows, download the installer from ollama.com. On Linux, the project publishes a one-line install script. After installing, confirm both the command-line tool and the background server respond.

```
# Linux (macOS and Windows users: use the installer from ollama.com)
curl -fsSL https://ollama.com/install.sh | sh

# Verify the CLI and the HTTP server
ollama --version
curl -s http://localhost:11434/api/version
```

The first command prints a version string. The second returns a small JSON object with the same number. If you see a version below 0.40.16, update before continuing, because tool-calling fixes land in the engine often and agents depend on them. A connection error here means the server is not running, which Step 3 fixes.

```
ollama version is 0.40.16
{"version":"0.40.16"}
```

### Step 2: Pull a model that supports tool calling

An agent is only as useful as its ability to call tools: read a file, write a file, run a command. Not every model on Ollama supports that, and a model that cannot will chat politely and never touch your code. For this build, pull Qwen3-Coder, the coding family from Alibaba’s Qwen team. Ollama’s blog says its Qwen3-Coder-30B build was updated for faster, more reliable tool calling in the new engine, which is exactly the property you need.

```
# Default pick for a workstation or a Mac with plenty of unified memory
ollama pull qwen3-coder

# Smaller fallback for tight memory (reported as the model used in a Goose local-setup workshop)
ollama pull qwen3:8b

# Confirm what is on disk
ollama list
```

The pull downloads several gigabytes, so start it and take a break. When it finishes, `ollama list` prints a table with the model name, an ID, the size on disk and a modified time. Note the exact name in the first column, tag included. Goose needs that string verbatim in Step 5. If you have the memory budget and want a second opinion model, OpenAI’s gpt-oss-20b is an Apache-2.0 open-weight option with tool-use and function-calling support, and you can pull it with `ollama pull gpt-oss:20b`.

### Step 3: Raise the context window and keep the server local

This step prevents the most common failure in local agent setups. Ollama serves models with a modest default context length, and an agent’s system prompt plus tool definitions can eat most of it before you type a word. When the window overflows, the oldest content falls off, usually the instructions that told the model how to call tools. The symptoms look like a dumb model, but the cause is a small buffer. Set the context length explicitly through the `OLLAMA_CONTEXT_LENGTH` variable and restart the server.

```
# Foreground, for a quick test
OLLAMA_CONTEXT_LENGTH=32768 ollama serve

# Linux with systemd: make it permanent
sudo systemctl edit ollama
#   add under [Service]:
#   Environment="OLLAMA_CONTEXT_LENGTH=32768"
sudo systemctl restart ollama

# macOS app: set the variable, then quit and reopen Ollama
launchctl setenv OLLAMA_CONTEXT_LENGTH 32768

# Smoke test, then check how the model loaded
ollama run qwen3-coder "Reply with the single word: ready"
ollama ps
```

The `ollama ps` output lists the loaded model, its size and the processor split. You want to see it fully on GPU, or on Apple’s unified memory. A split such as 40% CPU and 60% GPU tells you the context is too large for your memory, so lower it to 16384 or choose a smaller model. Also leave the bind address alone. Ollama listens on localhost by default, and that is the right setting for a single-user machine. If a teammate needs access, put an authenticated proxy in front of the port instead of opening it, as the [Ollama API key reverse proxy guide](https://shattered.io/ollama-api-key-reverse-proxy-docker-12-steps-2026/) shows.

## Phase 2: Install and Configure Goose (Steps 4 to 6)

### Step 4: Install the Goose CLI

The [Goose getting-started documentation](https://goose-docs.ai/docs/) lists the current install options for the desktop app and the command-line client. Copy the install command from that page rather than from a blog post, since URLs and package names changed when the repository moved to the aaif-goose organization. Homebrew users can also install the CLI formula directly.

```
# macOS or Linux with Homebrew
brew install block-goose-cli

# Any platform: use the install command printed on the official docs page, then:
goose --version
goose --help
```

Expect `goose --version` to report 1.58.0 or a later 1.x build. The `--help` output lists the subcommands you will use below: `configure`, `session`, `run` and `info`. If a subcommand is missing, you probably installed the 2.0 beta or a very old build. Reinstall the stable line before going on.

### Step 5: Point Goose at Ollama

Run the interactive configuration. It asks which provider to use, how to reach it and which model to call. Choose Ollama, accept the default host of `http://localhost:11434` and type the model name exactly as `ollama list` printed it. Goose stores the answers in a YAML file in your user config directory, and you can edit that file by hand later.

```
goose configure
#   1. Configure Providers
#   2. Pick: Ollama
#   3. Host: http://localhost:11434
#   4. Model: qwen3-coder

# Equivalent settings, usable in a shell profile or CI job
export GOOSE_PROVIDER=ollama
export GOOSE_MODEL=qwen3-coder
export OLLAMA_HOST=http://localhost:11434
```

Then enable the built-in developer extension, which gives the agent file editing and shell access. In the same `goose configure` menu, pick the option to add an extension, choose a built-in extension and select `developer`. Without it, Goose can talk but cannot change anything on disk. Goose also offers a built-in llama.cpp inference mode, described in Linux Foundation material, that needs no Docker, no Ollama and no API key. If your build shows that option in the provider list, it is a fine alternative for a machine where you do not want a separate server process.

### Step 6: Run a smoke test in an empty folder

Before touching real code, confirm the whole chain works in a throwaway directory. Start a session, ask for a trivial file operation and watch your approval prompts. Set the permission mode to approve so Goose asks before each action.

```
mkdir -p ~/scratch/goose-smoke && cd ~/scratch/goose-smoke
GOOSE_MODE=approve goose session

# At the prompt, type:
# Create hello.txt containing the word ready, then print the file back to me.
```

You should see Goose announce a tool call that writes the file and ask whether to allow it. Approve it. A second call reads the file back. The exact wording differs by model and Goose version, but the shape stays the same: a plan, a tool call, your approval, a result. Open a second terminal and run `ollama ps` while the session is active to confirm the model is loaded and on the processor you expect. If Goose answers in prose and never proposes a tool call, jump to the troubleshooting list, because the model or the extension is the likely culprit.

```
( shape of the output, wording will vary )
I'll create hello.txt and read it back.
  -> developer: write file hello.txt
  Allow this action? (yes / no)  yes
  -> developer: shell "cat hello.txt"
ready
Done. hello.txt now contains the word "ready".
```

## Phase 3: Build the Sample Project (Steps 7 and 8)

### Step 7: Create the tagcount repository with a planted bug

The working project is a small Python command-line tool called `tagcount`. It reads text or markdown files, finds hashtag-style tags and prints the most common ones. The code is deliberately tiny so you can read every change Goose makes, and it ships with one planted bug and one missing feature. Create the folder structure first, initialize git and set up a virtual environment.

```
mkdir -p tagcount/src/tagcount tagcount/tests tagcount/recipes tagcount/scripts
cd tagcount
git init
python3 -m venv .venv
. .venv/bin/activate
```

Add the packaging file, then the core module. The bug sits in the last line of `top_tags`: it asks for one fewer result than the caller requested.

```
# pyproject.toml
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"

[project]
name = "tagcount"
version = "0.1.0"
requires-python = ">=3.10"

[project.scripts]
tagcount = "tagcount.cli:main"

[tool.setuptools.packages.find]
where = ["src"]

[tool.pytest.ini_options]
testpaths = ["tests"]
# src/tagcount/__init__.py
"""tagcount: count #tags in text and markdown files."""

# src/tagcount/core.py
import re
from collections import Counter
from pathlib import Path

TAG_RE = re.compile(r"(?<!\w)#([A-Za-z][\w-]*)")

def extract_tags(text: str) -> list[str]:
    return [m.group(1).lower() for m in TAG_RE.finditer(text)]

def top_tags(paths, limit=5):
    counter = Counter()
    for path in paths:
        counter.update(extract_tags(Path(path).read_text(encoding="utf-8")))
    return counter.most_common(limit - 1)
python
# src/tagcount/cli.py
import argparse
import sys

from .core import top_tags

def build_parser():
    parser = argparse.ArgumentParser(prog="tagcount", description="Count #tags in text files.")
    parser.add_argument("files", nargs="+", help="text or markdown files")
    parser.add_argument("--limit", type=int, default=5, help="how many tags to show")
    return parser

def main(argv=None):
    args = build_parser().parse_args(argv)
    for name, count in top_tags(args.files, args.limit):
        print(f"{count:>4}  #{name}")
    return 0

if __name__ == "__main__":
    sys.exit(main())

# tests/test_core.py
from tagcount.core import extract_tags, top_tags

def test_extract_tags_ignores_headings():
    text = "# Title\nship #Python and #python-tools"
    assert extract_tags(text) == ["python", "python-tools"]

def test_top_tags_respects_limit(tmp_path):
    note = tmp_path / "a.md"
    note.write_text("#a #a #a #b #b #c #d", encoding="utf-8")
    assert top_tags([note], limit=3) == [("a", 3), ("b", 2), ("c", 1)]
```

Install the package in editable mode with pytest, run the tests and confirm the failure. Seeing the red test yourself matters, because it gives Goose a precise target and gives you a baseline to compare against.

```
pip install -e . pytest
pytest -q
.F                                                                       [100%]
=================================== FAILURES ===================================
_________________________ test_top_tags_respects_limit _________________________

    def test_top_tags_respects_limit(tmp_path):
        note = tmp_path / "a.md"
        note.write_text("#a #a #a #b #b #c #d", encoding="utf-8")
>       assert top_tags([note], limit=3) == [("a", 3), ("b", 2), ("c", 1)]
E       AssertionError: assert [('a', 3), ('b', 2)] == [('a', 3), ('b', 2), ('c', 1)]
E         Right contains one more item: ('c', 1)

tests/test_core.py:12: AssertionError
=========================== short test summary info ============================
FAILED tests/test_core.py::test_top_tags_respects_limit - AssertionError: ass...
1 failed, 1 passed in 0.03s
```

Commit this broken state so the agent’s work shows up as a clean diff: `git add -A && git commit -m "Initial tagcount with one planted bug"`. Add a `.gitignore` containing `.venv/` and `__pycache__/` first, or the commit will sweep up the virtual environment.

### Step 8: Give Goose project context and fence off secrets

Local models have small attention budgets compared with frontier hosted models, so a short, specific context file pays off. Goose reads a `.goosehints` file from the project root and feeds it to the model at the start of each session. Put the commands and conventions there that you would otherwise repeat in every prompt. AGENTS.md is the cross-tool equivalent, and since it is also an Agentic AI Foundation project, you can keep one file that several agents understand. A `.gooseignore` file lists paths the agent should not read or edit.

```
# .goosehints
Project: tagcount, a Python 3.12 CLI that counts #tags in text files.
Layout: src/tagcount/ holds code, tests/ holds pytest tests.
Run tests with: pytest -q   (the virtual environment is .venv)
Rules:
- Change only what the task needs. No new dependencies.
- Every behavior change needs a test in tests/test_core.py.
- Use the standard library only. Keep functions under 25 lines.
- Never edit pyproject.toml unless the task says so.

# .gooseignore
.venv/
.env
*.pem
secrets/
```

Keep the hints file under a page. Long instruction files crowd out the code in a limited context window, and small models follow short rules far better than long ones. Commit both files. You now have a project, a baseline failing test and an agent that knows the house rules.

## Phase 4: Let Goose Fix and Extend the Code (Steps 9 and 10)

### Step 9: Fix the failing test

Start a session in the project folder with approvals on. Give the task as a concrete goal with a verification command, not a vague wish. Small local models do best with one clear objective and an explicit finish line.

```
cd tagcount
GOOSE_MODE=approve goose session

# Prompt:
# The test test_top_tags_respects_limit fails. Run pytest -q, find the cause in
# src/tagcount/core.py, fix it with the smallest possible change, and run pytest -q again.
# Do not change any test.
```

A good run looks like this. Goose runs pytest, reads the traceback, opens `core.py`, spots that `most_common(limit - 1)` returns one item too few and proposes a one-line edit. Approve the edit and the follow-up test run. Do not skip the review. Exit the session and inspect the change with git before trusting it.

```
git diff

-    return counter.most_common(limit - 1)
+    return counter.most_common(limit)

pytest -q
..                                                                       [100%]
2 passed in 0.02s
```

Two things can go wrong here, and both teach something. If the model edits the test instead of the code, reject the change and repeat the prompt with the instruction not to touch tests (already included above, which is why it is there). If it rewrites the whole function, reject that too and tell it to make the smallest change. Commit the fix with a message that says what the agent did, so history stays honest about authorship.

### Step 10: Add a –json flag with a test

Now give Goose a feature request with several parts. This tests planning, since the agent has to touch the parser, the output path and the tests in a sensible order. Spell out the expected output format so the model has nothing to guess.

```
# Prompt:
# Add a --json flag to the tagcount CLI. With --json, print one JSON list of objects
# like [{"tag": "python", "count": 3}] and nothing else. Without it, keep the current
# text output. First write a failing test named test_cli_json in tests/test_core.py,
# then implement the flag, then run pytest -q until it passes.
```

Asking for the test first is a cheap way to keep the agent honest. It has to commit to the behavior before writing the code that satisfies it. The finished implementation should resemble the version below. Your model’s variable names may differ, and that is fine as long as the tests pass and the diff stays small.

``` python
# src/tagcount/cli.py (after the change)
import argparse
import json
import sys

from .core import top_tags

def build_parser():
    parser = argparse.ArgumentParser(prog="tagcount", description="Count #tags in text files.")
    parser.add_argument("files", nargs="+", help="text or markdown files")
    parser.add_argument("--limit", type=int, default=5, help="how many tags to show")
    parser.add_argument("--json", action="store_true", help="print JSON instead of text")
    return parser

def main(argv=None):
    args = build_parser().parse_args(argv)
    rows = top_tags(args.files, args.limit)
    if args.json:
        print(json.dumps([{"tag": name, "count": count} for name, count in rows]))
    else:
        for name, count in rows:
            print(f"{count:>4}  #{name}")
    return 0
printf '# Notes\n#python #python #testing\nship #goose and #Python\n' > sample.md

tagcount sample.md --limit 2
   3  #python
   1  #testing

tagcount sample.md --json
[{"tag": "python", "count": 3}, {"tag": "testing", "count": 1}, {"tag": "goose", "count": 1}]

pytest -q
...                                                                      [100%]
3 passed in 0.02s
```

All three tests pass and both output modes behave. Commit the result. If your local model stalls on a multi-part prompt, split it: one session for the test, another for the implementation. Goose sessions are cheap, and shorter conversations leave more context for the code.

## Phase 5: Automate and Harden the Workflow (Steps 11 and 12)

### Step 11: Capture a repeatable job as a recipe

Interactive sessions suit exploration. Repeated jobs suit recipes, which are YAML files that bundle instructions, a starting prompt and the extensions a task needs. A review recipe is a good first one because it is read-only in spirit and useful on every branch. This one asks Goose to review the staged git diff and report problems without editing anything.

```
# recipes/review.yaml
version: 1.0.0
title: Review staged diff
description: Read-only review of the staged git diff
instructions: |
  You are a careful code reviewer for a small Python project.
  Never edit files. Only read code and run read-only commands such as git diff --staged
  and pytest -q. Report findings as a short list ordered by severity.
prompt: |
  Run git diff --staged, read the changed files, run pytest -q, and report:
  1. bugs or missing tests, 2. risky changes, 3. one suggestion to simplify.
  If there is nothing staged, say so and stop.
extensions:
  - type: builtin
    name: developer
    timeout: 300
git add -A
goose run --recipe recipes/review.yaml

# One-off headless task without a recipe
goose run -t "Summarize what src/tagcount/core.py does in three bullet points"
```

The `run` subcommand starts a non-interactive pass, executes the task and exits, which makes it scriptable. Recipe fields and subcommand flags have shifted between Goose releases, so run `goose run --help` on your build and compare it with the example. If the recipe fails to parse, the error message names the offending field, and indentation is almost always the cause.

### Step 12: Wrap everything in a guarded launcher and a Makefile

The last step turns the setup into something a teammate can run without reading this page. The launcher checks that Ollama is alive and that the model is on disk, then exports the Goose settings and starts Goose. It keeps a separate URL variable because Ollama’s own `OLLAMA_HOST` means “bind address” for the server but “where to connect” for clients, and mixing the two causes confusing failures.

``` bash
#!/usr/bin/env bash
# scripts/goose-local.sh
set -euo pipefail

OLLAMA_URL="${OLLAMA_URL:-http://localhost:11434}"
MODEL="${GOOSE_MODEL:-qwen3-coder}"

if ! curl -sf "$OLLAMA_URL/api/tags" >/dev/null; then
  echo "Ollama is not answering at $OLLAMA_URL. Start it with: ollama serve" >&2
  exit 1
fi

if ! curl -sf "$OLLAMA_URL/api/tags" | grep -q "\"name\":\"$MODEL"; then
  echo "Model $MODEL is not pulled. Run: ollama pull $MODEL" >&2
  exit 1
fi

export GOOSE_PROVIDER=ollama
export GOOSE_MODEL="$MODEL"
export OLLAMA_HOST="$OLLAMA_URL"
export GOOSE_MODE="${GOOSE_MODE:-approve}"

exec goose "$@"
# Makefile  (recipe lines must start with a tab)
.PHONY: test review agent

test:
	. .venv/bin/activate && pytest -q

review:
	git add -A
	./scripts/goose-local.sh run --recipe recipes/review.yaml

agent:
	./scripts/goose-local.sh session
chmod +x scripts/goose-local.sh
make test
make review
make agent

# Final tree
tagcount/
  .goosehints
  .gooseignore
  .gitignore
  Makefile
  pyproject.toml
  recipes/review.yaml
  scripts/goose-local.sh
  src/tagcount/__init__.py
  src/tagcount/cli.py
  src/tagcount/core.py
  tests/test_core.py
```

Run `make test` first and expect three passing tests. Then run `make review` and confirm Goose reports on the staged diff without modifying files. If both work, the project is complete. The launcher defaults to approve mode on purpose. Switch to auto mode only inside a disposable container or a throwaway clone, never on a repository whose history you care about.

## Writing Prompts and Reviewing Changes Like a Maintainer

Local models reward discipline. A frontier model can often rescue a mushy request by guessing your intent. A 30B model running on a laptop usually cannot, and it will burn its small context budget wandering through your repository. Four habits close most of the gap. State the goal in one sentence. Name the files that matter. Give a command that proves success. Say what must not change. The prompts in Steps 9 and 10 follow that pattern, and you can reuse the skeleton for any task.

```
Goal: one sentence describing the end state.
Files: src/tagcount/core.py, tests/test_core.py
Proof: run `pytest -q` and stop when it passes.
Limits: no new dependencies, do not edit tests unless asked, smallest possible diff.
```

Review is the other half of the job. Treat every agent change as a pull request from a fast, tireless and occasionally overconfident junior. Read the diff before you read the explanation, because models describe their work more flatteringly than the code deserves. Check that tests changed only when you asked for test changes, that no unrelated files moved and that the change touches the smallest surface that solves the problem. Run the suite yourself, outside the agent session, so a stale cache or a quietly altered command cannot fool you.

Scope creep is the usual failure. Ask for a one-line fix and a chatty model may reformat the file, rename variables and add a helper nobody needs. Reject those diffs and say so plainly. Goose follows the rules in `.goosehints` better when you repeat the single most important one in the prompt itself, which is why the Step 9 prompt ends with “Do not change any test.” Over a week of use you will learn which instructions your chosen model ignores and which ones stick.

You can also measure instead of guessing. The script below runs one headless task against a model inside a disposable git worktree, so auto mode is safe, then prints the elapsed time and the final pytest line. Run it for each candidate model with the same task text and you get a rough speed and correctness comparison in a few minutes. It is crude, but it catches the common surprises, such as a model that finishes quickly by deleting the failing test.

``` bash
#!/usr/bin/env bash
# scripts/trial.sh MODEL "task text"
set -euo pipefail

model="$1"
task="$2"
repo="$(pwd)"
dir="$(mktemp -d)"

git worktree add -q "$dir" HEAD
cd "$dir"

start=$(date +%s)
GOOSE_PROVIDER=ollama GOOSE_MODEL="$model" GOOSE_MODE=auto goose run -t "$task" || true
end=$(date +%s)

echo "$model finished in $((end - start))s"
PYTHONPATH=src python3 -m pytest -q | tail -1
git diff --stat

cd "$repo"
git worktree remove --force "$dir"
```

Run it twice per model, since the first run pays the model loading cost. Compare the diffstat as well as the time. A model that fixes the bug with a two-line change beats one that rewrites the module in half the time, because you pay for the rewrite later during review. Log the numbers in a spreadsheet and you will have your own evidence the next time a new open-weight release tempts you to switch.

## Choosing a Local Model for Goose

Model choice changes results more than any Goose setting. Tool-calling reliability, context length and memory footprint pull against each other, and the right answer depends on your hardware. The table below lists the open-weight options with documented facts only. Check each model’s Ollama library page for the tags and download sizes available today, since libraries add and rename tags often.

| Model | Documented facts | Where it fits | 
|---|---|---|
| Qwen3-Coder (30B build) | Ollama says it was updated for faster, more reliable tool calling in its new engine | Default for this tutorial on a workstation or high-memory Mac | 
| Qwen3-Coder-Next | 80B total and 3B active parameters, 256K context window | Newest in the Qwen3-Coder family, so check the Ollama library for a runnable tag before planning around it | 
| Qwen3-Coder-480B-A35B | 480B total and 35B active parameters, 256K native context | Hosted or multi-GPU use, not a laptop | 
| gpt-oss-20b | OpenAI open-weight model, Apache-2.0, with tool use and function calling | Second opinion model when Qwen’s tool calls misfire | 
| gpt-oss-120b | Same release and license as the 20b model | Larger memory budgets or a shared inference server | 

For a broader view of which open-weight models lead on coding right now, the roundup of the [best open-source LLMs with Kimi, GLM and DeepSeek](https://shattered.io/best-open-source-llm-october-2026-kimi-glm-deepseek/) compares API prices and strengths. Those very large models mostly run through hosted endpoints, though, so a laptop setup lives in the smaller Qwen and gpt-oss tier. Teams that want a Qwen-first terminal agent should look at the [Qwen Code self-hosted setup](https://shattered.io/self-hosted-ai-coding-assistant-qwen-code-2026/), which pairs the same model family with its own purpose-built client.

A practical way to choose is to run the same three prompts against each candidate: the Step 9 bug fix, the Step 10 feature and a read-only repository summary. Time each run, note how many tool calls misfired and keep the winner. Ten minutes of that testing beats any leaderboard, because your repository, your prompt style and your hardware are the variables that matter. Keep the results in a note so you can re-run the same trio when a new model lands.

## How Goose Compares With Other Open-Source Assistants

No single open-source assistant wins every job, and the honest comparison is about working style. Goose favors a general-purpose agent with extensions and recipes. Aider favors a git-first pairing loop where every change becomes a commit. OpenCode favors a terminal-first interface with a very long provider list. Kilo Code and Cline live inside the editor. OpenHands favors autonomous tasks inside a container.

- **Pick Goose** when you want one agent for coding plus other chores, MCP-based extensions and shareable recipes, under neutral foundation governance.
- **Pick Aider** when you want tight git integration and small, reviewable commits as the default behavior.
- **Pick OpenCode** when you want a terminal agent with many providers and a model-agnostic design.
- **Pick an editor agent** such as the one in the[Kilo Code local setup](https://shattered.io/kilo-code-local-setup-ollama-vs-code-2026/) when you spend your day in VS Code and want diffs inline.
- **Pick a sandboxed agent** such as OpenHands when you want tasks to run unattended inside a container.

Teams comparing several of these tools should run a structured trial rather than argue from screenshots. The [team pilot method for AI coding assistants](https://shattered.io/best-ai-coding-assistants-team-pilot-12-steps-2026/) lays out a scoring harness you can reuse, and the same three-prompt test from the previous section slots straight into it. The tools overlap far more than their marketing suggests. What differs is how much friction each adds to the loop you actually repeat all day.

## Common Pitfalls

- **Leaving the default context length.** Tool definitions and file contents overflow a small window, the instructions fall off and the model forgets how to call tools. Set`OLLAMA_CONTEXT_LENGTH` as in Step 3 and confirm with`ollama ps` .
- **Using a model without tool calling.** The chat works and nothing ever changes on disk. Pick a model whose Ollama page lists tool support, and test with the Step 6 smoke test before real work.
- **Mixing up OLLAMA_HOST.** For the Ollama server it is a bind address, such as`0.0.0.0:11434` . For a client it is a URL. A bind address without a scheme breaks curl health checks, which is why the launcher uses a separate`OLLAMA_URL` .
- **Running auto mode on a real repository.** An agent that executes shell commands without asking can delete files or rewrite history. Keep approve mode on, work on a branch and commit before every session.
- **Following docs for the wrong major version.** The 1.x CLI and the 2.0 beta use different clients. Check`goose --version` before copying a command, and expect menus to differ if you installed the beta.
- **Asking for too much in one prompt.** Local models lose the thread on sprawling tasks. Split work into one goal per session, each with a verification command the agent can run.
- **Forgetting the ignore file.** Without a`.gooseignore` , the agent can read`.env` files and key material in the working tree and send that text to whichever provider you configured. With a local model the data stays home, but a later switch to a hosted provider would not.
- **Trusting a green test the agent wrote.** If the same session writes the test and the code, they can agree with each other and still be wrong. Review both and write your own edge cases.

## Troubleshooting

Most failures fall into a handful of patterns. Work through the list in order, since the early items cause the later symptoms.

1. **“Connection refused” from Goose.** The Ollama server is not running or listens elsewhere. Run`curl -s http://localhost:11434/api/version` . If it fails, start the server with`ollama serve` or restart the system service.
2. **“Model not found” or a 404 error.** The model name in Goose does not match the pulled tag. Run`ollama list` and copy the name exactly, including any tag after the colon.
3. **Ollama is missing from the provider list.** You may have a very old build or the 2.0 beta with a different menu. Run`goose --version` , reinstall the stable 1.x line and set`GOOSE_PROVIDER=ollama` by environment variable as a workaround.
4. **Goose replies in prose and never edits files.** Either the model lacks tool calling or the developer extension is off. Re-run`goose configure` , add the built-in developer extension and test with a different tool-capable model.
5. **The agent repeats the same tool call in a loop.** The context is probably full or the prompt is vague. Raise`OLLAMA_CONTEXT_LENGTH` , restart the session with a narrower goal and name the finish line, such as “stop when pytest -q passes.”
6. **The first response takes minutes.** The model is loading from disk or running partly on CPU. Run`ollama ps` , look at the processor split and lower the context or pick a smaller model. Setting a longer keep-alive avoids repeated reloads between prompts.
7. **The server dies with an out-of-memory error.** The model plus context exceeds available memory. Drop the context to 16384, close GPU-hungry apps or switch to the smaller fallback model from Step 2.
8. **The recipe will not parse.** Validate indentation first and run`goose run --help` for the fields your version expects. YAML block scalars (the lines after a pipe character) must be indented consistently.
9. **Goose asks permission for every harmless command.** That is approve mode working as designed. Move trusted, read-only tasks into a recipe, or use a smart-approve setting if your build offers one, and keep the strict mode for edits.
10. **It works in a shell but not inside WSL or a container.** The client cannot reach the host’s Ollama. Point`OLLAMA_URL` at the host address reachable from inside, and make sure the server binds to an interface the container can see. Secure that exposure with a proxy if the port leaves the machine.
11. **pytest cannot import tagcount.** The virtual environment is not active or the editable install is missing. Activate`.venv` and run`pip install -e .` again.

## Advanced Tips

**Trace what the agent does.** A Linux Foundation newsletter from October 2026 points to an Agentic AI Foundation tutorial for tracing Goose with OpenTelemetry, Jaeger and ClickHouse, including inspection of model and tool calls. Traces answer questions that logs cannot, such as which tool call burned the most time or where a loop began. Set that up before you roll Goose out to more than one person.

**Use the context tooling in v1.58.0.** The latest release adds context-window reporting and an opt-in context-relevance operation. On a local model with a tight window, seeing how full the context is tells you when to start a fresh session. Try the relevance operation on long-running sessions and compare how often the agent loses track of earlier decisions.

**Keep a hosted fallback.** Goose reportedly works with Anthropic, OpenAI, Google, Azure, Amazon Bedrock and OpenRouter, so a hard task your local model cannot finish can go to a frontier model with one environment change. Ollama itself added hosted models, and its pricing page lists $20 a month (or $200 billed annually) at its entry paid tier, with Team starting at $500 a month and $1,000 of usage credits shared across the team. Ollama has also moved its Pro, Max and Team plans to per-token pricing with usage included on every plan.

**Sandbox the agent.** One report says Goose v1.57.0 added macOS sandboxing and SLSA build provenance. Whether or not you rely on that, run auto-mode work inside a dev container or a disposable VM, mount only the project folder and keep credentials out of it. The agent can run any command you could, so treat it like a new contractor with shell access.

**Watch the ecosystem around Goose.** On October 22, 2026, the foundation added Agent Skills, Open Responses, OpenEnv and OpenSandbox, as [InfoQ reported from AGNTCon and MCPCon](https://www.infoq.com/news/2026/10/agntcon-mcpcon-2026/). OpenSandbox in particular points at where agent isolation is heading. Goose also has a Goose Development Kit, reportedly an open-source Rust SDK for building model-agnostic agentic apps that run locally. That matters if you want to embed the agent in your own tooling instead of using the stock client.

**Share the setup.** Commit `.goosehints`, recipes and the launcher script so everyone gets identical behavior, and keep personal provider settings out of the repository. Browse the [coding and developer tools coverage](https://shattered.io/category/software/) for adjacent tutorials on editor agents and code review.

## What Local Actually Costs and Protects

Goose and Ollama are free to download, so the real costs are hardware, electricity and your time. A machine that holds a coding model plus a large context is a real purchase if you do not own one already, and an always-on workstation adds a power bill. For a developer who already has a capable GPU or a Mac with generous unified memory, the marginal cost of local inference is close to zero. For a team that would need to buy hardware, a hosted plan can be cheaper than idle GPUs.

The privacy benefit is real but narrow. With a local model, prompts and file contents stay on your machine. That holds only for the model call itself. Extensions can make network requests, and any hosted provider you add later will see what you send it. Audit your extension list, keep secrets out of the working tree and record which provider each project uses. If a compliance team needs an answer, “local only” should be something you can verify with a firewall rule, not just a setting you remember choosing.

Expect the economics to keep shifting. Open-weight coding models improved quickly through 2026, hosted prices moved to per-token plans, and agent tooling now lives under neutral foundations rather than single vendors. A local setup built on open parts, as this one is, lets you swap any layer without rewriting your workflow.

## FAQ

### What is the best open source AI coding assistant?

No single tool wins for everyone. Goose suits developers who want a general-purpose agent with extensions and recipes, Aider suits git-centered pairing, and editor-based agents suit people who live in VS Code. Run the same three tasks through two or three candidates on your own code and keep the one that finishes them with the fewest corrections.

### Is Goose free to use?

Yes. Goose is Apache-2.0 licensed and the official results show no paid Goose plan. You still pay for whatever sits behind it: hardware and electricity for a local model, or per-token fees for a hosted provider.

### Can Goose work offline with a local model?

Yes, once everything is downloaded. Goose’s documentation says local models keep data private and support offline work. You need a connection to install Goose, install Ollama and pull the model. After that, a session against the local server needs no internet.

### Which Ollama model should I use with Goose?

Start with qwen3-coder if your memory allows it, since Ollama updated its 30B build for more reliable tool calling. Use a smaller model such as qwen3:8b on constrained machines, and try gpt-oss:20b as a second opinion. Whatever you pick, the model must support tool calling.

### Does Block still maintain Goose?

Goose began at Block and was contributed to the Agentic AI Foundation when the Linux Foundation formed it on December 9, 2025. The repository now lives under the aaif-goose organization. Governance sits with the foundation, which also hosts MCP and AGENTS.md.

### Can I run Goose headlessly in CI?

Yes. The `goose run` subcommand executes a task or a recipe and exits, which suits scripts. In CI, run it inside a disposable container, limit the working tree to the project and keep it read-only unless the job must edit files. A local model on a CI runner also needs enough memory, so many teams point CI at a hosted provider instead.

### Should I install the goose 2.0 beta instead?

Only if you want to test it. Goose’s blog describes the beta as a new architecture with new clients, so screens and commands will not match a 1.x tutorial. Use the stable 1.x line for work you depend on, and try the beta in a separate environment.
