Skip to content

fix(opencode,kilo): shell hook events via bash-gated named hooks, global instructions registration - #2547

Merged
dyoshikawa merged 2 commits into
mainfrom
resolve-scrap-issue-2501-opencode-followups
Aug 1, 2026
Merged

fix(opencode,kilo): shell hook events via bash-gated named hooks, global instructions registration#2547
dyoshikawa merged 2 commits into
mainfrom
resolve-scrap-issue-2501-opencode-followups

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

Resolves the two OpenCode gaps from #2501 (verified against sst/opencode v1.18.10; Kilo shares the hook surface):

  1. hooks — correctness fix. afterShellExecution was mapped to command.executed, which is a slash-command event — the hook never fired after a bash command and fired on every slash command instead, for OpenCode and Kilo. Both shell events now land in the named tool.execute.before/tool.execute.after hooks with an implicit input.tool === "bash" gate (the .env protection pattern from the OpenCode plugins doc), implemented via a SHELL_EVENT_TOOL_GATES table in the shared opencode-style generator so Kilo inherits the fix. beforeShellExecution joins OPENCODE_HOOK_EVENTS at the same time. Matchers on the shell events remain warned-and-dropped upstream (matcherEvents covers only preToolUse/postToolUse) — the named hooks expose no command text to match against.
  2. rules — global non-root rules no longer dropped. OpenCode reads instructions from the global ~/.config/opencode/opencode.json too, so global generate now writes non-root rules to ~/.config/opencode/memories/*.md and registers them (entries relative to the config file's directory, so the .config/opencode/ prefix is stripped). Wiring: a mcpInstructionsRegistrarGlobal opt-in on the rules factory meta (off by default — Kilo auto-discovers its global rules dir and must not register), a global nonRoot settable path, getExtraSharedWritePaths returning the global config at global scope, and a rules ownership declaration for .config/opencode/opencode.json in the shared-config gateway.

Docs: hooks prose + hand-maintained hook matrix cells updated (the generated matrix from #2540 will own this once merged), OpenCode rules note documents the global registration.

Testing

  • New tests: bash-gated named-hook emission (both events + coexistence with a matcher-driven preToolUse handler), global fromInstructions prefix stripping, updated global settable-paths expectation and the event-map completeness carve-out; derive snapshot updated.
  • pnpm cicheck green.

Closes #2501

🤖 Generated with Claude Code

cm-dyoshikawa and others added 2 commits July 31, 2026 16:57
…bal instructions registration

Resolves the two gaps from #2501, verified against sst/opencode v1.18.10:

1. hooks (correctness): afterShellExecution was mapped to OpenCode's
   command.executed - a slash-command event - so the hook never fired on
   shell commands and fired on every slash command instead (Kilo shared
   the same wrong mapping). Both shell events are now emitted into the
   named tool.execute.before/after hooks with an implicit
   input.tool === "bash" gate (the .env-protection pattern from the
   OpenCode plugins doc), and beforeShellExecution joins
   OPENCODE_HOOK_EVENTS (a capability OpenCode had that rulesync did
   not offer). Matchers on the shell events stay warned-and-dropped
   upstream (matcherEvents covers only preToolUse/postToolUse); the
   named hooks expose no command text to match against.
2. rules: global generate no longer drops non-root rules. OpenCode
   reads instructions from the global ~/.config/opencode/opencode.json,
   so global non-root rules are now written to
   ~/.config/opencode/memories/*.md and registered there (entries
   relative to the config file's directory), via a new
   mcpInstructionsRegistrarGlobal opt-in on the rules factory meta and
   a rules ownership declaration for the global config in the gateway.

Closes #2501

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…osed

Review follow-ups on PR #2547:

- The opencode and kilo hook factories now declare matcherEvents
  [preToolUse, postToolUse] (as amp does), so a matcher on any other
  event - the bash-gated shell events, preCompact, and the generic
  event dispatches - triggers the processor's 'Skipped matcher hook(s)'
  warning, which previously never fired for these targets.
- The generator now actually skips matcher-carrying definitions on
  events with no matchable subject, matching the warning text; running
  them unconditionally would over-fire hooks the user scoped with a
  matcher. The preCompact test is updated to the fail-closed behavior.
- Stale 'project-scope-only' comment above the opencode ownership
  entries corrected; processor-level test added for the shell-event
  matcher skip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dyoshikawa
dyoshikawa merged commit 6abec0e into main Aug 1, 2026
9 checks passed
@dyoshikawa

Copy link
Copy Markdown
Owner Author

@dyoshikawa Thank you!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow up OpenCode upstream updates: afterShellExecution mapped to slash-command event (also kilo), global non-root rules dropped

2 participants