Skip to content

Track upstream: collapse .opencode-plugin to a thin shell-script bridge once OpenCode ships native Claude Code hook compat #58

Description

@jsirish

Context

Jason raised a real architectural concern during #56's fix-up: .opencode-plugin/ is a full TypeScript reimplementation of the same capture/redaction/session-start logic that hooks/*.sh already implements for Claude Code and Codex, rather than one shared implementation with a thin per-harness adapter. That's a real maintenance cost — this session alone fixed two production bugs (#56) that were exactly this kind of reimplementation drift (a wrong naming-convention assumption, a wrong event-consumption model) that could not have happened if OpenCode ran the same shell scripts Claude Code and Codex do.

What's blocking a shell-out today

Researched via context7 + the upstream anomalyco/opencode repo:

  • anomalyco/opencode#12472 — "native Claude Code hooks compat," open, active (18 comments, last updated days ago), assigned to a maintainer. Proposes OpenCode natively read ~/.claude/settings.json-style hooks, translate tool names (bashBash, editEdit), and pipe the same JSON-on-stdin/exit-code protocol our shell scripts already speak — i.e. exactly what would let .opencode-plugin become a thin bridge instead of a reimplementation. Not shipped.
  • A community member got frustrated enough to submit the adjacent piece directly — #19519, tool.execute.after message injection — filed two weeks after the underlying issue (#17412) went unanswered by maintainers. Closed, unmerged. No committed timeline for either.
  • A community bridge plugin already exists, magarcia/opencode-claude-hooks — loads .claude/settings.json and runs its hooks as shell commands inside OpenCode's plugin system, real precedent for the shell-out pattern. Its own docs note "existing Claude Code hooks don't move to OpenCode due to different runtime and API requirements," so it's not a drop-in reference implementation, but it proves the pattern works.
  • Our own experimental.chat.system.transform usage (the only way to inject the HANDOFF.md/git-state block into context today) rests on the same missing primitive #17412 describes — plugin hooks can't inject AI-visible messages through any stable API yet. This is the correct tool available today, not a stopgap we chose poorly; it's just genuinely fragile until OpenCode ships something more stable, matching the plugin's own header comment.

Decision

Don't attempt a partial shell-out now — hand-rolling our own stdin/exit-code bridge ahead of any committed OpenCode compat surface would just be a second bespoke OpenCode integration, arguably worse than the current TypeScript port (which at least has full test coverage and doesn't depend on translating tool-call arg shapes across two independently-evolving protocols).

Trigger for revisiting: when anomalyco/opencode#12472 (or an equivalent native-hooks feature) ships, re-evaluate collapsing .opencode-plugin/src/hooks/*.ts down to a thin adapter that shells out to hooks/*.sh the same way Codex reuses them via its own convention — eliminating the version-drift and reimplementation-bug class entirely. Low priority until then; watch the upstream issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions