feat: TOML Part 1 — filter DSL engine + 14 built-in filters#349
feat: TOML Part 1 — filter DSL engine + 14 built-in filters#349FlorianBruniaux wants to merge 5 commits intomasterfrom
Conversation
Add a declarative TOML-based filter engine for zero-Rust command filtering, plus 14 built-in filters targeting open issues. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2093f33 to
9ad4540
Compare
Remove bundle_cmd.rs and rails_cmd.rs from this branch per upstream feedback (PR rtk-ai#349). These modules will be re-added in a separate feat/ruby-bundle-rails branch for future TOML filter DSL. Removed: Bundle/Rails enum variants, RailsCommands sub-enum, discover rules/registry tests, smoke test assertions. Renamed test-rails.sh to test-ruby.sh (rspec+rubocop only). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review — TOML Filter DSLThe TOML engine itself is well-designed: Note: This branch needs a rebase onto current master before merge (missing Graphite support, diff limit fixes, Discord notification, 0.27.2 changelog). The issues below are specific to this PR's code, not rebase artifacts. P1 — ImportantP1-1: Missing trailing newline in TOML-filtered output P1-2: Dead TOML filters — P1-3: P1-4: Tee hint silently discarded for TOML-filtered commands P1-5: P2 — Minor
P3 — Nits
Action items
|
What this PR does
Adds a declarative TOML-based filter engine that lets anyone add a new command filter without writing Rust. A TOML block in
src/builtin_filters.toml(or the user's.rtk/filters.toml) is enough for commands with stable, predictable output.This is a foundational change: it lowers the contribution bar for simple filters from ~200 LOC of Rust to a ~10-line TOML block.
Architecture
New files
src/toml_filter.rsrun_fallback()integrationsrc/builtin_filters.tomlinclude_str!)src/verify_cmd.rsrtk verifycommand — runs inline TOML tests, supports--require-allHow it works
User filters in
.rtk/filters.tomlare loaded at startup and merged with built-ins. User filters take precedence over built-ins.Filter pipeline
TOML vs Rust — decision guide
Filter primitives (8 total)
strip_ansistrip_lines_matchingkeep_lines_matchingreplacematch_outputtruncate_lines_athead_lines/tail_linesmax_lineson_empty14 new built-in filters
#240 — OpenTofu (4 filters)
Mirror of the existing
terraform-*filters, targetingtofuCLI.tofu-plantofu plantofu-inittofu inittofu-validatetofu validateSuccess!tofu-fmttofu fmton_emptyfor no changes#284 —
du(1 filter)Strips blank lines, truncates long paths at 120 chars, caps at 40 lines.
#281 —
fail2ban-client(1 filter)Strips blank lines, caps at 30 lines. Note: no
sudoprefix — the hook rewrite does not capturesudo, so the prefix would be dead code.#282 —
iptables(1 filter)Defensive regex: strips only Docker-autogenerated chains (
^Chain DOCKER,^Chain BR-). Does not strip the rule lines that follow those chains. Caps at 50 lines, truncates at 120 chars.#310 — Elixir
mix(2 filters)mix-formatmix formaton_empty→mix format: okmix-compilemix compileCompiling N files,Generated, blanks; preserves warnings/errors#280 — Shopify Theme (1 filter)
Strips
Uploading/Downloadinglines, keeps last 5 lines (the summary) viatail_lines, caps at 15.#231 — PlatformIO (1 filter, partial)
pio run: strips build noise (CONFIGURATION, LDF, Compiling, Linking, Building, Checking size). Errors and the final memory summary are preserved.Note: this closes the
pio runcase. Other commands from #231 (npm test,python,stty) remain open.#338 — Maven (1 filter, partial)
mvn compile|package|clean|install: usesstrip_lines_matching(notkeep) to strip[INFO] ---,[INFO] Building, download lines, and blanks. This preserves stacktraces, plugin warnings, and any unexpected output — only known noise is stripped.Note:
mvn test(Surefire state machine) is out of scope for TOML; it requires a Rust module.Inline test suite
Every filter has at minimum 2 inline tests (realistic fixture + edge case). Run with:
Test results at time of this PR: 38/38 passed.
Issues closed / addressed
Closed by this PR
rtkmust pass through unrecognized commands — resolved byrun_fallback()+ TOML routingdusupport — filter addedfail2ban-clientsupport — filter addediptablessupport — filter addedmix formatandmix compile— 2 filters addedPartially addressed
pio runfilter addednpm test,python,stty, other 7 commands from the issueshopify theme push/pullfilter addedmvn compile/package/clean/installfilter addedmvn test(needs Rust state machine for Surefire)Not addressed (documented reasons)
docker execstatstat -fvs Linux format divergence; savings < 60%; low utilitysshjjPRs with technical coordination needed
Based on the pre-merge impact analysis (
claudedocs/toml-impact-triage-2026-03-05.md):Conflicts (should merge before this PR ideally)
lazy_static→LazyLockmigrationlazy_static!intoml_filter.rs. If #306 merges first, we switch toLazyLock— cleaner result.run_fallback()stderr/--separatorrun_fallback(). Merging #326 first avoids a painful rebase.Architectural note (no code conflict)
Stdio::pipedfor matched commands; streaming behavior for unmatched commands (inherit) is unchanged. No conflict, but related architecturally.PRs NOT affected by this PR
All 7 PRs deep-dived in the impact analysis are Rust-required — they use state machines, JSON aggregation, or HashMaps that TOML primitives cannot express:
serde_json::Value, metrics aggregationBazelBuildState/BazelTestState, BTreeMap, streamingtest/connected/depssubcommands = state machinesin_failure_blockfailure trackingserde_json+HashMap<String, usize>aggregationThe ~35 other open PRs (Rust filters, bug fixes, docs, infra, hooks) are unaffected.
Out of scope (documented for follow-up)
rtk <cmd>. Addingtofu,du,fail2ban-client,iptables,mix,shopify,pio,mvnto the hook is a separate PR.rtk discoverTOML recommendations:rtk discovercould suggest TOML filters for unhandled commands — separate issue.Test plan
🤖 Generated with Claude Code