Status: Real bug surfaced during v0.9.0 spec research and confirmed by the spec reviewer.
Affected versions: v0.8.0, v0.8.1, v0.8.2 (every release with cline hooks)
Context
v0.8.0's cline plugin emits hook configuration as .clinerules/hooks/<event>.json files (one JSON config file per event). But Cline's actual hook dispatch model is filename-based: it expects scripts named exactly by event in .clinerules/hooks/<EventName> (no extension, no JSON layer). Single handler per event, no native matcher.
The JSON files we currently emit are never fired by Cline. Scoped Cline hooks have been silently no-op since v0.8.0.
What to implement
- In
plugins/cline.go, rewrite the hook emission path:
- Stop emitting
.clinerules/hooks/<event>.json
- Instead emit executable scripts at
.clinerules/hooks/<EventName> (filename = canonical event name mapped via mapClineEvent, no extension)
- For scoped hooks, the script content embeds the existing scope-guard wrapper inline (since Cline has no matcher layer, gating happens in the script itself)
- For multiple hooks targeting the same event with different matchers, generate one composite script that branches on the matcher
- Importer: update
internal/importer/cline.go to read .clinerules/hooks/<EventName> (filename-as-event) instead of looking for .json files
- Round-trip tests in
internal/engine/roundtrip_test.go need updating to match
- CHANGELOG note: the JSON files emitted by v0.8.0-v0.8.2 are orphans on disk and can be safely deleted
v0.9.0 includes this fix
The v0.9.0 design pass mandates filename-dispatch (see SPEC.md §4.4.5). This issue tracks the v0.8.3 backport for users not yet on v0.9.
Acceptance criteria
.clinerules/hooks/PreToolUse (executable, no extension) is emitted instead of PreToolUse.json
- Round-trip test confirms the new shape
- A real Cline install actually fires the hook (manual smoke test)
- CHANGELOG documents the orphan-JSON cleanup
Status: Real bug surfaced during v0.9.0 spec research and confirmed by the spec reviewer.
Affected versions: v0.8.0, v0.8.1, v0.8.2 (every release with cline hooks)
Context
v0.8.0's cline plugin emits hook configuration as
.clinerules/hooks/<event>.jsonfiles (one JSON config file per event). But Cline's actual hook dispatch model is filename-based: it expects scripts named exactly by event in.clinerules/hooks/<EventName>(no extension, no JSON layer). Single handler per event, no native matcher.The JSON files we currently emit are never fired by Cline. Scoped Cline hooks have been silently no-op since v0.8.0.
What to implement
plugins/cline.go, rewrite the hook emission path:.clinerules/hooks/<event>.json.clinerules/hooks/<EventName>(filename = canonical event name mapped viamapClineEvent, no extension)internal/importer/cline.goto read.clinerules/hooks/<EventName>(filename-as-event) instead of looking for.jsonfilesinternal/engine/roundtrip_test.goneed updating to matchv0.9.0 includes this fix
The v0.9.0 design pass mandates filename-dispatch (see SPEC.md §4.4.5). This issue tracks the v0.8.3 backport for users not yet on v0.9.
Acceptance criteria
.clinerules/hooks/PreToolUse(executable, no extension) is emitted instead ofPreToolUse.json