Tiny plugin lens for OpenCode Web.
Lens is a local reverse proxy that sits in front of opencode web, loads small web plugins, and injects them into the OpenCode Web HTML response. It exists because OpenCode's plugin API does not currently expose supported hooks for changing the bundled web UI.
git clone git@github.com:Flickwire-Agent/opencode-lens.git
cd opencode-lens
pnpm installStart OpenCode Web in one terminal:
opencode webStart Lens in another terminal:
OPENCODE_TARGET="http://127.0.0.1:5050" pnpm proxyOpen http://127.0.0.1:3000 instead of the direct OpenCode Web URL.
Use OPENCODE_WEB_PLUGINS for quick local installs:
OPENCODE_WEB_PLUGINS="../opencode-web-voice-plugin/lens.plugin.json" pnpm proxyOr create lens.config.json:
{
"plugins": ["../opencode-web-voice-plugin/lens.plugin.json"]
}Plugin entries can be local JavaScript files, remote JavaScript URLs, local JSON manifests, or inline manifest objects.
Plugins are enabled by default. To register a plugin but start with it disabled, use an object entry:
{
"plugins": [
{
"name": "Voice",
"description": "Adds a microphone button to the prompt composer.",
"path": "../opencode-web-voice-plugin/lens.plugin.json",
"enabled": false
}
]
}Lens adds a Lens Plugins section to the existing OpenCode Web settings modal. Open settings in OpenCode Web, choose Lens Plugins, then toggle registered plugins on or off.
Changing a plugin toggle reloads the OpenCode Web page so the current enabled plugin set is injected into the fresh UI. The Reload UI button in the same section reloads without changing plugin state.
Toggle state is stored locally in .lens-state.json by default. Override that path with LENS_STATE.
The minimal plugin is just browser JavaScript. Lens injects it as a module script.
const badge = document.createElement("div");
badge.textContent = "Lens plugin loaded";
badge.style.cssText = "position:fixed;right:12px;bottom:12px;z-index:2147483647";
document.body.appendChild(badge);Save that as plugin.js, then run:
OPENCODE_WEB_PLUGINS="./plugin.js" pnpm proxyFor HTML injection with optional JavaScript, use a JSON manifest:
{
"name": "hello-html",
"description": "Adds a small greeting banner to OpenCode Web.",
"html": "<div id=\"hello-lens\">Hello from Lens</div>",
"script": "./hello.js"
}The name and description fields appear in Lens settings. The html string is inserted before </head> when possible. The optional script path is resolved relative to the manifest file and injected as a module script.
OPENCODE_TARGET- direct OpenCode Web URL, defaults tohttp://127.0.0.1:5050.PORT- Lens proxy port, defaults to3000.OPENCODE_WEB_PLUGINS- comma-separated plugin paths or URLs.LENS_CONFIG- config file path, defaults tolens.config.json.LENS_STATE- plugin toggle state file, defaults to.lens-state.json.
pnpm typecheck
pnpm lint
pnpm format:check
pnpm build