cd /news/ai-tools/open-source-ai-coding-assistant-12-s… · home › topics › ai-tools › article
[ARTICLE · art-155683] src=shattered.io ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Open-Source AI Coding Assistant: 12 Steps, 60 Min [2026]

OpenCode 1.19.0, released October 11, 2026, ended automatic self-updates and made `opencode upgrade --major` the only path to OpenCode 2, according to Automater News, invalidating older tutorials that assumed the terminal coding agent would update itself. The change underpins a 12-step, roughly 60-minute setup guide that pairs a pinned OpenCode 1.x install with Ollama-served local models and a bring-your-own-key hosted model behind a one-word switch. The guide cites Stack Overflow's April 2025 analysis finding 61% of surveyed developers trust open-source AI for development work versus 47% for proprietary AI, and its 2025 survey finding 51% of developers building AI agents use Ollama.

by read33 min views2 publishedOct 22, 2026
Open-Source AI Coding Assistant: 12 Steps, 60 Min [2026]
Image: Shattered (auto-discovered)

OpenCode now makes you opt in to its next major version, and that single change reshapes how to set up an open source AI coding assistant this month. Release 1.19.0 landed on October 11, 2026, moved updates behind an explicit /update command, and added opencode upgrade --major as the only road to OpenCode 2, according to Automater News. Anyone who installed the tool in spring and trusted it to self-update is now running something different from what their old tutorial describes.

The setup below takes 12 steps and about 60 minutes. Ollama serves a coding model on your own hardware, OpenCode drives it from the terminal, and a bring-your-own-key hosted model waits behind a one-word switch for the hard tasks. Readers who prefer Alibaba’s agent can follow the separate self-hosted Qwen Code assistant build instead. The two stacks share the same local-model idea but differ in tooling, permissions and update behavior.

You finish with a working repository: a pinned OpenCode 1.x install, a local provider config, a locked-down permission policy, project rules, a review subagent, two wrapper scripts, and a passing test suite that the assistant itself extended. Every file is printed in full, so you can copy the project as is.

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

Why a Local-First Open Source AI Coding Assistant Makes Sense in 2026 #

Developers already trust open tooling more than the marketing around it suggests. In its April 2025 analysis of open-source AI, Stack Overflow reported that “61% of surveyed developers trust open-source AI for development work, compared with 47% who trust proprietary AI for the same work.” That gap explains why terminal agents that accept any model have outgrown the single-vendor assistants.

The runtime side tells the same story. Stack Overflow’s 2025 developer survey found that “Among developers building AI agents, 51% use Ollama, an open-source tool commonly used to run models locally.” So a stack built on Ollama is the default path, not an exotic one. Both figures date from 2025, which makes them a baseline rather than a fresh October reading.

OpenCode sits at the center of this shift. The project’s own website states: “OpenCode is 100% free to use. It also comes with a set of free models. There might be additional costs if you connect any other provider.” The client costs nothing. What you pay for is whatever model sits behind it, and that is exactly where a local-first design saves money. Routine edits, test runs and refactors go to a model on your own GPU for the price of electricity. Only the tasks that need a frontier model touch a metered API.

Privacy is the second reason. A local model never sends source code anywhere, which matters for client repositories, regulated environments and anything under an NDA. The catch, covered in the pitfalls section, is that the free models bundled with OpenCode run on its hosted service. They are convenient, but they are not local. A strict local-only policy means choosing your own Ollama model explicitly and staying away from those defaults.

Pricing pressure on the hosted side helps the hybrid approach too. OpenAI introduced GPT-6 Sol and GPT-6 Luna on October 21, 2026, and Google’s Gemini 4 Argon reached general availability on October 13 at an introductory rate. Cheap fallback models make a “local first, cloud when stuck” workflow affordable for most solo developers. The comparison of Claude Opus 5.5 and GPT-6 Astra on Terminal-Bench shows how large the quality gap at the top end still is, which is why keeping a hosted option wired in is worth the extra ten minutes.

The Stack: OpenCode, Ollama and a Bring-Your-Own-Key Fallback #

Three pieces make up this open source AI coding assistant, and each does one job. Ollama runs the model and exposes an OpenAI-compatible HTTP endpoint on your machine. OpenCode is the agent: it reads files, proposes edits, runs shell commands and talks to whatever endpoint you configure. The hosted provider is optional and sits behind an API key that never touches the config file.

OpenCode’s documentation lists support for more than 75 providers, plus any server that speaks the OpenAI-compatible protocol. That protocol is the glue. Because Ollama, LM Studio, llama.cpp and similar servers all expose the same /v1 routes, swapping the engine underneath never requires changing how the agent behaves. Other open-source agents, such as Aider, Cline, Goose and Kilo Code, can read the same endpoints, which keeps you from being locked into one front end.

The OpenCode release history matters for a pinned setup, so here is the timeline from the project’s official release notes. Version 1.19.0 added the upgrade path to OpenCode 2 and moved updates to the /update command in the terminal UI. Version 1.19.1 discontinued session sharing. Version 1.19.2 kept the 1.x line on 1.x builds. Version 1.19.3 added reasoning variants generated from a model’s reasoning options. Version 1.19.4, listed on October 22, 2026, upgraded the bundled Bun runtime to 1.4.4 with security fixes covering Brotli, TLS, HTTP/1.1, HTTP/2, HTTP/3, WebSocket and fetch.

Third-party trackers describe an OpenCode 2 line with a shared background service, code mode and background subagents. Reports on its exact version numbers conflict, and the official 1.x release page still labels v1.19.4 as the newest 1.x build. This tutorial therefore targets the 1.x line, which is documented and stable, and shows how to evaluate version 2 safely in a separate copy near the end. The four-day update cycle across Claude Code, Codex CLI and OpenCode is a good reminder that pinning, rather than chasing, keeps a working setup working.

Prerequisites and Versions #

Gather the following before you start. Versions reflect what was current on October 22, 2026, and anything marked pre-release should be avoided for a stable setup.

Component Version to use Notes
Ollama v0.40.8 (latest stable, October 21, 2026) v0.40.9 exists only as a pre-release, so skip it
OpenCode 1.19.x line (v1.19.4 listed as newest 1.x) Bundles Bun 1.4.4, so no separate Node or Bun install is needed
Local model Qwen3-Coder 30B via Ollama Ollama updated its tool calling for faster, more reliable results
Git Any recent 2.x release Lets you review and revert agent edits
Python 3.12 or newer For the sample project and pytest
Operating system Linux, macOS (Apple Silicon) or Windows with WSL Commands below use a POSIX shell
Hosted API key (optional) Anthropic, OpenAI or Google account Only for the cloud fallback in Step 7

On hardware, a 30B-class coding model at 4-bit quantization wants roughly 20 GB of free GPU memory or unified memory, and more if you raise the context window. A 24 GB NVIDIA card or an Apple Silicon Mac with 32 GB or more handles it. On smaller machines, pick a smaller coding model from the Ollama library and expect weaker multi-file edits. The steps work the same either way, because only the model name changes.

You also need about 25 GB of free disk space for the model files, a terminal you are comfortable in, and an hour of uninterrupted time. If you plan to use the hosted fallback, create a separate API key just for this tool. The security section explains why.

Phase 1: Run a Coding Model Locally (Steps 1 to 3) #

Step 1: Install Ollama and Confirm the Version

On Linux, Ollama’s installer script is the shortest route. On macOS and Windows, use the desktop installer from ollama.com. After installation, confirm the version and check that the background service answers.

curl -fsSL https://ollama.com/install.sh | sh
ollama --version
curl -s http://127.0.0.1:11434/api/version

You should see output close to this:

ollama version is 0.40.8
{"version":"0.40.8"}

If the second command prints nothing, the service is not running. On Linux, systemctl status ollama shows why. On macOS, open the Ollama app once so it starts the menu-bar service. Ollama has grown from a local runner into a hybrid platform with a paid cloud tier, so the installer may also offer you a sign-in. Skip it. Nothing in this tutorial needs an Ollama account.

Step 2: Pull a Tool-Capable Coding Model

An agent needs a model that supports tool calling, meaning it can emit structured requests like “read this file” or “run this command” instead of only chatting. Qwen3-Coder 30B is a solid default because Ollama updated its tool calling for speed and reliability. Pull it now. The download is large, so start it and read ahead while it runs.

ollama pull qwen3-coder:30b
ollama list

Two newer open models deserve a look once the basics work. Ollama lists NVIDIA Nemotron 3.5 Lightning, a 30 billion parameter model with 3 billion active parameters built for agents that keep running and calling tools. Ollama’s v0.40.8 release notes also reportedly add Recursive’s Apache-2.0 Flint coding model, with reasoning and multi-turn tool use. Treat the Flint details as unconfirmed until you check the model page, and benchmark any candidate on your own repository before switching.

Step 3: Raise the Context Window With a Modelfile

Coding agents stuff a lot into each request: system prompt, rules, file contents, tool results and history. A default context that is too small makes the model silently forget earlier turns, which looks like stupidity but is really truncation. Create a derived model with a larger window.

mkdir -p ~/oc-lab && cd ~/oc-lab
cat > Modelfile <<'EOF'
FROM qwen3-coder:30b
PARAMETER num_ctx 32768
EOF
ollama create qwen3-coder-32k -f Modelfile
ollama run qwen3-coder-32k "Reply with the single word: ready"

A larger window uses more memory, so watch ollama ps while the model is loaded. If the processor column shows a CPU share, the model has spilled out of GPU memory and generation will crawl. Drop num_ctx to 16384 or choose a smaller model before moving on. Finally, list the exact model ID the OpenAI-compatible endpoint reports, because OpenCode needs it character for character.

curl -s http://127.0.0.1:11434/v1/models | python3 -m json.tool | grep '"id"'

Expect a line like "id": "qwen3-coder-32k:latest". Write that string down, since Step 6 uses it.

Phase 2: Install OpenCode and Pin the 1.x Line (Steps 4 and 5) #

Step 4: Install OpenCode and Check Which Major Version You Got

The project’s install script works on Linux and macOS. Package managers carry OpenCode too, but the version they ship varies, and Homebrew Core reportedly tracks OpenCode 2 now. For a reproducible result, use the script and then verify what landed.

curl -fsSL https://opencode.ai/install | bash
opencode --version

The version line should start with 1.19. If it prints a 2.x number, you installed the new major line. That is a legitimate choice, but the config keys in this tutorial were written against 1.x, so reinstall a 1.x build or use the version-two evaluation steps in the advanced section. The project’s GitHub releases page is the authoritative source for the newest 1.x tag and its notes.

Two behaviors from recent OpenCode 1 releases change old habits. Updates no longer install themselves, so run /update inside the terminal UI when you want one. Session sharing is discontinued as of v1.19.1, which means guides that tell you to disable sharing in the config describe a feature that no longer exists.

Step 5: Create a Sample Repository for the Assistant to Work On

A small project with real tests gives the assistant a measurable job. Create a tiny expense-summary module and one passing test, commit it, and you have a clean baseline to diff against.

mkdir -p ~/oc-lab/ledgerlite && cd ~/oc-lab/ledgerlite
git init -q
python3 -m venv .venv && . .venv/bin/activate
pip install -q pytest

cat > ledger.py <<'EOF'
from collections import defaultdict

def summarize(rows):
    totals = defaultdict(float)
    for row in rows:
        totals[row["category"]] += row["amount"]
    return dict(totals)
EOF

cat > test_ledger.py <<'EOF'
from ledger import summarize

def test_summarize_groups_by_category():
    rows = [
        {"category": "food", "amount": 12.5, "date": "2026-10-01"},
        {"category": "food", "amount": 7.5, "date": "2026-10-02"},
        {"category": "rent", "amount": 900.0, "date": "2026-10-01"},
    ]
    assert summarize(rows) == {"food": 20.0, "rent": 900.0}
EOF

printf '.venv/\n__pycache__/\n.pytest_cache/\n' > .gitignore
python -m pytest -q
git add -A && git commit -qm "baseline"

The test run should end with 1 passed. Keep the virtual environment active in this terminal, because the assistant’s shell commands inherit it. Forgetting that is a classic cause of “pytest not found” errors later.

Phase 3: Wire Up Local and Hosted Providers (Steps 6 and 7) #

Step 6: Point OpenCode at the Local Ollama Endpoint

OpenCode reads a project-level opencode.json from the repository root. A custom provider needs four things: the OpenAI-compatible adapter package, a display name, the base URL, and a map of model IDs to labels. The official docs stress that each ID must match what the server returns from GET /v1/models, which is why Step 3 ended with that curl command.

cd ~/oc-lab/ledgerlite
cat > opencode.json <<'EOF'
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": {
        "baseURL": "http://127.0.0.1:11434/v1"
      },
      "models": {
        "qwen3-coder-32k:latest": {
          "name": "Qwen3-Coder 30B, 32k context (local)"
        }
      }
    }
  },
  "model": "ollama/qwen3-coder-32k:latest"
}
EOF
python3 -m json.tool opencode.json > /dev/null && echo "config is valid JSON"

Launch the terminal UI with opencode and run /models. The picker should list “Qwen3-Coder 30B, 32k context (local)” under the Ollama (local) provider, and the footer should show it as the active model. Type a short prompt such as “list the files in this project” to confirm the round trip. The first response is slow because Ollama loads the model into memory. Later turns are quicker.

The same pattern covers every other local server. Swap the base URL and the model map, and nothing else changes:

Local server Base URL How to list model IDs
Ollama http://127.0.0.1:11434/v1 curl http://127.0.0.1:11434/v1/models
LM Studio http://127.0.0.1:1234/v1 curl http://127.0.0.1:1234/v1/models
llama.cpp server http://127.0.0.1:8080/v1 curl http://127.0.0.1:8080/v1/models
Atomic Chat http://127.0.0.1:1337/v1 curl http://127.0.0.1:1337/v1/models

The last three ports come straight from OpenCode’s provider documentation examples. If another program already holds one of them, change the port in that program’s settings and mirror the change in baseURL. A silent port clash is one of the most common reasons a config that looks right still fails.

Step 7: Add a Bring-Your-Own-Key Hosted Model as the Fallback

Local models handle most routine work, but a hard multi-file refactor or an obscure framework bug is where a frontier model earns its price. OpenCode ships built-in support for the major vendors, so you do not add a provider block. You supply a key and pick a model. Keep the key in an environment variable rather than in opencode.json, so it can never end up in a commit.

export ANTHROPIC_API_KEY="paste-a-dedicated-key-here"

. ~/.config/oc-lab.env
opencode

Inside the UI, run /models and note the identifier the picker shows for the hosted model you want, in the form provider/model-id. Do not guess the string from a blog post, including this one. Model catalogs change weekly, and the picker is the one source that always matches your installed version. Export that string as OC_CLOUD_MODEL, because the wrapper in Step 11 reads it.

Which hosted model should sit in that slot? Prices shifted sharply in October, so compare current API rates before choosing. The table uses figures per million tokens that the vendors or price trackers published this month.

Model Input / output per 1M tokens Status on October 22, 2026
Claude Haiku 5.5 (Anthropic) Not listed Not listed
GPT 6 Luna Not listed Reported added to Zen
Gemini 4 Argon (Google) Not listed Not listed
Claude Opus 5.5 (Anthropic) Check Anthropic’s pricing page Leads in agentic coding, 40% cheaper than Opus 5 on typical workloads per Anthropic
Qwen3-Coder 30B (local) $0 per token Costs electricity and GPU wear only

Haiku 5.5 and Luna are the economical choices for a fallback, with identical listed rates according to Anthropic and ModelPriceWatch. Argon is priced like a flagship and carries a built-in rate hike, so factor in the November 30 jump if you budget monthly. Google describes the model as its next era of frontier intelligence. For hard agentic work, Opus 5.5 is the strongest of the four per Anthropic’s own claim, and you pay for it. Start cheap, escalate only when the cheap model fails twice on the same task.

Phase 4: Lock Down Permissions and Give the Agent Rules (Steps 8 and 9) #

Step 8: Write a Deny-by-Default Permission Policy

An agent that can run shell commands is an agent that can delete files, leak environment variables or pipe your repository to a stranger’s server if a prompt goes wrong. The permission block is the guardrail. The policy below asks before any edit, blocks web fetches entirely, allows a short list of harmless read and test commands, and flatly denies the dangerous ones. Everything not listed falls to the "*": "ask" rule.

"permission": {
  "edit": "ask",
  "webfetch": "deny",
  "bash": {
    "*": "ask",
    "git status": "allow",
    "git diff*": "allow",
    "git log*": "allow",
    "ls*": "allow",
    "python -m pytest*": "allow",
    "pytest*": "allow",
    "rm *": "deny",
    "curl *": "deny",
    "wget *": "deny",
    "sudo *": "deny",
    "git push*": "deny"
  }
}

Merge this block into opencode.json as a sibling of provider and model. The final file appears in the project section below. Deny git push even if you trust the model, because pushing is the one action you cannot undo from a local reflog. Once you have watched a few sessions and feel confident, relax edit to allow for the working directory, since the git baseline lets you revert anything. Keep bash on ask.

Encrypted storage adds a second layer. The place where credentials land on disk, whether an env file or the app’s own auth store, should sit on an encrypted volume. If you are choosing between built-in and third-party options, the breakdown of VeraCrypt and BitLocker covers the trade-offs for exactly that case.

Step 9: Add an AGENTS.md With Project Rules

OpenCode reads AGENTS.md from the repository root and adds it to the model’s context on every session. Local models benefit more from explicit rules than hosted ones do, because they guess less well about unwritten conventions. Keep the file short. A 30B model with a 32k window has no room to waste on a long essay.

cat > AGENTS.md <<'EOF'

## Project
- Tiny Python 3.12 library. Source lives in ledger.py, tests in test_ledger.py.
- Run tests with: python -m pytest -q

## Rules
- Write or update a test before changing behavior.
- Keep functions small and typed where it helps readability.
- Never touch .venv, .git or any file outside this directory.
- Do not add dependencies. Standard library only, plus pytest for tests.
- After every change, run the tests and show the result.
- If a task is ambiguous, ask one clarifying question instead of guessing.

## Style
- Plain functions, no classes unless state is needed.
- Raise ValueError with a clear message for bad input.
EOF
git add -A && git commit -qm "add opencode config and rules"

The “ask one clarifying question” rule matters more than it looks. Small models tend to push ahead on a vague request and produce confident nonsense. A rule that makes them stop and ask turns many bad runs into short conversations.

Phase 5: Commands, Subagent and Routing (Steps 10 and 11) #

Step 10: Define a Read-Only Reviewer Subagent and a /review Command

A reviewer that cannot edit is a cheap safety net. It reads the diff, reports problems, and stops. Define it as a subagent with its own tighter permissions, then expose it through a custom slash command so one keystroke triggers the review. Add both blocks to opencode.json:

"agent": {
  "reviewer": {
    "description": "Read-only reviewer for the working-tree diff",
    "mode": "subagent",
    "permission": {
      "edit": "deny",
      "webfetch": "deny",
      "bash": {
        "*": "deny",
        "git diff*": "allow",
        "git status": "allow"
      }
    }
  }
},
"command": {
  "review": {
    "description": "Review uncommitted changes for bugs and missing tests",
    "agent": "reviewer",
    "subtask": true,
    "template": "Run git diff and review the changes. List bugs, missing tests and unsafe shell use as a numbered list. Do not edit anything."
  }
}

Inside the UI, typing /review now spawns the subagent, which can run only the two git commands. If the model tries anything else, the deny rule stops it. This pattern is worth copying: one agent with write access that you supervise, and one without that audits it. Running the reviewer on a hosted model gives you a second opinion from a different system, which catches errors a single model repeats.

Step 11: Build the oc-local and oc-cloud Wrapper Scripts

Typing model names by hand invites mistakes, and a forgotten flag can send private code to a hosted API. Two tiny wrappers remove the guesswork. oc-local checks that Ollama is alive and forces the local model. oc-cloud refuses to run unless you have named a hosted model explicitly.

mkdir -p bin
cat > bin/oc-local <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
if ! curl -fsS http://127.0.0.1:11434/v1/models > /dev/null; then
  echo "Ollama is not answering on port 11434" >&2
  exit 1
fi
unset ANTHROPIC_API_KEY OPENAI_API_KEY GEMINI_API_KEY GOOGLE_GENERATIVE_AI_API_KEY
exec opencode --model "ollama/qwen3-coder-32k:latest" "$@"
EOF

cat > bin/oc-cloud <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
: "${OC_CLOUD_MODEL:?Set OC_CLOUD_MODEL to the provider/model shown by /models}"
exec opencode --model "$OC_CLOUD_MODEL" "$@"
EOF

chmod +x bin/oc-local bin/oc-cloud

The unset line in oc-local is deliberate. Even if your shell has hosted keys exported, the local wrapper strips them, so a misrouted request has no credential to use. That makes “local” a property the script enforces, not a habit you must remember. Add bin to your PATH or call the scripts by relative path.

A rough routing rule keeps the cloud bill small. Use the local model for test writing, small refactors, docstrings, renames, explaining unfamiliar code and boilerplate. Switch to the hosted model for cross-file architectural changes, debugging a failure the local model could not crack in two attempts, and migrations across many files. Track how often you switch. If it is more than a few times a day, the local model is too small for your codebase, and a larger one is the better investment.

Step 12: Run the First Task and Verify the Result #

Time to make your open source AI coding assistant earn its keep. Give it a concrete, testable task through the non-interactive run mode so the transcript is easy to read. The request adds a date filter to the sample library and demands tests, including an error case.

. .venv/bin/activate
bin/oc-local run "Add filter_by_month(rows, year, month) to ledger.py. It returns only rows whose ISO date falls in that month. Raise ValueError if a row has a malformed date. Add tests for both cases, then run the tests."

Because edits are set to ask, the run s for approval before each file change. In an interactive session, you press a key to accept. The wording of the transcript differs between versions, but it should look roughly like this:

> build / qwen3-coder-32k:latest
→ Read ledger.py
→ Read test_ledger.py
← Edit ledger.py        (approved)
← Edit test_ledger.py   (approved)
$ python -m pytest -q
...
3 passed in 0.04s
Added filter_by_month with ISO date parsing. Malformed dates raise ValueError.

Never trust the summary line. Verify with your own eyes and your own commands. Read the diff, run the suite yourself, and call the reviewer:

git diff --stat
python -m pytest -q
bin/oc-local run --command review

A healthy result shows two changed files, a green test run, and a short numbered review. If the model edited a file you did not expect, git checkout -- . restores the baseline. That safety net is the reason Step 5 committed first. When the local model fails the same task twice, escalate once with bin/oc-cloud run and the identical prompt, then compare the diffs. The comparison tells you how much quality you are trading for privacy and cost on that kind of task.

The Complete Working Project: Every File in One Place #

Here is the finished layout. If you followed along, your directory already matches it. If you skipped ahead, recreate the files below and you will have an identical, working setup. Open-weight releases keep arriving at a steady clip, as the wave of open-source model releases from Beam and Mistral shows, so the only file you will ever need to edit for a new model is opencode.json.

ledgerlite/
  .gitignore
  AGENTS.md
  opencode.json
  ledger.py
  test_ledger.py
  bin/oc-local
  bin/oc-cloud
  scripts/smoke.sh

The merged configuration file, combining Steps 6, 8 and 10, reads as follows. Validate it with python3 -m json.tool opencode.json after every edit, because a stray comma makes OpenCode ignore the whole file without much complaint.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": { "baseURL": "http://127.0.0.1:11434/v1" },
      "models": {
        "qwen3-coder-32k:latest": { "name": "Qwen3-Coder 30B, 32k context (local)" }
      }
    }
  },
  "model": "ollama/qwen3-coder-32k:latest",
  "permission": {
    "edit": "ask",
    "webfetch": "deny",
    "bash": {
      "*": "ask",
      "git status": "allow",
      "git diff*": "allow",
      "git log*": "allow",
      "ls*": "allow",
      "python -m pytest*": "allow",
      "pytest*": "allow",
      "rm *": "deny",
      "curl *": "deny",
      "wget *": "deny",
      "sudo *": "deny",
      "git push*": "deny"
    }
  },
  "agent": {
    "reviewer": {
      "description": "Read-only reviewer for the working-tree diff",
      "mode": "subagent",
      "permission": {
        "edit": "deny",
        "webfetch": "deny",
        "bash": { "*": "deny", "git diff*": "allow", "git status": "allow" }
      }
    }
  },
  "command": {
    "review": {
      "description": "Review uncommitted changes for bugs and missing tests",
      "agent": "reviewer",
      "subtask": true,
      "template": "Run git diff and review the changes. List bugs, missing tests and unsafe shell use as a numbered list. Do not edit anything."
    }
  }
}

One last file turns the whole setup into a repeatable health check. The smoke script confirms that Ollama answers, that the configured model exists, that the config parses, and that the baseline tests pass. Run it after every OpenCode or Ollama upgrade, so a breaking change shows up in seconds instead of mid-task.

mkdir -p scripts
cat > scripts/smoke.sh <<'EOF'
#!/usr/bin/env bash
set -uo pipefail
ok() { echo "PASS  $1"; }
bad() { echo "FAIL  $1"; FAILED=1; }
FAILED=0

curl -fsS http://127.0.0.1:11434/v1/models > /tmp/models.json \
  && ok "ollama endpoint answers" || bad "ollama endpoint down"

grep -q "qwen3-coder-32k" /tmp/models.json \
  && ok "configured model is installed" || bad "model missing, run ollama create"

python3 -m json.tool opencode.json > /dev/null \
  && ok "opencode.json parses" || bad "opencode.json is invalid"

opencode --version | grep -q "^1\." \
  && ok "opencode is on the 1.x line" || bad "opencode is not 1.x"

python -m pytest -q > /dev/null \
  && ok "tests pass" || bad "tests fail"

exit $FAILED
EOF
chmod +x scripts/smoke.sh
scripts/smoke.sh

All five lines should print PASS. Commit everything except secrets. The env file from Step 7 lives outside the repository on purpose.

Keeping Your API Keys Safe After the OpenCode Console Incident #

On October 19, 2026, BleepingComputer reported that an OpenCode hack exposed API keys amid AI distillation attacks. TechCrunch ran a matching report the same day, describing attackers who ran up charges on users’ AI accounts. The coverage points at OpenCode’s hosted console and model gateway, and reports say the open-source command-line client was not affected. Treat that last point as unconfirmed, because the investigation was still unfolding when both stories ran and the company had not published a full postmortem in the sources reviewed.

The lesson applies to any agent, not only this one. Your API keys are only as safe as the least careful service that holds a copy. This tutorial’s design already limits the damage, since local inference needs no key and the hosted key lives in a file you control. A few extra habits close the remaining gaps:

  • Create a dedicated key per tool, labeled with the tool name, so revoking one never breaks anything else.
  • Set a hard monthly spending cap in each vendor’s billing console. A stolen key then burns a capped amount instead of an open-ended one.
  • Rotate the key now if you ever pasted it into the hosted OpenCode console, a chat window or a shared terminal log.
  • Keep keys out of opencode.json , shell history and screenshots. Use an env file withchmod 600 .
  • Deny curl ,wget andwebfetch in the permission policy, so a prompt-injected instruction cannot exfiltrate environment variables.
  • Review billing dashboards weekly for the first month. Anomalies show up as unfamiliar models or off-hours spikes.

One naming trap deserves a mention. OpenCode now sells optional hosted access under several labels, including a curated gateway called Zen and a low-cost subscription called Go. Users on public issue trackers report confusion between the similarly named providers, with some choosing a credit-billed entry when they meant the subscription. If you use either, read the provider label in the model picker carefully before the first prompt. If you want none of it, the local setup above never contacts those services at all.

Common Pitfalls That Break Local AI Coding Setups #

Pitfall 1: Treating the bundled free models as local. OpenCode ships with a set of free models, but they run on hosted infrastructure. If your goal is privacy, they defeat the purpose. Always confirm in the footer that the active model reads “Ollama (local)” before pasting anything sensitive.

Pitfall 2: Pulling a model tag that ends in :cloud. Ollama now offers cloud-hosted models through the same CLI, such as the Clef decision models it added on October 14, 2026. Those tags run on Ollama’s servers, not on your GPU. A local-only policy means checking every tag you pull for the cloud suffix. Fast generation on a laptop that should not be that fast is a red flag.

Pitfall 3: Running the major upgrade in the middle of a project. The explicit upgrade command exists so you can choose your moment. Run it in a copy of the project on a quiet afternoon, not on the branch that has a deadline. Version 1.19.2 made sure ordinary 1.x updates stay on 1.x, so skipping the major step costs you nothing in the short term.

Pitfall 4: Ignoring the context window. A model that “forgets” instructions halfway through a session is usually truncating. Rules from AGENTS.md fall off the front first. Verify the window with ollama ps and a Modelfile, as in Step 3, and keep the rules file brief.

Pitfall 5: Opening permissions too wide, too early. Setting "bash": "allow" to stop the prompts is tempting on day one. It also hands a 30B model unreviewed shell access to your machine. Widen permissions one command pattern at a time, based on what you actually see the agent run.

Pitfall 6: Following instructions written for another version. Guides from earlier in 2026 describe automatic updates and session sharing, and both behave differently now. Session sharing was discontinued in v1.19.1. When a tutorial’s output does not match your screen, check its date against the October release notes before debugging your machine. Hardware assumptions age badly as well, and with Nvidia funding AI factories built around open-source models, expect the recommended local model to change again within months.

Troubleshooting: 10 Problems and Their Fixes #

  1. “Connection refused” on port 11434. Ollama is not running. Start it withollama serve or the desktop app, then repeat the curl check from Step 1. On Linux,systemctl status ollama shows crash reasons.
  2. “Model not found” in OpenCode. The ID inopencode.json differs from what the server reports. Run the/v1/models curl again and paste the exact string, including the:latest suffix.
  3. The model chats but never edits files. The model lacks tool-calling support, or the adapter cannot parse its output. Switch to a model with documented tool use, such as Qwen3-Coder, and check that Ollama is on a current stable build.
  4. Replies slow to a crawl. The model spilled to the CPU. Runollama ps . If the processor column shows a CPU split, lowernum_ctx , close GPU-hungry apps or choose a smaller model.
  5. The agent forgets earlier instructions. The context is truncating. Rebuild the model with a largernum_ctx if memory allows, trimAGENTS.md , and start fresh sessions per task instead of one endless thread.
  6. Config changes have no effect. A JSON syntax error makes the file fail to load. Validate withpython3 -m json.tool opencode.json , and confirm you launched OpenCode from the repository root, since the project config is found relative to the working directory.
  7. Every command triggers a permission prompt. Your allow patterns do not match what the model types. Watch the prompts, then add narrow patterns such as"pytest*": "allow" . Avoid a blanket allow.
  8. “pytest: command not found” inside the agent. The virtual environment is not active in the shell that launched OpenCode. Activate.venv first, or prefix commands withpython -m pytest as the rules file instructs.
  9. 401 or 403 from the hosted provider. The key is missing from that shell, expired, or lacks credit. Run. ~/.config/oc-lab.env in the same terminal, check the billing page, and if you use an OpenCode subscription, confirm you picked the subscription entry rather than the credit-billed one, since users report both mix-ups.
  10. The /review command does nothing or errors. The subagent name incommand.review.agent must match a key underagent . Check spelling, confirm"mode": "subagent" , and make sure you are on a 1.19.x build, because older releases handle subtasks differently.

When none of these fits, reproduce the problem with the smoke script from the project section. A failing line tells you which layer to investigate: the model server, the config, the OpenCode version or the tests. Narrowing it to one layer typically takes under two minutes.

Advanced Tips: Sandboxing, Model Benchmarks and OpenCode 2 #

Benchmark on your own code. Public leaderboards rarely predict how an open source AI coding assistant performs on your stack. Write three real tasks from your backlog, run each on the local model and the hosted one, and score pass or fail with your test suite. A short comparison script does the job:

#!/usr/bin/env bash
set -u
git diff --quiet || { echo "Commit your work first" >&2; exit 1; }
for runner in bin/oc-local bin/oc-cloud; do
  "$runner" run "$1" > "/tmp/$(basename $runner).log" 2>&1
  if python -m pytest -q > /dev/null; then echo "$runner: PASS"; else echo "$runner: FAIL"; fi
  git checkout -q -- . && git clean -fdq
done

Treat the output as a rough signal. Run each task a few times, because sampling makes a single result noisy. Note the permission prompts too, since they will interrupt unattended runs, so for a true benchmark use a scratch clone with edit permissions set to allow.

Try newer local models without breaking the setup. Because the provider map is just a list, you can register two or three Ollama models side by side and switch with /models. Candidates include the Nemotron 3.5 Lightning model built for long-running agents, and Flint once its Ollama listing is confirmed. Keep Qwen3-Coder as the baseline, and only promote a challenger when it beats the baseline on your three benchmark tasks.

Sandbox the agent for risky work. For untrusted repositories, run OpenCode inside a container or a disposable virtual machine with the repository mounted and outbound network blocked except for the model endpoint. Pair that with git worktrees, one per task, so parallel experiments never collide. If an experiment goes wrong, you delete a directory.

Evaluate OpenCode 2 in a copy. Third-party reports describe OpenCode 2 as running one local background service shared by the terminal UI, web, desktop and scripts, with code mode, background subagents and an SDK. Cloudflare reportedly announced hosting support through its Agents SDK on October 12. Because version numbers for the new line conflict across sources, do not guess. Clone the project to a throwaway folder, run opencode upgrade --major there, replay your three benchmark tasks, and compare. If the new line wins and the config keys still apply, migrate on your own schedule. The broader coding and dev tools coverage tracks how these agents evolve.

Add MCP servers carefully. OpenCode can connect to Model Context Protocol servers for databases, issue trackers and docs. Each server widens what a prompt injection can reach. Add them one at a time, give each its own permission rule, and prefer read-only credentials.

Frequently Asked Questions #

Is OpenCode really free to use?

The client is free, and the project’s website says so directly. Costs appear only when you connect a paid provider, such as a hosted model with an API key, or optional hosted plans. A fully local setup with Ollama costs no per-token fees, only the electricity and hardware you already own.

Can an open source AI coding assistant run fully offline?

Yes, once the model files are downloaded. The local provider talks only to 127.0.0.1, and the permission policy blocks web fetches. Use the oc-local wrapper so no hosted key is available, and avoid any model tag with a cloud suffix.

Which local model is best for coding agents right now?

No single answer holds for every codebase. Qwen3-Coder 30B is a dependable baseline for tool calling on Ollama, and newer open models like Nemotron 3.5 Lightning and Flint are worth benchmarking on your own tasks. Pick the one that passes your tests most often within your memory budget.

Should I stay on OpenCode 1.x or move to OpenCode 2?

Stay on 1.x for a stable, documented setup, and test version 2 in a separate copy. The official 1.x line no longer offers version 2 as an ordinary update, so nothing forces your hand. Move when your benchmark tasks run at least as well on the new line.

How much GPU memory do I need?

Plan for roughly 20 GB of free GPU or unified memory for a 4-bit 30B-class model, plus extra for a long context window. Smaller models run on less memory with weaker results on multi-file edits. Check the model page on Ollama for the exact size of the build you pull.

Is it safe to use after the reported OpenCode API key exposure?

Reports describe the exposure as hitting OpenCode’s hosted console and gateway, with the open-source client reportedly unaffected, though that was unconfirmed at last check. Use a dedicated key, cap spending, rotate any key you entered into the hosted service, and rely on local inference for sensitive code.

Can I use Aider, Cline or Goose with the same Ollama model?

Generally yes. These agents support OpenAI-compatible endpoints, so they can point at the same Ollama URL. Their permission models and config formats differ, so the guardrails in this tutorial do not carry over automatically. Rebuild the policy in each tool before trusting it.

How do I update OpenCode now that automatic updates are off?

Run /update in the terminal UI for a regular 1.x update. The major jump needs opencode upgrade --major. After either, run the smoke script, so a breaking change shows up immediately.

── more in #ai-tools 4 stories · sorted by recency
── more on @opencode 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/open-source-ai-codin…] indexed:0 read:33min 2026-10-22 · —