OpenCode: el agente de código abierto, instalado y desmontado

OpenCode se instala sin cuenta y responde desde el primer comando con un modelo gratuito, también carga, sin decirlo, los skills ya instalados para otras herramientas si olvidas aislar tu directorio personal.

OpenCode: el agente de código abierto, instalado y desmontado
Respuesta rápida

OpenCode es un agente de código de código abierto (Anomaly, licencia MIT) que funciona en terminal, en extensión de editor o en aplicación de escritorio. Instalado sin dejar nada en el sistema, funciona desde el primer comando gracias a un modelo gratuito y soporta servidores MCP y el formato de skills SKILL.md, incluidos los ya instalados para otros agentes si no están aislados. Los modelos locales pasan por un proveedor genérico compatible con OpenAI, no por una integración de Ollama dedicada.

Un agente de código de código abierto promete no encerrarte en un solo editor. El modelo se elige, el código se queda en tu máquina, la licencia es permisiva. Instalé OpenCode sin tocar el sistema ni introducir un solo identificador, antes de descubrir que un export de variable olvidado basta para hacerle cargar los skills ya instalados para otras herramientas.

OpenCode, tres interfaces bajo licencia MIT

OpenCode está desarrollado por Anomaly y publicado bajo licencia MIT en el repositorio anomalyco/opencode, que mostraba unas 206.000 estrellas el 7 de septiembre de 2026. La herramienta se presenta como «an open source agent that helps you write code in your terminal, IDE, or desktop». Se ofrece en tres interfaces: un cliente de terminal (TUI), una extensión para editor y una aplicación de escritorio en beta para macOS, Windows y Linux.

Un LSP se carga en principio automáticamente según el lenguaje detectado, y más de 75 proveedores de modelos están soportados vía Models.dev y el AI SDK, desde la API de pago hasta el modelo local. En mi miniproyecto de prueba, el registro anotó sin embargo «all LSPs are disabled»: detectar el lenguaje no basta, el servidor correspondiente debe estar presente para que la funcionalidad se active. El sitio afirma además que «OpenCode does not store any of your code or context data». Nada sale hacia los servidores de Anomaly por defecto, pero todo queda en una base SQLite local, como muestra la sección siguiente.

OpenCode se suma a una lista ya larga de agentes en línea de comandos: nuestro panorama de los agentes de código los compara todos. Este artículo se centra en lo que se descubre al instalar y desmontar este en concreto, pieza por pieza.

Instalar OpenCode sin dejar nada en el sistema

El paquete npm opencode-ai instala un binario compilado (opencode-darwin-arm64 en este Mac) detrás de un ejecutable opencode.exe. Para no dejar nada en las ubicaciones globales, usamos un prefijo temporal del laboratorio, con una caché npm local y un HOME aislado para todos los comandos que siguen:

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

El comando devuelve 1.18.29, publicada el 4 de septiembre de 2026 a las 23:47 según las releases de GitHub, tres días antes de esta prueba. Quinta versión en ocho días: de la 1.18.25 a la 1.18.29 entre el 28 de agosto y el 4 de septiembre. El registro npm confirma que se trata de la última versión disponible. La documentación también propone un script curl -fsSL https://opencode.ai/install | bash y paquetes Homebrew, Scoop o pacman, mantuve npm para que toda la instalación cupiera en una carpeta que se elimina al final.

La instalación no se detiene necesariamente ahí. Tras lanzar unos cuantos comandos desde el proyecto, OpenCode instaló por su cuenta 54 MB de dependencias en .opencode/node_modules, sin pedirlo: su propio SDK de plugins, la biblioteca effect, y una presencia más sorprendente, kubernetes-types. Un .opencode/.gitignore ya estaba listo para excluirlas del seguimiento de Git.

Dónde lee OpenCode su configuración

Una vez aislado HOME, el comando opencode debug paths, una subherramienta de diagnóstico ausente del menú principal, muestra la estructura al estilo XDG que OpenCode se ha construido en ese falso directorio personal (rutas acortadas para facilitar la lectura):

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

El archivo opencode.log escrito en data/log detalla el orden exacto de lectura al arrancar: primero la carpeta de configuración global (opencode.json, .jsonc), luego, partiendo de la carpeta actual, opencode.json y .opencode/opencode.json del proyecto. El skill integrado en el binario, legible con opencode debug skill, documenta la misma jerarquía, con una tabla que merece copiarse:

Ámbito Ruta
Configuración del proyecto ./opencode.json, ./opencode.jsonc o .opencode/opencode.json (buscada subiendo desde la carpeta actual hasta la raíz del repositorio Git)
Configuración global ~/.config/opencode/opencode.json o .jsonc, no ~/.opencode/
Skills del proyecto .opencode/skill(s)/<nom>/SKILL.md
Skills globales ~/.config/opencode/skill(s)/<nom>/SKILL.md
Skills externos (cargados automáticamente) ~/.claude/skills/<nom>/SKILL.md, ~/.agents/skills/<nom>/SKILL.md

Las configuraciones de cada ámbito se fusionan (deep-merge), con el proyecto prevaleciendo sobre lo global. La última línea de la tabla es la que llega más lejos. OpenCode lee, sin ninguna declaración adicional, los skills ya instalados para Claude Code y para otros agentes compatibles con el estándar abierto Agent Skills, descrito en nuestra guía del SKILL.md.

Los skills: ¿hasta dónde llega el descubrimiento automático?

Para comprobar lo que dice la documentación embebida, añadí dos skills-señuelo directamente en el falso HOME, en el lugar exacto donde OpenCode dice buscarlos, antes de relanzar el mismo diagnóstico:

bash
mkdir -p home/.claude/skills/decoy-claude home/.agents/skills/decoy-agents
# un SKILL.md mínimo (frontmatter name + description) en cada carpeta
opencode debug skill

Resultado: cuatro skills detectados, el skill integrado, el skill del proyecto, y los dos señuelos, cada uno con su ruta completa en home/.claude/skills/… y home/.agents/skills/…. OpenCode simplemente respeta la variable HOME que se le da, solo mira más allá de su propia carpeta de configuración.

Sin HOME reexportado en el comando, el mismo listado vuelve a caer en el directorio personal real de la máquina y saca 120 skills, los realmente instalados para Claude Code y para otros agentes. Ninguna fuga de sandbox ahí dentro. Basta un solo comando sin HOME explícito para pegar de nuevo una prueba que se cree aislada a tu directorio personal real, y por tanto a los skills ya instalados para otras herramientas, nunca declarados en el proyecto. El comando en sí es revelador: no existe ningún opencode skill list en el primer nivel, hay que pasar por opencode debug skill, una herramienta de diagnóstico.

MCP: configurar e interrogar un servidor local

El archivo de configuración del proyecto declara un servidor MCP local, los permisos asociados, y restringe el acceso a la herramienta para el 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 } }
  }
}

El servidor, mcp/serveur.mjs, es un script Node autónomo de una cuarentena de líneas que habla JSON-RPC 2.0 sobre la entrada estándar y expone una sola herramienta, 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 la conexión:

bash
opencode mcp list

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

1 server(s)

Un skill del proyecto, slug-gekkode, explica la regla de negocio (cinco palabras como máximo, sin artículo) y remite a la herramienta. Un ida y vuelta con opencode run activa las dos seguidas (salida limpiada de los códigos de color y los iconos, contenido sin cambios):

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

El nombre de herramienta mostrado, slug_slug_fr, muestra la convención de nomenclatura. OpenCode antepone a cada herramienta MCP el nombre del servidor declarado en la configuración (slug), pegado al nombre de la herramienta expuesta (slug_fr), de ahí la repetición. El modelo eligió el skill por su descripción, llamó a la herramienta, y luego recalculó el resultado a mano para respetar la regla de las cinco palabras. Un skill que complementa una herramienta en vez de sustituirla se comporta exactamente así. Para un servidor remoto, la documentación describe un bloque "type": "remote" con url y headers u oauth, más opencode mcp auth para el flujo OAuth. El tema se profundiza en nuestro artículo sobre la creación de un servidor MCP en PHP.

Agentes y permisos, regla por regla

opencode agent list muestra ocho agentes en este proyecto: build (agente principal por defecto, acceso amplio), plan (principal, lectura y planificación), compaction, summary y title (internos), explore y general (subagentes), y relecteur, declarado en .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 permiso acepta allow, ask o deny, por patrón glob, con la regla más específica ganando. El ajuste vale para edit, bash, webfetch, skill, e incluso para una herramienta MCP concreta como slug_*. El agente plan del proyecto ilustra el principio: su configuración desactiva la herramienta slug_* y solo autoriza la escritura en .opencode/plans/*.md, nunca en el código. En modo no interactivo, sin terminal para responder a una pregunta, un permiso ask no se deja pendiente: se rechaza automáticamente:

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

El comportamiento por defecto es, por tanto, cerrado: sin supervisión humana, OpenCode falla en vez de ejecutar un comando no autorizado explícitamente. El código de salida se queda sin embargo en 0 pese al fallo, una trampa para quien script una comprobación sobre eso. El tema de los permisos y del sandbox, común a todos estos agentes, se profundiza en nuestro artículo sobre agentes de código, sandbox y permisos.

Los modelos: una prueba gratuita, y el caso de los modelos locales

Sin cuenta ni clave, opencode run "dis bonjour" funciona desde el primer comando. El modelo usado por defecto, big-pickle («stealth model» según su ficha), forma parte de los seis modelos gratuitos de OpenCode Zen, la pasarela propia. Los otros cinco son MiMo-V2.5 Free, Ling 3.0 Flash Fin Free, dos variantes de Nemotron 3 y Muse Spark 1.3 Contributor Free. La base SQLite local (tabla message) guarda el rastro del intercambio. Las tablas credential y account se quedan en cero filas: ningún identificador pedido ni guardado para ese modelo, y un coste nulo en el registro de sesión.

Un modelo de marca del mismo catálogo (GPT, Claude, Gemini, Grok, DeepSeek, Qwen…) exige una cuenta OpenCode Zen y un método de pago. La facturación se hace por token, de 0,20 $ a varios dólares el millón según el modelo. El saldo se recarga automáticamente de 20 $ en cuanto baja de 5 $.

Para un modelo local, la comprobación es sencilla:

bash
which ollama
# ollama no encontrado

El catálogo de modelos cacheado por OpenCode solo ofrece un proveedor en la nube, ollama-cloud (clave OLLAMA_API_KEY), sin entrada dedicada para un Ollama local. Para un servidor local, Ollama, llama.cpp o LM Studio, la documentación describe un proveedor genérico compatible con OpenAI que hay que declarar uno mismo:

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

El puerto 11434 y la API nativa (/api/generate, entre otras) están documentados en docs.ollama.com. La compatibilidad con OpenAI que exige @ai-sdk/openai-compatible se resuelve en dos llamadas, verificadas sobre un Ollama 0.34.0 lanzado en contenedor:

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 es exactamente la que espera el SDK: object: "list" en el catálogo, objeto chat.completion completo con choices, finish_reason y usage en la compleción. Un modelo desconocido responde 404 con el objeto de error de OpenAI, y la cabecera Authorization se acepta sea cual sea su valor: el campo apiKey del proveedor puede contener cualquier cosa.

Lo que falta, visto desde aquí

El panorama completo de los agentes de código en línea de comandos, fortalezas y debilidades frente a Claude Code, Codex, Gemini CLI y los demás, se trata aparte en nuestro comparativo dedicado. La lista de skills y la configuración resuelta solo son accesibles mediante comandos de diagnóstico, debug skill y debug config. Ambos están ausentes del menú principal: útiles una vez que se conocen, pero poco descubribles. El almacenamiento local es bien real: sesión, mensajes y llamadas a herramientas viven en una base SQLite en tu disco, así que «ningún dato enviado a los servidores de Anomaly» no equivale a «nada se escribe». Y el acceso gratuito se detiene en el modelo propio: en cuanto llega el primer modelo de marca, aparecen la cuenta y la tarjeta bancaria que se encontrarían en cualquier otro sitio.

Lo que hay que recordar

  • OpenCode (Anomaly, licencia MIT) se instala sin dejar nada en el sistema vía npm install opencode-ai --prefix y un HOME aislado, versión probada: 1.18.29.
  • La configuración se lee en tres niveles fusionados: proyecto (subiendo hasta la raíz Git), global (~/.config/opencode, nunca ~/.opencode), y skills externos cargados automáticamente desde ~/.claude/skills y ~/.agents/skills.
  • Aislar HOME funciona, siempre que se exporte en cada comando. Un olvido reconecta OpenCode a tu directorio personal real, skills de otras herramientas incluidos: dos skills-señuelo lo confirman, y un listado sin HOME saca 120.
  • Un skill de proyecto y una herramienta MCP local funcionan juntos desde el primer intento, sin identificador, con el modelo gratuito big-pickle de OpenCode Zen.
  • Los permisos ask se rechazan automáticamente en modo no interactivo, pero el código de salida se queda en 0: hay que vigilarlo si se scriptan comprobaciones alrededor de opencode run.
  • Los modelos locales (Ollama, llama.cpp, LM Studio) pasan por un proveedor genérico compatible con OpenAI que hay que declarar a mano, no por una integración de Ollama dedicada.

Errores frecuentes

Aislar HOME solo protege a medias Si un solo comando olvida exportar la variable, OpenCode vuelve a caer en tu directorio personal real y carga los skills ya instalados para otras herramientas.
~/.claude/skills y ~/.agents/skills se leen automáticamente No es un fallo de aislamiento: la documentación embebida lo confirma (external skills, auto-loaded). En una máquina ya equipada para Claude Code, sus skills aparecen ahí sin declaración explícita.
Sin comando skill visible La lista de skills no aparece en opencode --help: está escondida bajo opencode debug skill, una herramienta de diagnóstico que puede cambiar sin previo aviso.
~/.config/opencode, no ~/.opencode La documentación embebida precisa explícitamente esta trampa de nomenclatura, la segunda ruta se ignora en silencio.
Un código de salida 0 pese a un rechazo de permiso En modo no interactivo, un comando bash rechazado hace fallar la herramienta, pero opencode run termina de todos modos con el código 0.

MCPOllamaOpenCodeSkills

Damien Flandrin Desarrollador web desde 2010, creador de Gekkode y de Email Impact. Cada artículo se prueba en un proyecto real antes de publicarse. Contacto
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.