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
Add rtk init --agent kilocode and rtk init --agent antigravity commands.
Kilo Code: installs .kilocode/rules/rtk-rules.md (project-scoped)
Google Antigravity: installs .agents/rules/antigravity-rtk-rules.md (project-scoped)
Both follow the same prompt-level guidance pattern as Cline and Windsurf,
using rules files that instruct the agent to prefix shell commands with rtk.
The PreToolUse hook was emitting `permissionDecision: "allow"` on every
rewritten command, bypassing deny and ask rules in .claude/settings.json.
- Add `src/permissions.rs`: loads Bash deny/ask rules from all 4 Claude
Code settings files (project + global, settings.json + settings.local.json),
checks commands (including compound && / || / | / ;) and returns
Allow / Deny / Ask verdict. 16 unit tests.
- Modify `src/rewrite_cmd.rs`: after finding a rewrite, check the original
command against permissions. Exit 0 = allow (auto-approve rewrite),
exit 2 = deny (passthrough, let CC native deny handle it),
exit 3 = ask (print rewrite but no permissionDecision, CC prompts user).
- Update both hook files to handle exit codes 2 and 3. Version bumped 2→3.
- Bump `CURRENT_HOOK_VERSION` 2→3 in `hook_check.rs` so users with the old
hook get the upgrade prompt.
- Fix set -euo pipefail bug in .claude/hooks/rtk-rewrite.sh: capture exit
code with `|| EXIT_CODE=$?` instead of bare assignment.
Fixes#260
Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com>
Install RTK rules in .clinerules (project-scoped) so Cline
prefixes shell commands with rtk for token savings.
Same rules-based approach as Windsurf and Codex.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Install RTK rules in .windsurfrules (project-scoped) so Cascade
prefixes shell commands with rtk for token savings.
Windsurf hooks don't support command rewriting (only blocking),
so RTK uses the rules-based approach (like Codex with AGENTS.md).
Tested: Windsurf Cascade correctly uses rtk git status after install.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Add `rtk hook copilot` command that handles both VS Code Copilot Chat
(updatedInput rewrite) and GitHub Copilot CLI (deny-with-suggestion).
- Auto-detects format: snake_case (VS Code) vs camelCase (Copilot CLI)
- Delegates to `rtk rewrite` (single source of truth)
- 14 hook tests (format detection, rewrite gating, output shape)
- .github/hooks/rtk-rewrite.json for repo-scoped hook config
- .github/copilot-instructions.md for RTK awareness
- Test script: hooks/test-copilot-rtk-rewrite.sh
Rebased on develop (includes Gemini #573, Codex #377, OpenClaw #358).
Original work by @jeziellopes, cleaned up and rebased by maintainer.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Co-authored-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: handle tail rewrites with read tail-lines
* feat: add 32 TOML-filtered commands to hook rewrite rules (#475)
Add rewrite rules for all TOML-filtered commands so the Claude Code
hook automatically rewrites them to `rtk proxy <cmd>`. This ensures
TOML filters apply transparently without manual `rtk` prefixing.
Commands added: ansible-playbook, brew, composer, df, dotnet, du,
fail2ban-client, gcloud, hadolint, helm, iptables, make,
markdownlint, mix, mvn, ping, pio, poetry, pre-commit, ps, quarto,
rsync, shellcheck, shopify, sops, swift, systemctl, terraform, tofu,
trunk, uv, yamllint.
Tests updated to use `htop` as unsupported command example since
terraform is now supported via TOML filter.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: git log --oneline no longer silently truncated to 10 entries (#461) (#478)
Only inject -10 limit when RTK applies its own compact format.
When user provides --oneline/--pretty/--format, respect git's
default behavior (no limit). Also detect -n and --max-count as
user-provided limit flags.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: gh run view --job flag loses its value (#416) (#477)
Add --job and --attempt to flags_with_value in
extract_identifier_and_extra_args() so their values are not
mistaken for the run identifier when placed before it.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: rtk read no longer corrupts JSON files with glob patterns (#464) (#479)
Add Language::Data variant for JSON, YAML, TOML, XML, Markdown, CSV
and other data formats. These files have no comment syntax, so the
MinimalFilter skips comment stripping entirely.
Previously, `packages/*` in package.json was treated as a block
comment start (`/*`), causing everything until the next `*/` to be
stripped — corrupting the JSON structure.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: npm routing, discover cat redirect, proxy quoted args (#480)
* fix: npm routing, discover cat redirect, proxy quoted args (#470, #315, #388)
#470: rtk npm now correctly routes npm subcommands (install, list,
audit, etc.) without injecting "run". Previously, `rtk npm install`
was executed as `npm run install`.
#315: discover no longer counts `cat >`, `cat >>`, `cat |` as missed
savings. These are write/pipe operations with no terminal output to
compress.
#388: rtk proxy now auto-splits a single quoted argument containing
spaces. `rtk proxy 'head -50 file.php'` now works like
`rtk proxy head -50 file.php`.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: proxy quote-aware split, redirect detection scan all tokens, npm test routing
- Proxy: replace split_whitespace with shell_split() that respects quotes (#388)
e.g. 'git log --format="%H %s"' no longer splits on space inside quotes
- Discover: scan all tokens for redirect operators, not just nth(1) (#315)
e.g. 'cat file.txt > output.txt' now correctly detected as write
- npm: replace tautological test with actual routing logic verification
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* feat: add 11 new TOML built-in filters (xcodebuild, jq, basedpyright, ty, skopeo, stat, biome, oxlint, jj, ssh, gcc) (#490)
Closes#484, #483, #449, #448, #428, #283, #316, #195, #271, #333, #87, #376
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: rtk rewrite accepts multiple args without quotes (#504)
* fix: rtk rewrite accepts multiple args without quotes
`rtk rewrite ls -al` now works the same as `rtk rewrite "ls -al"`.
Previously, args after the command were rejected or caused ENOENT.
Also adds rewrite tests to benchmark.sh to prevent regression.
Signed-off-by: Patrick Szymkowiak <patrick.szymkowiak@rtk-ai.app>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* test: add Clap rewrite tests + fix benchmark false failures
- Add 2 Clap try_parse_from tests for rewrite multi-args (catches the
KuSh bug at unit test level, not just benchmark)
- Fix git diff benchmark: use HEAD~1 on both sides for fair comparison
- Skip cargo/rustc benchmarks when tools not in PATH instead of false FAIL
- Benchmark: 0 fail, 4 skip (env-dependent), 52 green
Signed-off-by: Patrick Szymkowiak <patrick.szymkowiak@rtk-ai.app>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick Szymkowiak <patrick.szymkowiak@rtk-ai.app>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: use rtk <cmd> instead of rtk proxy for TOML-filtered commands (#507)
- Replace all 32 `rtk proxy <cmd>` rules with `rtk <cmd>` so TOML filters
actually apply (proxy bypasses filters, giving 0% real savings)
- Extract NPM_SUBCOMMANDS to module-level const to prevent test/prod drift
Reported-by: FlorianBruniaux
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: warn when no hook installed + rtk gain hook status + PR #499 fixes
- hook_check: detect missing hook (not just outdated), warn with ⚠️
Only warns if ~/.claude/ exists (Claude Code user) — once per day
- gain: show hook status warning (missing/outdated) in rtk gain output
- ssh.toml: bump max_lines 50→200, truncate_lines_at 120→200 (Florian review)
- git.rs: mark integration test #[ignore] + assert binary exists (Florian review)
- Add HookStatus enum for reuse across gain/diagnostics
Fixes#508, Fixes#509
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: address code review — hook_check edge cases
- status() checks .claude/ existence (no false warning for non-CC users)
- Unreadable hook file returns Outdated not Missing
- Swap marker/warning order (emit warning before touching rate-limit marker)
- Rename misleading test, add end-to-end status() test
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: review iteration 2 — double-warning, case-sensitive test, ssh truncate
- Refactor check_and_warn to delegate to status() (single source of truth)
- Fix double-warning: skip maybe_warn() for `rtk gain` (has its own inline warning)
- Fix git test: case-insensitive assertion for cross-locale compatibility
- ssh.toml: keep truncate_lines_at=120 (terminal width convention)
- Robust mtime handling: unwrap_or(u64::MAX) instead of nested .ok()?
- Test handles all CI environments (no hook, no .claude, hook present)
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: detect and warn RTK_DISABLED=1 overuse (#508)
- discover: count RTK_DISABLED= bypassed commands, report top 5 examples
- gain: lightweight 7-day JSONL scan, warn if >10% commands bypassed
- registry: add has_rtk_disabled_prefix() and strip_disabled_prefix() helpers
- gitignore: add .fastembed_cache/ and .next/
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: preserve trailing newline in tail_lines + add missing test
- apply_line_window() now preserves trailing newline when input has one
- Add test for tail --lines N (space form) rewrite
- Add test for tail_lines without trailing newline
Signed-off-by: Patrick <patrick@rtk-ai.com>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: respect user-specified git log limits instead of silently truncating
RTK was silently capping git log output in two ways:
1. `--oneline` without `-N` defaulted to 10 entries (now 50)
2. `filter_log_output()` re-truncated even when user explicitly set `-N`
3. Lines >80 chars were truncated, hiding PR numbers and author names
This matters for LLM workflows: Claude needs full commit history for
rebase, squash, and changelog operations. Silent truncation caused
incomplete context and repeated re-runs.
Changes:
- User-explicit `-N` → no line cap, wider 120-char truncation
- `--oneline`/`--pretty` without `-N` → default 50 (was 10)
- No flags → unchanged (default 10)
- Extract `truncate_line()` helper for clarity
Fixes#461
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: handle -n N and --max-count=N forms in git log limit parsing
- Extract parse_user_limit() to handle all 4 forms: -20, -n 20, --max-count=20, --max-count 20
- Add token savings test for filter_log_output (≥60%)
- Add 5 tests for parse_user_limit edge cases
Signed-off-by: Patrick <patrick@rtk-ai.com>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* feat: add structured dotnet support (build/test/restore/format)
Integrate PR #172 by @danielmarbach onto develop:
- MSBuild binlog parser (binary format, gzip, 7-bit varint)
- TRX test result parser (quick-xml)
- Format report JSON parser
- Subcommand routing: build, test, restore, format + passthrough
- Sensitive env var scrubbing (GH_TOKEN, AWS_SECRET_ACCESS_KEY, etc.)
- Fallback to text parsing when binlog unavailable
- 86-93% token savings on real .NET projects
Maintainer fixes applied:
- Removed binlog temp path from output (wastes tokens)
- Dropped hook file changes (incompatible with develop architecture)
- Fixed unused variable warnings
888 tests pass.
Signed-off-by: Patrick <patrick@rtk-ai.com>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* feat: add OpenCode plugin support (#300)
* feat(opencode): add OpenCode plugin support
Add `--opencode` flag to `rtk init` for installing a global OpenCode
plugin that rewrites Bash/shell commands through `rtk rewrite`.
- New plugin: hooks/opencode-rtk.ts (thin delegator to rtk rewrite)
- New init modes: --opencode (OpenCode only), combinable with Claude modes
- Plugin install/update/remove lifecycle with idempotent writes
- Uninstall cleans up OpenCode plugin alongside Claude Code artifacts
- `rtk init --show` reports OpenCode plugin status
- Replace unreachable!() with bail!() in match exhaustiveness guard
* docs: add OpenCode plugin documentation
- README: OpenCode plugin section, install flags, troubleshooting
- TROUBLESHOOTING: OpenCode-specific checklist
- Update init mode table to reflect Claude Code default
---------
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick Szymkowiak <patrick.szymkowiak@rtk-ai.app>
Signed-off-by: Patrick <patrick@rtk-ai.com>
Co-authored-by: Qingyu Li <2310301201@stu.pku.edu.cn>
Co-authored-by: Ousama Ben Younes <benyounes.ousama@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: José Almeida <57680069+zeval@users.noreply.github.com>
* fix(cicd): Add security check on dev branch PR
add security check cicd on dev branch PR
Signed-off-by: aesoft <43991222+aeppling@users.noreply.github.com>
* fix: enrich telemetry with install_method and token savings
- Add install_method detection (homebrew/cargo/script/nix/other)
- Add tokens_saved_24h and tokens_saved_total to payload
- Add Tracker::total_tokens_saved() and Tracker::tokens_saved_24h() methods
- Point telemetry to new dedicated rtk-telemetry service
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: detect install method on Windows paths
Add backslash variants for .cargo\bin and .local\bin detection
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: enrich telemetry with install_method and token savings (#432)
- Add install_method detection (homebrew/cargo/script/nix/other)
- Add tokens_saved_24h and tokens_saved_total to payload
- Add Tracker::total_tokens_saved() and Tracker::tokens_saved_24h() methods
- Point telemetry to new dedicated rtk-telemetry service
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: 4 critical bugs — git exit code, jq warning, npm run doubling, pnpm build filter (#458)
* fix: propagate exit code 128 when rtk git status runs outside a repo (#435)
Previously printed "Not a git repository" to stdout and returned exit 0.
Now prints to stderr and exits with git's actual exit code (128).
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: warn when jq is not installed instead of silent exit (#430)
Hook now prints a warning to stderr before exiting cleanly,
so users know the rewrite pipeline is not functioning.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: strip leading 'run' arg to prevent npm run run doubling (#438)
When user types 'rtk npm run build', args contain ["run", "build"].
Since npm_cmd always prepends 'run', this caused 'npm run run build'.
Now strips the leading 'run' from args if present.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: route pnpm build through generic passthrough instead of Next.js filter (#454)
pnpm build was hardcoded to next_cmd::run which misparses Vite/other
framework output as errors. Now uses generic passthrough.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* docs: bump README version to 0.28.0
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: warn when rtk binary is not in PATH instead of silent exit (#430) (#465)
Applies the same fix as jq — all silent exits now warn on stderr.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: aesoft <43991222+aeppling@users.noreply.github.com>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Co-authored-by: aesoft <43991222+aeppling@users.noreply.github.com>
- #345: rewrite_segment() now returns None when env_prefix contains
RTK_DISABLED= — prevents rewriting commands the user explicitly
opted out of
- #346: rewrite_compound() detects redirect operators (2>&1, >&2,
&>/dev/null, &>>) before treating bare & as background operator —
fixes corrupted compound commands containing stderr redirects
- #347: validate_json_extension() helper added to json_cmd.rs — early
rejection with clear error message for TOML/YAML/XML/CSV/etc. files,
with a dedicated tip for Cargo.toml (suggests rtk deps)
Tests: 16 new unit tests (4 + 6 + 6), 7 new hook integration tests.
All 672 tests pass. Quality gate clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add `rtk rewrite` command — single source of truth for hook rewrites
Implements `rtk rewrite <cmd>` as the canonical rewrite engine for all
LLM hook integrations (Claude Code, Gemini CLI, future tools).
- Add `rewrite_prefixes` field to `RtkRule` in discover/registry.rs
- Add public `rewrite_command()` with compound command support (&&, ||, ;, |)
- Add `rewrite_segment()`, `rewrite_compound()`, `strip_word_prefix()` helpers
- Handle already-rtk commands (exit 0, identical output)
- Handle unsupported/ignored commands (exit 1, no output)
- Add 20 unit tests covering all branches and edge cases
- Create `src/rewrite_cmd.rs` thin CLI wrapper
- Register `Commands::Rewrite` in main.rs
- Simplify `.claude/hooks/rtk-rewrite.sh` from 357 → 60 lines
Hooks no longer need duplicate mapping logic — a single
`REWRITTEN=$(rtk rewrite "$CMD") || exit 0` handles everything.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: fix version references and module count for 0.22.2
- README.md, CLAUDE.md, ARCHITECTURE.md: 0.20.1 → 0.22.2
- ARCHITECTURE.md: module count 48 → 51 (added rewrite_cmd + 2 from master)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: update hook coverage check to verify registry (not hook script)
Since PR #241, the hook delegates to `rtk rewrite` — command mappings
live in src/discover/registry.rs, not the bash hook script.
Update the "Verify hook coverage" CI step to:
- Check that the hook calls `rtk rewrite` (new architecture)
- Check that registry.rs has rewrite_prefixes for all Python/Go commands
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: support single `&` background operator in compound rewrites
Per feedback from @xDelph: AI agents increasingly use `cmd1 & cmd2`
for parallel execution. This commit adds support alongside existing
`&&`, `||`, `;`, and `|` operators.
Changes:
- rewrite_compound: add match arm for single `&` (after `&&` check)
- rewrite_command: add `" & "` to has_compound detection
- init: show "installed/updated" vs "already up to date" so users
know whether rtk init changed the hook on re-run
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add Python/Go commands to rewrite registry
Add `ruff`, `pytest`, `pip`, `go`, and `golangci-lint` to both
PATTERNS and RULES in registry.rs so the CI coverage check passes
and `rtk rewrite` correctly identifies these commands.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version reference to 0.23.0 in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version reference to 0.23.0 in CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version and module count to 0.23.0/52 in ARCHITECTURE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address P0 review feedback on rtk-rewrite PR
P0.1 - Replace 218-line bash hook with 58-line thin delegating hook.
All rewrite logic now lives exclusively in `rtk rewrite` (Rust registry).
`rtk init` installs the thin hook via include_str!.
P0.2 - Fix `head -20 file` crash at runtime.
Generic prefix replacement produced `rtk read -20 file` (invalid clap args).
Now translates `head -N file` → `rtk read file --max-lines N` and skips
unsupported head flags (e.g. -c) by returning exit 1.
P0.3 - Add version guard in hook for rtk < 0.23.0.
Prints a warning to stderr instead of silently doing nothing.
Also adds missing registry entries vs old hook:
- gh release, cargo install
- docker run/exec/build, kubectl describe/apply
- tree, diff
474 tests pass, 0 clippy warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* style: cargo fmt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(discover): extract rules/patterns into rules.rs
Per aeppling review: registry.rs was too large (~1500 lines).
Extract all static data into src/discover/rules.rs:
- RtkRule struct (with pub fields)
- PATTERNS const array
- RULES const array
- IGNORED_PREFIXES and IGNORED_EXACT const arrays
registry.rs now contains only logic + tests.
rules.rs is the single place to add a new command mapping.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version reference to 0.24.0 in README
* docs: update version references to 0.24.0 in CLAUDE.md and ARCHITECTURE.md
* fix(discover): add aws and psql to rewrite registry
rtk aws and rtk psql modules exist since PR #216 but were missing
from the registry rules — rewrite was silently skipping them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(discover): exhaustive regression tests for rewrite registry
Cover all command categories added in PR #241 and missing from
the previous test suite:
- aws / psql (PR #216 modules, gap detected during non-reg run)
- Python: ruff, pytest, python -m pytest, pip, uv pip
- Go: go test/build/vet, golangci-lint
- JS/TS: vitest, pnpm vitest, prisma, prettier, pnpm list
- Compound operators: || and ; rewrites, 4-segment chains,
mixed supported/unsupported segments, all-unsupported → None
- sudo prefix rewrite, env var prefix rewrite
- find with native flags
- Registry invariants: PATTERNS/RULES aligned, all rules valid,
all patterns are valid regex
Before: 559 tests. After: 607 tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(migration): document breaking change + detect outdated hook in rtk config
CHANGELOG [Unreleased]:
- Migration required: rtk init --global needed after upgrade
- Documents upgrade path and explains no immediate breakage
rtk init --show / rtk config now detects old hook (inline if-else)
vs new thin delegator (rtk rewrite) and prints actionable warning:
⚠️ Hook: ~/.claude/hooks/rtk-rewrite.sh (outdated — inline logic, not thin delegator)
→ Run `rtk init --global` to upgrade to the single source of truth hook
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update hook references for thin delegator (0.24.0)
- ARCHITECTURE.md: fix hook description (shell script → thin delegator)
- INSTALL.md: add upgrade path for old hook users (pre-0.24 breaking change)
- SECURITY.md: add registry.rs + hook files to Tier 1 critical files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(arch): fix module count 52→55, add aws/psql/rewrite to module map
Adds aws_cmd, psql_cmd (PR #216) and rewrite_cmd (this PR) to the
Complete Module Map table. Updates total from 52 to 55 to match main.rs.
Fixes CI validate-docs.sh module count mismatch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: fix hook coverage check to search rules.rs instead of registry.rs
After the PR #241 refactor, rewrite_prefixes constants moved from
registry.rs to rules.rs. Update grep to search the whole discover/
directory so it finds them in the right file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add mypy command with grouped error output (80% token reduction)
Add rtk mypy module that parses mypy type checker output, groups errors
by file and error code, and produces compact summaries. Includes
discovery registry pattern, hook rewrites, and 11 new tests (324 total).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address review - remove specs/ and clean CLAUDE.md
Remove process docs (spec, plan, tasks, research, checklists) from
specs/001-mypy-cmd/ and strip "Active Technologies" / "Recent Changes"
sections from CLAUDE.md per PR #109 review feedback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address review - deduplicate mypy handler, delegate from lint_cmd
Make lint_cmd.rs delegate to mypy_cmd::filter_mypy_output() instead of
maintaining a separate, less capable implementation. The mypy_cmd version
handles column numbers, note continuations, file-less errors, and shows
full error details. Removes 145 lines of duplicate code + 2 redundant tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Robert Mohid <rmohid@Roberts-Mini.ht.home>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The hook was rewriting all `docker compose` commands to `rtk docker
compose`, but rtk only supports ps, logs, and build. Unsupported
subcommands (up, down, exec, restart...) and compose-level flags
(-f, --project-name) caused hard failures.
Now matches the approach used by the regular docker branch: only
rewrite when the subcommand is known to be supported.
Fixes#244
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add opt-in audit logging to the RTK rewrite hook and a new `rtk hook-audit`
command to analyze the collected metrics. This provides verifiable data on
hook reliability (rewrite rate, skip reasons, top commands) instead of
relying on anecdotal claims.
- Add `_rtk_audit_log()` function to rtk-rewrite.sh (opt-in via RTK_HOOK_AUDIT=1)
- Log each invocation: timestamp | action | original_cmd | rewritten_cmd
- Actions: rewrite, skip:already_rtk, skip:heredoc, skip:no_match, skip:no_deps, skip:empty
- New `src/hook_audit_cmd.rs` module with log parser and stats display
- New `rtk hook-audit --since N` subcommand (default: last 7 days)
- 8 Rust unit tests + 7 hook bash tests for audit mode
- Make HOOK var overridable in test suite for repo-local testing
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(hook): use POSIX character classes for cross-platform grep compatibility
Replace \s with [[:space:]] in all grep -E patterns. The \s shorthand
is a PCRE extension not guaranteed by POSIX ERE, causing intermittent
match failures on macOS depending on grep version and locale settings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(hook): handle global options before subcommands in git/cargo/docker/kubectl
Normalize commands by stripping global options (git -C, --no-pager;
cargo +toolchain; docker -H, --context; kubectl --context, -n) to
correctly identify the subcommand for rewrite matching. Preserves all
original arguments in the rewritten command.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Two root causes for low interception rates:
1. Environment variable prefixes broke pattern matching.
Commands like `TEST_SESSION_ID=2 npx playwright test` start
with an env var, not the command name, so no pattern matched.
Fix: strip leading env vars for matching, preserve for execution.
2. Missing patterns for commands RTK already supports:
npm run/test, vue-tsc, docker compose, docker run/build/exec,
kubectl describe/apply, gh api/release.
Also fixes vitest "run" duplication bug where `vitest run` became
`rtk vitest run run`.
Includes 50-test regression suite (hooks/test-rtk-rewrite.sh).
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace \s with [[:space:]] in all grep -E patterns. The \s shorthand
is a PCRE extension not guaranteed by POSIX ERE, causing intermittent
match failures on macOS depending on grep version and locale settings.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>