Skip to content

feat: TOML-based filter DSL for community contributions #299

@pszymkowiak

Description

@pszymkowiak

Problem

Adding a new filter to RTK currently requires writing a full Rust module (~100-200 lines), adding a variant to the Commands enum, updating main.rs, and passing the full quality gate. This is a high barrier for contributors who just want to add simple output filtering for a tool like pre-commit, helm show values, or ansible-playbook.

There are currently 30+ open PRs, many of which are simple line-oriented filters that follow the same pattern.

Proposal

A declarative TOML filter DSL for the ~45% of commands with simple line-oriented output. Contributors add a TOML block instead of writing Rust:

[[filter]]
command = "pre-commit run"
strip_lines_matching = ["^Passed$", "^\\[INFO\\]"]
keep_lines_matching  = []
strip_ansi           = true
max_lines            = 100
on_empty             = "✓ All hooks passed"

[[filter]]
command = "helm show values"
strip_lines_matching = ["^#", "^\\s*$"]
max_lines            = 100

The Rust engine interprets and applies these rules. Built-in rules ship with the binary (include_str!). Users can add custom rules at multiple levels:

Filter lookup priority

1. Rust built-in filters          (highest priority, always win)
2. .rtk/filters.toml              (project-level, in current directory)
3. ~/.config/rtk/filters.toml     (user-level, global custom rules)
4. Built-in TOML rules            (shipped with binary)
5. Passthrough                    (no filter → raw execution)

Project-level .rtk/filters.toml allows teams to define custom filters for their own tools and scripts without polluting the global config — similar to .eslintrc or .prettierrc.

Scope

TOML-feasible (~45% of open issues): commands with line-oriented text output — pre-commit, helm, terraform fmt, gcloud, ansible-playbook, make, du, stat, jj, oxlint...

Rust-required (~55%): JSON/NDJSON parsing, multi-line state machines, complex grouping — docker inspect, psql, go test, aws ec2 describe-instances...

DSL primitives (8 max — no feature creep)

strip_lines_matching, keep_lines_matching, strip_ansi, max_lines, head_lines, tail_lines, truncate_lines_at, on_empty

No line_format, no group_by, no transforms — if a filter needs structured data parsing, it belongs in a Rust module.

Architecture

  • New rtk run -- <command> dispatch path (additive, no breaking changes)
  • Rust filters keep priority over TOML filters
  • rtk rewrite registry extended with TOML fallback
  • schema_version = 1 from day one for future migrations
  • .rtk/ directory convention for project-level customization

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions