mix-compression
Reduce mix output noise (5-15% token savings) by installing rtk filters that compress mix test/credo/dialyzer/compile output before it reaches Claude. Use when long mix output floods context.
Install
npx skills add https://github.com/oliver-kriska/claude-elixir-phoenix/tree/main/plugins/elixir-phoenix/skills/mix-compression
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install oliver-kriska-claude-elixir-phoenix@llmmart
git clone https://github.com/oliver-kriska/claude-elixir-phoenix.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole oliver-kriska/claude-elixir-phoenix collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Mix Output Compression
Mix commands (mix test, mix credo, mix dialyzer, mix compile) emit
verbose, repetitive output that consumes context fast. This skill installs
rtk — a CLI proxy that filters tool output
before it lands in the transcript.
The filters short-circuit happy paths to a single line (mix test: all pass)
while preserving full failure blocks, compile errors, and stack traces. Net win:
5-15% per-session token reduction on mix-heavy workflows.
When to use
- Long sessions —
/phx:workor/phx:fullhitting context limits from mix output - Debugging loops —
/phx:investigateretryingmix compile/mix testrepeatedly - Dialyzer-heavy projects —
mix dialyzeroutput dominates the transcript
Iron Laws
- NEVER strip critical signals — compile errors (
** (CompileError),== Compilation error in), test failures (FAILURES,0 failures— preserved even on short-circuit), dialyzer warnings, and stack traces withfile:lineMUST pass through unchanged - Verify after install — run
rtk verify(orrtk verify --filter mix-test) to confirm the bundled test fixtures pass before declaring success - Never overwrite existing
.rtk/filters.toml— diff and merge instead
Workflow
Step 1: Detect rtk
which rtk && rtk --version
Read ${CLAUDE_SKILL_DIR}/references/install.md if rtk is missing — covers
homebrew install + shell hook setup.
Step 2: Seed .rtk/filters.toml
Reference filters live at ${CLAUDE_SKILL_DIR}/references/rtk-filters.toml. Six
production-tested filters covering:
mix-test— short-circuits all-pass, preserves failure blocks + compile errorsmix-credo— collapses clean runs, preserves violation blocksmix-dialyzer— drops PLT progress, keeps warnings + summarymix-deps-get— collapses unchanged package listsmix-ecto-migrate— strips compile prefix, short-circuits "already up"mix-compile— handles parallel worker prefixes (N>) and MIX_ENV
Run this if the project has no .rtk/filters.toml yet:
mkdir -p .rtk
cp "${CLAUDE_SKILL_DIR}/references/rtk-filters.toml" .rtk/filters.toml
Read both files if one already exists. Present a diff to the user. Merge only the filters they don't already have.
Step 3: Verify filters work
rtk verify # runs all embedded [[tests.*]] fixtures
rtk verify --filter mix-test # one filter only
Check that all report "passed". Flag and stop if any fail — usually means the user has a custom rtk version with regex differences.
Step 4: Confirm shell hook
Run rtk init zsh (or rtk init bash) to install the transparent rewrite hook
that turns mix X into rtk mix X. Re-running is safe (idempotent). Skip this
step and mix calls run unfiltered.
Customization
Add custom regex patterns to strip_lines_matching for project-specific noise
sources (e.g., third-party hex deps spamming stack traces). See the inline
example in ${CLAUDE_SKILL_DIR}/references/rtk-filters.toml lines 57-59.
What this is NOT
- Not a hook — Claude Code's
PostToolUsehooks fire after the tool result is in the transcript and cannot shrink it. rtk works at the subprocess layer (the only layer where transcript-shortening is possible). - Not project-analysis — the bundled filter set is universal across Phoenix
projects. No
mix.exsinspection needed. - Not telemetry — rtk has telemetry off by default (
enabled = falseinconfig.toml). Filters run locally, no data leaves the machine.
References
${CLAUDE_SKILL_DIR}/references/rtk-filters.toml— bundled filter set${CLAUDE_SKILL_DIR}/references/install.md— rtk install + shell hook setup- rtk on GitHub
Files (claude-elixir-phoenix)
-
references
-
install.md 3.3 KB
# Installing rtk [rtk (Rust Token Killer)](https://github.com/rtk-ai/rtk) is a CLI proxy that intercepts terminal commands, runs them, and filters output through TOML rules before returning to the caller. For Claude Code, this means mix output gets compressed *before* it reaches the transcript — the only architectural layer where token savings are possible. ## Install ### macOS (homebrew) ```bash brew install rtk-ai/tap/rtk rtk --version # verify (expect 0.39.0+) ``` ### Other platforms See the [rtk README](https://github.com/rtk-ai/rtk#install) for Linux and manual install options. ## Shell hook (required) rtk only intercepts commands when its shell hook is installed. The hook rewrites `mix X` to `rtk mix X` transparently — no manual prefixing. ```bash rtk init zsh # or `rtk init bash` ``` This adds a hook to `~/.zshrc` (or `~/.bashrc`). Reload your shell: ```bash exec $SHELL -l ``` Verify the hook works: ```bash mix --help # should run normally — rtk passes through commands without filters ``` If you see `rtk: command not found` or `mix` runs raw without filtering, the hook didn't install. Check `~/.zshrc` for an `rtk init` block. ## Verify filters After dropping filters into `.rtk/filters.toml`: ```bash rtk verify # run all embedded [[tests.*]] fixtures rtk verify --filter mix-test # run fixtures for one filter only rtk verify --filter mix-ash-codegen ``` Each filter should report all fixtures as passed. If any fail, the regex patterns may not match your rtk version's regex engine — file an issue on the rtk repo. ## Measure the win ```bash rtk gain # token savings summary rtk gain --history # per-command breakdown rtk cc-economics # spending vs savings analysis ``` Run after a week of normal usage to see actual reduction. Expected ranges for Phoenix projects: | Command | Typical compression | Big win cases | |---------|-------------------:|---------------| | `mix test` (passing) | 90%+ | All-green runs collapse to one line | | `mix credo` (clean) | 95%+ | Clean runs collapse to one line | | `mix dialyzer` (clean) | 95%+ | PLT progress disappears | | `mix compile` (no warnings) | 70-90% | Worker-prefix noise stripped | | `mix test` (failures) | 10-30% | Failure blocks preserved verbatim | ## Telemetry rtk has telemetry **disabled by default**. Verify in `~/Library/Application Support/rtk/config.toml`: ```toml [telemetry] enabled = false consent_given = false ``` Filters run locally. No command output, file paths, or filter content leaves your machine. ## Disable / uninstall To disable temporarily without uninstalling: ```bash # Remove the rtk init line from ~/.zshrc, then: exec $SHELL -l ``` To uninstall: ```bash brew uninstall rtk rm -rf ~/Library/Application\ Support/rtk rm -rf .rtk # in any project that has one ``` ## Troubleshooting **Filter not applying**: rtk only filters when the command matches a filter's `match_command` regex. Check `rtk config show-filters` to list registered filters in the current directory. **Test fixtures fail after copying**: rtk uses Rust's regex crate which does NOT support backreferences (`\1`, `\2`). If you wrote your own patterns, avoid them. **Want raw output for one command**: prefix with `command`: ```bash command mix test # bypasses rtk ``` -
rtk-filters.toml 15.6 KB
schema_version = 1 # RTK TOML filters for Elixir mix commands. # # Drop into `.rtk/filters.toml` at the project root. Filters apply when mix # commands run via `rtk mix ...` (rtk's shell hook rewrites `mix X` -> `rtk mix X` # transparently — see references/install.md). # # Design notes: # - Every mix-* filter includes shared compile-strip patterns because parallel # deps.compile often runs as a side effect, emitting "Compiling N files" and # "Generated X app" noise with worker-prefix form `N> `. # - filter_stderr = true because mix emits warnings to stderr; we want them # filtered through the same pipeline, not leaking raw. # - match_output short-circuits the "happy path" to a one-liner before any # other processing — biggest wins for `mix test` (passing runs are the norm). # - Rust regex crate (RTK's engine) does NOT support backreferences (\1, \2). # Any pattern using them will silently fail. # - Critical-preserve: compile errors, test failures, dialyzer warnings, and # stack traces with file:line are NEVER stripped — only progress noise is. # ============================================================================ # mix test — compact pass/fail, preserve failure blocks, stacktraces, compile errors # ============================================================================ [filters.mix-test] description = "Compact mix test — short-circuit all-green, preserve failures and compile errors" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+test(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "\\b0 failures\\b", message = "mix test: all pass" }, ] replace = [ { pattern = "^[.*sF]{3,}", replacement = "" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^Excluding tags:", "^Including tags:", "^Randomized with seed", "^OK$", "^Compiling \\d+ file", "^Generated \\w+ app$", "^\\d+> Compiling \\d+ file", "^\\d+> Generated \\w+ app", "^\\d+> ==> \\w+", "^\\d+> ===> (Compiling|Analyzing)", "^==> \\w+$", "^build ended with \\d+ errors$", "^\\d{2}:\\d{2}:\\d{2}\\.\\d+ ", "^\\d{2}:\\d{2}:\\d{2}\\.\\d+ app_version=", "^\\d{2}:\\d{2}:\\d{2}\\.\\d+ line=\\d+", # Stack-trace frame strippers — drop frames from libraries you don't care about. # Add your own deps here: e.g., "^\\s+\\(my_dep \\d" strips lines like " (my_dep 1.2.3) ..." "^\\s+\\(phoenix_live_view \\d", "^\\s+\\(elixir \\d", "^\\s+\\(ecto \\d", "^warning: Range\\.new", "^warning: redefining module ", "^Query: INSERT INTO", "^Query: UPDATE", "^Query: SELECT", "^Params: ", "^Reason: %Postgrex", "^Function: #Function<", "^ Args: \\[\\]", ] tail_lines = 200 on_empty = "mix test: ok" [[tests.mix-test]] name = "all pass short-circuits" input = """ Running ExUnit with seed: 986129, max_cases: 28 Excluding tags: [:ci_only] . Finished in 1.1 seconds (0.00s async, 1.1s sync) 1 test, 0 failures OK """ expected = "mix test: all pass" [[tests.mix-test]] name = "compile error preserved" input = """ Running ExUnit with seed: 755757, max_cases: 28 Excluding tags: [:ci_only] error: undefined variable ^b_item │ 20 │ assert [{^a_item, ^b_item}] = [Enum.at(a, 0)] │ ^ │ └─ test/validation_match_test.exs:20:26: ValidationMatchTest == Compilation error in file test/validation_match_test.exs == ** (CompileError) test/validation_match_test.exs: cannot compile module """ expected = """Running ExUnit with seed: 755757, max_cases: 28 error: undefined variable ^b_item │ 20 │ assert [{^a_item, ^b_item}] = [Enum.at(a, 0)] │ ^ │ └─ test/validation_match_test.exs:20:26: ValidationMatchTest == Compilation error in file test/validation_match_test.exs == ** (CompileError) test/validation_match_test.exs: cannot compile module""" # ============================================================================ # mix credo — drop redefining-module warnings, progress lines, keep violations # ============================================================================ [filters.mix-credo] description = "Compact mix credo — drop custom-check redefine warnings and progress" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+credo(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "found no issues\\.", message = "mix credo: clean" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^Compiling \\d+ file", "^Generated \\w+ app$", "^\\d+> Compiling", "^\\d+> Generated", "^\\s*warning: redefining module ", "^\\s+│$", "^\\s+~+$", "^ \\d+ │ defmodule ", "^\\s+└─ lib/mix/credo/", "^Checking \\d+ source files", "^Please report incorrect results:", "^Analysis took \\d", "^Use `mix credo explain`", ] on_empty = "mix credo: clean" [[tests.mix-credo]] name = "clean run short-circuits" input = """ warning: redefining module MyApp.Test.Credo.WarnApplicationConfig │ 1 │ defmodule MyApp.Test.Credo.WarnApplicationConfig do │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ │ └─ lib/mix/credo/warn_application_config.ex:1: MyApp.Test.Credo.WarnApplicationConfig (module) Checking 2579 source files (this might take a while) ... Analysis took 13.4 seconds 29543 mods/funs, found no issues. Use `mix credo explain` to explain issues. OK """ expected = "mix credo: clean" [[tests.mix-credo]] name = "violation block preserved" input = """ Compiling 2 files (.ex) Generated my_app app Code Readability ┃ ┃ [R] ↗ Variable names should be written in snake_case. ┃ config/runtime.exs:16:1 #() ┃ [R] ↘ Line is too long (max is 120, was 158). ┃ config/runtime.exs:85:121 #() Please report incorrect results: https://github.com/rrrene/credo/issues Analysis took 0.3 seconds 0 mods/funs, found 2 code readability issues. Use `mix credo explain` to explain issues. """ expected = """ Code Readability ┃ ┃ [R] ↗ Variable names should be written in snake_case. ┃ config/runtime.exs:16:1 #() ┃ [R] ↘ Line is too long (max is 120, was 158). ┃ config/runtime.exs:85:121 #() 0 mods/funs, found 2 code readability issues.""" # ============================================================================ # mix dialyzer — drop PLT progress and config dumps, keep warnings + summary # ============================================================================ [filters.mix-dialyzer] description = "Compact mix dialyzer — drop PLT progress, keep warnings and summary" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+dialyzer(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "done \\(passed successfully\\)", message = "mix dialyzer: clean" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^Compiling \\d+ file", "^Generated \\w+ app$", "^Finding suitable PLTs", "^Checking PLT\\.\\.\\.", "^Looking up modules in ", "^Finding applications for ", "^Finding modules for ", "^Checking \\d+ modules in ", "^Adding \\d+ modules to ", "^Removing \\d+ modules from ", "^done in \\d+m?\\d+", "^ignore_warnings: ", "^Starting Dialyzer", "^\\[$", "^ check_plt: ", "^ init_plt: ", "^ files: ", "^ ~c\"", "^ \\.\\.\\.\\],", "^ \\.\\.\\.", "^\\]$", "^\\[:[a-z_]+,", "^_{40,}$", "^Halting VM with exit status \\d", ] on_empty = "mix dialyzer: clean" [[tests.mix-dialyzer]] name = "clean run short-circuits" input = """ Generated my_app app Finding suitable PLTs Checking PLT... [:abnf_parsec, :acceptor_pool, :algoliax, :apollo_io] Looking up modules in dialyxir_erlang-_elixir-_deps-dev.plt Checking 9618 modules in dialyxir_erlang-_elixir-_deps-dev.plt Adding 223 modules to dialyxir_erlang-_elixir-_deps-dev.plt done in 0m51.82s ignore_warnings: .dialyzer_ignore_warnings.exs Starting Dialyzer [ check_plt: false, init_plt: ~c"priv/plts/dev/dialyxir_erlang.plt", files: [~c"/Users/.../my_app.beam", ...], ... ] Total errors: 156, Skipped: 156, Unnecessary Skips: 0 done in 0m27.35s done (passed successfully) OK """ expected = "mix dialyzer: clean" [[tests.mix-dialyzer]] name = "warnings preserved dividers stripped" input = """ Total errors: 156, Skipped: 154, Unnecessary Skips: 0 done in 0m40.32s ________________________________________________________________________________ lib/my_app/reports/excel_formatting.ex:407:14:unknown_function Function Elixlsx.Sheet.set_col_width/3 does not exist. ________________________________________________________________________________ lib/my_app/reports/excel_formatting.ex:418:13:unknown_function Function Elixlsx.Sheet.set_col_width/3 does not exist. ________________________________________________________________________________ done (warnings were emitted) Halting VM with exit status 2 """ expected = """Total errors: 156, Skipped: 154, Unnecessary Skips: 0 lib/my_app/reports/excel_formatting.ex:407:14:unknown_function Function Elixlsx.Sheet.set_col_width/3 does not exist. lib/my_app/reports/excel_formatting.ex:418:13:unknown_function Function Elixlsx.Sheet.set_col_width/3 does not exist. done (warnings were emitted)""" # ============================================================================ # mix deps.get — collapse "Unchanged" package list # ============================================================================ [filters.mix-deps-get] description = "Compact mix deps.get — collapse unchanged package lists" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+deps\\.get(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "All dependencies (have been fetched|are up to date)", message = "mix deps.get: unchanged" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^Resolving Hex dependencies", "^Resolution completed in ", "^Unchanged:$", "^ [a-z_][a-z0-9_]* \\d+\\.\\d+", "^Compiling \\d+ file", "^Generated \\w+ app$", ] on_empty = "mix deps.get: unchanged" [[tests.mix-deps-get]] name = "unchanged collapses" input = """ Resolving Hex dependencies... Resolution completed in 1.638s Unchanged: abnf_parsec 2.1.0 acceptor_pool 1.0.1 algoliax 0.10.0 credo 1.7.18 All dependencies have been fetched OK """ expected = "mix deps.get: unchanged" # ============================================================================ # mix ecto.migrate / rollback / gen.migration — strip compile prefix # ============================================================================ [filters.mix-ecto-migrate] description = "Compact mix ecto.migrate — strip compile prefix" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+ecto\\.(migrate|rollback|gen\\.migration)(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "\\[info\\] Migrations already up", message = "mix ecto.migrate: up to date" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^Compiling \\d+ file", "^Generated \\w+ app$", "^\\d+> Compiling", "^\\d+> Generated", ] on_empty = "mix ecto.migrate: ok" [[tests.mix-ecto-migrate]] name = "already up short-circuits" input = """ Compiling 2 files (.ex) Generated my_app app 06:54:27.843 [info] Migrations already up """ expected = "mix ecto.migrate: up to date" # ============================================================================ # mix compile (extended) — handles parallel worker prefix `N> ` and MIX_ENV # Shadows the built-in mix-compile filter. # ============================================================================ [filters.mix-compile] description = "Compact mix compile — handles parallel workers and MIX_ENV prefixes" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+compile(\\s|$)" strip_ansi = true filter_stderr = true replace = [ { pattern = "^\\d+> ", replacement = "" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^mix deps\\.compile running across \\d+ OS processes", "^Compiling \\d+ file", "^Generated \\w+ app$", "^==> \\w+$", "^===> (Compiling|Analyzing) ", "^\\[debug\\] Copying NIF ", "^AppSignal extension installation", ] on_empty = "mix compile: ok" [[tests.mix-compile]] name = "parallel compile with worker prefix strips cleanly" input = """ mix deps.compile running across 7 OS processes 2> ==> peri 2> Compiling 7 files (.ex) 3> ==> fine 3> Compiling 1 file (.ex) 3> Generated fine app 2> Generated peri app Compiling 1821 files (.ex) Generated my_app app OK """ expected = "mix compile: ok" [[tests.mix-compile]] name = "preserves warning with file:line" input = """ 2> ==> peri 2> Compiling 7 files (.ex) 3> warning: variable "assigns" is unused 3> │ 3> 183 │ defp prepare_icon_name(assigns) do 3> │ ~~~~~~~ 3> │ 3> └─ lib/icon.ex:183:28: Iconify.Icon.prepare_icon_name/1 2> Generated peri app Compiling 1821 files (.ex) Generated my_app app """ expected = """ warning: variable "assigns" is unused │ 183 │ defp prepare_icon_name(assigns) do │ ~~~~~~~ │ └─ lib/icon.ex:183:28: Iconify.Icon.prepare_icon_name/1""" # ============================================================================ # mix ash.codegen — strip compile prefix, preserve snapshot/migration lists # ============================================================================ [filters.mix-ash-codegen] description = "Compact mix ash.codegen — strip compile prefix, preserve snapshot and migration file lists" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+ash\\.codegen(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "No changes", message = "mix ash.codegen: no changes" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^Compiling \\d+ file", "^Generated \\w+ app$", "^\\d+> Compiling", "^\\d+> Generated", ] on_empty = "mix ash.codegen: ok" [[tests.mix-ash-codegen]] name = "no changes short-circuits" input = """ Compiling 5 files (.ex) Generated my_app app No changes detected. OK """ expected = "mix ash.codegen: no changes" [[tests.mix-ash-codegen]] name = "snapshot and migration list preserved" input = """ Compiling 5 files (.ex) Generated my_app app Snapshots Updated: * priv/resource_snapshots/repo/accounts/user_v2.json Migrations Generated: * priv/repo/migrations/20260511120000_migrate_resources2.exs """ expected = """Snapshots Updated: * priv/resource_snapshots/repo/accounts/user_v2.json Migrations Generated: * priv/repo/migrations/20260511120000_migrate_resources2.exs""" # ============================================================================ # mix ash.migrate — strip compile prefix, preserve migration steps # ============================================================================ [filters.mix-ash-migrate] description = "Compact mix ash.migrate — strip compile prefix, preserve migration steps" match_command = "^(?:[A-Z_][A-Z0-9_]*=\\S+\\s+)*mix\\s+ash\\.(migrate|rollback)(\\s|$)" strip_ansi = true filter_stderr = true match_output = [ { pattern = "\\[info\\] Migrations already up", message = "mix ash.migrate: up to date" }, ] strip_lines_matching = [ "^$", "^\\s*$", "^OK$", "^Compiling \\d+ file", "^Generated \\w+ app$", "^\\d+> Compiling", "^\\d+> Generated", ] on_empty = "mix ash.migrate: ok" [[tests.mix-ash-migrate]] name = "already up short-circuits" input = """ Compiling 2 files (.ex) Generated my_app app 06:54:27.843 [info] Migrations already up """ expected = "mix ash.migrate: up to date" [[tests.mix-ash-migrate]] name = "migration steps preserved" input = """ Compiling 2 files (.ex) Generated my_app app 07:00:00.000 [info] == Running 20260511120000 MyApp.Repo.Migrations.MigrateResources2.up/0 forward 07:00:00.000 [info] == Migrated 20260511120000 in 0.0s """ expected = """07:00:00.000 [info] == Running 20260511120000 MyApp.Repo.Migrations.MigrateResources2.up/0 forward 07:00:00.000 [info] == Migrated 20260511120000 in 0.0s"""
-
-
SKILL.md 4 KB
--- name: mix-compression description: Reduce mix output noise (5-15% token savings) by installing rtk filters that compress mix test/credo/dialyzer/compile output before it reaches Claude. Use when long mix output floods context. effort: low --- # Mix Output Compression Mix commands (`mix test`, `mix credo`, `mix dialyzer`, `mix compile`) emit verbose, repetitive output that consumes context fast. This skill installs [rtk](https://github.com/rtk-ai/rtk) — a CLI proxy that filters tool output **before it lands in the transcript**. The filters short-circuit happy paths to a single line (`mix test: all pass`) while preserving full failure blocks, compile errors, and stack traces. Net win: 5-15% per-session token reduction on mix-heavy workflows. ## When to use - **Long sessions** — `/phx:work` or `/phx:full` hitting context limits from mix output - **Debugging loops** — `/phx:investigate` retrying `mix compile`/`mix test` repeatedly - **Dialyzer-heavy projects** — `mix dialyzer` output dominates the transcript ## Iron Laws 1. **NEVER strip critical signals** — compile errors (`** (CompileError)`, `== Compilation error in`), test failures (`FAILURES`, `0 failures` — preserved even on short-circuit), dialyzer warnings, and stack traces with `file:line` MUST pass through unchanged 2. **Verify after install** — run `rtk verify` (or `rtk verify --filter mix-test`) to confirm the bundled test fixtures pass before declaring success 3. **Never overwrite existing `.rtk/filters.toml`** — diff and merge instead ## Workflow ### Step 1: Detect rtk ```bash which rtk && rtk --version ``` Read `${CLAUDE_SKILL_DIR}/references/install.md` if rtk is missing — covers homebrew install + shell hook setup. ### Step 2: Seed `.rtk/filters.toml` Reference filters live at `${CLAUDE_SKILL_DIR}/references/rtk-filters.toml`. Six production-tested filters covering: - **`mix-test`** — short-circuits all-pass, preserves failure blocks + compile errors - **`mix-credo`** — collapses clean runs, preserves violation blocks - **`mix-dialyzer`** — drops PLT progress, keeps warnings + summary - **`mix-deps-get`** — collapses unchanged package lists - **`mix-ecto-migrate`** — strips compile prefix, short-circuits "already up" - **`mix-compile`** — handles parallel worker prefixes (`N>`) and MIX_ENV Run this if the project has no `.rtk/filters.toml` yet: ```bash mkdir -p .rtk cp "${CLAUDE_SKILL_DIR}/references/rtk-filters.toml" .rtk/filters.toml ``` Read both files if one already exists. Present a diff to the user. Merge only the filters they don't already have. ### Step 3: Verify filters work ```bash rtk verify # runs all embedded [[tests.*]] fixtures rtk verify --filter mix-test # one filter only ``` Check that all report "passed". Flag and stop if any fail — usually means the user has a custom rtk version with regex differences. ### Step 4: Confirm shell hook Run `rtk init zsh` (or `rtk init bash`) to install the transparent rewrite hook that turns `mix X` into `rtk mix X`. Re-running is safe (idempotent). Skip this step and `mix` calls run unfiltered. ## Customization Add custom regex patterns to `strip_lines_matching` for project-specific noise sources (e.g., third-party hex deps spamming stack traces). See the inline example in `${CLAUDE_SKILL_DIR}/references/rtk-filters.toml` lines 57-59. ## What this is NOT - **Not a hook** — Claude Code's `PostToolUse` hooks fire after the tool result is in the transcript and cannot shrink it. rtk works at the subprocess layer (the only layer where transcript-shortening is possible). - **Not project-analysis** — the bundled filter set is universal across Phoenix projects. No `mix.exs` inspection needed. - **Not telemetry** — rtk has telemetry off by default (`enabled = false` in `config.toml`). Filters run locally, no data leaves the machine. ## References - `${CLAUDE_SKILL_DIR}/references/rtk-filters.toml` — bundled filter set - `${CLAUDE_SKILL_DIR}/references/install.md` — rtk install + shell hook setup - [rtk on GitHub](https://github.com/rtk-ai/rtk)
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.