@hasna/terminal 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/dist/cli.js +29 -12
  2. package/package.json +1 -1
  3. package/src/ai.ts +50 -36
  4. package/src/cli.tsx +29 -12
  5. package/src/context-hints.ts +89 -0
  6. package/src/discover.ts +238 -0
  7. package/src/economy.ts +53 -0
  8. package/src/output-store.ts +65 -0
  9. package/src/providers/index.ts +4 -4
  10. package/src/sessions-db.ts +81 -0
  11. package/temp/rtk/.claude/agents/code-reviewer.md +221 -0
  12. package/temp/rtk/.claude/agents/debugger.md +519 -0
  13. package/temp/rtk/.claude/agents/rtk-testing-specialist.md +461 -0
  14. package/temp/rtk/.claude/agents/rust-rtk.md +511 -0
  15. package/temp/rtk/.claude/agents/technical-writer.md +355 -0
  16. package/temp/rtk/.claude/commands/diagnose.md +352 -0
  17. package/temp/rtk/.claude/commands/test-routing.md +362 -0
  18. package/temp/rtk/.claude/hooks/bash/pre-commit-format.sh +16 -0
  19. package/temp/rtk/.claude/hooks/rtk-rewrite.sh +70 -0
  20. package/temp/rtk/.claude/hooks/rtk-suggest.sh +152 -0
  21. package/temp/rtk/.claude/rules/cli-testing.md +526 -0
  22. package/temp/rtk/.claude/skills/issue-triage/SKILL.md +348 -0
  23. package/temp/rtk/.claude/skills/issue-triage/templates/issue-comment.md +134 -0
  24. package/temp/rtk/.claude/skills/performance.md +435 -0
  25. package/temp/rtk/.claude/skills/pr-triage/SKILL.md +315 -0
  26. package/temp/rtk/.claude/skills/pr-triage/templates/review-comment.md +71 -0
  27. package/temp/rtk/.claude/skills/repo-recap.md +206 -0
  28. package/temp/rtk/.claude/skills/rtk-tdd/SKILL.md +78 -0
  29. package/temp/rtk/.claude/skills/rtk-tdd/references/testing-patterns.md +124 -0
  30. package/temp/rtk/.claude/skills/security-guardian.md +503 -0
  31. package/temp/rtk/.claude/skills/ship.md +404 -0
  32. package/temp/rtk/.github/workflows/benchmark.yml +34 -0
  33. package/temp/rtk/.github/workflows/dco-check.yaml +12 -0
  34. package/temp/rtk/.github/workflows/release-please.yml +51 -0
  35. package/temp/rtk/.github/workflows/release.yml +343 -0
  36. package/temp/rtk/.github/workflows/security-check.yml +135 -0
  37. package/temp/rtk/.github/workflows/validate-docs.yml +78 -0
  38. package/temp/rtk/.release-please-manifest.json +3 -0
  39. package/temp/rtk/ARCHITECTURE.md +1491 -0
  40. package/temp/rtk/CHANGELOG.md +640 -0
  41. package/temp/rtk/CLAUDE.md +605 -0
  42. package/temp/rtk/CONTRIBUTING.md +199 -0
  43. package/temp/rtk/Cargo.lock +1668 -0
  44. package/temp/rtk/Cargo.toml +64 -0
  45. package/temp/rtk/Formula/rtk.rb +43 -0
  46. package/temp/rtk/INSTALL.md +390 -0
  47. package/temp/rtk/LICENSE +21 -0
  48. package/temp/rtk/README.md +386 -0
  49. package/temp/rtk/README_es.md +159 -0
  50. package/temp/rtk/README_fr.md +197 -0
  51. package/temp/rtk/README_ja.md +159 -0
  52. package/temp/rtk/README_ko.md +159 -0
  53. package/temp/rtk/README_zh.md +167 -0
  54. package/temp/rtk/ROADMAP.md +15 -0
  55. package/temp/rtk/SECURITY.md +217 -0
  56. package/temp/rtk/TEST_EXEC_TIME.md +102 -0
  57. package/temp/rtk/build.rs +57 -0
  58. package/temp/rtk/docs/AUDIT_GUIDE.md +432 -0
  59. package/temp/rtk/docs/FEATURES.md +1410 -0
  60. package/temp/rtk/docs/TROUBLESHOOTING.md +309 -0
  61. package/temp/rtk/docs/filter-workflow.md +102 -0
  62. package/temp/rtk/docs/images/gain-dashboard.jpg +0 -0
  63. package/temp/rtk/docs/tracking.md +583 -0
  64. package/temp/rtk/hooks/opencode-rtk.ts +39 -0
  65. package/temp/rtk/hooks/rtk-awareness.md +29 -0
  66. package/temp/rtk/hooks/rtk-rewrite.sh +61 -0
  67. package/temp/rtk/hooks/test-rtk-rewrite.sh +442 -0
  68. package/temp/rtk/install.sh +124 -0
  69. package/temp/rtk/release-please-config.json +10 -0
  70. package/temp/rtk/scripts/benchmark.sh +592 -0
  71. package/temp/rtk/scripts/check-installation.sh +162 -0
  72. package/temp/rtk/scripts/install-local.sh +37 -0
  73. package/temp/rtk/scripts/rtk-economics.sh +137 -0
  74. package/temp/rtk/scripts/test-all.sh +561 -0
  75. package/temp/rtk/scripts/test-aristote.sh +227 -0
  76. package/temp/rtk/scripts/test-tracking.sh +79 -0
  77. package/temp/rtk/scripts/update-readme-metrics.sh +32 -0
  78. package/temp/rtk/scripts/validate-docs.sh +73 -0
  79. package/temp/rtk/src/aws_cmd.rs +880 -0
  80. package/temp/rtk/src/binlog.rs +1645 -0
  81. package/temp/rtk/src/cargo_cmd.rs +1727 -0
  82. package/temp/rtk/src/cc_economics.rs +1157 -0
  83. package/temp/rtk/src/ccusage.rs +340 -0
  84. package/temp/rtk/src/config.rs +187 -0
  85. package/temp/rtk/src/container.rs +855 -0
  86. package/temp/rtk/src/curl_cmd.rs +134 -0
  87. package/temp/rtk/src/deps.rs +268 -0
  88. package/temp/rtk/src/diff_cmd.rs +367 -0
  89. package/temp/rtk/src/discover/mod.rs +274 -0
  90. package/temp/rtk/src/discover/provider.rs +388 -0
  91. package/temp/rtk/src/discover/registry.rs +2022 -0
  92. package/temp/rtk/src/discover/report.rs +202 -0
  93. package/temp/rtk/src/discover/rules.rs +667 -0
  94. package/temp/rtk/src/display_helpers.rs +402 -0
  95. package/temp/rtk/src/dotnet_cmd.rs +1771 -0
  96. package/temp/rtk/src/dotnet_format_report.rs +133 -0
  97. package/temp/rtk/src/dotnet_trx.rs +593 -0
  98. package/temp/rtk/src/env_cmd.rs +204 -0
  99. package/temp/rtk/src/filter.rs +462 -0
  100. package/temp/rtk/src/filters/README.md +52 -0
  101. package/temp/rtk/src/filters/ansible-playbook.toml +34 -0
  102. package/temp/rtk/src/filters/basedpyright.toml +47 -0
  103. package/temp/rtk/src/filters/biome.toml +45 -0
  104. package/temp/rtk/src/filters/brew-install.toml +37 -0
  105. package/temp/rtk/src/filters/composer-install.toml +40 -0
  106. package/temp/rtk/src/filters/df.toml +16 -0
  107. package/temp/rtk/src/filters/dotnet-build.toml +64 -0
  108. package/temp/rtk/src/filters/du.toml +16 -0
  109. package/temp/rtk/src/filters/fail2ban-client.toml +15 -0
  110. package/temp/rtk/src/filters/gcc.toml +49 -0
  111. package/temp/rtk/src/filters/gcloud.toml +22 -0
  112. package/temp/rtk/src/filters/hadolint.toml +24 -0
  113. package/temp/rtk/src/filters/helm.toml +29 -0
  114. package/temp/rtk/src/filters/iptables.toml +27 -0
  115. package/temp/rtk/src/filters/jj.toml +28 -0
  116. package/temp/rtk/src/filters/jq.toml +24 -0
  117. package/temp/rtk/src/filters/make.toml +41 -0
  118. package/temp/rtk/src/filters/markdownlint.toml +24 -0
  119. package/temp/rtk/src/filters/mix-compile.toml +27 -0
  120. package/temp/rtk/src/filters/mix-format.toml +15 -0
  121. package/temp/rtk/src/filters/mvn-build.toml +44 -0
  122. package/temp/rtk/src/filters/oxlint.toml +43 -0
  123. package/temp/rtk/src/filters/ping.toml +63 -0
  124. package/temp/rtk/src/filters/pio-run.toml +40 -0
  125. package/temp/rtk/src/filters/poetry-install.toml +50 -0
  126. package/temp/rtk/src/filters/pre-commit.toml +35 -0
  127. package/temp/rtk/src/filters/ps.toml +16 -0
  128. package/temp/rtk/src/filters/quarto-render.toml +41 -0
  129. package/temp/rtk/src/filters/rsync.toml +48 -0
  130. package/temp/rtk/src/filters/shellcheck.toml +27 -0
  131. package/temp/rtk/src/filters/shopify-theme.toml +29 -0
  132. package/temp/rtk/src/filters/skopeo.toml +45 -0
  133. package/temp/rtk/src/filters/sops.toml +16 -0
  134. package/temp/rtk/src/filters/ssh.toml +44 -0
  135. package/temp/rtk/src/filters/stat.toml +34 -0
  136. package/temp/rtk/src/filters/swift-build.toml +41 -0
  137. package/temp/rtk/src/filters/systemctl-status.toml +33 -0
  138. package/temp/rtk/src/filters/terraform-plan.toml +35 -0
  139. package/temp/rtk/src/filters/tofu-fmt.toml +16 -0
  140. package/temp/rtk/src/filters/tofu-init.toml +38 -0
  141. package/temp/rtk/src/filters/tofu-plan.toml +35 -0
  142. package/temp/rtk/src/filters/tofu-validate.toml +17 -0
  143. package/temp/rtk/src/filters/trunk-build.toml +39 -0
  144. package/temp/rtk/src/filters/ty.toml +50 -0
  145. package/temp/rtk/src/filters/uv-sync.toml +37 -0
  146. package/temp/rtk/src/filters/xcodebuild.toml +99 -0
  147. package/temp/rtk/src/filters/yamllint.toml +25 -0
  148. package/temp/rtk/src/find_cmd.rs +598 -0
  149. package/temp/rtk/src/format_cmd.rs +386 -0
  150. package/temp/rtk/src/gain.rs +723 -0
  151. package/temp/rtk/src/gh_cmd.rs +1651 -0
  152. package/temp/rtk/src/git.rs +2012 -0
  153. package/temp/rtk/src/go_cmd.rs +592 -0
  154. package/temp/rtk/src/golangci_cmd.rs +254 -0
  155. package/temp/rtk/src/grep_cmd.rs +288 -0
  156. package/temp/rtk/src/gt_cmd.rs +810 -0
  157. package/temp/rtk/src/hook_audit_cmd.rs +283 -0
  158. package/temp/rtk/src/hook_check.rs +171 -0
  159. package/temp/rtk/src/init.rs +1859 -0
  160. package/temp/rtk/src/integrity.rs +537 -0
  161. package/temp/rtk/src/json_cmd.rs +231 -0
  162. package/temp/rtk/src/learn/detector.rs +628 -0
  163. package/temp/rtk/src/learn/mod.rs +119 -0
  164. package/temp/rtk/src/learn/report.rs +184 -0
  165. package/temp/rtk/src/lint_cmd.rs +694 -0
  166. package/temp/rtk/src/local_llm.rs +316 -0
  167. package/temp/rtk/src/log_cmd.rs +248 -0
  168. package/temp/rtk/src/ls.rs +324 -0
  169. package/temp/rtk/src/main.rs +2482 -0
  170. package/temp/rtk/src/mypy_cmd.rs +389 -0
  171. package/temp/rtk/src/next_cmd.rs +241 -0
  172. package/temp/rtk/src/npm_cmd.rs +236 -0
  173. package/temp/rtk/src/parser/README.md +267 -0
  174. package/temp/rtk/src/parser/error.rs +46 -0
  175. package/temp/rtk/src/parser/formatter.rs +336 -0
  176. package/temp/rtk/src/parser/mod.rs +311 -0
  177. package/temp/rtk/src/parser/types.rs +119 -0
  178. package/temp/rtk/src/pip_cmd.rs +302 -0
  179. package/temp/rtk/src/playwright_cmd.rs +479 -0
  180. package/temp/rtk/src/pnpm_cmd.rs +573 -0
  181. package/temp/rtk/src/prettier_cmd.rs +221 -0
  182. package/temp/rtk/src/prisma_cmd.rs +482 -0
  183. package/temp/rtk/src/psql_cmd.rs +382 -0
  184. package/temp/rtk/src/pytest_cmd.rs +384 -0
  185. package/temp/rtk/src/read.rs +217 -0
  186. package/temp/rtk/src/rewrite_cmd.rs +50 -0
  187. package/temp/rtk/src/ruff_cmd.rs +402 -0
  188. package/temp/rtk/src/runner.rs +271 -0
  189. package/temp/rtk/src/summary.rs +297 -0
  190. package/temp/rtk/src/tee.rs +405 -0
  191. package/temp/rtk/src/telemetry.rs +248 -0
  192. package/temp/rtk/src/toml_filter.rs +1655 -0
  193. package/temp/rtk/src/tracking.rs +1416 -0
  194. package/temp/rtk/src/tree.rs +209 -0
  195. package/temp/rtk/src/tsc_cmd.rs +259 -0
  196. package/temp/rtk/src/utils.rs +432 -0
  197. package/temp/rtk/src/verify_cmd.rs +47 -0
  198. package/temp/rtk/src/vitest_cmd.rs +385 -0
  199. package/temp/rtk/src/wc_cmd.rs +401 -0
  200. package/temp/rtk/src/wget_cmd.rs +260 -0
  201. package/temp/rtk/tests/fixtures/dotnet/build_failed.txt +11 -0
  202. package/temp/rtk/tests/fixtures/dotnet/format_changes.json +31 -0
  203. package/temp/rtk/tests/fixtures/dotnet/format_empty.json +1 -0
  204. package/temp/rtk/tests/fixtures/dotnet/format_success.json +12 -0
  205. package/temp/rtk/tests/fixtures/dotnet/test_failed.txt +18 -0
@@ -0,0 +1,52 @@
1
+ # Built-in Filters
2
+
3
+ Each `.toml` file in this directory defines one filter and its inline tests.
4
+ Files are concatenated alphabetically by `build.rs` into a single TOML blob embedded in the binary.
5
+
6
+ ## Adding a filter
7
+
8
+ 1. Copy any existing `.toml` file and rename it (e.g. `my-tool.toml`)
9
+ 2. Update the three required fields: `description`, `match_command`, and at least one action field
10
+ 3. Add `[[tests.my-tool]]` entries to verify the filter behaves correctly
11
+ 4. Run `cargo test` — the build step validates TOML syntax and runs inline tests
12
+
13
+ ## File format
14
+
15
+ ```toml
16
+ [filters.my-tool]
17
+ description = "Short description of what this filter does"
18
+ match_command = "^my-tool\\b" # regex matched against the full command string
19
+ strip_ansi = true # optional: strip ANSI escape codes first
20
+ strip_lines_matching = [ # optional: drop lines matching any of these regexes
21
+ "^\\s*$",
22
+ "^noise pattern",
23
+ ]
24
+ max_lines = 40 # optional: keep only the first N lines after filtering
25
+ on_empty = "my-tool: ok" # optional: message to emit when output is empty after filtering
26
+
27
+ [[tests.my-tool]]
28
+ name = "descriptive test name"
29
+ input = "raw command output here"
30
+ expected = "expected filtered output"
31
+ ```
32
+
33
+ ## Available filter fields
34
+
35
+ | Field | Type | Description |
36
+ |-------|------|-------------|
37
+ | `description` | string | Human-readable description |
38
+ | `match_command` | regex | Matches the command string (e.g. `"^docker\\s+inspect"`) |
39
+ | `strip_ansi` | bool | Strip ANSI escape codes before processing |
40
+ | `strip_lines_matching` | regex[] | Drop lines matching any regex |
41
+ | `keep_lines_matching` | regex[] | Keep only lines matching at least one regex |
42
+ | `replace` | array | Regex substitutions (`{ pattern, replacement }`) |
43
+ | `match_output` | array | Short-circuit rules (`{ pattern, message }`) |
44
+ | `truncate_lines_at` | int | Truncate lines longer than N characters |
45
+ | `max_lines` | int | Keep only the first N lines |
46
+ | `tail_lines` | int | Keep only the last N lines (applied after other filters) |
47
+ | `on_empty` | string | Fallback message when filtered output is empty |
48
+
49
+ ## Naming convention
50
+
51
+ Use the command name as the filename: `terraform-plan.toml`, `docker-inspect.toml`, `mix-compile.toml`.
52
+ For commands with subcommands, prefer `<cmd>-<subcommand>.toml` over grouping multiple filters in one file.
@@ -0,0 +1,34 @@
1
+ [filters.ansible-playbook]
2
+ description = "Compact ansible-playbook output"
3
+ match_command = "^ansible-playbook\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^ok: \\[",
8
+ "^skipping: \\[",
9
+ ]
10
+ max_lines = 60
11
+
12
+ [[tests.ansible-playbook]]
13
+ name = "strips ok and skipping lines, keeps changed and failures"
14
+ input = """
15
+ PLAY [all] *********************************************************************
16
+
17
+ TASK [Gathering Facts] *********************************************************
18
+ ok: [web01]
19
+ ok: [web02]
20
+
21
+ TASK [Install nginx] ***********************************************************
22
+ changed: [web01]
23
+ skipping: [web02]
24
+
25
+ PLAY RECAP *********************************************************************
26
+ web01 : ok=2 changed=1 unreachable=0 failed=0
27
+ web02 : ok=1 changed=0 unreachable=0 failed=0
28
+ """
29
+ expected = "PLAY [all] *********************************************************************\nTASK [Gathering Facts] *********************************************************\nTASK [Install nginx] ***********************************************************\nchanged: [web01]\nPLAY RECAP *********************************************************************\nweb01 : ok=2 changed=1 unreachable=0 failed=0\nweb02 : ok=1 changed=0 unreachable=0 failed=0"
30
+
31
+ [[tests.ansible-playbook]]
32
+ name = "failed task preserved"
33
+ input = "TASK [Start service] ***\nfailed: [web01] => {\"msg\": \"Service not found\"}\nPLAY RECAP ***\nweb01 : ok=1 failed=1"
34
+ expected = "TASK [Start service] ***\nfailed: [web01] => {\"msg\": \"Service not found\"}\nPLAY RECAP ***\nweb01 : ok=1 failed=1"
@@ -0,0 +1,47 @@
1
+ [filters.basedpyright]
2
+ description = "Compact basedpyright type checker output — strip blank lines, keep errors"
3
+ match_command = "^basedpyright\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^Searching for source files",
8
+ "^Found \\d+ source file",
9
+ "^Pyright \\d+\\.\\d+",
10
+ "^basedpyright \\d+\\.\\d+",
11
+ ]
12
+ max_lines = 50
13
+ on_empty = "basedpyright: ok"
14
+
15
+ [[tests.basedpyright]]
16
+ name = "strips noise, keeps errors and summary"
17
+ input = """
18
+ basedpyright 1.22.0
19
+ Searching for source files
20
+ Found 42 source files
21
+
22
+ /home/user/app/main.py
23
+ /home/user/app/main.py:10:5 - error: "foo" is not defined (reportUndefinedVariable)
24
+ /home/user/app/main.py:25:1 - error: Type "str" is not assignable to type "int" (reportAssignmentType)
25
+
26
+ /home/user/app/utils.py
27
+ /home/user/app/utils.py:8:9 - warning: Variable "x" is not accessed (reportUnusedVariable)
28
+
29
+ 3 errors, 1 warning, 0 informations
30
+ """
31
+ expected = "/home/user/app/main.py\n /home/user/app/main.py:10:5 - error: \"foo\" is not defined (reportUndefinedVariable)\n /home/user/app/main.py:25:1 - error: Type \"str\" is not assignable to type \"int\" (reportAssignmentType)\n/home/user/app/utils.py\n /home/user/app/utils.py:8:9 - warning: Variable \"x\" is not accessed (reportUnusedVariable)\n3 errors, 1 warning, 0 informations"
32
+
33
+ [[tests.basedpyright]]
34
+ name = "clean output"
35
+ input = """
36
+ basedpyright 1.22.0
37
+ Searching for source files
38
+ Found 10 source files
39
+
40
+ 0 errors, 0 warnings, 0 informations
41
+ """
42
+ expected = "0 errors, 0 warnings, 0 informations"
43
+
44
+ [[tests.basedpyright]]
45
+ name = "empty input passes through"
46
+ input = ""
47
+ expected = ""
@@ -0,0 +1,45 @@
1
+ [filters.biome]
2
+ description = "Compact Biome lint/format output — strip blank lines, keep diagnostics"
3
+ match_command = "^biome\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^Checked \\d+ file",
8
+ "^Fixed \\d+ file",
9
+ "^The following command",
10
+ "^Run it with",
11
+ ]
12
+ max_lines = 50
13
+ on_empty = "biome: ok"
14
+
15
+ [[tests.biome]]
16
+ name = "lint strips noise, keeps diagnostics"
17
+ input = """
18
+ Checked 42 files in 0.5s
19
+
20
+ src/app.tsx:5:3 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━
21
+ × Unexpected any. Specify a different type.
22
+ 3 │ interface Props {
23
+ 4 │ data: any;
24
+ 5 │ ^^^
25
+
26
+ src/utils.ts:12:1 lint/complexity/noForEach ━━━━━━━━━━━━━━━━━━━━
27
+ × Prefer for...of instead of forEach.
28
+ 12 │ items.forEach(item => process(item));
29
+ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30
+
31
+ Found 2 errors.
32
+ """
33
+ expected = "src/app.tsx:5:3 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━\n × Unexpected any. Specify a different type.\n 3 │ interface Props {\n 4 │ data: any;\n 5 │ ^^^\nsrc/utils.ts:12:1 lint/complexity/noForEach ━━━━━━━━━━━━━━━━━━━━\n × Prefer for...of instead of forEach.\n 12 │ items.forEach(item => process(item));\n │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nFound 2 errors."
34
+
35
+ [[tests.biome]]
36
+ name = "clean check"
37
+ input = """
38
+ Checked 42 files in 0.3s
39
+ """
40
+ expected = "biome: ok"
41
+
42
+ [[tests.biome]]
43
+ name = "empty input passes through"
44
+ input = ""
45
+ expected = ""
@@ -0,0 +1,37 @@
1
+ [filters.brew-install]
2
+ description = "Compact brew install/upgrade output — strip downloads, short-circuit when already installed"
3
+ match_command = "^brew\\s+(install|upgrade)\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^==> Downloading",
8
+ "^==> Pouring",
9
+ "^Already downloaded:",
10
+ "^###",
11
+ "^==> Fetching",
12
+ ]
13
+ match_output = [
14
+ { pattern = "already installed", message = "ok (already installed)" },
15
+ ]
16
+ max_lines = 20
17
+
18
+ [[tests.brew-install]]
19
+ name = "already installed short-circuits"
20
+ input = """
21
+ Warning: rtk 0.27.1 is already installed and up-to-date.
22
+ To reinstall 0.27.1, run:
23
+ brew reinstall rtk
24
+ """
25
+ expected = "ok (already installed)"
26
+
27
+ [[tests.brew-install]]
28
+ name = "install strips download lines"
29
+ input = """
30
+ ==> Fetching jq
31
+ ==> Downloading https://homebrew.bintray.com/bottles/jq-1.7.1.arm64_sonoma.bottle.tar.gz
32
+ ######################################################################## 100.0%
33
+ ==> Pouring jq-1.7.1.arm64_sonoma.bottle.tar.gz
34
+ ==> Summary
35
+ /opt/homebrew/Cellar/jq/1.7.1: 18 files, 1.2MB
36
+ """
37
+ expected = "==> Summary\n/opt/homebrew/Cellar/jq/1.7.1: 18 files, 1.2MB"
@@ -0,0 +1,40 @@
1
+ [filters.composer-install]
2
+ description = "Compact composer install/update/require output — strip downloads, short-circuit when up-to-date"
3
+ match_command = "^composer\\s+(install|update|require)\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^ - Downloading ",
8
+ "^ - Installing ",
9
+ "^Loading composer",
10
+ "^Updating dependencies",
11
+ ]
12
+ match_output = [
13
+ { pattern = "Nothing to install, update or remove", message = "ok (up to date)" },
14
+ ]
15
+ max_lines = 30
16
+
17
+ [[tests.composer-install]]
18
+ name = "nothing to do short-circuits"
19
+ input = """
20
+ Loading composer repositories with package information
21
+ Updating dependencies
22
+ Lock file operations: 0 installs, 0 updates, 0 removals
23
+ Nothing to install, update or remove
24
+ Generating autoload files
25
+ """
26
+ expected = "ok (up to date)"
27
+
28
+ [[tests.composer-install]]
29
+ name = "install strips download lines"
30
+ input = """
31
+ Loading composer repositories with package information
32
+ Updating dependencies
33
+ - Downloading symfony/console (v6.4.0)
34
+ - Installing symfony/console (v6.4.0): Extracting archive
35
+ - Downloading psr/log (3.0.0)
36
+ - Installing psr/log (3.0.0): Extracting archive
37
+ Writing lock file
38
+ Generating autoload files
39
+ """
40
+ expected = "Writing lock file\nGenerating autoload files"
@@ -0,0 +1,16 @@
1
+ [filters.df]
2
+ description = "Compact df output — truncate wide columns, limit rows"
3
+ match_command = "^df(\\s|$)"
4
+ strip_ansi = true
5
+ truncate_lines_at = 80
6
+ max_lines = 20
7
+
8
+ [[tests.df]]
9
+ name = "short output passes through unchanged"
10
+ input = "Filesystem 1K-blocks Used Available Use% Mounted on\n/dev/sda1 4096000 123456 3972544 4% /"
11
+ expected = "Filesystem 1K-blocks Used Available Use% Mounted on\n/dev/sda1 4096000 123456 3972544 4% /"
12
+
13
+ [[tests.df]]
14
+ name = "empty input passes through"
15
+ input = ""
16
+ expected = ""
@@ -0,0 +1,64 @@
1
+ [filters.dotnet-build]
2
+ description = "Compact dotnet build output — short-circuit on success, strip banners"
3
+ match_command = "^dotnet\\s+build\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^Microsoft \\(R\\)",
8
+ "^Copyright \\(C\\)",
9
+ "^ Determining projects",
10
+ ]
11
+ match_output = [
12
+ { pattern = "0 Warning\\(s\\)\\n\\s+0 Error\\(s\\)", message = "ok (build succeeded)" },
13
+ ]
14
+ max_lines = 40
15
+
16
+ [[tests.dotnet-build]]
17
+ name = "successful build short-circuits to ok"
18
+ input = """
19
+ Microsoft (R) Build Engine version 17.8.3+195e7f5a3
20
+ Copyright (C) Microsoft Corporation. All rights reserved.
21
+
22
+ Determining projects to restore...
23
+ All projects are up-to-date for restore.
24
+ MyApp -> /home/user/MyApp/bin/Debug/net8.0/MyApp.dll
25
+
26
+ Build succeeded.
27
+ 0 Warning(s)
28
+ 0 Error(s)
29
+
30
+ Time Elapsed 00:00:02.34
31
+ """
32
+ expected = "ok (build succeeded)"
33
+
34
+ [[tests.dotnet-build]]
35
+ name = "build with warnings not short-circuited"
36
+ input = """
37
+ Microsoft (R) Build Engine version 17.8.3+195e7f5a3
38
+ Copyright (C) Microsoft Corporation. All rights reserved.
39
+
40
+ Determining projects to restore...
41
+ MyApp -> /home/user/MyApp/bin/Debug/net8.0/MyApp.dll
42
+
43
+ Build succeeded.
44
+ 3 Warning(s)
45
+ 0 Error(s)
46
+
47
+ Time Elapsed 00:00:01.87
48
+ """
49
+ expected = " MyApp -> /home/user/MyApp/bin/Debug/net8.0/MyApp.dll\nBuild succeeded.\n 3 Warning(s)\n 0 Error(s)\nTime Elapsed 00:00:01.87"
50
+
51
+ [[tests.dotnet-build]]
52
+ name = "build errors pass through"
53
+ input = """
54
+ Microsoft (R) Build Engine version 17.8.3+195e7f5a3
55
+ Copyright (C) Microsoft Corporation. All rights reserved.
56
+
57
+ Determining projects to restore...
58
+ src/Program.cs(10,5): error CS1002: ; expected [/home/user/MyApp/MyApp.csproj]
59
+
60
+ Build FAILED.
61
+ 0 Warning(s)
62
+ 1 Error(s)
63
+ """
64
+ expected = "src/Program.cs(10,5): error CS1002: ; expected [/home/user/MyApp/MyApp.csproj]\nBuild FAILED.\n 0 Warning(s)\n 1 Error(s)"
@@ -0,0 +1,16 @@
1
+ [filters.du]
2
+ description = "Compact du output"
3
+ match_command = "^du\\b"
4
+ strip_lines_matching = ["^\\s*$"]
5
+ truncate_lines_at = 120
6
+ max_lines = 40
7
+
8
+ [[tests.du]]
9
+ name = "preserves sizes, strips blank lines"
10
+ input = "4.0K\t./src\n\n8.0K\t./tests\n16K\t."
11
+ expected = "4.0K\t./src\n8.0K\t./tests\n16K\t."
12
+
13
+ [[tests.du]]
14
+ name = "single line passthrough"
15
+ input = "128K\t."
16
+ expected = "128K\t."
@@ -0,0 +1,15 @@
1
+ [filters.fail2ban-client]
2
+ description = "Compact fail2ban-client output"
3
+ match_command = "^fail2ban-client\\b"
4
+ strip_lines_matching = ["^\\s*$"]
5
+ max_lines = 30
6
+
7
+ [[tests.fail2ban-client]]
8
+ name = "strips blank lines"
9
+ input = "Status for the jail: sshd\n|- Filter\n| |- Currently failed: 3\n\n|- Actions\n `- Total banned: 42"
10
+ expected = "Status for the jail: sshd\n|- Filter\n| |- Currently failed: 3\n|- Actions\n `- Total banned: 42"
11
+
12
+ [[tests.fail2ban-client]]
13
+ name = "single line passthrough"
14
+ input = "Shutdown successful"
15
+ expected = "Shutdown successful"
@@ -0,0 +1,49 @@
1
+ [filters.gcc]
2
+ description = "Compact gcc/g++ compiler output — strip notes, keep errors and warnings"
3
+ match_command = "^g(cc|\\+\\+)\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^\\s+\\|\\s*$",
8
+ "^In file included from",
9
+ "^\\s+from\\s",
10
+ "^\\d+ warnings? generated",
11
+ "^\\d+ errors? generated",
12
+ ]
13
+ max_lines = 50
14
+ on_empty = "gcc: ok"
15
+
16
+ [[tests.gcc]]
17
+ name = "strips include chain, keeps errors and warnings"
18
+ input = """
19
+ In file included from /usr/include/stdio.h:42:
20
+ from main.c:1:
21
+ main.c:10:5: error: use of undeclared identifier 'foo'
22
+ foo();
23
+ ^
24
+ main.c:15:12: warning: unused variable 'x' [-Wunused-variable]
25
+ int x = 42;
26
+ ^
27
+ 2 warnings generated.
28
+ 1 error generated.
29
+ """
30
+ expected = "main.c:10:5: error: use of undeclared identifier 'foo'\n foo();\n ^\nmain.c:15:12: warning: unused variable 'x' [-Wunused-variable]\n int x = 42;\n ^"
31
+
32
+ [[tests.gcc]]
33
+ name = "clean compilation"
34
+ input = """
35
+ """
36
+ expected = "gcc: ok"
37
+
38
+ [[tests.gcc]]
39
+ name = "linker error kept"
40
+ input = """
41
+ /usr/bin/ld: /tmp/main.o: undefined reference to 'missing_func'
42
+ collect2: error: ld returned 1 exit status
43
+ """
44
+ expected = "/usr/bin/ld: /tmp/main.o: undefined reference to 'missing_func'\ncollect2: error: ld returned 1 exit status"
45
+
46
+ [[tests.gcc]]
47
+ name = "empty input passes through"
48
+ input = ""
49
+ expected = ""
@@ -0,0 +1,22 @@
1
+ [filters.gcloud]
2
+ description = "Compact gcloud output"
3
+ match_command = "^gcloud\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = ["^\\s*$"]
6
+ truncate_lines_at = 120
7
+ max_lines = 30
8
+
9
+ [[tests.gcloud]]
10
+ name = "strips blank lines, preserves output"
11
+ input = """
12
+ Updated property [core/project].
13
+
14
+ NAME REGION STATUS
15
+ my-cluster us-central1 RUNNING
16
+ """
17
+ expected = "Updated property [core/project].\nNAME REGION STATUS\nmy-cluster us-central1 RUNNING"
18
+
19
+ [[tests.gcloud]]
20
+ name = "single line passthrough"
21
+ input = "Listed 0 items."
22
+ expected = "Listed 0 items."
@@ -0,0 +1,24 @@
1
+ [filters.hadolint]
2
+ description = "Compact hadolint Dockerfile linting output"
3
+ match_command = "^hadolint\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ ]
8
+ truncate_lines_at = 120
9
+ max_lines = 40
10
+
11
+ [[tests.hadolint]]
12
+ name = "Dockerfile warnings kept, blank lines stripped"
13
+ input = """
14
+ Dockerfile:3 DL3008 warning: Pin versions in apt-get install
15
+ Dockerfile:5 DL3009 info: Delete apt-get lists after installing
16
+
17
+ Dockerfile:8 DL4006 warning: Set SHELL option -o pipefail before RUN with pipe
18
+ """
19
+ expected = "Dockerfile:3 DL3008 warning: Pin versions in apt-get install\nDockerfile:5 DL3009 info: Delete apt-get lists after installing\nDockerfile:8 DL4006 warning: Set SHELL option -o pipefail before RUN with pipe"
20
+
21
+ [[tests.hadolint]]
22
+ name = "empty input passes through"
23
+ input = ""
24
+ expected = ""
@@ -0,0 +1,29 @@
1
+ [filters.helm]
2
+ description = "Compact helm output"
3
+ match_command = "^helm\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^W\\d{4}",
8
+ ]
9
+ truncate_lines_at = 120
10
+ max_lines = 40
11
+
12
+ [[tests.helm]]
13
+ name = "strips blank lines, preserves release info"
14
+ input = """
15
+ NAME: my-release
16
+ LAST DEPLOYED: Mon Jan 15 10:30:00 2024
17
+ NAMESPACE: default
18
+ STATUS: deployed
19
+ REVISION: 3
20
+
21
+ NOTES:
22
+ Application is running.
23
+ """
24
+ expected = "NAME: my-release\nLAST DEPLOYED: Mon Jan 15 10:30:00 2024\nNAMESPACE: default\nSTATUS: deployed\nREVISION: 3\nNOTES:\nApplication is running."
25
+
26
+ [[tests.helm]]
27
+ name = "strips glog W-prefix warnings"
28
+ input = "W0115 10:30:00 warning message from internal\nNAME: my-chart\nSTATUS: deployed"
29
+ expected = "NAME: my-chart\nSTATUS: deployed"
@@ -0,0 +1,27 @@
1
+ [filters.iptables]
2
+ description = "Compact iptables output"
3
+ match_command = "^iptables\\b"
4
+ strip_lines_matching = [
5
+ "^\\s*$",
6
+ "^Chain DOCKER",
7
+ "^Chain BR-",
8
+ ]
9
+ max_lines = 50
10
+ truncate_lines_at = 120
11
+
12
+ [[tests.iptables]]
13
+ name = "strips Docker chains, preserves real rules"
14
+ input = """
15
+ Chain INPUT (policy ACCEPT)
16
+ num target prot opt source destination
17
+ 1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
18
+ Chain DOCKER (1 references)
19
+ DOCKER all -- 0.0.0.0/0 0.0.0.0/0
20
+ Chain BR-abcdef (0 references)
21
+ """
22
+ expected = "Chain INPUT (policy ACCEPT)\nnum target prot opt source destination\n1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0\n DOCKER all -- 0.0.0.0/0 0.0.0.0/0"
23
+
24
+ [[tests.iptables]]
25
+ name = "preserves FORWARD and OUTPUT chains"
26
+ input = "Chain FORWARD (policy DROP)\n1 ACCEPT tcp\nChain OUTPUT (policy ACCEPT)\n1 ACCEPT all"
27
+ expected = "Chain FORWARD (policy DROP)\n1 ACCEPT tcp\nChain OUTPUT (policy ACCEPT)\n1 ACCEPT all"
@@ -0,0 +1,28 @@
1
+ [filters.jj]
2
+ description = "Compact Jujutsu (jj) output — strip blank lines, truncate"
3
+ match_command = "^jj\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ "^Hint:",
8
+ "^Working copy now at:",
9
+ ]
10
+ max_lines = 30
11
+ truncate_lines_at = 120
12
+
13
+ [[tests.jj]]
14
+ name = "log output stripped of hints"
15
+ input = """
16
+ @ qpvuntsm patrick@example.com 2026-03-10 12:00 abc123
17
+ │ feat: add new feature
18
+ ◉ zzzzzzzz root()
19
+
20
+ Working copy now at: qpvuntsm abc123 feat: add new feature
21
+ Hint: use `jj log` to see the full history
22
+ """
23
+ expected = "@ qpvuntsm patrick@example.com 2026-03-10 12:00 abc123\n│ feat: add new feature\n◉ zzzzzzzz root()"
24
+
25
+ [[tests.jj]]
26
+ name = "empty input passes through"
27
+ input = ""
28
+ expected = ""
@@ -0,0 +1,24 @@
1
+ [filters.jq]
2
+ description = "Compact jq output — truncate large JSON results"
3
+ match_command = "^jq\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ ]
8
+ max_lines = 40
9
+ truncate_lines_at = 120
10
+
11
+ [[tests.jq]]
12
+ name = "short output passes through"
13
+ input = """
14
+ {
15
+ "name": "test",
16
+ "version": "1.0"
17
+ }
18
+ """
19
+ expected = "{\n \"name\": \"test\",\n \"version\": \"1.0\"\n}"
20
+
21
+ [[tests.jq]]
22
+ name = "empty input passes through"
23
+ input = ""
24
+ expected = ""
@@ -0,0 +1,41 @@
1
+ [filters.make]
2
+ description = "Compact make output"
3
+ match_command = "^make\\b"
4
+ strip_lines_matching = [
5
+ "^make\\[\\d+\\]:",
6
+ "^\\s*$",
7
+ "^Nothing to be done",
8
+ ]
9
+ max_lines = 50
10
+ on_empty = "make: ok"
11
+
12
+ [[tests.make]]
13
+ name = "strips entering/leaving lines"
14
+ input = """
15
+ make[1]: Entering directory '/home/user'
16
+ gcc -O2 foo.c
17
+ make[1]: Leaving directory '/home/user'
18
+ """
19
+ expected = """
20
+ gcc -O2 foo.c
21
+ """
22
+
23
+ [[tests.make]]
24
+ name = "strips blank lines"
25
+ input = """
26
+ gcc -O2 foo.c
27
+
28
+ gcc -O2 bar.c
29
+ """
30
+ expected = """
31
+ gcc -O2 foo.c
32
+ gcc -O2 bar.c
33
+ """
34
+
35
+ [[tests.make]]
36
+ name = "on_empty when all stripped"
37
+ input = """
38
+ make[1]: Entering directory '/home/user'
39
+ make[1]: Leaving directory '/home/user'
40
+ """
41
+ expected = "make: ok"
@@ -0,0 +1,24 @@
1
+ [filters.markdownlint]
2
+ description = "Compact markdownlint output — strip blank lines, limit rows"
3
+ match_command = "^markdownlint\\b"
4
+ strip_ansi = true
5
+ strip_lines_matching = [
6
+ "^\\s*$",
7
+ ]
8
+ max_lines = 50
9
+ truncate_lines_at = 120
10
+
11
+ [[tests.markdownlint]]
12
+ name = "linting errors stripped of blank lines"
13
+ input = """
14
+ README.md:1:1 MD041/first-line-heading/first-line-h1 First line in file should be a top level heading
15
+ README.md:10:1 MD022/blanks-around-headings Headings should be surrounded by blank lines
16
+
17
+ README.md:15:80 MD013/line-length Line length [Expected: 80; Actual: 95]
18
+ """
19
+ expected = "README.md:1:1 MD041/first-line-heading/first-line-h1 First line in file should be a top level heading\nREADME.md:10:1 MD022/blanks-around-headings Headings should be surrounded by blank lines\nREADME.md:15:80 MD013/line-length Line length [Expected: 80; Actual: 95]"
20
+
21
+ [[tests.markdownlint]]
22
+ name = "empty input passes through"
23
+ input = ""
24
+ expected = ""