52 Commits

Author SHA1 Message Date
Xavier Pestel 94ae76b2da docs(vibe): add hooks/vibe/README.md and link from Directory Structure
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').
2026-08-05 15:37:02 +02:00
Xavier Pestel 1847b07f7a fix(vibe): address PR review — exit code contract, tests, telemetry, docs
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.
2026-08-05 13:55:09 +02:00
Takayuki Maeda ca418939c3 Merge pull request #3128 from TaKO8Ki/fix/pipe-rewrite-safety 2026-07-23 23:33:15 +09:00
Adrien Eppling a1673f7428 docs: scope savings claims to bash output and document the estimator
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.
2026-07-22 18:33:54 +02:00
Takayuki Maeda 297d664f24 docs: explain safe pipeline rewriting 2026-07-22 04:44:47 +09:00
Nicolas Le Cam bd10b002d0 Follow up on #2609:
- 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
2026-06-30 22:18:39 +02:00
Guy Oron a0c16ef0bc fix(hook): use ask permission for AskRewrite in Cursor 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
2026-06-29 14:18:05 +02:00
guy oron ff0b9ac28c fix(hook): handle AskRewrite in Cursor hook when no rules configured
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
2026-06-29 14:18:05 +02:00
Nicolas Le Cam c59a76375a review: cleanup code, comments and uneeded undocumented RTK_CLAUDE_DIR now that we have CLAUDE_CONFIG_DIR 2026-06-09 21:51:23 +02:00
gitbluf f6a54518bd chore: minor cleanup 2026-05-23 01:58:47 +02:00
gitbluf 8bc8b46384 chore: sync with pi api 2026-05-23 01:57:37 +02:00
gitbluf 9bd6e6f392 feat: address pr suggestions 2026-05-23 01:36:07 +02:00
gitbluf cb1661e68d feat(init): remove --pi flag, canonicalize Pi install to --agent pi
chore: sync the codebase after mergew
2026-05-11 21:46:46 +02:00
Marko Petrovic 1ef5b10f73 Merge branch 'develop' into develop 2026-05-11 20:17:22 +02:00
Kayphoon 9d3b99dec8 feat(hermes): add rtk integration
Signed-off-by: Kayphoon <109347466+Kayphoon@users.noreply.github.com>
2026-05-12 00:30:39 +08:00
Marko Petrovic a7cab79084 chore: update hooks/pi/rtk.ts to reflect new package name
Co-authored-by: Jean du Plessis <jeandp@gmail.com>
2026-05-08 00:32:31 +02:00
gitbluf b2a3ad9443 feat: rm rtk awareness injection 2026-05-06 18:44:27 +02:00
gitbluf d6e27527ea refactor: handling of uninstallation 2026-05-06 16:38:01 +02:00
gitbluf 1da5793b92 feat(hooks): add Pi coding agent integration 2026-05-06 15:43:04 +02:00
aesoft 2e401ac38f fix(docs): add missing docs for exclude commands patterns 2026-04-19 13:59:03 +02:00
aesoft 9e96caa0a1 Merge pull request #355 from KuSh/pnpx+dlx
feat(discover): handle more npm/npx/pnpm/pnpx patterns
2026-04-13 20:31:12 +02:00
Florian BRUNIAUX fadd46b6e4 Merge pull request #970 from zerone0x/fix/issue-968-hook-spawn-eagain 2026-04-13 09:25:48 +02:00
Nicolas Le Cam 45938b2a4d feat(js): distinguish between jest and vitest and don't rewrite npm test commands as we don't know which test framework is used under the hood
Signed-off-by: Nicolas Le Cam <niko.lecam@gmail.com>
2026-04-12 22:03:39 +02:00
michaelschleiss d442799e34 fix(init): honor CODEX_HOME for Codex global paths 2026-04-09 10:32:43 +02:00
yosoyepa d0a3797ec5 feat(init): add native support for Kilo Code and Google Antigravity
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.
2026-04-08 15:37:29 -05:00
zerone0x 74a1fd2765 fix(hooks): reduce jq invocations in rtk-rewrite\n\nFixes #968 2026-04-02 12:59:46 +02:00
zerone0x b3a7e753fe fix(hook): reduce rewrite hook spawn overhead
Fixes #968

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-02 12:59:37 +02:00
sveitser bec18c40a2 fix: use /usr/bin/env shebangs for portability across systems 2026-03-26 19:46:28 +01:00
aesoft 967d2bfcf9 Merge branch 'develop' of https://github.com/rtk-ai/rtk into refacto-folders-and-documentation 2026-03-25 19:55:42 +01:00
aesoft 0925cf21e0 fix(docs): last review 2026-03-25 19:12:46 +01:00
aesoft 46fa31c4b8 chore(refacto-codebase): Folders + Technical docs
- codebase more clear for humans and AI agents
- alignement on vision and filter quality in technical docs
2026-03-24 22:14:35 +01:00
aesoft f1ac236e46 fix: start folder & docs refacto 2026-03-23 19:00:52 +01:00
Florian BRUNIAUX a9c610a9af fix(hook): respect Claude Code deny/ask permission rules on rewrite
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>
2026-03-20 14:09:29 +01:00
patrick szymkowiak d921cc4fa0 feat: add Cline/Roo Code support via rtk init --agent cline (#701) (#702)
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>
2026-03-18 18:58:43 +01:00
patrick szymkowiak 86d50698c1 feat: add Windsurf support via rtk init --agent windsurf (#695) (#697)
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>
2026-03-18 18:34:56 +01:00
Moisei Rabinovich c3917e4de2 feat: add Cursor Agent support via --agent flag (#595)
Add `rtk init -g --agent cursor` to install RTK hooks for Cursor Agent.
Cursor's preToolUse hook supports command rewriting via updated_input,
functionally identical to Claude Code's PreToolUse. Works with both the
Cursor editor and cursor-cli (they share ~/.cursor/hooks.json).

Changes:
- New `--agent <name>` flag (claude|cursor) on `rtk init`, extensible
  for future agents. Default is claude (backward compatible).
- Cursor hook script (hooks/cursor-rtk-rewrite.sh) outputs Cursor's
  JSON format: {permission, updated_input} vs Claude's hookSpecificOutput.
- `rtk init --show` reports Cursor hook and hooks.json status.
- `rtk init -g --uninstall` removes Cursor artifacts.
- `rtk discover` notes that Cursor sessions are tracked via `rtk gain`
  (Cursor transcripts lack structured tool_use/tool_result blocks).
- Unit tests for Cursor hooks.json patching, detection, and removal.

Made-with: Cursor

Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Co-authored-by: Moisei <1199723+moisei@users.noreply.github.com>
2026-03-18 16:39:03 +01:00
Jeziel Lopes 0800bbecef feat(copilot): add Copilot hook support (VS Code + CLI) (#605)
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>
2026-03-18 16:21:07 +01:00
Zacaria Chtatar 7d04b485a7 feat(init): add Codex CLI support via AGENTS.md + RTK.md workflow (#377)
* feat(init): add Codex CLI support via AGENTS.md + RTK.md workflow

Add --codex mode to rtk init for Codex CLI integration using AGENTS.md + RTK.md, while keeping the newer develop init/opencode flow intact. Includes Codex install/show/uninstall handling, ASCII status output, stricter flag validation, and expanded tests for Codex AGENTS lifecycle and patch-mode rejection.

Signed-off-by: Zacaria <havesomecode@gmail.com>

* docs: fix validation metadata

Signed-off-by: Zacaria <havesomecode@gmail.com>

---------

Signed-off-by: Zacaria <havesomecode@gmail.com>
2026-03-18 15:54:53 +01:00
patrick szymkowiak d0396da1ce chore: merge develop into master (#499)
* 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>
2026-03-12 13:49:08 +01:00
patrick szymkowiak 7d76af84b9 fix: 4 critical bugs + telemetry enrichment (#462)
* 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>
2026-03-10 16:46:54 +01:00
Florian BRUNIAUX 6c13d23436 fix: RTK_DISABLED ignored, 2>&1 broken, json TOML error (#345, #346, #347)
- #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>
2026-03-05 22:50:17 +01:00
patrick szymkowiak 3141fecf95 feat: warn when installed hook is outdated (#344) (#350)
- Add `# rtk-hook-version: 2` header to hook file
- New `hook_check` module: detect outdated hook on startup, warn 1/day
- Homebrew caveats: remind users to run `rtk init -g` after upgrade
2026-03-05 22:33:17 +01:00
Florian BRUNIAUX f447a3d5b1 feat: rtk rewrite — single source of truth for LLM hook rewrites (#241)
* 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>
2026-03-05 14:20:01 +01:00
Itai b934466364 feat: add AWS CLI and psql modules with token-optimized output (#216)
AWS CLI (rtk aws):
- Specialized filters for sts, s3 ls, ec2, ecs, rds, cloudformation
- Generic fallback injects --output json for structured ops only
  (describe-*, list-*, get-*); mutating ops (s3 cp, deploy) pass through
- join_with_overflow() and truncate_iso_date() helpers in utils.rs

psql (rtk psql):
- Table format: strips separators/padding, outputs tab-separated
- Expanded format: compresses -[ RECORD N ]- blocks to key=val one-liners
- Passthrough for COPY results, notices, and non-table output
- 40%+ savings (table), 60%+ savings (expanded display)

Co-authored-by: itai.sagi <itai.sagi@clarityo.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 11:12:25 +01:00
Rmohid e8ef341853 feat: add mypy command with grouped error output (#109)
* 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>
2026-02-28 19:51:40 +01:00
mercierj dbbf980f3b fix: filter docker compose hook rewrites to supported subcommands (#245)
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>
2026-02-28 18:49:24 +01:00
Florian BRUNIAUX 70c37867e7 feat: add hook audit mode for verifiable rewrite metrics (#151)
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>
2026-02-16 22:05:28 +01:00
Michael Coen 7401f1099f feat(hook): handle global options before subcommands (#99)
* 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>
2026-02-15 08:15:02 +01:00
polamin 6612f22060 improve: hook coverage from 0.2% to ~80% with env prefix stripping (#97)
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>
2026-02-13 18:31:23 +01:00
Michael Coen 4aafc832d4 fix(hook): use POSIX character classes for cross-platform grep compatibility (#98)
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>
2026-02-13 12:53:25 +01:00