Files
community-plugins/opencode-companion
weinguyenandGitHub e77d7ef7fb Add OpenCode Companion plugin (#286)
* Add OpenCode Panel plugin
Introduce initial implementation of the OpenCode Panel plugin.
This commit includes:
- Bar widget for status and quick actions.
- Chat panel with session selection, message history, and input.
- Background service for OpenCode server management, SSE event
  handling, and state persistence.
- Plugin configuration, documentation, and internationalization.

* Refine session chooser UI layout

Remove an unnecessary spacer and apply top-justification to improve
vertical alignment. Add a subtle background fill to the session list.

* Introduce session search in chooser

Enable live filtering of sessions in the chooser. Matches against
title, slug, ID, and directory. Search is case-insensitive.

* Support multi-question agent requests and clear composer

Implement multi-question agent replies by accumulating choices locally.
A "Submit" button becomes enabled only after all questions are answered.
The chat composer clears its text after sending by updating its key,
forcing the UI to re-render an empty input field.
Updated translations for send hints and question submit button.

* Add UI mode setting for compact layout

Introduce a `ui_mode` setting (Full/Compact) that dynamically adjusts
panel
layout. Compact mode reduces padding, font sizes, and gaps, hiding some
secondary details to minimize the panel footprint. Layout metrics
recompute on every render based on this setting.

* Delete opencode-panel

* Update thumbnail.webp

* Render chat messages newest-first

Newest message shows at top. Scrolling down reveals older messages.
This avoids scroll offset resets on re-mount in older shell APIs.
Thinking bubble now appears above the newest message.

* FEAT: Add panel layout setting

Provide option for panel to fill right side or appear compact near
click.
Introduces a new panel entry for the "fill right" mode.

* Rename plugin to OpenCode Companion

Update plugin ID, panel entries, IPC commands, and state paths.

* Only send model override when known

Stale default_model now falls back to no override instead of failing
every turn. Warn when configured default unavailable.

* Update service.luau

* fix(opencode-companion): secure terminal open, publish MCP status,
respect auto_start

- Shell-quote host and session id in the "open in terminal" command so a
  crafted server_host cannot inject extra shell commands
- Publish opencode.mcp_status and render it as a collapsible footer
  (previously declared but never observable)
- Honor auto_start: skip managed-server start on load when set to false
- Fix broken thumbnail link in README (assets/thumbnail.webp ->
  thumbnail.webp)

* fix Terminal command injection,MCP status publication and UI
2026-08-09 13:43:51 -04:00
..
2026-08-09 13:43:51 -04:00

OpenCode Companion

A Noctalia v5 plugin that puts OpenCode on your bar — a glanceable status dot, a native chat panel, session management, and MCP status — all driven by the OpenCode HTTP API. No embedded terminal, no key emulation.

OpenCode Companion

Plugin

Field Value
ID weinguyen/opencode-companion
Entries Bar widget: widget; panels: panel-fill, panel; service: service
Plugin API 3

Built and tested against:

  • Noctalia v5.0.0 (97917d9ca07e)
  • OpenCode v1.18.13

Requirements

  • Noctalia v5 (beta or newer) with plugin_api >= 3 support
  • OpenCode installed and available on your PATH (opencode --version to verify)
  • A configured OpenCode provider (run opencode once to set up auth)

Install

# Clone the community-plugins repo (if you haven't already)
git clone https://github.com/... community-plugins

# Symlink into Noctalia plugins directory
ln -s "$PWD/community-plugins/opencode-companion" ~/.local/share/noctalia/plugins/opencode-companion

# Enable the plugin
noctalia msg plugins enable weinguyen/opencode-companion

Usage

Adding the widget to your bar

  1. Open Noctalia Settings → Bar
  2. Click Add Widget
  3. Select OpenCode Companion (the code-circle icon)
  4. The widget appears on your bar

Opening the panel

  • Left click the bar widget → opens/closes the panel
  • Right click → quick-create a new session
  • Middle click → open current session in terminal (opencode attach)

Panel workflow

When you first open the panel (after a reboot), the session chooser appears. From there you can:

  • Create a new session
  • Pick an existing session (sorted by most recently updated)
  • Filter sessions by workspace (visible in the subtitle)

Once a session is selected, the chat view shows:

  • Message history (user + assistant)
  • Tool call status cards (if enabled)
  • Reasoning text (if enabled)
  • Streaming responses as they arrive

Type a prompt in the composer and press Enter or click Send.

IPC

# Toggle the panel (full-height, right side)
noctalia msg panel-toggle weinguyen/opencode-companion:panel-fill

# Toggle the panel (compact, near click)
noctalia msg panel-toggle weinguyen/opencode-companion:panel

# Force refresh
noctalia msg plugin weinguyen/opencode-companion:service all refresh

# Reconnect to server
noctalia msg plugin weinguyen/opencode-companion:service all reconnect

# Create a new session
noctalia msg plugin weinguyen/opencode-companion:service all create_session

Settings

Setting Type Default Description
server_mode string "auto" "auto" manages a local server; "external" connects to a URL
server_host string "127.0.0.1" Hostname the managed server binds to (loopback only)
server_port double 4096 Port the managed server listens on
server_url string "" External server URL (used in "external" mode)
default_workspace folder "" Default working directory for new sessions
default_model string "" Default model in provider/model format
default_agent string "build" Default agent for new sessions
auto_start bool true Auto-start the managed server
show_tool_calls bool true Show tool call status cards
show_reasoning bool false Show reasoning/thinking text
notify_on_complete bool true Notify when a response completes
max_messages_load double 50 Max messages to load per session
debug_logging bool false Print debug messages

Session Lifecycle

Within the same boot

  • Selecting a session, closing the panel, and reopening it preserves the active session
  • Draft text is preserved when the panel closes
  • Unread responses are tracked and shown as a badge on the bar widget
  • The SSE connection stays alive while the panel is closed

After reboot

  • The plugin detects reboot via /proc/sys/kernel/random/boot_id
  • After reboot, the session chooser appears instead of auto-opening the last session
  • Old sessions are still available to select
  • The active session is persisted to ~/.local/state/noctalia/opencode-companion/opencode_state.json

Boot-ID behavior

Condition Behavior
Boot ID matches saved state Restore active session on first open
Boot ID differs (reboot) Show session chooser; keep session list
Saved session no longer exists Show session chooser

Security Notes

  • Loopback only: The managed server binds to 127.0.0.1 by default
  • No credential storage: The plugin does not store API keys or tokens
  • Shell quoting: All paths and arguments are shell-escaped before command execution
  • No auto-approve: Permission requests are never auto-approved
  • No secret logging: Passwords and tokens are not written to logs

When running in auto mode without authentication, any local process can reach the managed server. For multi-user systems, consider:

  • Setting OPENCODE_SERVER_PASSWORD before starting the server
  • Using external mode with a password-protected server

MCP Status

The plugin reads MCP status from OpenCode's /mcp endpoint. To check Context7 and Firecrawl:

curl http://127.0.0.1:4096/mcp | jq

Example response:

{
  "context7": { "status": "connected" },
  "firecrawl": { "status": "connected" },
  "github": { "status": "connected" }
}

Status values: connected, failed, disabled.

The plugin does not add or configure MCP servers — it only reports their status. Configure OpenCode MCP servers through your opencode.json or the TUI.

Troubleshooting

Widget shows offline

# Verify opencode is on PATH
which opencode

# Start a server manually to test
opencode serve --hostname 127.0.0.1 --port 4096 &

# Check health
curl http://127.0.0.1:4096/global/health

Server fails to start

# Check for port conflicts
ss -tlnp | grep 4096

# Try a different port in plugin settings

Panel doesn't open

# Verify plugin is enabled
noctalia msg plugins list

# Try toggling manually
noctalia msg panel-toggle weinguyen/opencode-companion:panel

SSE events not arriving

OpenCode 1.14.42+ had SSE regressions. Upgrade to 1.18.13+ if events stop flowing. The plugin handles reconnection with exponential backoff.

Debug logging

Enable debug_logging in plugin settings, then check Noctalia logs:

journalctl --user -u noctalia -f

Logs

Debug output (when enabled) is prefixed with [opencode-companion]. Look for:

  • Connection state changes
  • SSE events received
  • IPC messages handled
  • HTTP request failures

Known Limitations

  • No ui.markdown: Responses are rendered as plain ui.label. Code blocks lose syntax highlighting.
  • Single-line composer fallback: If multiline input is not fully supported, the composer falls back to single-line.
  • Panel layer: Panels render at Layer::Top — notifications and polkit prompts may cover the panel.
  • No desktop orb: Initial release includes only the bar widget. A desktop presence orb is planned.
  • Boot-ID edge case: If the boot ID file is unreadable, session restoration is skipped.
  • SSE reconnection: After server restart, SSE reconnects with backoff (up to 30s delay).
  • No model/agent switching mid-session: Model and agent are set at session creation.

Uninstall

# Disable the plugin
noctalia msg plugins disable weinguyen/opencode-companion

# Remove the symlink
rm ~/.local/share/noctalia/plugins/opencode-companion

# Optionally remove saved state
rm -rf ~/.local/state/noctalia/opencode-companion

Roadmap

  • Desktop presence orb
  • Model/agent switching from header
  • Session rename/delete from panel
  • MCP status panel
  • Multi-workspace profiles
  • ui.markdown support when available
  • Attachment support (images, files)

License

MIT