# How to Configure Custom TOML Filters in RTK for Specific Projects

> Learn how to configure custom TOML filters in RTK for your projects. Create a filters.toml file define rules and trust it with RTK to enable runtime loading.

- Repository: [rtk-ai/rtk](https://github.com/rtk-ai/rtk)
- Tags: how-to-guide
- Published: 2026-04-24

---

**Configure custom TOML filters in RTK by creating a [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) file in your project root, defining filter rules using the TOML DSL, and marking the file as trusted with `rtk trust .rtk/filters.toml` so that `TomlFilterRegistry` loads it at runtime.**

RTK is an extensible command runner that uses TOML-based output filtering to clean up and transform command output before displaying it. By configuring **custom TOML filters in RTK** for specific projects, you can strip debug noise, truncate long logs, and highlight errors without modifying the underlying tools. This project-local configuration lives in your repository and is parsed dynamically, allowing you to tailor output processing to each codebase.

## How RTK Loads Filter Configurations

RTK builds a filter registry at runtime by searching for TOML definitions in a strict priority order (first match wins). According to the source code in [`src/core/toml_filter.rs`](https://github.com/rtk-ai/rtk/blob/main/src/core/toml_filter.rs)【L5-L8】, the hierarchy is:

1. **Project-local** [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) — stored in the repository root and loaded only when the file is *trusted*
2. **User-global** `~/.config/rtk/filters.toml` — applies to every project
3. **Built-in** filters compiled into the binary from `src/filters/*.toml`【L31-L33】
4. **Passthrough** — if no TOML matches, the command runs unfiltered

The registry is instantiated by `TomlFilterRegistry::load()` in [`src/core/toml_filter.rs`](https://github.com/rtk-ai/rtk/blob/main/src/core/toml_filter.rs)【L85-L103】, which parses the TOML and prepares the filtering pipeline without requiring recompilation.

## Creating a Trusted Project-Local Filter

To use a custom filter for a single repository, you must create the file in a specific location and explicitly authorize it.

### File Location and Trust Requirements

Place your configuration at [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) in the project root. RTK will ignore this file until you mark it as trusted. Run the trust command from your repository root:

```bash
rtk trust .rtk/filters.toml

```

This command calculates the SHA256 hash of the file and stores it in `~/.local/share/rtk/trust.db`. On every subsequent run, RTK verifies the hash against the recorded value in [`src/hooks/trust.rs`](https://github.com/rtk-ai/rtk/blob/main/src/hooks/trust.rs)【L191-L199】 to prevent execution of untrusted code.

### The Trust Security Model

The trust mechanism exists because TOML filters execute regex transformations that could potentially expose sensitive data or modify output maliciously. Until you explicitly trust the file, RTK skips the project-local filter and falls back to user-global or built-in rules.

## TOML Filter DSL Reference

The filter syntax is documented in [`src/filters/README.md`](https://github.com/rtk-ai/rtk/blob/main/src/filters/README.md)【L27-L62】. Each filter is defined under a `[filters.<name>]` table with the following fields:

- **`description`** (`string`) — Human-readable summary of the filter’s purpose.
- **`match_command`** (`regex`) — Pattern that determines which commands trigger this filter.
- **`strip_ansi`** (`bool`) — Remove ANSI escape sequences before applying other rules.
- **`strip_lines_matching`** / **`keep_lines_matching`** (`regex[]`) — Arrays of patterns to drop or preserve lines.
- **`replace`** (`[{ pattern, replacement }]`) — Array of regex substitution objects.
- **`match_output`** (`[{ pattern, message }]`) — Short-circuit: return *message* if pattern matches the entire output.
- **`truncate_lines_at`** (`int`) — Maximum characters per line.
- **`max_lines`**, **`head_lines`**, **`tail_lines`** (`int`) — Limit the number of lines kept.
- **`on_empty`** (`string`) — Fallback text when filtering removes all content.
- **`filter_stderr`** (`bool`) — Merge stderr into stdout before filtering.

### Inline Testing

You can validate filters by adding test cases directly in the TOML. These are executed by `cargo test` or `rtk test` to prevent regressions【L41-L45】:

```toml
[[tests.mytool]]
name = "removes debug lines"
input = """
INFO: start
DEBUG: hidden detail
RESULT: success
"""
expected = """
INFO: start
RESULT: success
"""

```

## Step-by-Step Configuration Guide

Follow these steps to activate a custom filter for your project:

1. **Create the directory** `.rtk/` in your repository root if it does not exist.
2. **Create** [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) and define your filter using the TOML DSL.
3. **Trust the file** by running `rtk trust .rtk/filters.toml` to authorize RTK to load it.
4. **Run your command** — RTK now applies the custom filter before printing output.

All processing happens at runtime; no recompilation of RTK is required.

## Working Example: Cleaning Build Output

Here is a complete [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) that strips noisy debug lines from a fictional `mytool` command and limits output to 30 lines:

```toml
[filters.mytool]
description = "Strip noisy 'debug' lines from mytool output"
match_command = "^mytool\\b"
strip_ansi = true

# Remove empty lines and lines starting with "DEBUG:"

strip_lines_matching = [
  "^\\s*$",
  "^DEBUG:",
]

# Keep at most 30 lines after stripping

max_lines = 30

# Friendly note when everything is filtered away

on_empty = "mytool: no relevant output"

[[tests.mytool]]
name = "removes debug lines"
input = """
INFO: start
DEBUG: hidden detail
RESULT: success
"""
expected = """
INFO: start
RESULT: success
"""

```

**Explanation**: The filter activates for any command starting with `mytool`. It first strips ANSI codes, then removes empty lines and debug statements, and finally truncates to 30 lines. If all lines are removed, it displays the `on_empty` message. Running `cargo test` validates the `[[tests.mytool]]` block against the expected output.

### Trusting and Running the Filter

```bash

# In the project root:

rtk trust .rtk/filters.toml

# Output:

# [rtk] .rtk/filters.toml trusted (sha256: <hash>)

# Now run the command:

rtk mytool --verbose-flag

```

The output will be filtered according to your TOML rules.

## Summary

- RTK searches for filters in the order: project-local [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml), user-global `~/.config/rtk/filters.toml`, then built-in `src/filters/*.toml`.
- Project-local filters require explicit trust via `rtk trust .rtk/filters.toml` to prevent untrusted code execution, with hashes stored in `~/.local/share/rtk/trust.db`.
- The `TomlFilterRegistry::load()` function in [`src/core/toml_filter.rs`](https://github.com/rtk-ai/rtk/blob/main/src/core/toml_filter.rs) dynamically parses TOML at runtime.
- The TOML DSL supports regex-based line filtering, replacements, truncation, and inline test cases defined in [`src/filters/README.md`](https://github.com/rtk-ai/rtk/blob/main/src/filters/README.md).

## Frequently Asked Questions

### What is the priority order for filter loading in RTK?

RTK checks for TOML filter definitions in four locations in descending priority: first the project-local [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) (if trusted), then the user-global `~/.config/rtk/filters.toml`, followed by built-in filters compiled from `src/filters/*.toml`, and finally falls back to unfiltered passthrough if none match. This hierarchy is implemented in [`src/core/toml_filter.rs`](https://github.com/rtk-ai/rtk/blob/main/src/core/toml_filter.rs)【L5-L8】.

### How do I debug a custom TOML filter that is not applying?

First, verify the file is trusted by running `rtk trust .rtk/filters.toml` again—RTK skips untrusted project-local files silently. Second, check that your `match_command` regex actually matches your command invocation. Finally, add inline `[[tests]]` blocks and run `rtk test` or `cargo test` to validate your regex patterns without running the full command.

### Can I use regular expressions in all pattern fields?

Yes, any field ending in `_matching` or named `pattern` accepts valid regular expressions. This includes `match_command`, `strip_lines_matching`, `keep_lines_matching`, and the `pattern` keys inside `replace` and `match_output` arrays. Refer to [`src/filters/README.md`](https://github.com/rtk-ai/rtk/blob/main/src/filters/README.md)【L27-L62】 for the complete syntax reference.

### Where does RTK store trust records for project filters?

Trust hashes are stored in `~/.local/share/rtk/trust.db`. Each time you run a command, RTK recalculates the SHA256 hash of [`.rtk/filters.toml`](https://github.com/rtk-ai/rtk/blob/main/.rtk/filters.toml) and compares it against this database, as defined in [`src/hooks/trust.rs`](https://github.com/rtk-ai/rtk/blob/main/src/hooks/trust.rs)【L191-L199】. If the file is modified, you must re-run `rtk trust` to update the stored hash.