Description
opencode v1.14.42 silently removed the entire api.command namespace from the public TUI plugin API (api.command.register, api.command.trigger, api.command.show) in PR #26053 ("introduce opentui keymap as sole key/cmd engine"). The replacement is api.keymap.registerLayer({ commands, bindings }).
There was no deprecation cycle, no console warning, and no mention in the v1.14.42 or v1.14.43 release notes. Plugins that used the public API now crash on init with:
TypeError: undefined is not an object (evaluating 'api.command.register')
Because the crash happens during TUI plugin init, api.slots.register(...) never runs — so affected plugins not only lose their command palette entries, they also disappear entirely from the sidebar. To the user it looks like the plugin was uninstalled.
Not a duplicate of #26546. #26546 covers the cascading bootstrap crash introduced by the same PR (terminal goes blank on startup), and it was fixed in v1.14.43. This issue is about the underlying public-API removal — which is not fixed in v1.14.43: TUI plugins that call api.command.* still crash on 1.14.43 (just no longer crashing the whole TUI host). The bot pattern-matched on api.command; the surface area and the resolution are different.
Why this is a problem
A breaking change to a public, documented plugin API inside a patch-version bump is bad practice for any project — even one whose audience is plugin authors. Concretely:
- Semver violation.
1.14.41 → 1.14.42 is a patch bump. Removing a public API (not even renaming it under the same shape) is unambiguously breaking.
- No deprecation cycle. The new
api.keymap.registerLayer could have been added in one release with api.command.* kept as a thin shim that delegated to the new code (and emitted a one-time console.warn naming the new API). Removal could have happened in a follow-up minor.
- Missing changelog entry. v1.14.42 release notes mention "Scout agent", HTTP compression, footer mode, etc. — but nothing about the TUI plugin API surface change. v1.14.43 is the same.
- No migration guide. The new
api.keymap.registerLayer({ commands, bindings }) shape is documented in packages/opencode/specs/tui-plugins.md, but there is no "porting from api.command.register" note pointing existing plugin authors at it. Plugin authors find out by getting bug reports.
- The bundled
@opencode-ai/plugin types still declare the old surface for many users (~/.opencode/node_modules/@opencode-ai/plugin/dist/tui.d.ts is still 1.14.29 here). Plugin authors who type-check against those types get no compile-time signal that they should migrate. The runtime crash is the first they hear about it.
Suggested remediation
- Re-add
api.command as a thin compat shim that calls into the new api.keymap registry under the hood (with a one-time console.warn naming api.keymap.registerLayer as the replacement). Mark it @deprecated in the type definitions.
- Document the migration in the next release notes, ideally in a dedicated "Plugin API" section.
- For future API removals: at least one minor-bump deprecation window where the old API still works but warns, then a clean removal in the next minor.
- Consider a small
BREAKING_CHANGES.md for the plugin surface specifically — plugin authors don't read every release note, but they will read a file that exists for them.
Plugins
@cortexkit/opencode-magic-context@0.17.2, @cortexkit/aft-opencode@0.20.1, local concord plugin (all three call api.command.register(...) unconditionally with no fallback).
OpenCode version
1.14.42 (also confirmed broken on 1.14.43)
Steps to reproduce
bun add -g opencode-ai@1.14.43
- Install any TUI plugin that calls
api.command.register(...) — e.g. @cortexkit/aft-opencode@latest in ~/.config/opencode/tui.json plugin array.
- Hard-restart opencode (
pkill -f 'opencode-ai/bin/.opencode' from a separate terminal, then relaunch).
- Plugin's sidebar pane is missing. Check
~/.local/share/opencode/log/*.log for the TypeError: undefined is not an object (evaluating 'api.command.register') entry.
Affected plugins observed on this machine:
| Plugin |
Source path |
Failing call site |
@cortexkit/opencode-magic-context@0.17.2 |
src/tui/index.tsx |
line 468 |
@cortexkit/aft-opencode@0.20.1 |
src/tui/index.tsx |
line 206 |
Local concord plugin (now patched) |
tui/index.tsx |
line 503 |
Stack trace excerpt (identical for all three):
ERROR service=tui.plugin path=@cortexkit/aft-opencode@latest id=aft-opencode
error={"type":"TypeError","message":"undefined is not an object (evaluating 'api.command.register')",
"stack":"...at tui (.../@cortexkit/aft-opencode/src/tui/index.tsx:188:7)..."}
failed to initialize tui plugin
Screenshot and/or share link
N/A — see log excerpt above. Filed in parallel: cortexkit/aft#33 and a comment on cortexkit/magic-context#61.
Operating System
macOS 15.2 (Darwin 24.x, arm64)
Terminal
Ghostty
Description
opencode
v1.14.42silently removed the entireapi.commandnamespace from the public TUI plugin API (api.command.register,api.command.trigger,api.command.show) in PR #26053 ("introduce opentui keymap as sole key/cmd engine"). The replacement isapi.keymap.registerLayer({ commands, bindings }).There was no deprecation cycle, no console warning, and no mention in the v1.14.42 or v1.14.43 release notes. Plugins that used the public API now crash on init with:
Because the crash happens during TUI plugin init,
api.slots.register(...)never runs — so affected plugins not only lose their command palette entries, they also disappear entirely from the sidebar. To the user it looks like the plugin was uninstalled.Why this is a problem
A breaking change to a public, documented plugin API inside a patch-version bump is bad practice for any project — even one whose audience is plugin authors. Concretely:
1.14.41 → 1.14.42is a patch bump. Removing a public API (not even renaming it under the same shape) is unambiguously breaking.api.keymap.registerLayercould have been added in one release withapi.command.*kept as a thin shim that delegated to the new code (and emitted a one-timeconsole.warnnaming the new API). Removal could have happened in a follow-up minor.api.keymap.registerLayer({ commands, bindings })shape is documented inpackages/opencode/specs/tui-plugins.md, but there is no "porting fromapi.command.register" note pointing existing plugin authors at it. Plugin authors find out by getting bug reports.@opencode-ai/plugintypes still declare the old surface for many users (~/.opencode/node_modules/@opencode-ai/plugin/dist/tui.d.tsis still1.14.29here). Plugin authors who type-check against those types get no compile-time signal that they should migrate. The runtime crash is the first they hear about it.Suggested remediation
api.commandas a thin compat shim that calls into the newapi.keymapregistry under the hood (with a one-timeconsole.warnnamingapi.keymap.registerLayeras the replacement). Mark it@deprecatedin the type definitions.BREAKING_CHANGES.mdfor the plugin surface specifically — plugin authors don't read every release note, but they will read a file that exists for them.Plugins
@cortexkit/opencode-magic-context@0.17.2,@cortexkit/aft-opencode@0.20.1, local concord plugin (all three callapi.command.register(...)unconditionally with no fallback).OpenCode version
1.14.42(also confirmed broken on1.14.43)Steps to reproduce
bun add -g opencode-ai@1.14.43api.command.register(...)— e.g.@cortexkit/aft-opencode@latestin~/.config/opencode/tui.jsonpluginarray.pkill -f 'opencode-ai/bin/.opencode'from a separate terminal, then relaunch).~/.local/share/opencode/log/*.logfor theTypeError: undefined is not an object (evaluating 'api.command.register')entry.Affected plugins observed on this machine:
@cortexkit/opencode-magic-context@0.17.2src/tui/index.tsx468@cortexkit/aft-opencode@0.20.1src/tui/index.tsx206concordplugin (now patched)tui/index.tsx503Stack trace excerpt (identical for all three):
Screenshot and/or share link
N/A — see log excerpt above. Filed in parallel:
cortexkit/aft#33and a comment oncortexkit/magic-context#61.Operating System
macOS 15.2 (Darwin 24.x, arm64)
Terminal
Ghostty