OpenCode: de open source code-agent, geïnstalleerd en uit elkaar gehaald

OpenCode installeer je zonder account en het antwoordt al bij het eerste commando met een gratis model. Het laadt ook, zonder het te zeggen, de skills die al voor andere tools zijn geïnstalleerd als je vergeet je persoonlijke map te isoleren.

OpenCode: de open source code-agent, geïnstalleerd en uit elkaar gehaald
Kort antwoord

OpenCode is een open source code-agent (Anomaly, MIT-licentie) die draait in een terminal, als editor-extensie of als desktopapplicatie. Zonder iets op het systeem achter te laten, werkt hij al bij het eerste commando dankzij een gratis model, en hij ondersteunt MCP-servers en het skillformaat SKILL.md, inclusief skills die al voor andere agents zijn geïnstalleerd als ze niet geïsoleerd zijn. Lokale modellen verlopen via een generieke OpenAI-compatibele leverancier, niet via een speciale Ollama-integratie.

Een open source code-agent belooft je niet bij één enkele uitgever op te sluiten. Het model kies je zelf, de code blijft op je machine, de licentie is permissief. Ik heb OpenCode geïnstalleerd zonder het systeem aan te raken of één identifier in te voeren, voordat ik ontdekte dat één vergeten variable-export volstaat om hem de skills te laten laden die al voor andere tools waren geïnstalleerd.

OpenCode, drie interfaces onder MIT-licentie

OpenCode wordt ontwikkeld door Anomaly en gepubliceerd onder MIT-licentie in de repository anomalyco/opencode, die op 7 september 2026 ongeveer 206.000 sterren telde. De tool presenteert zich als “an open source agent that helps you write code in your terminal, IDE, or desktop”. Hij komt in drie interfaces: een terminalclient (TUI), een editor-extensie en een desktopapplicatie in bèta voor macOS, Windows en Linux.

Een LSP laadt in principe automatisch afhankelijk van de gedetecteerde taal, en meer dan 75 modelleveranciers worden ondersteund via Models.dev en de AI SDK, van de betaalde API tot het lokale model. In mijn testproject noteerde het logboek echter “all LSPs are disabled”: de taal detecteren volstaat niet, de bijbehorende server moet aanwezig zijn opdat de functie zich activeert. De site claimt verder “OpenCode does not store any of your code or context data”. Er vertrekt standaard niets naar de servers van Anomaly, maar alles blijft in een lokale SQLite-database, zoals de volgende sectie laat zien.

OpenCode voegt zich bij een al lange lijst van command line-agents: ons overzicht van code-agents vergelijkt ze allemaal. Dit artikel richt zich op wat je ontdekt door deze agent te installeren en stuk voor stuk uit elkaar te halen.

OpenCode installeren zonder iets op het systeem achter te laten

Het npm-package opencode-ai installeert een gecompileerde binary (opencode-darwin-arm64 op deze Mac) achter een uitvoerbaar bestand opencode.exe. Om niets in de globale locaties achter te laten, gaan we naar een tijdelijk labprefix, met een lokale npm-cache en een geïsoleerde HOME voor alle volgende commando’s:

bash
mkdir -p docker/articles/2026-09-07/lab/opencode-agent-code-open-source/{prefix,home,projet-demo}
cd docker/articles/2026-09-07/lab/opencode-agent-code-open-source

npm install opencode-ai --prefix ./prefix --cache ./prefix/.npm-cache

export HOME="$PWD/home"
./prefix/node_modules/.bin/opencode --version

Het commando geeft 1.18.29 terug, volgens de GitHub-releases gepubliceerd op 4 september 2026 om 23u47, drie dagen vóór deze test. Vijfde versie in acht dagen: 1.18.25 tot 1.18.29 tussen 28 augustus en 4 september. Het npm-register bevestigt dat het om de laatst beschikbare versie gaat. De documentatie biedt ook een script curl -fsSL https://opencode.ai/install | bash en Homebrew-, Scoop- of pacman-pakketten, ik heb npm aangehouden zodat de hele installatie past in een map die ik aan het eind verwijder.

De installatie stopt niet noodzakelijk daar. Zodra er een paar commando’s vanuit het project zijn uitgevoerd, installeerde OpenCode uit zichzelf 54 MB aan dependencies in .opencode/node_modules, zonder het te vragen: zijn eigen plugin-SDK, de bibliotheek effect, en een verrassender aanwezigheid, kubernetes-types. Een .opencode/.gitignore stond al klaar om ze uit te sluiten van Git-tracking.

Waar OpenCode zijn configuratie leest

Zodra HOME geïsoleerd is, toont het commando opencode debug paths, een diagnosetool die niet in het hoofdmenu staat, de XDG-achtige structuur die OpenCode zichzelf heeft opgebouwd in deze nepthuismap (paden ingekort voor de leesbaarheid):

bash
opencode debug paths

home    .../lab/opencode-agent-code-open-source/home
config  .../home/.config/opencode
data    .../home/.local/share/opencode
cache   .../home/.cache/opencode
state   .../home/.local/state/opencode
tmp     /var/folders/.../T/opencode

Het bestand opencode.log, geschreven in data/log, geeft de exacte leesvolgorde bij het opstarten: eerst de globale configuratiemap (opencode.json, .jsonc), dan, vanuit de huidige map, opencode.json en .opencode/opencode.json van het project. De skill die in de binary is ingebouwd, leesbaar met opencode debug skill, documenteert dezelfde hiërarchie, met een tabel die het overnemen waard is:

Scope Pad
Projectconfiguratie ./opencode.json, ./opencode.jsonc of .opencode/opencode.json (gezocht vanuit de huidige map tot aan de root van de Git-repository)
Globale configuratie ~/.config/opencode/opencode.json of .jsonc, niet ~/.opencode/
Skills van het project .opencode/skill(s)/<nom>/SKILL.md
Globale skills ~/.config/opencode/skill(s)/<nom>/SKILL.md
Externe skills (automatisch geladen) ~/.claude/skills/<nom>/SKILL.md, ~/.agents/skills/<nom>/SKILL.md

De configuraties van elke scope worden samengevoegd (deep-merge), waarbij het project voorrang heeft op het globale niveau. De laatste rij van de tabel reikt het verst. OpenCode leest, zonder extra declaratie, de skills die al zijn geïnstalleerd voor Claude Code en voor andere agents die compatibel zijn met de open standaard Agent Skills, beschreven in onze gids over het SKILL.md-bestand.

De skills: hoe ver gaat de automatische ontdekking?

Om te controleren wat de ingebouwde documentatie zegt, heb ik twee lokskills rechtstreeks toegevoegd in de nep-HOME, precies op de plek waar OpenCode zegt ze te zoeken, voordat ik dezelfde diagnose opnieuw draaide:

bash
mkdir -p home/.claude/skills/decoy-claude home/.agents/skills/decoy-agents
# een minimaal SKILL.md (frontmatter name + description) in elke map
opencode debug skill

Resultaat: vier gedetecteerde skills, de ingebouwde skill, de projectskill, en de twee lokskills, elk met zijn volledige pad in home/.claude/skills/… en home/.agents/skills/…. OpenCode respecteert gewoon de variabele HOME die je hem meegeeft, hij kijkt alleen breder dan zijn eigen configuratiemap.

Zonder HOME opnieuw geëxporteerd in het commando valt dezelfde lijst terug op de echte persoonlijke map van de machine en haalt ze 120 skills op, degene die echt waren geïnstalleerd voor Claude Code en voor andere agents. Geen enkele sandbox-ontsnapping daarin. Eén enkel commando zonder expliciete HOME volstaat om een test die je isolerend waant, weer te koppelen aan je echte persoonlijke map, en dus aan de skills die al voor andere tools zijn geïnstalleerd, nooit gedeclareerd in het project. Het commando zelf is veelzeggend: er bestaat geen opencode skill list op het eerste niveau, je moet via opencode debug skill gaan, een diagnosetool.

MCP: een lokale server configureren en bevragen

Het configuratiebestand van het project declareert een lokale MCP-server, de bijbehorende permissies, en beperkt de toegang tot de tool voor de agent plan:

json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "slug": {
      "type": "local",
      "command": ["node", "./mcp/serveur.mjs"],
      "enabled": true
    }
  },
  "permission": {
    "edit": { "*": "ask", "docs/**": "allow" },
    "bash": { "*": "ask", "git status": "allow", "git diff *": "allow", "rm *": "deny" },
    "webfetch": "deny",
    "skill": { "*": "allow" }
  },
  "agent": {
    "plan": { "tools": { "slug_*": false } }
  }
}

De server, mcp/serveur.mjs, is een zelfstandig Node-script van een veertigtal regels dat JSON-RPC 2.0 spreekt op de standaardinvoer en één enkele tool blootstelt, slug_fr:

javascript
const TOOLS = [{
  name: "slug_fr",
  description: "Transforme un titre francais en slug d'URL (minuscules, sans accent).",
  inputSchema: {
    type: "object",
    properties: { titre: { type: "string", description: "Le titre a convertir" } },
    required: ["titre"]
  }
}];

function slug(titre) {
  return titre.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
    .toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
}

opencode mcp list bevestigt de verbinding:

bash
opencode mcp list

MCP Servers
  slug   connected
    node ./mcp/serveur.mjs

1 server(s)

Een projectskill, slug-gekkode, legt de bedrijfsregel uit (maximaal vijf woorden, zonder lidwoord) en verwijst naar de tool. Eén heen-en-weer met opencode run activeert beide na elkaar (uitvoer ontdaan van kleurcodes en iconen, inhoud ongewijzigd):

bash
opencode run "Utilise la regle de slug du projet pour convertir ce titre : Les secrets d'une bonne architecture PHP"

> build - big-pickle
Skill "slug-gekkode"
slug_slug_fr {"titre":"Les secrets d'une bonne architecture PHP"}

Le slug genere par l'outil MCP est : les-secrets-d-une-bonne-architecture-php

Mais selon les regles du skill (max 5 mots, sans article ni preposition),
le slug correct est : secrets-bonne-architecture-php

De weergegeven toolnaam, slug_slug_fr, toont de naamgevingsconventie. OpenCode zet voor elke MCP-tool de naam van de server die in de config is gedeclareerd (slug), gevolgd door de naam van de blootgestelde tool (slug_fr), vandaar de herhaling. Het model koos de skill op basis van zijn beschrijving, riep de tool aan, en herberekende vervolgens het resultaat met de hand om de regel van vijf woorden te respecteren. Een skill die een tool aanvult in plaats van te vervangen, gedraagt zich precies zo. Voor een externe server beschrijft de documentatie een blok "type": "remote" met url en headers of oauth, plus opencode mcp auth voor de OAuth-flow. Het onderwerp wordt uitgediept in ons artikel over het bouwen van een MCP-server in PHP.

Agents en permissies, regel voor regel

opencode agent list toont acht agents in dit project: build (standaard hoofdagent, ruime toegang), plan (hoofdagent, lezen en plannen), compaction, summary en title (intern), explore en general (subagents), en relecteur, gedeclareerd in .opencode/agents/relecteur.md:

markdown
---
description: Relit un article et signale les fautes, sans jamais modifier de fichier.
mode: subagent
temperature: 0.1
permission:
  edit: deny
  bash: deny
---
Vous relisez un article de blog en francais. Vous signalez les erreurs, vous ne corrigez rien.

Elke permissie aanvaardt allow, ask of deny, per glob-patroon, waarbij de specifiekste regel wint. De instelling geldt voor edit, bash, webfetch, skill, en zelfs voor een specifieke MCP-tool zoals slug_*. De agent plan van het project illustreert het principe: zijn configuratie schakelt de tool slug_* uit en staat schrijven alleen toe in .opencode/plans/*.md, nooit in de code. In niet-interactieve modus, zonder terminal om een vraag te beantwoorden, blijft een permissie ask niet in de wacht: ze wordt automatisch afgewezen:

bash
opencode run "Execute la commande shell : echo test-permission"

> build - big-pickle
! permission requested: bash (echo test-permission); auto-rejecting
Error: The user rejected permission to use this specific tool call.

$ echo $?
0

Het standaardgedrag is dus gesloten: zonder menselijk toezicht faalt OpenCode liever dan een niet expliciet toegestaan commando uit te voeren. De exitcode blijft niettemin 0 ondanks de mislukking, een valstrik voor wie daar een controle op scriptet. Het onderwerp permissies en sandbox, gemeenschappelijk voor al deze agents, wordt uitgediept in ons artikel over code-agents, sandbox en permissies.

De modellen: een gratis proefrit, en het geval van lokale modellen

Zonder account of sleutel werkt opencode run "zeg hallo" al bij het eerste commando. Het standaard gebruikte model, big-pickle (“stealth model” volgens zijn fiche), hoort bij de zes gratis modellen van OpenCode Zen, de eigen gateway. De vijf andere zijn MiMo-V2.5 Free, Ling 3.0 Flash Fin Free, twee varianten van Nemotron 3 en Muse Spark 1.3 Contributor Free. De lokale SQLite-database (tabel message) houdt de uitwisseling bij. De tabellen credential en account blijven op nul rijen: voor dat model is geen enkele identifier gevraagd of opgeslagen, en de kosten in het sessielogboek zijn nul.

Een merkmodel uit dezelfde catalogus (GPT, Claude, Gemini, Grok, DeepSeek, Qwen…) vraagt een OpenCode Zen-account en een betaalmiddel. De facturatie gebeurt per token, van 0,20 $ tot meerdere dollars per miljoen afhankelijk van het model. Het saldo laadt zich automatisch op met 20 $ zodra het onder 5 $ zakt.

Voor een lokaal model is de controle eenvoudig:

bash
which ollama
# ollama niet gevonden

De modellencatalogus die OpenCode in cache heeft, biedt alleen een cloudleverancier aan, ollama-cloud (sleutel OLLAMA_API_KEY), geen speciale vermelding voor een lokale Ollama. Voor een lokale server, Ollama, llama.cpp of LM Studio, beschrijft de documentatie een generieke OpenAI-compatibele leverancier die je zelf moet declareren:

json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama-local": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": { "baseURL": "http://127.0.0.1:11434/v1" },
      "models": { "mon-modele": { "name": "Mon modele local" } }
    }
  }
}

Poort 11434 en de eigen API (/api/generate, onder andere) staan gedocumenteerd op docs.ollama.com. De OpenAI-compatibiliteit die @ai-sdk/openai-compatible vereist, komt neer op twee aanroepen, gecontroleerd op een Ollama 0.34.0 in een container:

bash
curl -s http://127.0.0.1:11434/v1/models
# {"object":"list","data":[{"id":"qwen2.5:0.5b","object":"model",
#   "created":1789038968,"owned_by":"library"}]}

curl -s http://127.0.0.1:11434/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen2.5:0.5b","messages":[{"role":"user",
       "content":"Réponds par le seul mot OK."}],"max_tokens":5}'
# {"id":"chatcmpl-704","object":"chat.completion","model":"qwen2.5:0.5b",
#  "choices":[{"index":0,"message":{"role":"assistant","content":"OK."},
#   "finish_reason":"stop"}],
#  "usage":{"prompt_tokens":38,"completion_tokens":3,"total_tokens":41}}

De vorm is precies wat de SDK verwacht: object: "list" op de catalogus, een volledig chat.completion-object met choices, finish_reason en usage op de completion. Een onbekend model antwoordt 404 met het OpenAI-foutobject, en de header Authorization wordt aanvaard ongeacht zijn waarde: het veld apiKey van de provider mag om het even wat bevatten.

Wat ontbreekt, van hieruit gezien

Het volledige overzicht van command line-code-agents, sterke en zwakke punten tegenover Claude Code, Codex, Gemini CLI en de andere, wordt apart behandeld in onze vergelijking. De lijst met skills en de opgeloste configuratie zijn alleen toegankelijk via diagnosecommando’s, debug skill en debug config. Beide ontbreken in het hoofdmenu: nuttig zodra je ze kent, maar niet echt vindbaar. De lokale opslag is heel reëel: sessie, berichten en tool-aanroepen leven in een SQLite-database op je schijf, dus “geen data verstuurd naar de servers van Anomaly” staat niet gelijk aan “er wordt niets geschreven”. En de gratis toegang stopt bij het eigen model: bij het eerste merkmodel kom je het account en de bankkaart tegen die je elders ook zou tegenkomen.

Wat je moet onthouden

  • OpenCode (Anomaly, MIT-licentie) installeer je zonder iets op het systeem achter te laten via npm install opencode-ai --prefix en een geïsoleerde HOME, geteste versie: 1.18.29.
  • De configuratie wordt op drie samengevoegde niveaus gelezen: project (opklimmend tot de Git-root), globaal (~/.config/opencode, nooit ~/.opencode), en externe skills die automatisch worden geladen vanuit ~/.claude/skills en ~/.agents/skills.
  • HOME isoleren werkt, op voorwaarde dat je hem in elk commando exporteert. Één vergetelheid koppelt OpenCode weer aan je echte persoonlijke map, skills van andere tools inbegrepen: twee lokskills bevestigen het, en een lijst zonder HOME levert er 120 op.
  • Een projectskill en een lokale MCP-tool werken samen vanaf de eerste poging, zonder identifier, met het gratis model big-pickle van OpenCode Zen.
  • Permissies ask worden automatisch afgewezen in niet-interactieve modus, maar de exitcode blijft 0: iets om in de gaten te houden als je controles scriptet rond opencode run.
  • Lokale modellen (Ollama, llama.cpp, LM Studio) verlopen via een generieke OpenAI-compatibele leverancier die je met de hand moet declareren, niet via een speciale Ollama-integratie.

Veelgemaakte fouten

HOME isoleren beschermt maar half Als één enkel commando vergeet de variabele te exporteren, valt OpenCode terug op je echte persoonlijke map en laadt hij de skills die al voor andere tools zijn geïnstalleerd.
~/.claude/skills en ~/.agents/skills worden automatisch gelezen Dat is geen isolatiefout: de ingebouwde documentatie bevestigt het (external skills, auto-loaded). Op een machine die al is uitgerust voor Claude Code, komen diens skills daar zonder expliciete declaratie terecht.
Geen zichtbaar skill-commando De lijst met skills verschijnt niet in opencode --help: ze zit verstopt onder opencode debug skill, een diagnosetool die zonder aankondiging kan veranderen.
~/.config/opencode, niet ~/.opencode De ingebouwde documentatie vermeldt deze naamgevingsvalstrik expliciet, het tweede pad wordt stilzwijgend genegeerd.
Een exitcode 0 ondanks een geweigerde permissie In niet-interactieve modus laat een geweigerd bash-commando de tool falen, maar opencode run eindigt toch met code 0.

MCPOllamaOpenCodeSkills

Damien Flandrin Webdeveloper sinds 2010, maker van Gekkode en Email Impact. Elk artikel wordt vóór publicatie getest op een echt project. Contact
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.