diff --git a/CHANGELOG.md b/CHANGELOG.md index 09bc4cc..2e2a3bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - SemVer. ## [Unreleased] +## [1.0.1] - 2026-10-19 + +### Added + +- Installation straight from GitHub with the `github:` plugin specifier, verified end to + end (clone, cache, load, inference) with no npm publication and no build step. +- Troubleshooting section for the plugins-directory auto-discovery asymmetry: a plugin + removed from `opencode.json`, or renamed inside `~/.config/opencode/plugins/`, keeps + loading until the directory leaves `plugins/` (then the watcher drops it live). + +### Changed + +- README and configuration docs document three installation paths: GitHub specifier + (recommended), local clone, and the auto-discovered plugins directory. + ## [1.0.0] - 2026-10-18 First modular release. Migrates the single-file `commandcode-quota` plugin into a diff --git a/README.es.md b/README.es.md index 71e615a..082d023 100644 --- a/README.es.md +++ b/README.es.md @@ -112,14 +112,25 @@ un request): ## Instalacion -Clona el repositorio y apunta OpenCode al directorio: +### Opcion A: Directo desde GitHub (recomendada) + +```jsonc +// ~/.config/opencode/opencode.json +{ + "plugins": ["github:JoshRob297/opencode-commandcode"] +} +``` + +OpenCode clona, cachea y ejecuta el plugin desde el repositorio. Sin publicacion en npm y +sin build: el codigo fuente es TypeScript ejecutado por Bun. + +### Opcion B: Clon local ```bash git clone git@github.com:JoshRob297/opencode-commandcode.git ``` ```jsonc -// opencode.json { "plugins": [ "/ruta/absoluta/a/opencode-commandcode" @@ -127,6 +138,14 @@ git clone git@github.com:JoshRob297/opencode-commandcode.git } ``` +### Opcion C: directorio de plugins + +OpenCode tambien auto-descubre todo directorio dentro de `~/.config/opencode/plugins/`, +asi que un clon ahi se carga sin tocar `opencode.json`. La remocion no es simetrica: +borrar la entrada del config o renombrar el directorio **no** lo descarga; el directorio +tiene que salir de `plugins/` por completo. Ver +[TROUBLESHOOTING](docs/es/troubleshooting.md#plugin-cargado-dos-veces-o-un-plugin-eliminado-sigue-corriendo). + Reinicia OpenCode. En el siguiente arranque se descubre el catalogo de modelos, se registran la herramienta y el comando de barra, y se enganchan los hooks. diff --git a/README.md b/README.md index 116104a..12b665b 100644 --- a/README.md +++ b/README.md @@ -107,14 +107,25 @@ request): ## Installation -Clone the repository and point OpenCode at the directory: +### Option A: Direct from GitHub (recommended) + +```jsonc +// ~/.config/opencode/opencode.json +{ + "plugins": ["github:JoshRob297/opencode-commandcode"] +} +``` + +OpenCode clones, caches and runs the plugin straight from the repository. No npm +publication and no build step: the source is TypeScript executed by Bun. + +### Option B: Local clone ```bash git clone git@github.com:JoshRob297/opencode-commandcode.git ``` ```jsonc -// opencode.json { "plugins": [ "/absolute/path/to/opencode-commandcode" @@ -122,6 +133,14 @@ git clone git@github.com:JoshRob297/opencode-commandcode.git } ``` +### Option C: plugins directory + +OpenCode also auto-discovers every directory under `~/.config/opencode/plugins/`, so a +clone placed there loads without touching `opencode.json`. Removal is not symmetric: +deleting the config entry or renaming the directory **does not** unload it - the +directory has to leave `plugins/` entirely. See +[TROUBLESHOOTING](docs/TROUBLESHOOTING.md#plugin-loaded-twice-or-a-removed-plugin-still-runs). + Restart OpenCode. On the next start the model catalog is discovered, the toolbar tool and the slash command are registered, and the hooks are attached. diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 12ec17f..d672303 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -88,11 +88,13 @@ Logs are append-only and never rotated by the plugin. At the observed event rate ## OpenCode integration The plugin registers itself; only the provider block belongs in `opencode.json`. +Install it with the GitHub specifier (no npm, no build), a local clone, or by dropping it +into the auto-discovered plugins directory - see the readme for the three options. ```jsonc { "plugins": [ - "/absolute/path/to/opencode-commandcode" + "github:JoshRob297/opencode-commandcode" ], "providers": { "commandcode": { diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 86529cb..9cbead6 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -177,3 +177,41 @@ mkdir -p "${COMMANDCODE_STATE_DIR:-$HOME/.local/state/opencode}" && touch "$_/pr An empty sanitizer log is the normal state: it only gets an entry when a payload actually needed repair. + +## Plugin loaded twice, or a removed plugin still runs + +OpenCode loads plugins from two places: the `plugins` array in `opencode.json` **and** +every directory under `~/.config/opencode/plugins/` (auto-discovery). That asymmetry +explains the two confusing cases: + +| Symptom | Cause | +| --- | --- | +| A plugin removed from `plugins` is still listed by `opencode plugin list` | It lives in `~/.config/opencode/plugins/` and is picked up by the directory scan | +| A plugin renamed to `.disabled` inside that directory still loads | The scan takes any subdirectory, not only `.ts` files or the old name | + +What works and what does not: + +```bash +# does NOT unload it +# - removing the entry from opencode.json +# - renaming the directory inside plugins/ +# - rewriting opencode.json to force a reload + +# DOES unload it (the watcher drops it live) +mv ~/.config/opencode/plugins/your-plugin ~/somewhere-outside/your-plugin +``` + +Verify with: + +```bash +opencode plugin list +``` + +If the plugin is still listed after moving it out, the running service kept it in +memory: restart the background server (`opencode service stop`) and start OpenCode +again. Note that `opencode service restart` alone also works, but it drops the current +TUI connection. + +Two plugins registering `commandcode_quota` is not fatal - the sanitizer is idempotent, +so a second pass returns `modified: false`, and the tool is exposed once - but it doubles +the hook work and makes the telemetry confusing, so keep a single copy installed. diff --git a/docs/es/configuration.md b/docs/es/configuration.md index e7a1bd5..2a5237e 100644 --- a/docs/es/configuration.md +++ b/docs/es/configuration.md @@ -88,11 +88,13 @@ lineas por semana) no es un problema; si querés rotacion, apunta ## Integracion con OpenCode El plugin se registra solo; en `opencode.json` unicamente va el bloque del provider. +Se instala con el especificador de GitHub (sin npm, sin build), con un clon local, o +dejandolo en el directorio de plugins auto-descubierto (ver el readme para las tres opciones). ```jsonc { "plugins": [ - "/ruta/absoluta/a/opencode-commandcode" + "github:JoshRob297/opencode-commandcode" ], "providers": { "commandcode": { diff --git a/docs/es/troubleshooting.md b/docs/es/troubleshooting.md index 4c90b14..4f29a46 100644 --- a/docs/es/troubleshooting.md +++ b/docs/es/troubleshooting.md @@ -179,3 +179,42 @@ mkdir -p "${COMMANDCODE_STATE_DIR:-$HOME/.local/state/opencode}" && touch "$_/pr Un log de sanitizador vacio es el estado normal: solo recibe una entrada cuando un payload realmente necesito reparacion. + +## Plugin cargado dos veces, o un plugin eliminado sigue corriendo + +OpenCode carga plugins desde dos lugares: el array `plugins` de `opencode.json` **y** +todo directorio dentro de `~/.config/opencode/plugins/` (auto-descubrimiento). Esa +asimetria explica los dos casos confusos: + +| Sintoma | Causa | +| --- | --- | +| Un plugin que quitaste de `plugins` sigue apareciendo en `opencode plugin list` | Vive en `~/.config/opencode/plugins/` y lo toma el scan de directorio | +| Un plugin renombrado a `.disabled` dentro de ese directorio igual se carga | El scan toma cualquier subdirectorio, no solo archivos `.ts` ni el nombre original | + +Que funciona y que no: + +```bash +# NO lo descarga +# - quitar la entrada de opencode.json +# - renombrar el directorio dentro de plugins/ +# - reescribir opencode.json para forzar un reload + +# SI lo descarga (el watcher lo suelta en vivo) +mv ~/.config/opencode/plugins/tu-plugin ~/fuera-del-directorio/tu-plugin +``` + +Verifica con: + +```bash +opencode plugin list +``` + +Si el plugin sigue listado despues de moverlo, el servicio en ejecucion lo mantuvo en +memoria: reinicia el servidor en background (`opencode service stop`) y volve a abrir +OpenCode. Nota que `opencode service restart` por si solo tambien sirve, pero corta la +conexion del TUI actual. + +Dos plugins registrando `commandcode_quota` no es fatal - el sanitizador es idempotente, +asi que la segunda pasada devuelve `modified: false`, y el tool se expone una sola vez - +pero duplica el trabajo de los hooks y enturbia la telemetria, asi que mantene una sola +copia instalada. diff --git a/package.json b/package.json index dcfb3ed..c4d3b8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "opencode-commandcode", - "version": "1.0.0", + "version": "1.0.1", "description": "Production-grade OpenCode plugin for Command Code: dynamic model discovery, stability hooks and quota telemetry", "main": "index.ts", "type": "module",