
O OpenCode é um agente de código open source (Anomaly, licença MIT) que corre em terminal, em extensão de editor ou em aplicação de ambiente de trabalho. Instalado sem pôr nada no sistema, funciona logo no primeiro comando graças a um modelo gratuito e suporta servidores MCP e o formato de skills SKILL.md, incluindo os já instalados para outros agentes se não estiverem isolados. Os modelos locais passam por um fornecedor genérico compatível com OpenAI, não por uma integração Ollama dedicada.
Um agente de código open source promete não te prender a um único fornecedor. O modelo escolhe-se, o código fica na tua máquina, a licença é permissiva. Instalei o OpenCode sem tocar no sistema nem introduzir um único identificador, antes de descobrir que um export de variável esquecido basta para o fazer carregar os skills já instalados para outras ferramentas.
OpenCode, três interfaces sob licença MIT
O OpenCode é desenvolvido pela Anomaly e publicado sob licença MIT no repositório anomalyco/opencode, que exibia cerca de 206 000 estrelas a 7 de setembro de 2026. A ferramenta apresenta-se como «an open source agent that helps you write code in your terminal, IDE, or desktop». Existe em três interfaces: um cliente de terminal (TUI), uma extensão para editor e uma aplicação de ambiente de trabalho em beta para macOS, Windows e Linux.
Um LSP carrega-se em princípio automaticamente segundo a linguagem detetada, e mais de 75 fornecedores de modelos são suportados via Models.dev e o AI SDK, da API paga ao modelo local. No meu mini-projeto de teste, o registo anotou no entanto «all LSPs are disabled»: detetar a linguagem não chega, o servidor correspondente tem de estar presente para que a funcionalidade se ative. O site reivindica ainda «OpenCode does not store any of your code or context data». Nada sai para os servidores da Anomaly por defeito, mas tudo fica numa base SQLite local, como mostra a secção seguinte.
O OpenCode junta-se a uma lista já longa de agentes em linha de comandos: o nosso panorama dos agentes de código compara-os todos. Este artigo concentra-se no que se descobre ao instalar e desmontar este, peça por peça.
Instalar o OpenCode sem pôr nada no sistema
O pacote npm opencode-ai instala um binário compilado (opencode-darwin-arm64 neste Mac) por trás de um executável opencode.exe. Para não deixar nada nos locais globais, opta-se por um prefixo temporário do laboratório, com uma cache npm local e um HOME isolado para todos os comandos que se seguem:
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 --versionO comando devolve 1.18.29, publicada a 4 de setembro de 2026 às 23h47 segundo as releases do GitHub, três dias antes deste teste. Quinta versão em oito dias: 1.18.25 a 1.18.29 entre 28 de agosto e 4 de setembro. O registo npm confirma que se trata da última versão disponível. A documentação propõe também um script curl -fsSL https://opencode.ai/install | bash e pacotes Homebrew, Scoop ou pacman, mantive o npm para que toda a instalação coubesse numa pasta que se apaga no final.
A instalação não fica necessariamente por aí. Depois de lançados alguns comandos a partir do projeto, o OpenCode instalou por sua conta 54 MB de dependências em .opencode/node_modules, sem o pedir: o seu próprio SDK de plugin, a biblioteca effect, e uma presença mais surpreendente, kubernetes-types. Um .opencode/.gitignore já estava pronto a excluí-las do controlo Git.
Onde o OpenCode lê a sua configuração
Depois de isolado o HOME, o comando opencode debug paths, uma subferramenta de diagnóstico ausente do menu principal, mostra a estrutura à moda XDG que o OpenCode construiu para si neste falso diretório pessoal (caminhos encurtados para leitura):
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/opencodeO ficheiro opencode.log escrito em data/log detalha a ordem de leitura exata no arranque: primeiro a pasta de configuração global (opencode.json, .jsonc), depois, a partir da pasta corrente, opencode.json e .opencode/opencode.json do projeto. O skill integrado no binário, legível com opencode debug skill, documenta a mesma hierarquia, com uma tabela que vale a pena reproduzir:
| Âmbito | Caminho |
|---|---|
| Config do projeto | ./opencode.json, ./opencode.jsonc ou .opencode/opencode.json (procurado subindo da pasta corrente até à raiz do repositório Git) |
| Config global | ~/.config/opencode/opencode.json ou .jsonc, nunca ~/.opencode/ |
| Skills do projeto | .opencode/skill(s)/<nom>/SKILL.md |
| Skills globais | ~/.config/opencode/skill(s)/<nom>/SKILL.md |
| Skills externos (carregados automaticamente) | ~/.claude/skills/<nom>/SKILL.md, ~/.agents/skills/<nom>/SKILL.md |
As configurações de cada âmbito são fundidas (deep-merge), com o projeto a prevalecer sobre o global. A última linha da tabela é a que vai mais longe. O OpenCode lê, sem declaração suplementar, os skills já instalados para o Claude Code e para outros agentes compatíveis com o standard aberto Agent Skills, descrito no nosso guia do SKILL.md.
Os skills: até onde vai a descoberta automática?
Para verificar o que diz a documentação embutida, acrescentei dois skills-isco diretamente no falso HOME, no local exato onde o OpenCode diz procurá-los, antes de relançar o mesmo diagnóstico:
mkdir -p home/.claude/skills/decoy-claude home/.agents/skills/decoy-agents
# um SKILL.md mínimo (frontmatter name + description) em cada pasta
opencode debug skillResultado: quatro skills detetados, o skill integrado, o skill do projeto, e os dois iscos, cada um com o seu caminho completo em home/.claude/skills/… e home/.agents/skills/…. O OpenCode limita-se a respeitar a variável HOME que lhe é dada, apenas olha mais longe do que a sua própria pasta de configuração.
Sem HOME reexportado no comando, a mesma listagem recai no verdadeiro diretório pessoal da máquina e traz 120 skills, os realmente instalados para o Claude Code e para outros agentes. Nenhuma fuga de sandbox aí dentro. Um único comando sem HOME explícito basta para colar de novo um teste que se acredita isolado ao teu diretório pessoal real, e portanto aos skills já instalados para outras ferramentas, nunca declarados no projeto. O próprio comando é revelador: não existe nenhum opencode skill list ao primeiro nível, é preciso passar por opencode debug skill, uma ferramenta de diagnóstico.
MCP: configurar e interrogar um servidor local
O ficheiro de configuração do projeto declara um servidor MCP local, as permissões associadas, e restringe o acesso à ferramenta para o agente plan:
{
"$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 } }
}
}O servidor, mcp/serveur.mjs, é um script Node autónomo de umas quarenta linhas que fala JSON-RPC 2.0 na entrada padrão e expõe uma única ferramenta, slug_fr:
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 confirma a ligação:
opencode mcp list
MCP Servers
slug connected
node ./mcp/serveur.mjs
1 server(s)Um skill de projeto, slug-gekkode, explica a regra de negócio (cinco palavras no máximo, sem artigo) e remete para a ferramenta. Uma ida e volta com opencode run desencadeia as duas em sequência (saída limpa dos códigos de cor e dos ícones, conteúdo inalterado):
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-phpO nome de ferramenta exibido, slug_slug_fr, mostra a convenção de nomenclatura. O OpenCode prefixa cada ferramenta MCP com o nome do servidor declarado na configuração (slug), colado ao nome da ferramenta exposta (slug_fr), daí a repetição. O modelo escolheu o skill pela sua descrição, chamou a ferramenta, depois recalculou o resultado à mão para respeitar a regra das cinco palavras. Um skill que complementa uma ferramenta em vez de a substituir comporta-se exatamente assim. Para um servidor remoto, a documentação descreve um bloco "type": "remote" com url e headers ou oauth, mais opencode mcp auth para o fluxo OAuth. O assunto é aprofundado no nosso artigo sobre a criação de um servidor MCP em PHP.
Agentes e permissões, regra a regra
opencode agent list mostra oito agentes neste projeto: build (agente principal por defeito, acesso amplo), plan (principal, leitura e planeamento), compaction, summary e title (internos), explore e general (subagentes), e relecteur, declarado em .opencode/agents/relecteur.md:
---
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.Cada permissão aceita allow, ask ou deny, por padrão glob, com a regra mais específica a ganhar. A definição vale para edit, bash, webfetch, skill, e até para uma ferramenta MCP precisa como slug_*. O agente plan do projeto ilustra o princípio: a sua configuração desativa a ferramenta slug_* e só autoriza a escrita em .opencode/plans/*.md, nunca no código. Em modo não interativo, sem terminal para responder a uma pergunta, uma permissão ask não fica em espera: é automaticamente rejeitada:
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 $?
0O comportamento por defeito é portanto fechado: sem vigilância humana, o OpenCode falha em vez de executar um comando não explicitamente autorizado. O código de saída fica no entanto em 0 apesar da falha, uma armadilha para quem faz um script de verificação sobre isso. O tema das permissões e da sandbox, comum a todos estes agentes, é aprofundado no nosso artigo sobre agentes de código, sandbox e permissões.
Os modelos: um ensaio gratuito, e o caso dos modelos locais
Sem conta nem chave, opencode run "dis bonjour" funciona logo no primeiro comando. O modelo usado por defeito, big-pickle («stealth model» segundo a sua ficha), faz parte dos seis modelos gratuitos do OpenCode Zen, a passagem da casa. Os outros cinco são MiMo-V2.5 Free, Ling 3.0 Flash Fin Free, duas variantes do Nemotron 3 e Muse Spark 1.3 Contributor Free. A base SQLite local (tabela message) guarda o rasto da troca. As tabelas credential e account ficam a zero linhas: nenhum identificador pedido nem guardado para este modelo, e um custo nulo no registo de sessão.
Um modelo de marca do mesmo catálogo (GPT, Claude, Gemini, Grok, DeepSeek, Qwen…) exige uma conta OpenCode Zen e um meio de pagamento. A faturação faz-se ao token, de 0,20 $ a vários dólares o milhão consoante o modelo. O saldo recarrega-se automaticamente de 20 $ assim que desce abaixo de 5 $.
Para um modelo local, a verificação é simples:
which ollama
# ollama not foundO catálogo de modelos posto em cache pelo OpenCode só propõe um fornecedor cloud, ollama-cloud (chave OLLAMA_API_KEY), sem entrada dedicada para um Ollama local. Para um servidor local, Ollama, llama.cpp ou LM Studio, a documentação descreve um fornecedor genérico compatível com OpenAI a declarar por conta própria:
{
"$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" } }
}
}
}A porta 11434 e a API nativa (/api/generate, entre outras) estão documentadas em docs.ollama.com. A compatibilidade OpenAI que o @ai-sdk/openai-compatible exige resolve-se em duas chamadas, verificadas num Ollama 0.34.0 lançado em contentor:
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}}A forma é exatamente a que o SDK espera: object: "list" no catálogo, objeto chat.completion completo com choices, finish_reason e usage na conclusão. Um modelo desconhecido responde 404 com o objeto de erro OpenAI, e o cabeçalho Authorization é aceite seja qual for o seu valor: o campo apiKey do fornecedor pode conter qualquer coisa.
O que falta, visto daqui
O panorama completo dos agentes de código em linha de comandos, pontos fortes e fracos face ao Claude Code, ao Codex, ao Gemini CLI e aos outros, é tratado à parte no nosso comparativo dedicado. A lista dos skills e a configuração resolvida só são acessíveis por comandos de diagnóstico, debug skill e debug config. Ambos estão ausentes do menu principal: úteis uma vez que se conhecem, mas nada fáceis de descobrir. O armazenamento local é bem real: sessão, mensagens e chamadas de ferramentas vivem numa base SQLite no teu disco, logo «nenhum dado enviado aos servidores da Anomaly» não equivale a «nada é escrito». E o acesso gratuito para no modelo da casa: ao primeiro modelo de marca, encontra-se a conta e o cartão bancário que se encontrariam noutro lado.
A reter
- O OpenCode (Anomaly, licença MIT) instala-se sem pôr nada no sistema via
npm install opencode-ai --prefixe umHOMEisolado, versão testada: 1.18.29. - A configuração lê-se em três níveis fundidos: projeto (subindo até à raiz Git), global (
~/.config/opencode, nunca~/.opencode), e skills externos carregados automaticamente a partir de~/.claude/skillse~/.agents/skills. - Isolar o
HOMEfunciona, desde que se exporte em cada comando. Um esquecimento religa o OpenCode ao teu diretório pessoal real, skills de outras ferramentas incluídos: dois skills-isco confirmam-no, e uma listagem semHOMEtraz 120. - Um skill de projeto e uma ferramenta MCP local funcionam juntos logo no primeiro ensaio, sem identificador, com o modelo gratuito
big-pickledo OpenCode Zen. - As permissões
asksão automaticamente rejeitadas em modo não interativo, mas o código de saída fica em 0: a vigiar se fizeres scripts de verificação à volta deopencode run. - Os modelos locais (Ollama, llama.cpp, LM Studio) passam por um fornecedor genérico compatível com OpenAI a declarar à mão, não por uma integração Ollama dedicada.
Erros frequentes
opencode --help: está escondida sob opencode debug skill, uma ferramenta de diagnóstico que pode mudar sem aviso.opencode run termina na mesma com o código 0.

