Treat pre-existing extensions without ownership state as uncertain, cover project-scope aliases, clean canonical sidecars after symlink removal, and classify protected extension overwrites as breaking.
BREAKING CHANGE: non-interactive installs of modified or unrelated Pi/OMP extensions now require --auto-patch to approve overwrites.
Also fixes two docs left stale by the barrel-import removal: hooks/pi/README.md
and hooks/README.md still described bash-tool detection via the removed
isToolCallEventType value import.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The extension is shared with OMP via its legacy-pi-compat layer. Add
guarded helpers that are strict no-ops on Pi: a persistent
"RTK disabled: <reason>" session status registered on session_start
(OMP wipes one-shot notify toasts on the initial render) and a
setLabel("RTK") UI label set before the version probe, so the
extension is identifiable in the session UI even when rtk is missing
or too old.
Co-authored-by: makoMakoGo <makoMakoGo@users.noreply.github.com>
Add `--agent omp` to `rtk init` (with `-g`, `--uninstall`, `--show`)
for the Oh My Pi coding agent (https://github.com/can1357/oh-my-pi).
OMP loads the same `hooks/pi/rtk.ts` extension via its built-in
legacy-pi-compat layer, which remaps the Pi package imports to OMP's
bundled equivalent — so no separate OMP implementation is needed and
the rewrite behavior stays byte-identical (mutualization).
- Local scope: <project>/.omp/extensions/rtk.ts
- Global scope: ~/.omp/agent/extensions/rtk.ts
- `--uninstall` is three-way safe: missing → no-op, stock content →
removed, modified RTK content → bail with manual-removal guidance
- `--show` reports both scopes (installed / stock / modified / absent)
Co-authored-by: makoMakoGo <makoMakoGo@users.noreply.github.com>
Replace the RTK reference (meta commands, rtk proxy bypass, install
verification, branding, hook framing) with a minimal note stating that
condensed output is complete/authoritative and commands should be run
normally. Removes the runnable command blocks and bypass hint that led
agents to run extra commands and re-verify. Claude only.
Every other agent with a dedicated hook implementation carries a
hooks/<agent>/README.md (see antigravity/cline/opencode/copilot/hermes
for the shape). The initial Vibe commit skipped this, leaving Vibe as
the odd one out in the hooks/ layout.
- Add hooks/vibe/README.md following the Copilot template (Rust binary
hook, no shell dependency). Documents the pre_tool hook location,
input JSON shape, rewrite response, passthrough / deny behavior,
and the belt-and-suspenders prompt fallback.
- Fix hooks/README.md Directory Structure entry to point at
vibe/README.md (previously claimed 'no dedicated subdirectory').
Addresses @aeppling's review on #3391:
Blocking fixes:
- run_vibe now returns Ok(()) on malformed JSON (matches run_droid /
run_copilot / run_cursor pattern). Prior code violated the exit-code
contract documented at src/hooks/README.md:100 — a bad payload exited
non-zero and blocked the agent's command. Fixed via a match on
serde_json::from_str with a stderr warning fallback.
- Extract run_vibe_inner(input: &str) -> Option<String> from run_vibe so
the hook contract is unit-testable (mirrors run_droid_inner). Public
run_vibe becomes a thin stdin/stdout wrapper.
- Add 6 runtime tests exercising the hook contract: bash rewrite happy
path, non-bash tool passthrough, empty command passthrough, malformed
JSON returns None, unknown binary passthrough, substitution defers.
Should-fix:
- Telemetry agent detection: add ~/.vibe/hooks.toml to detect_hook_type()
checks in src/core/telemetry.rs, plus the two test enum arrays so Vibe
sessions no longer report as 'unknown' in rtk gain history.
- Dead deny arm: add a comment on Host::Vibe in permissions.rs
documenting that the empty-rules branch is defensive scaffolding for
when Vibe ships native denylist/allowlist config we can honor.
- Broken link: patch_vibe_hooks_toml skip-message now points at
https://www.rtk-ai.app/guide/getting-started/supported-agents#mistral-vibe
instead of a fragment that doesn't resolve.
Nits addressed:
- Install summary no longer prints 'hook installed' when the user chose
PatchMode::Skip or declined the interactive prompt. patch_vibe_hooks_toml
now returns a VibeHookPatchOutcome enum (Installed / AlreadyPresent /
Skipped) and the caller gates the summary on it.
- Document the string-spacing tradeoff on vibe_hooks_toml_has_rtk: a
reformatted 'name="rtk-rewrite"' would defeat idempotency, acceptable
because we control the writer and toml_edit round-trip would clobber
user comments.
- Fix stale line in src/hooks/README.md 'Adding New Functionality':
hook_check.rs::maybe_warn() only checks the Claude Code hook now,
not every agent.
Documentation:
- docs/guide/getting-started/supported-agents.md: frontmatter now lists
Mistral Vibe, drop 'planned' from the intro, tier table row flipped
from 'Planned (#800)' to 'Rust binary (pre_tool) / Yes', replace the
### Mistral Vibe (planned) placeholder with a full user-facing section
modeled on Factory Droid (install/uninstall commands, hook mechanism,
permission semantics, idempotency contract).
- hooks/README.md: agent count 9 -> 10, add Vibe entry to Directory
Structure list, add Vibe row to Supported Agents table, add
'### Mistral Vibe (Rust Binary)' entry to the JSON Formats section
showing the pre_tool input shape and rewrite response shape.
- src/hooks/README.md: agent count 5 -> 6, add Vibe row to per-host
ask-support table.
- README.md: '15 AI coding tools' -> '16'.
No behavior change for existing agents.
RTK was documented as delivering "60-90% token savings", which reads as a
cost reduction. What RTK actually reduces is bash output bytes. Those are
one contributor to input tokens, which are themselves only part of a bill
that also counts output tokens, so the reduction dilutes at every step.
- add docs/guide/resources/savings-explained.md as the canonical explainer:
the savings chain, both estimators, and what RTK does not reduce
- rescope the headline claim across README (7 languages), the guide, hook
rules, agent definitions and module READMEs
- relabel per-command tables as bash output reduction, keeping every figure
- document that reported tokens are estimates: rtk gain uses bytes/4
(src/core/tracking.rs), filter tests use split_whitespace().count().
Neither is a real tokenizer, so ratios hold but absolute counts do not
Remove figures that had no source: the $3/Mtok constant and its $36
example, the +/-10% tokenization accuracy claim, the 99.5% hook-install
figure, the invented session tables in README and INSTALL, and the 30-50%
parser range.
CHANGELOG is untouched. Shipped release notes stay as a historical record.
- Fix documentation, Cursor now uses native rust binary hook
- Fix rtk-rewrite.sh shell script to fail on any exit code except 0 and 3
- Test that "continue": true is also present for "permission": "ask" and sync shell rewrite hook
Address PR #2609 review feedback:
- RC=3 in shell script now emits "permission": "ask" (future-proof)
- Add cursor_ask() and use it for all AskRewrite decisions
- Remove has_rules guard (unnecessary with ask semantics)
- Remove dead cursor_has_explicit_rules() function
When no explicit permission rules exist in ~/.cursor/cli-config.json
(the default for fresh installs), every command gets Default verdict
which maps to AskRewrite. The Cursor hook only handled AllowRewrite,
silently dropping all rewrites and making RTK non-functional.
Now treat AskRewrite as allow when no rules are configured — Cursor
has no ask-the-user UX, so deferring is indistinguishable from
dropping. When explicit rules exist, preserve the conservative
behavior of deferring mixed/unmatched commands.
Also fix the legacy shell script (rtk-rewrite.sh) which treated
exit code 3 (ask) as failure via || short-circuit.
Fixes#2372