OpenCode: o agente de código open source, instalado e desmontado

O OpenCode instala-se sem conta e responde logo no primeiro comando com um modelo gratuito, carrega também, sem o dizer, os skills já instalados para outras ferramentas se esqueceres de isolar o teu diretório pessoal.

OpenCode: o agente de código open source, instalado e desmontado
Resposta rápida

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:

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

O 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):

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

O 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:

bash
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 skill

Resultado: 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:

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

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:

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 confirma a ligação:

bash
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):

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

O 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:

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.

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:

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

O 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:

bash
which ollama
# ollama not found

O 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:

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

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:

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

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 --prefix e um HOME isolado, 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/skills e ~/.agents/skills.
  • Isolar o HOME funciona, 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 sem HOME traz 120.
  • Um skill de projeto e uma ferramenta MCP local funcionam juntos logo no primeiro ensaio, sem identificador, com o modelo gratuito big-pickle do OpenCode Zen.
  • As permissões ask sã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 de opencode 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

Isolar o HOME só protege a meias Se um único comando esquecer de exportar a variável, o OpenCode recai no teu diretório pessoal real e carrega os skills já instalados para outras ferramentas.
~/.claude/skills e ~/.agents/skills são lidos automaticamente Não é uma falha de isolamento: a documentação embutida confirma-o (external skills, auto-loaded). Numa máquina já equipada para o Claude Code, os seus skills aparecem aí sem declaração explícita.
Nenhum comando skill visível A lista dos skills não aparece em opencode --help: está escondida sob opencode debug skill, uma ferramenta de diagnóstico que pode mudar sem aviso.
~/.config/opencode, não ~/.opencode A documentação embutida esclarece explicitamente esta armadilha de nomenclatura, o segundo caminho é ignorado em silêncio.
Um código de saída 0 apesar de uma recusa de permissão Em modo não interativo, um comando bash recusado faz falhar a ferramenta mas o opencode run termina na mesma com o código 0.

MCPOllamaOpenCodeSkills

Damien Flandrin Programador web desde 2010, criador da Gekkode e do Email Impact. Cada artigo é testado num projeto real antes de ser publicado. Contacto
Newsletter

Os novos testes, tutoriais e projetos, por e-mail.

Testes reproduzíveis, código versionado, resultados datados. Nunca spam.