OpenCode: l’agente di codice open source, installato e smontato

OpenCode si installa senza account e risponde dalla prima riga di comando con un modello gratuito, carica anche, senza dirlo, gli skill già installati per altri strumenti se dimentichi di isolare la tua directory personale.

OpenCode: l’agente di codice open source, installato e smontato
Risposta rapida

OpenCode è un agente di codice open source (Anomaly, licenza MIT) che gira in terminale, come estensione per editor o come applicazione desktop. Installato senza lasciare nulla sul sistema, funziona dalla prima riga di comando grazie a un modello gratuito e supporta i server MCP e il formato di skill SKILL.md, compresi quelli già installati per altri agenti se non sono isolati. I modelli locali passano da un fornitore generico compatibile OpenAI, non da un'integrazione Ollama dedicata.

Un agente di codice open source promette di non rinchiuderti presso un solo editore. Il modello si sceglie, il codice resta sulla tua macchina, la licenza è permissiva. Ho installato OpenCode senza toccare il sistema né digitare un solo identificativo, prima di scoprire che un export di variabile dimenticato basta a fargli caricare gli skill già installati per altri strumenti.

OpenCode, tre interfacce sotto licenza MIT

OpenCode è sviluppato da Anomaly e pubblicato sotto licenza MIT nel repository anomalyco/opencode, che mostrava circa 206.000 stelle il 7 settembre 2026. Lo strumento si presenta come «an open source agent that helps you write code in your terminal, IDE, or desktop». Si declina in tre interfacce: un client da terminale (TUI), un’estensione per editor e un’applicazione desktop in beta per macOS, Windows e Linux.

Un LSP si carica in linea di principio automaticamente secondo il linguaggio rilevato, e più di 75 fornitori di modelli sono supportati tramite Models.dev e l’AI SDK, dall’API a pagamento al modello locale. Nel mio mini-progetto di test, il log ha però segnalato «all LSPs are disabled»: il rilevamento del linguaggio non basta, il server corrispondente deve essere presente perché la funzionalità si attivi. Il sito rivendica peraltro «OpenCode does not store any of your code or context data». Nulla parte verso i server di Anomaly per impostazione predefinita, ma tutto resta in un database SQLite locale, come mostra la sezione seguente.

OpenCode si unisce a una lista già lunga di agenti a riga di comando: il nostro panorama degli agenti di codice li confronta tutti. Questo articolo si concentra su ciò che si scopre installando e smontando questo, pezzo per pezzo.

Installare OpenCode senza lasciare nulla sul sistema

Il pacchetto npm opencode-ai installa un binario compilato (opencode-darwin-arm64 su questo Mac) dietro un eseguibile opencode.exe. Per non lasciare nulla nelle posizioni globali, si va verso un prefisso temporaneo del laboratorio, con una cache npm locale e un HOME isolato per tutti i comandi che seguono:

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

Il comando restituisce 1.18.29, pubblicata il 4 settembre 2026 alle 23:47 secondo le release GitHub, tre giorni prima di questo test. Quinta versione in otto giorni: dalla 1.18.25 alla 1.18.29 tra il 28 agosto e il 4 settembre. Il registro npm conferma che si tratta dell’ultima versione disponibile. La documentazione propone anche uno script curl -fsSL https://opencode.ai/install | bash e pacchetti Homebrew, Scoop o pacman, ho mantenuto npm perché tutta l’installazione stesse in una cartella che si elimina alla fine.

L’installazione non si ferma necessariamente lì. Una volta lanciati alcuni comandi dal progetto, OpenCode ha installato da solo 54 MB di dipendenze in .opencode/node_modules, senza chiederlo: il proprio SDK di plugin, la libreria effect, e una presenza più sorprendente, kubernetes-types. Un .opencode/.gitignore era già pronto a escluderle dal tracciamento Git.

Dove OpenCode legge la sua configurazione

Una volta isolato HOME, il comando opencode debug paths, un sotto-strumento di diagnostica assente dal menu principale, mostra la struttura in stile XDG che OpenCode si è costruita in questa falsa directory personale (percorsi abbreviati per la lettura):

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

Il file opencode.log scritto in data/log dettaglia l’ordine di lettura esatto all’avvio: prima la cartella di configurazione globale (opencode.json, .jsonc), poi, partendo dalla cartella corrente, opencode.json e .opencode/opencode.json del progetto. Lo skill integrato nel binario, leggibile con opencode debug skill, documenta la stessa gerarchia, con una tabella che vale la pena ricopiare:

Ambito Percorso
Config progetto ./opencode.json, ./opencode.jsonc o .opencode/opencode.json (cercato risalendo dalla cartella corrente alla radice del repository Git)
Config globale ~/.config/opencode/opencode.json o .jsonc, non ~/.opencode/
Skill del progetto .opencode/skill(s)/<nom>/SKILL.md
Skill globali ~/.config/opencode/skill(s)/<nom>/SKILL.md
Skill esterni (caricati automaticamente) ~/.claude/skills/<nom>/SKILL.md, ~/.agents/skills/<nom>/SKILL.md

Le configurazioni di ogni ambito sono fuse (deep-merge), con il progetto che prevale sul globale. L’ultima riga della tabella è quella che va più lontano. OpenCode legge, senza dichiarazione supplementare, gli skill già installati per Claude Code e per altri agenti compatibili con lo standard aperto Agent Skills, descritto nella nostra guida al SKILL.md.

Gli skill: fin dove arriva la scoperta automatica?

Per verificare cosa dice la documentazione integrata, ho aggiunto due skill-esca direttamente nel falso HOME, esattamente dove OpenCode dice di cercarli, prima di rilanciare la stessa diagnostica:

bash
mkdir -p home/.claude/skills/decoy-claude home/.agents/skills/decoy-agents
# un SKILL.md minimo (frontmatter name + description) in ogni cartella
opencode debug skill

Risultato: quattro skill rilevati, lo skill integrato, lo skill del progetto, e le due esche, ciascuno con il proprio percorso completo in home/.claude/skills/… e home/.agents/skills/…. OpenCode rispetta semplicemente la variabile HOME che gli si dà, guarda soltanto più in largo della propria cartella di configurazione.

Senza HOME riesportato nel comando, lo stesso elenco ricade sulla vera directory personale della macchina e riporta 120 skill, quelli effettivamente installati per Claude Code e per altri agenti. Nessuna fuga da una sandbox lì dentro. Un solo comando senza HOME esplicito basta a ricollegare un test che si crede isolato alla tua vera directory personale, e quindi agli skill già installati per altri strumenti, mai dichiarati nel progetto. Il comando stesso è rivelatore: non esiste nessun opencode skill list al primo livello, bisogna passare da opencode debug skill, uno strumento di diagnostica.

MCP: configurare e interrogare un server locale

Il file di configurazione del progetto dichiara un server MCP locale, i permessi associati, e restringe l’accesso allo strumento per l’agente 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 } }
  }
}

Il server, mcp/serveur.mjs, è uno script Node autonomo di una quarantina di righe che parla JSON-RPC 2.0 sull’ingresso standard ed espone un solo strumento, 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 conferma la connessione:

bash
opencode mcp list

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

1 server(s)

Uno skill di progetto, slug-gekkode, spiega la regola di business (cinque parole massimo, senza articolo) e rimanda allo strumento. Un andirivieni con opencode run attiva entrambi in sequenza (output ripulito dai codici colore e dalle icone, contenuto invariato):

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

Il nome dello strumento mostrato, slug_slug_fr, mostra la convenzione di denominazione. OpenCode prefissa ogni strumento MCP con il nome del server dichiarato nella config (slug), accostato al nome dello strumento esposto (slug_fr), da cui la ripetizione. Il modello ha scelto lo skill sulla sua descrizione, chiamato lo strumento, poi ricalcolato il risultato a mano per rispettare la regola delle cinque parole. Uno skill che completa uno strumento invece di sostituirlo si comporta esattamente così. Per un server remoto, la documentazione descrive un blocco "type": "remote" con url e headers o oauth, più opencode mcp auth per il flusso OAuth. L’argomento è approfondito nel nostro articolo sulla creazione di un server MCP in PHP.

Agenti e permessi, regola per regola

opencode agent list mostra otto agenti in questo progetto: build (agente principale predefinito, accesso ampio), plan (principale, lettura e pianificazione), compaction, summary e title (interni), explore e general (sottoagenti), e relecteur, dichiarato 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.

Ogni permesso accetta allow, ask o deny, per pattern glob, con la regola più specifica che vince. L’impostazione vale per edit, bash, webfetch, skill, e persino per uno strumento MCP preciso come slug_*. L’agente plan del progetto illustra il principio: la sua configurazione disattiva lo strumento slug_* e autorizza la scrittura solo in .opencode/plans/*.md, mai nel codice. In modalità non interattiva, senza terminale per rispondere a una domanda, un permesso ask non resta in attesa: viene automaticamente respinto:

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

Il comportamento predefinito è quindi chiuso: senza sorveglianza umana, OpenCode fallisce piuttosto che eseguire un comando non esplicitamente autorizzato. Il codice di uscita resta però a 0 nonostante il fallimento, una trappola per chi scripta una verifica su questo. L’argomento dei permessi e della sandbox, comune a tutti questi agenti, è approfondito nel nostro articolo sugli agenti di codice, sandbox e permessi.

I modelli: una prova gratuita, e il caso dei modelli locali

Senza account né chiave, opencode run "dis bonjour" funziona dalla prima riga di comando. Il modello usato per impostazione predefinita, big-pickle («stealth model» secondo la sua scheda), fa parte dei sei modelli gratuiti di OpenCode Zen, la passerella di casa. Gli altri cinque sono MiMo-V2.5 Free, Ling 3.0 Flash Fin Free, due varianti di Nemotron 3 e Muse Spark 1.3 Contributor Free. Il database SQLite locale (tabella message) conserva la traccia dello scambio. Le tabelle credential e account restano a zero righe: nessun identificativo richiesto né memorizzato per questo modello, e un costo nullo nel log di sessione.

Un modello di marca dello stesso catalogo (GPT, Claude, Gemini, Grok, DeepSeek, Qwen…) richiede un account OpenCode Zen e un mezzo di pagamento. La fatturazione avviene a token, da 0,20 $ a diversi dollari al milione a seconda del modello. Il saldo si ricarica automaticamente di 20 $ non appena scende sotto i 5 $.

Per un modello locale, la verifica è semplice:

bash
which ollama
# ollama not found

Il catalogo di modelli messo in cache da OpenCode propone solo un fornitore cloud, ollama-cloud (chiave OLLAMA_API_KEY), nessuna voce dedicata per un Ollama locale. Per un server locale, Ollama, llama.cpp o LM Studio, la documentazione descrive un fornitore generico compatibile OpenAI da dichiarare da soli:

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" } }
    }
  }
}

La porta 11434 e l’API nativa (/api/generate, tra le altre) sono documentate su docs.ollama.com. La compatibilità OpenAI che esige @ai-sdk/openai-compatible si risolve in due chiamate, verificate su un Ollama 0.34.0 lanciato in 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}}

La forma è proprio quella che si aspetta l’SDK: object: "list" sul catalogo, oggetto chat.completion completo con choices, finish_reason e usage sul completamento. Un modello sconosciuto risponde 404 con l’oggetto d’errore OpenAI, e l’intestazione Authorization è accettata qualunque sia il suo valore: il campo apiKey del fornitore può contenere qualsiasi cosa.

Cosa manca, visto da qui

Il panorama completo degli agenti di codice a riga di comando, punti di forza e debolezze rispetto a Claude Code, Codex, Gemini CLI e gli altri, è trattato a parte nel nostro confronto dedicato. La lista degli skill e la configurazione risolta sono accessibili solo tramite comandi di diagnostica, debug skill e debug config. Entrambi sono assenti dal menu principale: utili una volta che li si conosce, ma non proprio scopribili. L’archiviazione locale è ben reale: sessione, messaggi e chiamate di strumenti vivono in un database SQLite sul tuo disco, quindi «nessun dato inviato ai server di Anomaly» non equivale a «nulla viene scritto». E l’accesso gratuito si ferma al modello di casa: al primo modello di marca, si ritrovano l’account e la carta di credito che si ritroverebbero altrove.

Cosa ricordare

  • OpenCode (Anomaly, licenza MIT) si installa senza lasciare nulla sul sistema tramite npm install opencode-ai --prefix e un HOME isolato, versione testata: 1.18.29.
  • La configurazione si legge su tre livelli fusi: progetto (risalendo fino alla radice Git), globale (~/.config/opencode, mai ~/.opencode), e skill esterni caricati automaticamente da ~/.claude/skills e ~/.agents/skills.
  • Isolare HOME funziona, a condizione di esportarlo in ogni comando. Una dimenticanza riconnette OpenCode alla tua vera directory personale, skill di altri strumenti compresi: due skill-esca lo confermano, e un elenco senza HOME ne riporta 120.
  • Uno skill di progetto e uno strumento MCP locale funzionano insieme dal primo tentativo, senza identificativo, con il modello gratuito big-pickle di OpenCode Zen.
  • I permessi ask vengono automaticamente respinti in modalità non interattiva, ma il codice di uscita resta 0: da tenere d’occhio se scripti verifiche intorno a opencode run.
  • I modelli locali (Ollama, llama.cpp, LM Studio) passano da un fornitore generico compatibile OpenAI da dichiarare a mano, non da un’integrazione Ollama dedicata.

Errori frequenti

Isolare HOME protegge solo a metà Se un solo comando dimentica di esportare la variabile, OpenCode ricade sulla tua directory personale reale e carica gli skill già installati per altri strumenti.
~/.claude/skills e ~/.agents/skills sono letti automaticamente Non è un difetto di isolamento: la documentazione integrata lo conferma (external skills, auto-loaded). Su una macchina già equipaggiata per Claude Code, i suoi skill vi si ritrovano senza dichiarazione esplicita.
Nessun comando skill visibile La lista degli skill non compare in opencode --help: è nascosta sotto opencode debug skill, uno strumento di diagnostica che può cambiare senza preavviso.
~/.config/opencode, non ~/.opencode La documentazione integrata precisa esplicitamente questa trappola di denominazione, il secondo percorso viene ignorato in silenzio.
Un codice di uscita 0 nonostante un rifiuto di permesso In modalità non interattiva, un comando bash rifiutato fa fallire lo strumento ma opencode run termina comunque con il codice 0.

MCPOllamaOpenCodeSkills

Damien Flandrin Sviluppatore web dal 2010, creatore di Gekkode e di Email Impact. Ogni articolo è testato su un progetto reale prima della pubblicazione. Contatti
Newsletter

I nuovi test, tutorial e progetti, via e-mail.

Test riproducibili, codice versionato, risultati datati. Mai spam.