`Apache 2.0` is not a valid SPDX expression, so `cargo publish` rejects
the manifest and `brew audit` flags the generated formula. Use the
`Apache-2.0` identifier in both places.
The release workflow regenerates `Formula/rtk.rb` on every release, so
its heredoc was overwriting the already-correct value checked in at
`Formula/rtk.rb:10`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest` resolves
on the unversioned module path, which stops at v1.64.8 (March 2025, the last v1).
v2 is published under /v2, so `@latest` never moved.
Since runners picked up Go 1.27, that pinned v1.64.8 fails before it lints
anything -- its vendored go/types rejects the newer export data:
could not load export data: internal error in importing "internal/goarch"
(export data version 4 is greater than maximum supported version 2)
It writes 628 bytes to stderr, leaves stdout empty and exits 3, which is the
157-token benchmark row that turns the job red.
Reproduced in golang:1.27 and verified there: the /v2 path installs v2.13.2 and
lints the benchmark fixture cleanly. `@latest` is kept deliberately -- the /v2 in
the path is what carries the fix, and a future major would publish under /v3
rather than being picked up silently. This is also the only configuration in
which RTK's v2 output branch is exercised at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Per review: permissions: {} + actions/create-github-app-token, same
pattern as cd.yml/release.yml/pr-target-check.yml, instead of relying
on the default GITHUB_TOKEN. Cron moved from daily to weekly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Config mirrors facebook/react's actions/stale setup, adapted to rtk's
label taxonomy for exemptions (bug, enhancement, area:security,
P0-critical, P1-high, DONE_REVIEW, good first issue, help wanted).
Context: #348 originally scoped a stale bot out of its triage-automation
plan ("oldest item is 17 days, no staleness problem yet" — true in March
2026 at 51 open PRs). At current volume (1049 open PRs), 253 have had no
activity in 90+ days, 182 of those with zero labels at all — the
assumption in #348 no longer holds.
Thresholds are a starting point (React's numbers), open to tuning.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Add check-test-presence.sh script and CI job that fails if any *_cmd.rs
file added or modified in a PR is missing a #[cfg(test)] block.
- New CI job runs with no dependencies (parallel to all other jobs, <10s)
- Uses --diff-filter=AM to catch both added files and test deletions
- --self-test mode for local verification
- Add missing tests to wget_cmd.rs (17 tests) and env_cmd.rs (12 tests)
covering pure functions: compact_url, format_size, parse_error,
extract_filename, mask_value, is_lang_var, is_cloud_var, etc.
Fixes the enforcement gap: CONTRIBUTING.md required tests but CI did not
check. Now 34/34 *_cmd.rs modules have #[cfg(test)].
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com>
Pre-release tags on develop used v* prefix (e.g. v0.33.1-rc.60) which
release-please interpreted as the latest version, causing it to generate
wrong release versions. Changed to dev- prefix (e.g. dev-0.34.0-rc.61)
so release-please only sees stable v* tags.
Cleaned up: 42 RC releases and tags deleted.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
added script to act like release please (release please flag was unclear)
added workflow dispatch event + dev like for prelease debug
guards for workflow_dispatch (limit to push master for release events)
Signed-off-by: aesoft <43991222+aeppling@users.noreply.github.com>
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: P1 exit codes, grep regex perf, SQLite WAL (#631)
* fix: P1 exit codes, grep regex perf, SQLite concurrency
Exit code propagation (same pattern as existing modules):
- wget_cmd: run() and run_stdout() now exit on failure
- container: docker_logs, kubectl_pods/services/logs now check
status before parsing JSON (was showing "No pods found" on error)
- pnpm_cmd: replace bail!() with eprint + process::exit in
run_list and run_install
Performance:
- grep_cmd: compile context regex once before loop instead of
per-line in clean_line() (was N compilations per grep call)
Data integrity:
- tracking: add PRAGMA journal_mode=WAL and busy_timeout=5000
to prevent SQLite corruption with concurrent Claude Code instances
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: address review findings on P1 fixes
- tracking: WAL pragma non-fatal (NFS/read-only compat)
- wget: forward raw stderr on failure, track raw==raw (no fake savings)
- container: remove stderr shadow in docker_logs, add empty-stderr
guard on all 4 new exit code paths for consistency with prisma pattern
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: raise output caps for P0 bugs (#617, #618, #620) (#630)
* fix: raise output caps for grep, git status, and parser fallback (#617, #618, #620)
- grep: per-file match cap 10 → 25, global max 50 → 200
- git status: file list caps 5/5/3 → 15/15/10
- parser fallback: truncate 500 → 2000 chars across all modules
These P0 bugs caused LLM retry loops when RTK returned less signal
than the raw command, making RTK worse than not using it.
Fixes#617, #618, #620
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: update README example and add truncation tests for modified/untracked
- parser/README.md: update example from 500 → 2000 to match code
- git.rs: add test_format_status_modified_truncation (cap 15)
- git.rs: add test_format_status_untracked_truncation (cap 10)
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* refactor: extract output caps into [limits] config section
Move hardcoded caps into config.toml so users can tune them:
[limits]
grep_max_results = 200 # global grep match limit
grep_max_per_file = 25 # per-file match limit
status_max_files = 15 # staged/modified file list cap
status_max_untracked = 10 # untracked file list cap
passthrough_max_chars = 2000 # parser fallback truncation
All 8 modules now read from config::limits() instead of hardcoded
values. Defaults unchanged from previous commit.
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* feat(.claude): add /rtk-triage skill — cross-analysis of PRs and issues (#662)
* feat(.claude): add /rtk-triage skill — orchestrated PR+issue cross-analysis
New skill that runs issue-triage + pr-triage in parallel then produces
a cross-analysis layer that neither skill can do individually:
- Double coverage detection: identifies when 2+ PRs target the same issue
(via body scan + file overlap), recommends which to keep/close
- Security gap detection: for security review issues, maps each finding
to a PR (or flags it as uncovered)
- P0/P1 bugs without PR: groups by pattern to suggest sprint batching
- Our dirty PRs: identifies probable cause (conflict with sibling PR,
needs rebase, missing linked issue)
Output is saved automatically to claudedocs/RTK-YYYY-MM-DD.md.
Usage: /rtk-triage (French, auto-save)
/rtk-triage en (English output)
Signed-off-by: Florian Bruniaux <florian@bel-etage.com>
Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com>
* docs(architecture): update module count to 66
Sync ARCHITECTURE.md with current main.rs state.
Previous count (60) was stale since several modules were added
(dotnet_cmd, dotnet_format_report, dotnet_trx, npm_cmd, gt_cmd, etc.).
Signed-off-by: Florian Bruniaux <florian@bel-etage.com>
Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com>
---------
Signed-off-by: Florian Bruniaux <florian@bel-etage.com>
Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com>
* fix: subcommand routing drops unrecognized subcommands (#600) (#601)
- git stash: pass unknown subcommands (save, branch, clear) through
instead of silently falling back to git stash push
- git branch: add --show-current, --set-upstream-to, --format, --sort
to flag detection so they don't get overridden by -a injection
- pip: replace bail!() with passthrough for unknown subcommands
(freeze, download, wheel, etc.)
Fixes#600
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: resolve cargo fmt + 54 clippy warnings blocking CI (#663)
cargo fmt diffs in config.rs, git.rs, playwright_cmd.rs were failing
the fmt CI check, which cascaded to block clippy/test/security on
PRs #632, #635, #638. Also fixes all clippy warnings: dead code
annotations, iterator simplifications, assert patterns, and
unnecessary allocations.
Signed-off-by: Patrick Szymkowiak <patrick@rtk-ai.app>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: discover absolute paths + git global options (#485, #163) (#518)
* fix: discover classifies absolute paths like /usr/bin/grep (#485)
Normalize absolute binary paths before classification:
/usr/bin/grep → grep, /bin/ls → ls, /usr/local/bin/git → git
Adds strip_absolute_path() helper + 5 tests.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: discover and rewrite support git global options -C, --no-pager, etc. (#163)
Strip git global options (-C <path>, -c <key=val>, --git-dir, --work-tree,
--no-pager, --no-optional-locks, --bare, --literal-pathspecs) before
classification so git -C /tmp status is recognized as rtk git.
Rewrite preserves global options: git -C /tmp status → rtk git -C /tmp status
Adds GIT_GLOBAL_OPT lazy_static regex + strip_git_global_opts() helper + 6 tests.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: prevent double `--` separator in cargo clippy with -p flags (#519)
When running `rtk cargo clippy -p my-crate -- -D warnings`, Clap with
`trailing_var_arg = true` preserves the `--` in parsed args when flags
precede it. `restore_double_dash()` then added a second `--`, producing
`cargo clippy -p my-crate -- -- -D warnings`. This caused rustc to
interpret `-D` as a filename instead of a lint flag.
Fix: skip restoration when args already contain `--` (Clap preserved it).
Fixes#496
Signed-off-by: Ousama Ben Younes <benyounes.ousama@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* ci: add PR template + target branch check (#521)
- PR template reminds contributors to target develop
- CI workflow labels PRs targeting master with 'wrong-base' and posts a comment
- Excludes develop→master PRs (maintainer releases)
Signed-off-by: Patrick <patrick@rtk-ai.com>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: prevent rtk read from corrupting JSON/YAML/data files (#522)
Add Language::Data variant for data formats (JSON, YAML, TOML, XML, CSV, etc.)
with empty comment patterns to prevent comment stripping. AggressiveFilter
falls back to MinimalFilter for data files.
Fixes#464
Signed-off-by: Ousama Ben Younes <benyounes.ousama@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: skip rewriting find/fd in pipes to preserve xargs compatibility (#439) (#563)
rtk find outputs a grouped format incompatible with pipe consumers
like xargs, grep, wc, sort. Skip rewrite when find/fd is followed
by a pipe, preserving native one-per-line output.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: add hint when git diff is truncated + fix --no-compact passthrough (#427) (#564)
When compact_diff truncates output, append a hint line so Claude knows
how to get the full diff: [full diff: rtk git diff --no-compact]
Also fix --no-compact flag being passed to git (causing usage error)
and remove decorative emoji from compact_diff output.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: propagate exit codes in git diff, status+args, commit, and branch (#632)
4 P1 bugs where git exit codes were swallowed:
- git diff: failure silently printed empty stat output
- git status (with args): failure was filtered instead of propagated
- git commit: failure printed "FAILED" but returned Ok(()) breaking pre-commit hooks
- git branch (list mode): failure was silently ignored
All now follow the established pattern: eprint stderr, track raw==raw, process::exit(code).
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* feat: add 5 new TOML filters (ollama, nx, gradle, spring-boot, jira) (#635)
* feat: add 5 new TOML built-in filters (ollama, nx, gradle, spring-boot, jira)
New filters for commands not covered by Rust modules:
- ollama: strip ANSI spinners, keep final text response (#624)
- nx: strip Nx monorepo noise, keep build results (#444)
- gradle/gradlew: strip UP-TO-DATE tasks, keep build summary (#147)
- spring-boot: strip banner and verbose logs, keep startup/errors (#147)
- jira: strip blanks, truncate wide columns (#524)
All 5 filters pass inline tests via rtk verify (123/123).
Updated builtin filter count: 47 -> 52.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* feat: add 5 more TOML filters (turbo, mise, just, task, yadm)
New filters for task runners and git wrapper:
- turbo: strip cache/Tasks/Duration noise, keep task output (#531)
- mise: strip install/download progress, keep task results (#607)
- just: strip blanks and recipe headers, keep output (#607)
- task: strip task headers and up-to-date lines, keep results (#607)
- yadm: strip hint lines, compact git-like output (#567)
All verified with fake binaries through catch-all TOML engine.
137/137 TOML tests pass, 934 Rust tests pass.
Updated builtin filter count: 52 -> 57.
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
* fix: replace emojis with plain text in git status output (#603) (#638)
Git status output used emojis (📌, 📝, ❓, ✅, ⚠️) that confuse
non-Claude LLMs (GPT, etc.) causing retry loops. Replace with plain
text labels (branch:, modified:, staged:, untracked:, conflicts:).
Also add "clean — nothing to commit" when working tree is clean,
so LLMs understand the repo state without ambiguity.
Before: 📌 master
After: branch: master
clean — nothing to commit
Fixes#603
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
---------
Signed-off-by: Patrick <patrick@rtk.ai>
Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu>
Signed-off-by: Florian Bruniaux <florian@bel-etage.com>
Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com>
Signed-off-by: Patrick Szymkowiak <patrick@rtk-ai.app>
Signed-off-by: Ousama Ben Younes <benyounes.ousama@gmail.com>
Signed-off-by: Patrick <patrick@rtk-ai.com>
Co-authored-by: Florian BRUNIAUX <florian@bruniaux.com>
Co-authored-by: Ben Younes <benyounes.ousama@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Cleaned all files for a more reusable cicd
- Added pre-release on develop
- Added jobs dependencies to gain time (avoid running all if mandatory fail)
- Add CICD.md documentation