Skip to content

OpenCode server is never reaped — orphaned on SessionEnd #19

@JohnnyVicious

Description

@JohnnyVicious

Summary

ensureServer in plugins/opencode/scripts/lib/opencode-server.mjs:93-99 spawns opencode serve with stdio: "ignore", detached: true, and proc.unref(). Nothing in the plugin ever kills that server. On SessionEnd, plugins/opencode/scripts/session-lifecycle-hook.mjs only reaps job records; the opencode serve process keeps running and holding port 4096.

This is the OpenCode equivalent of the "process outlives session" cluster upstream (openai/codex-plugin-cc#108 for the app-server broker, #193 for the orphaned codex binary). The failure mode here is milder — the server is idle HTTP, not a CPU busy-loop — but over time users accumulate orphaned opencode serve processes that hold a port the user may also try to use manually.

Complication

We can't unconditionally kill the server on SessionEnd because the user may have started it themselves outside the plugin (isServerRunning check in ensureServer already reuses a pre-existing server). We should only kill what we started.

Suggested fix

  1. When ensureServer actually spawns a new process, persist the PID into workspace state with a startedByPlugin: true flag.
  2. On SessionEnd, if the persisted PID belongs to the last plugin-spawned server and no other Claude session is active against the same port, process.kill(pid, "SIGTERM").
  3. Consider an idle-timeout-based self-shutdown as a defense in depth.

Upstream references

Class derived from openai/codex-plugin-cc#108 and #193 — opencode equivalent.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions