- Drop the needless borrow at the format_diff_changes call site; with
warnings = "deny" this was failing cargo clippy --all-targets and
blocking the clippy job that build, test and release depend on.
- Keep the original both-files dump as the timer.track baseline. The
synthesized classic diff is empty for identical files, which recorded
input_tokens = 0 and reported ~0% instead of ~46% in rtk gain --history.
- Un-gate render_file_diff: fold it into render_diff rather than compiling
a production helper only under cfg(test).
- Update the scripts/test-all.sh assertion to match the real output.
Condense the Grep variant and its tests to the comment rules in
CONTRIBUTING.md (explain why, not what), and carry the -l/-t change
through the files that still assumed the old behavior.
- scripts/test-aristote.sh: add -r to the two grep assertions, since
`grep PATTERN <dir>` exits 2, and move the type filter to `rtk rg`,
the engine where -t is valid.
- docs/usage/FEATURES.md: extra args go to the engine actually invoked,
not always to rg; drop the per-row shortcut justifications.
- tests/search_compress_test.rs: guard grep-engine tests on
grep_available() instead of rg_available(), which skipped them into a
false green on a box without ripgrep.
- .claude/hooks/rtk-suggest.sh: reverted; the rg -> rtk rg fix is
correct but belongs in its own PR.
BREAKING CHANGE: `rtk grep --file-type` and its `-t` short are removed.
The option never reached the engine, so it was a silent no-op; `-t` now
flows through, which means `rtk rg -t rust` filters by type while
`rtk grep -t rust` returns grep's own `invalid option -- 't'`. `-l` and
`-m` under `rtk grep` are likewise the native grep flags now rather than
rtk's --max-len and --max.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review caught that my replacement assertion was inert. `assert_fails` passes
on ANY non-zero exit, and the base command already failed for an unrelated
reason:
$ rtk grep "pub fn" src/
grep: src/: Is a directory
exit=2
So it passed whether or not `-t` was handled correctly. I replaced a wrong
assertion with one that cannot fail.
Adding `-r` was not enough either: with `-r` first, trailing_var_arg swallows
`-t` before clap ever sees it, so the mutant still exits 2. The form has to
put `-t` FIRST, use a pattern that MATCHES, and target a single file, so the
only reason the command can fail is `-t` itself. Mutation-proved both ways by
re-adding `--file-type` with `short = 't'`:
mutant: rtk grep -t rust "fn main" src/main.rs -> exit=0 (assert_fails fires)
fixed: rtk grep -t rust "fn main" src/main.rs -> exit=2 (assert_fails passes)
The comment above the assertion records the three ways to make it inert
again, since I hit two of them.
Adding `-r` to the two adjacent assertions fixes them too -- they were red on
develop because `grep PATTERN <dir>` without `-r` exits 2. Both line 260 and
261 were failing, not just 260 as I said earlier.
Corrects two false statements from earlier commit messages in this branch:
- The FEATURES.md `--line-numbers | -n` row was STALE, not fabricated. The
option existed from 7d69299 (2026-02-15) until 84616d1 (2026-06-10) --
the same commit the struct NOTE credits for the -v/-n cleanup. Removing
the row is still right; my justification was wrong.
- `scripts/test-all.sh` is not wired into CI, but it is not "referenced
only from .github/copilot-instructions.md" either. It is a documented
contributor command: CONTRIBUTING.md:253 and CLAUDE.md:46.
scripts/test-all.sh asserted `rtk grep "pub fn" src/ -t rust` exits 0. That
only held because --file-type swallowed `-t` and never passed it to the
engine, so the assertion was pinning a silent no-op. With --file-type gone,
`-t` reaches GNU grep, which has no such flag:
$ rtk grep "pub fn" src/ -t rust
grep: invalid option -- t
exit=2
Replaced with an assert_fails pinning that rejection, plus an assert_ok
against rg (which does have -t), guarded on rg being installed. Verified:
rtk grep "pub fn" src/ -t rust -> exit=2 (assert_fails wants non-zero)
rtk rg "pub fn" src/ -t rust -> exit=0 (assert_ok wants 0)
$ bash -n scripts/test-all.sh
syntax OK
Also drops a `--line-numbers | -n` row from the FEATURES.md grep table. No
such option exists on Commands::Grep -- its fields are max_len, max,
context_only, extra_args. The `line_numbers` field at src/main.rs:118
belongs to Read. The row predates this PR but sits in the table it edits.
Note, NOT fixed here as it is pre-existing and unrelated: the adjacent
`assert_ok "rtk grep pattern" rtk grep "pub fn" src/` on the line above
also fails, because grep without -r on a directory exits 2. The smoke
suite is not wired into CI (referenced only from
.github/copilot-instructions.md), which is how it rotted unnoticed.
rtk diff treated files whose changes were all classified as modified
(similar lines, e.g. "a: 1" vs "a: 2" in YAML/JSON) as identical,
because the identical check only looked at added/removed counts.
Report any non-empty change set as a difference, and exit 1 when
files differ per diff convention (0 when identical).
Fixes#2364
Call skip_test instead of nonexistent skip function, consistent
with all other conditional sections (Python, Go, tree, etc.).
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: prettier reports "All OK" when not installed (#221)
Empty or failed prettier output was incorrectly treated as "all files
formatted". Now detects empty output and non-zero exit code, shows the
actual error message instead of a false positive.
* test: add smoke tests for rewrite, verify, proxy, discover, diff, wc, smart, docker, json edge cases
Covers bug fixes#196, #344, #345, #346, #347 and previously untested
commands. Adds assert_fails helper. 118 assertions total (was 69).
* chore: update benchmark.sh with missing commands and fix paths
- Add cargo (build/test/clippy/check), diff, smart, wc, curl, wget sections
- Fix Python commands: use dedicated rtk ruff/pytest instead of rtk test
- Fix Go commands: use dedicated rtk go/golangci-lint, add go build/vet
- Make BENCH_DIR absolute so debug files work from temp fixture dirs
- Fallback to installed rtk if target/release/rtk not found
* feat: passthrough fallback when Clap parse fails
When RTK cannot parse a command (e.g. `rtk git -C /path status`),
instead of exiting with error code 2, it now falls back to running
the raw command directly. This keeps developer workflows unbroken.
- Replace Cli::parse() with try_parse() + run_fallback()
- Add parse_failures SQLite table for failure analytics
- Add `rtk gain --failures` / `-F` to view failure log
- Fallback preserves stdin/stdout/stderr via Stdio::inherit()
- --help and --version still work normally
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: guard RTK meta-commands from fallback to raw execution
When Clap fails to parse a meta-command like `rtk gain --badtypo`,
show the Clap error directly instead of trying to execute `gain`
as a binary from $PATH. Adds RTK_META_COMMANDS constant listing
gain, discover, learn, init, config, proxy, hook-audit, cc-economics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: move timer start before command execution in fallback
TimedExecution::start() was called after the command finished,
so all fallback commands showed ~0ms in rtk gain --history.
Now the timer captures actual command runtime.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add cleanup_old() call to record_parse_failure()
The parse_failures table was never cleaned up because only record()
called cleanup_old(). Now parse failures also trigger 90-day retention
cleanup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: strip ANSI codes from Clap error before SQLite storage
Clap errors may contain terminal color codes. Strip them with
utils::strip_ansi() before storing in the parse_failures table
to avoid garbled output and wasted space.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: smoke test cargo test assertion and missing skip_test calls
- cargo test check now matches RTK's filtered output format ("passed")
in addition to raw "test result:" and "FAILURES"
- Fix undefined `skip` calls to use existing `skip_test` function
with proper (name, reason) arguments
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: fmt upstream files after rebase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update version refs to 0.23.0 and module count to 51
Upstream v0.23.0 release bumped Cargo.toml version and added mypy_cmd
module. Update docs to match for CI validation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(cargo): aggregate test output into single line (#83)
Problem: `cargo test` shows 24+ summary lines even when all pass.
An LLM only needs to know IF something failed, not 24x "ok".
Before (24 lines):
```
✓ test result: ok. 2 passed; 0 failed; ...
✓ test result: ok. 0 passed; 0 failed; ...
... (x24)
```
After (1 line):
```
✓ cargo test: 137 passed (24 suites, 1.45s)
```
Changes:
- Add AggregatedTestResult struct with regex parsing
- Merge multiple test summaries when all pass
- Format: "N passed, M ignored, P filtered out (X suites, Ys)"
- Fallback to original behavior if parsing fails
- Failures still show full details (no aggregation)
Tests: 6 new + 1 modified, covering all cases:
- Multi-suite aggregation
- Single suite (singular "suite")
- Zero tests
- With ignored/filtered out
- Failures → no aggregation (detail preserved)
- Regex fallback
Closes#83
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add Python and Go language support
Implements comprehensive support for Python and Go development tooling
with 70-90% token reduction across all commands.
Python commands (3):
- rtk ruff: Linter/formatter with JSON (check) and text (format) parsing (80%+)
- rtk pytest: Test runner with state machine text parser (90%+)
- rtk pip: Package manager with auto-detect uv (70-85%)
Go commands (4):
- rtk go test: NDJSON streaming parser for interleaved test events (90%+)
- rtk go build: Text filter showing errors only (80%)
- rtk go vet: Text filter for issues (75%)
- rtk golangci-lint: JSON parser grouped by rule (85%)
Architecture:
- Standalone Python commands (mirror lint/prettier pattern)
- Go sub-enum (mirror git/cargo pattern)
- 5 new modules: ruff_cmd, pytest_cmd, pip_cmd, go_cmd, golangci_cmd
- Hook integration in rtk-rewrite.sh for transparent rewrites
- Comprehensive tests (47 new tests, all passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat(benchmark): add Python and Go commands
Add benchmark sections for Python (ruff, pytest, pip) and Go (go test/build/vet, golangci-lint) to validate >80% token savings in CI pipeline.
Sections conditionally execute based on project markers (pyproject.toml, go.mod) and tool availability.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
- ls: rewrite to strip permissions/owner/group/dates, show only
names with dir/ suffix and human sizes. Properly handle flag
ordering (path -l), -lh, multi-paths, --all.
- discover: remove orphan diff pattern that caused index out of
bounds panic (PATTERNS had 22 entries vs RULES 21)
- benchmark: add 8 ls test cases
- test-all: add 5 ls smoke tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove rtk diff from docs, tests, discover registry (command exists
but was over-promoted)
- docker ps: include container ID in compact output
- diff_cmd: widen truncation from 35 to 70 chars per side
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to read from stdin using the special path "-", following
Unix conventions. Also fixes a pre-existing bug in git.rs push output.
Changes:
- src/main.rs: Check for Path::new("-") and route to run_stdin()
- src/read.rs: Add run_stdin() function for stdin processing
- src/read.rs: Use Language::Unknown for stdin (no file extension)
- src/git.rs: Fix unused format! result in push command
- Unit test: test_stdin_support_signature verifies function exists
- Smoke tests: 1 assertion for stdin pipe
Usage:
echo "code" | rtk read -
cat file.txt | rtk read - --level aggressive
somecommand | rtk read - -n
Note: Stdin detection requires explicit "-" path to avoid hanging.
No automatic stdin detection is performed.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add support for passing additional ripgrep arguments to rtk grep
while preserving RTK's token-optimized output formatting.
Changes:
- src/main.rs: Add extra_args field to Grep command variant
- src/main.rs: Pass extra_args to grep_cmd::run()
- src/grep_cmd.rs: Add extra_args parameter to run() signature
- src/grep_cmd.rs: Inject extra_args into ripgrep command
- Unit test: test_extra_args_accepted verifies parameter exists
- Smoke tests: 2 assertions for -i and -A flags
Usage note: Extra args must come AFTER pattern and path:
✓ rtk grep "pattern" src/ -i
✗ rtk grep "pattern" -i (clap interprets -i as path)
This enables full ripgrep functionality (case-insensitive, context
lines, word boundaries, globs) while maintaining RTK's compact output.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add external_subcommand variant to PnpmCommands enum to handle
unsupported pnpm operations by passing them through directly.
Changes:
- src/pnpm_cmd.rs: Add run_passthrough() function with OsString support
- src/pnpm_cmd.rs: Add OsString import
- src/main.rs: Add PnpmCommands::Other variant with external_subcommand
- src/main.rs: Add match arm for pnpm passthrough
- Unit test: test_run_passthrough_accepts_args verifies signature
- Smoke tests: Conditional test for pnpm help if pnpm is available
This maintains compatibility with all pnpm commands while preserving
RTK's token-optimized versions for list/outdated/install.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add external_subcommand variant to GitCommands enum to handle
unsupported git operations (tag, remote, rev-parse, etc.) by
passing them through directly to git.
Changes:
- src/git.rs: Add run_passthrough() function with OsString support
- src/main.rs: Add GitCommands::Other variant with external_subcommand
- src/main.rs: Add OsString import and match arm for passthrough
- Unit test: test_run_passthrough_accepts_args verifies signature
- Smoke tests: 3 new assertions for tag, remote, rev-parse
This preserves all git functionality while maintaining RTK's
token-optimized commands for supported operations.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously, `rtk git status` was the only git subcommand that rejected
all arguments. This fix aligns it with other git subcommands (diff, log,
show, etc.) by accepting native git flags.
Changes:
- Extract format_status_output() as pure testable function
- Add args variant to Clap Status command with trailing_var_arg
- Modify run_status() to accept args parameter
- Passthrough mode: if user provides flags (--short, -s, --porcelain),
forward directly to git without RTK formatting
- Default mode: no flags = RTK compact formatting (unchanged behavior)
- Add 5 unit tests for format_status_output (clean, modified, untracked,
mixed, truncation)
- Add 4 smoke tests for flag passthrough (--short, -s, --porcelain)
Test results:
- 151 unit tests passed (5 new)
- 69 smoke tests passed (4 new for status flags)
Fixes the issue where commands like `rtk git status --short` were
rejected with "unexpected argument" error.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>