- drop the synthetic "search failed with exit code N" line (an rtk addition)
- surface the engine stderr verbatim in every path, incl. partial match + error
- remove the now-vestigial is_grep_error_exit (the "0 matches" it guarded is gone)
- error/exit matrix tests vs real grep/rg (#2465: an error is never a silent no-match)
- grep_compress_test.rs -> search_compress_test.rs (tests the shared grep/rg filter)
- binary match skipped as noise by default, -a opts back in
- fix parse_flags doc: -I is an intentional binary skip, not a no-op
- leading ^ anchor must stay scoped to the path (tenequm)
- line ending in `:` keeps full content (BTCAlchemist)
- rg surfaces a regex parse error as exit 2, not a silent 0 (jhagberg)
- line number always (the openable position); filename only when grep/rg prints one (multi-file, dir, -r, -H)
- single file and stdin equal `grep -n` byte-for-byte: no synthetic filename, header, or lossy truncation
- read piped stdin instead of injecting `.`; rg no longer searches the cwd on a pipe
- pattern-less and format-flag commands run verbatim (rg --type-list, --files, grep -c/-o)
- grouped/capped form only when capping actually shrinks the output
- byte-for-byte tests vs grep -n across flags, pipes and edge cases (incl #1436)
- grep runs grep, rg runs rg: drop the substitution, forced --no-ignore-vcs, and BRE-to-rg translation
- add `rtk rg` command (native ripgrep, sharing the same output filter)
- split rewrite rule: grep to rtk grep, rg to rtk rg
- record the agent's real command in tracking (was synthesized as "grep -rn")
- emit nothing on a clean no-match (never-worse parity with the shared guard)
- rename grep_cmd.rs to search.rs, now hosting both engines
- cover engine faithfulness, ignore semantics, and rg savings with issue-referenced tests
- benchmark the grep and rg paths
RTK could emit more tokens than the underlying command on small inputs:
filters that add headers, summaries, re-indentation, or a tee hint, plus
synthetic no-result messages ("0 matches", "No stashes", "[docker] 0
containers") printed where the raw command emitted nothing. Both break the
Transparency principle and inflate tokens instead of saving them.
- core::guard::never_worse(raw, filtered) returns raw when the filtered form
has more tokens (reuses tracking::estimate_tokens), so RTK output is never
larger than the real command.
- runner::emit_guarded(filtered, hint, raw) composes body + tee hint, guards
the whole, prints, and returns what was shown so printed == tracked.
- run_captured_filter guards the run_filtered* family centrally; per-site
guards cover the remaining single-string filters.
- On empty raw, emit empty and preserve the exit code instead of a synthetic
no-result message (the messages were cosmetic with no dependents; #2461
reports the grep one as actively harmful).
- git stash show now propagates its exit code instead of masking a real
failure as Ok(0).
Resolves#2551.
Review feedback on #2550: the flag-shape tests all used standalone flags, leaving the exact #2543 repro -- a bundled -rln/-ln files-with-matches cluster -- unexercised. Assert rtk grep -rln <pat> <dir> lists matching files instead of a false '0 matches'.
The grep argument-parsing rework routed many flag shapes through the
grouping reparse, which silently dropped any line it could not parse and
returned a success exit. Common invocations produced wrong or empty
output -- and grep-only syntax like `--include` failed outright -- which
pushed agents back to unfiltered `rtk proxy grep`.
Every valid grep invocation now produces correct output:
- Context (`-A`/`-B`/`-C`) is grouped and compressed instead of dropped;
the header counts matches only and context lines are shown.
- Output the reparse cannot represent (`-N`, `-I`, `--color`, `-p`,
`--heading`, binary-file notices, ...) is passed through verbatim
instead of reported as a false "0 matches".
- Format/shape flags (`-c`, `-l`, `-o`, `-Z`, `--column`, `-b`,
`--vimgrep`, `--null-data`) pass through cleanly with no NUL leak.
- grep-only syntax (`--include`, `--exclude`, ...) works: ripgrep is the
fast path and rtk falls back to system grep when ripgrep rejects a flag.
- rtk grep never emits more than plain grep: if grouping is not smaller
than `file:line:content`, the raw form is shown.
Resolves#2543.
Surefire 3.x emits one blank-separated detail block per failing test
under a single class close line. The trail previously ended at the
first blank line and never re-armed, so failures after the first lost
their exception message (unindented -> dropped) and leaked the full
junit/jdk framework stack (indented -> kept by keep_continuation).
SurefireBlock now remembers the trail's keep/drop decision when it
ends at a blank line (trail_rearm) and re-enters the trail on the next
per-test subline with the same decision — a capped class drops all its
per-test blocks, not just the first. Any other non-blank line disarms
re-entry; RUNNING/commit/drop clear it so an unrelated class can never
inherit the decision. Extra blanks between per-test blocks stay armed.
Per-test sublines use '<<< ERROR!' for thrown (non-assertion)
exceptions — accept both markers via a shared is_per_test_subline()
(also reused by filter_quiet, which already re-armed correctly), and
widen the CLOSE regex to tolerate an ERROR! marker defensively
(Surefire 3.5.5 emits FAILURE! even for errors-only classes, per the
fixture capture; detection keys off the counts, not the marker).
Fixture captured from real Maven 3.9.9 / Surefire 3.5.5 output against
the new tests/fixtures/multifail-skeleton/ (CalcTest: assertion failure
+ thrown exception in one class; BoomTest: errors-only class). A
byte-exact pin locks the single-failure path unchanged.
The generic AWS handler (used for subcommands outside the hardcoded
specialized list) called json_cmd::filter_json_string, which extracts
a type-only schema and discards every value.
$ rtk aws backup describe-global-settings --output json
{
GlobalSettings:
{
isCrossAccountBackupEnabled: string,
isDelegatedAdministratorEnabled: string,
isMpaEnabled: string
}
LastUpdateTime: string
}
Callers got the schema instead of the data they asked for.
Swap to json_cmd::filter_json_compact, which preserves values while
still applying depth, string-length, and array-size truncation:
$ rtk aws backup describe-global-settings --output json
{
GlobalSettings:
{
isCrossAccountBackupEnabled: "false",
isDelegatedAdministratorEnabled: "false",
isMpaEnabled: "false"
}
LastUpdateTime: "2026-05-28T09:52:17.525000+02:00"
}
Affects every AWS subcommand not on the hardcoded list (backup,
route53, kms, ssm, apigateway, ...) when output is valid JSON
(explicit `--output json` or auto-injected for describe-/list-/get-/scan).
In a reactor build (parent pom with `<modules>`), Maven appends a
`Reactor Summary for <root>` block at the end listing each module's
status:
[INFO] Reactor Summary for multi-module-skeleton 1.0.0-SNAPSHOT:
[INFO]
[INFO] multi-module-skeleton ...... SUCCESS [ 0.353 s]
[INFO] child-a .................... SUCCESS [ 1.676 s]
[INFO] child-b .................... FAILURE [ 0.940 s]
`filter_surefire` / `filter_package` were dropping these rows because
`keep_outside_block` only keeps `[INFO]` lines that match a specific
prefix (`Building`, `Installing`, `Total time:`, etc.). The per-module
status rows match none of them.
Add a `REACTOR_SUMMARY` regex and `reactor_summary_keep` helper that
toggles a flag on the header and clears it on `BUILD SUCCESS` /
`BUILD FAILURE`. While the flag is set the helper returns `true` so
the rows survive — including `[WARNING]` (activated-profile notices)
and the in-summary horizontal rule. Caller invokes the helper before
`keep_outside_block` so the clears-flag side effect runs regardless
of `||` short-circuit.
Fixtures captured against a hand-rolled 2-module skeleton checked in
under `tests/fixtures/multi-module-skeleton/` (parent pom + child-a
+ child-b with `Empty.java` stubs). The fail fixture is captured by
temporarily replacing child-b's `Empty.java` with one that references
a `BogusType` symbol. Reproducible from the committed skeleton.
When `mvn test` fails at the compile step before Surefire runs, the
`[ERROR]` block's indented `symbol:` / `location:` / `^` continuation
lines were being dropped. `filter_surefire` had no `keep_continuation`
state, unlike `filter_compile:302` and `filter_package:408`.
Add the missing state machine: reset in the RUNNING branch, set on each
kept `[ERROR]` line (except `Tests run:` / `Failures:` / `Errors:`
headers — same predicate as `filter_package:402-405`), and pass through
indented continuation lines before the outside-block keep-list check.
Fixture `mvn_test_compile_fail_slice_raw.txt` captures the
`mvn test` slice for a project with a deliberate `cannot find symbol`
in a `src/main/java` source. New tests:
- `surefire_keeps_compile_continuation_on_test_phase` — the bug.
- `package_still_keeps_compile_error_continuation_after_refactor` —
drift guard on the `install`/`verify` path.
Under `mvn -q`, Maven 3.x suppresses all `[INFO]` lines: no
`BUILD SUCCESS` footer, no `[INFO] Running` markers, no module
banners. The existing surefire/compile/package filters all key off
the English-footer guard and `[INFO] Running`/CLOSE state machine,
so under `-q` they fell through and shipped the raw output unchanged
(0% savings on PR #1956 reviewer's measurement).
Reviewer (@pszymkowiak on PR #1956) listed `-q` handling in the
path-to-merge as "worth a note or handling". This commit implements
the handling.
Behavior captured from `mvn -q test` on Maven 3.9.9 + Surefire 3.5.5
with JUnit 5:
- Green run emits ZERO bytes — filter returns empty output.
- Failure run emits ~27 lines: per-class CLOSE line, exception +
stack trace, `[ERROR] Failures:` summary, aggregate
`[ERROR] Tests run: N, Failures: F, ...`, and the
`[ERROR] Failed to execute goal` terminator, followed by a
~10-line `[ERROR] See .../[Help 1].../Re-run Maven .../To see
the full stack trace .../For more information ...` boilerplate
block pointing at log files and help URLs.
`filter_quiet` keeps the failure-signal lines and the user-code
stack frames; drops the framework frames (existing deny-list) and
the post-failure boilerplate block.
Routing: `is_quiet` checks argv for `-q` or `--quiet`. When set,
`run()` short-circuits the phase-based filter selection and routes
non-passthrough phases to `filter_quiet`. Passthrough phases
(`clean`, `site`, plugin goals) remain passthrough under `-q`.
Measured savings on the captured fail fixture: 51.1%
(174 -> 85 tokens). Green run: 0 -> 0 (no overhead).
Safety net: unclassified `[ERROR]` lines are kept rather than
dropped — better to leak a line than hide signal.
Tests added (7):
- `quiet_detects_short_flag` / `quiet_detects_long_flag` /
`quiet_does_not_match_unrelated_flags` for `is_quiet`.
- `quiet_green_run_is_empty` — empty input contract.
- `quiet_fail_strips_framework_and_boilerplate` — kept-list and
drop-list assertions on the real fixture.
- `savings_mvn_quiet_fail` — >=50% savings target on the fixture.
- `quiet_unknown_error_line_kept_as_safety_net` — unclassified
`[ERROR]` not silently dropped.
New fixture: `tests/fixtures/mvn_quiet_fail_raw.txt` (27 lines,
770 bytes) captured from a real `mvn -q test` run against a
JUnit 5 / Surefire 3.5.5 project with one failing test.
CLOSE regex previously required ` - in ` (single-dash, Surefire 2.x).
Surefire 3.x emits ` -- in ` (double-dash), so close lines never matched
on Maven 3.9 default toolchains: blocks stayed open, every new
`[INFO] Running …` flushed the prior block as kept, and real-world
savings dropped to ~27% on commons-cli.
Changes:
- CLOSE separator widened to `\s+--?\s+in ` (matches 2.x and 3.x).
- CLOSE prefix widened to `INFO|ERROR|WARNING` (3.x emits WARNING for
classes whose only tests are skipped).
- `filter_surefire` and `filter_package` gain a `failure_trail` flag:
Surefire 3.x emits the exception class and stack frames *after* the
CLOSE line; keep them (stripping framework frames) until the next
blank line. Without this, the failing-test signal was silently dropped.
Fixtures replaced with output from a real `apache/commons-cli` build in
`maven:3.9-eclipse-temurin-21`. Synthetic 2.x shape removed; 2.x compat
locked by a dedicated unit test using the single-dash separator.
Measured token savings on commons-cli fixtures:
- `mvn test` (full): 1896 -> 38 tokens (98.0%)
- `mvn install` (full): 2021 -> 78 tokens (96.1%)
Refs: pszymkowiak review on PR #1956
Replaces the stateless src/filters/mvn-build.toml (4 phases, 50-line cap) with
a Rust module under src/cmds/jvm/mvn_cmd.rs handling all common Maven lifecycle
phases with stateful Surefire/Failsafe block collapse.
Why TOML couldn't do this: the dominant noise on a healthy Maven project is
expected-exception stack traces inside passing tests (assertThrows). Collapsing
these requires deciding to drop a block based on its closing
`Tests run: N, Failures: 0, Errors: 0` line — a stateful decision the TOML DSL
cannot express.
Measured savings on synthetic full-shape fixtures (~1100 lines each, gzipped):
- mvn test: 3 422 tok → 36 tok (98.9% savings)
- mvn install: 3 460 tok → 85 tok (97.5% savings)
Coverage:
| Phase | Filter |
|------------------------------------|----------------------------------------|
| test, integration-test | filter_surefire (block collapse) |
| compile, test-compile | filter_compile (ERROR + indent + dedup)|
| package, install, verify, deploy | filter_package (compile + surefire) |
| clean, site, plugin goals, version | passthrough |
Key behaviours:
- ANSI strip first in every filter (real Maven output contains colour escapes).
- English-footer guard: if no `BUILD SUCCESS`/`BUILD FAILURE` line is present,
return ANSI-stripped raw input unchanged — protects non-English locales.
- Verbose bypass: `-X`, `--debug`, `-e`, `--errors` skip filtering.
- Stack-frame deny-list strips framework frames (`at org.junit.`, `at java.util.`,
`at sun.reflect.`, etc.); user-code frames (any other prefix) preserved.
- Duration normalisation (`Time elapsed: 2.341 s` → `Time elapsed: T s`) for
deterministic test output.
- Wrapper detection: `./mvnw` / `mvnw.cmd` via string-literal `Command::new`
(semgrep-safe); falls back to `resolved_command("mvn")`.
Hook regex changes (src/discover/rules.rs):
- Adds wrapper prefixes (./mvnw, mvnw.cmd, mvnw).
- Adds test, integration-test, verify, deploy to the alternation.
- Drops clean + site so bare invocations bypass RTK entirely (0 overhead).
- Lazy quantifier skips flags before the goal (`mvn -B clean install` now
rewrites correctly; previously failed because the regex required the goal
as the first token after `mvn`).
- Drops subcmd_savings (lazy match captures first phase, which would mis-tier
`clean install` to clean); uses flat 82.0.
Tests:
- 33 unit tests in mvn_cmd.rs (phase detection, footer guard, framework deny,
duration normalisation, ERROR continuation, WARNING dedup, install/jar lines).
- 2 inline savings assertions on gzipped synthetic full fixtures (~3 KB each)
using flate2 already in Cargo.toml. Run as part of standard `cargo test --all`.
- 12 classifier/rewrite tests in src/discover/registry.rs under new Maven
section.
Files changed:
- ADD src/cmds/jvm/mvn_cmd.rs (~810 LoC incl. tests)
- ADD src/cmds/jvm/README.md (documents whitelist omission decision)
- ADD tests/fixtures/mvn_*_raw.txt (6 inline) + 2 .gz synthetic full fixtures
- MOD src/main.rs (1 use, 1 Commands variant, 1 dispatch arm)
- MOD src/discover/rules.rs (replace mvn entry)
- MOD src/discover/registry.rs (12 classifier tests)
- MOD src/core/toml_filter.rs (drop mvn-build from expected-filters list,
adjust the 2 count assertions)
- DEL src/filters/mvn-build.toml
Fixtures are entirely synthetic — generic `com.example.app.*` package names and
`com.example:myapp` Maven coordinates. Same SHAPE as real Maven output (block
structure, ANSI codes, framework stack frames, BUILD footer, plugin banners)
without any project-identifying content.
Integrity-check whitelist: Commands::Mvn is intentionally omitted from
is_operational_command at src/main.rs:2455-2501, matching the gradle precedent
(Commands::Gradlew also omitted). The whitelist is opt-in by design per the
comment at L2452-2454 — filter modules invoked through an already-verified
hook do not need a second integrity check on their own dispatch path.
Documented in src/cmds/jvm/README.md.
Out-of-scope (follow-ups noted in module + README):
- Parallel mode `-T2C` (interleaved blocks across threads).
- Plugin goals (`mvn dependency:tree`, `mvn versions:*`).
- `mvnw.bat` legacy wrapper (Maven Wrapper 3.x emits `.cmd`).
BREAKING CHANGE: `rtk mvn <args>` output format changed. Previously: TOML
filter strips INFO/Downloading lines and caps at 50 lines. Now: state-machine
filter with Surefire block collapse + locale guard + verbose bypass. Different
output shape; significantly better savings tier; behaviour is otherwise a
superset (all previously-handled cases still handled, plus test/verify/etc.).
Adds rtk gradlew command for build, test, lint, and dependency
operations on Gradle projects. Filters task progress noise, preserves
build scan URLs, test failures, lint violations, and compiler warnings.
Recognises ./gradlew, gradlew, gradlew.bat, and gradle invocations.
Surfaces unit-test report paths and shows a progress indicator for
long-running tasks.
Targets 75% savings (90% on test, 80% on build).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* 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>