shrinker-ai 0.3.3 → 0.7.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.
package/README.md CHANGED
@@ -1,363 +1,494 @@
1
- # shrinker
2
-
3
- A small local CLI proof of concept that removes noise from command output before a coding agent or LLM reads it.
4
-
5
- this POC proves that a few conservative, deterministic filters can save useful context without requiring an API key, service, UI, database, or agent-specific integration.
6
-
7
- ## What the POC demonstrates
8
-
9
- - Explicit cross-agent command wrapping: `shrinker exec -- <command>`.
10
- - Filters for Git status, Git diff, test output, and generic logs.
11
- - Failures, warnings, changed paths, and command exit codes are preserved.
12
- - Omitted raw output is saved locally for recovery.
13
- - Optional per-run metrics report bytes and approximate before/after tokens.
14
- - Local SQLite statistics accumulate savings across runs.
15
- - No command output leaves the machine.
16
-
17
- ## Quick start
18
-
19
- Requires Node.js 22.13 or newer. This is the first Node 22 release where the built-in SQLite module no longer requires an experimental flag.
20
-
21
- ### One-command install (macOS zsh)
22
-
23
- ```bash
24
- curl -fsSL https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/macos/install.sh | bash
25
- ```
26
-
27
- ### One-command install (Windows PowerShell)
28
-
29
- ```powershell
30
- irm https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/windows/install.ps1 | iex
31
- ```
32
-
33
- ### Install from npm package
34
-
35
- Windows PowerShell:
36
-
37
- ```powershell
38
- npm install --global shrinker-ai --registry=https://registry.npmjs.org
39
- $pkg = Join-Path ((npm root --global).Trim()) "shrinker-ai"
40
- pwsh -ExecutionPolicy Bypass -File (Join-Path $pkg "integrations\\windows\\install.ps1") -Local -SkipNpmInstall -SkipBuild -SkipLink
41
- ```
42
-
43
- To enable automatic PowerShell routing, add `-EnableProfileRouting` to the final command.
44
-
45
- macOS zsh:
46
-
47
- ```bash
48
- npm install --global shrinker-ai --registry=https://registry.npmjs.org
49
- pkg="$(npm root --global)/shrinker-ai"
50
- bash "$pkg/integrations/macos/install.sh" --local --skip-npm-install --skip-build --skip-link --enable-profile-routing
51
- ```
52
-
53
- ### Install from local checkout
54
-
55
- Windows PowerShell:
56
-
57
- ```powershell
58
- pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Local
59
- ```
60
-
61
- macOS zsh:
62
-
63
- ```bash
64
- bash ./integrations/macos/install.sh --local
65
- ```
66
-
67
- This writes managed guidance blocks globally to:
68
-
69
- - `~/.copilot/copilot-instructions.md`
70
- - `~/.claude/CLAUDE.md`
71
-
72
- The shared guidance source is `templates/agent-rules.md`; the files above are created in the corresponding global agent directory.
73
-
74
- The rules tell agents to prefer `shrinker <command>` for high-volume commands while leaving native commands untouched.
75
-
76
- ### Uninstall
77
-
78
- If you installed from npm, remove the package first:
79
-
80
- ```bash
81
- npm uninstall --global shrinker-ai --registry=https://registry.npmjs.org
82
- ```
83
-
84
- If you also installed profile/rules through the package scripts, run the matching local uninstaller from the installed package before uninstalling:
85
-
86
- Windows PowerShell:
87
-
88
- ```powershell
89
- $pkg = Join-Path ((npm root --global).Trim()) "shrinker-ai"
90
- pwsh -ExecutionPolicy Bypass -File (Join-Path $pkg "integrations\\windows\\uninstall.ps1") -SkipUnlink
91
- ```
92
-
93
- macOS zsh:
94
-
95
- ```bash
96
- pkg="$(npm root --global)/shrinker-ai"
97
- bash "$pkg/integrations/macos/uninstall.sh" --skip-unlink
98
- ```
99
-
100
- macOS one-liner uninstall:
101
-
102
- ```bash
103
- curl -fsSL https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/macos/uninstall.sh | bash
104
- ```
105
-
106
- ### Local repo install/uninstall (contributors)
107
-
108
- If you cloned this repository and want to run scripts directly from the local path:
109
-
110
- ```powershell
111
- pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Local
112
- ```
113
-
114
- Or on macOS:
115
-
116
- ```bash
117
- bash ./integrations/macos/install.sh --local
118
- ```
119
-
120
- To uninstall:
121
-
122
- ```powershell
123
- pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Uninstall
124
- ```
125
-
126
- Or on macOS:
127
-
128
- ```bash
129
- bash ./integrations/macos/install.sh --uninstall
130
- ```
131
-
132
- Uninstall options:
133
-
134
- ```powershell
135
- # Keep shrinker command installed, but remove profile integration and managed rules
136
- pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Uninstall -SkipUnlink
137
-
138
- # Keep managed rules files unchanged while uninstalling command/profile hooks
139
- pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Uninstall -SkipAgentRules
140
- ```
141
-
142
- macOS uninstall options:
143
-
144
- ```bash
145
- # Keep shrinker command installed, but remove profile integration and managed rules
146
- bash ./integrations/macos/install.sh --uninstall --skip-unlink
147
-
148
- # Keep managed rules files unchanged while uninstalling command/profile hooks
149
- bash ./integrations/macos/install.sh --uninstall --skip-agent-rules
150
- ```
151
-
152
- If your current terminal had already loaded `shrinker-profile.ps1` or `shrinker-profile.zsh`, restart terminal (or remove loaded wrapper functions) to fully return to native command behavior.
153
-
154
- ```powershell
155
- npm install
156
- npm run build
157
- node dist\src\cli.js exec -- git status
158
- node dist\src\cli.js exec -- git diff
159
- node dist\src\cli.js exec -- git log -n 10
160
- node dist\src\cli.js exec -- npm test
161
- Get-Content .\tests\fixtures\generic-log.txt -Raw |
162
- node dist\src\cli.js pipe --kind log
163
- ```
164
-
165
- To install the `shrinker` command locally:
166
-
167
- ```powershell
168
- npm link
169
- shrinker git status
170
- shrinker git log -n 10
171
- shrinker npm test
172
- ```
173
-
174
- ## CLI
175
-
176
- ```text
177
- shrinker <command> [args...]
178
- shrinker exec [options] [--] <command> [args...]
179
- shrinker pipe [options]
180
- shrinker stats [--json]
181
- shrinker last [--path]
182
- shrinker raw <capture-id> [--path]
183
- shrinker help
184
-
185
- --kind <auto|git-status|git-diff|git-log|test|log>
186
- --max-lines <number> default: 120
187
- --per-file-lines <number> default: 40
188
- --raw bypass filtering
189
- --metrics print per-run savings and duration
190
- --no-save do not save omitted raw output
191
- --no-stats do not record this run
192
- ```
193
-
194
- `help`, `stats`, `last`, `raw`, `pipe`, and `exec` are reserved shrinker commands. Every other top-level token starts a wrapped command, so `shrinker git log` is equivalent to `shrinker exec git log`. The `--` separator remains optional because npm's PowerShell shim may consume it. `pipe` reads existing text from stdin and defaults to the generic log filter unless `--kind` is specified.
195
-
196
- ## Automatic PowerShell routing
197
-
198
- The optional profile integration routes allowlisted commands through `shrinker` and invokes the native executable for everything else. Install it after `npm link`:
199
-
200
- ```powershell
201
- if (!(Test-Path $PROFILE)) {
202
- New-Item -ItemType File -Path $PROFILE -Force | Out-Null
203
- }
204
-
205
- $integration = (Resolve-Path .\integrations\windows\shrinker-profile.ps1).Path
206
- Add-Content $PROFILE "`n. `"$integration`""
207
- . $PROFILE
208
- ```
209
-
210
- macOS zsh profile integration:
211
-
212
- ```bash
213
- echo '' >> ~/.zshrc
214
- echo '# >>> shrinker integration >>>' >> ~/.zshrc
215
- echo 'source "'"$(pwd)/integrations/macos/shrinker-profile.zsh"'"' >> ~/.zshrc
216
- echo '# <<< shrinker integration <<<' >> ~/.zshrc
217
- source ~/.zshrc
218
- ```
219
-
220
- The default rules are:
221
-
222
- ```text
223
- git status -> shrinker git status
224
- git diff -> shrinker git diff
225
- git log -> shrinker git log
226
- npm test -> shrinker npm test
227
- docker ps -> shrinker docker ps
228
- kubectl get -> shrinker kubectl get
229
- gh pr list -> shrinker gh pr list
230
- rg/find/tail/cat/ls/dir -> shrinker <command>
231
-
232
- git push, git fetch, and all other commands -> native executable
233
- ```
234
-
235
- Edit `$global:ShrinkPowerShellRules` in `integrations\windows\shrinker-profile.ps1` to change the allowlist. The router is now option-aware for common global flags, so forms like `git -C <path> log` and `kubectl --context prod get pods` are routed correctly.
236
-
237
- ## Savings statistics
238
-
239
- Filtered runs are recorded locally in `~/.shrinker/stats.db`. The database stores only measurements, filter kind, executable basename, duration, omission state, and exit code. It does **not** store command arguments or command output.
240
-
241
- ```powershell
242
- node dist\src\cli.js stats
243
- node dist\src\cli.js stats --json
244
- node dist\src\cli.js stats --chart
245
- node dist\src\cli.js stats --dashboard
246
- ```
247
-
248
- The summary shows all-time and last-seven-day savings plus a breakdown by filter. Use `--no-stats` before `--` to opt out for an individual run:
249
-
250
- `stats --chart` shows daily runs, estimated tokens saved, reduction percentage, and an activity bar for the last 30 days.
251
- `stats --dashboard` writes a self-contained browser dashboard to `~/.shrinker/dashboard.html` with a line chart and filter breakdown.
252
-
253
- ```powershell
254
- node dist\src\cli.js exec --no-stats -- git log -n 10
255
- ```
256
-
257
- Detailed per-run measurements are hidden by default so agents do not spend tokens reading wrapper telemetry. Enable them for benchmarking or demos:
258
-
259
- ```powershell
260
- shrinker --metrics git log -n 10
261
- ```
262
-
263
- When meaningful content is omitted, the full capture is saved under `~/.shrinker/raw` and a compact exact-recovery hint such as `[full: shrinker raw ab12cd34]` is printed instead of an absolute path. Retrieve it only when needed:
264
-
265
- ```powershell
266
- shrinker raw ab12cd34
267
- shrinker raw ab12cd34 --path
268
- shrinker last
269
- shrinker last --path
270
- ```
271
-
272
- `raw` retrieves the exact capture referenced by a hint; `last` is a convenience for human use. The cache uses atomic publication and best-effort rotation to retain up to 20 recent files. File names contain only the executable name, not command arguments. Wrapped `git log` output never creates a recovery file or hint because the full history can be reproduced by rerunning Git; piped Git-log text still gets a recovery hint when meaningful content is omitted. Use `--no-save` for other output that should not be persisted.
273
-
274
- ## Demo
275
-
276
- ```powershell
277
- npm run demo
278
- ```
279
-
280
- Current representative fixtures:
281
-
282
- | Output | Estimated token reduction |
283
- |---|---:|
284
- | Git status | 62% |
285
- | Git diff | 26% |
286
- | Git log with commit bodies | 39% |
287
- | Git log with one short commit | 69%, but only 27 estimated tokens |
288
- | Test failure | 51% |
289
- | Noisy log | 39% |
290
- | **Average** | **48%** |
291
-
292
- The token estimate uses `ceil(characters / 4)`. It is suitable for relative before/after comparisons, not billing claims. Byte counts and absolute estimated tokens saved are also reported; gains below 50 tokens are labeled as small.
293
-
294
- ## Architecture
295
-
296
- ```text
297
- command/stdin
298
- |
299
- v
300
- capture output + exit code
301
- |
302
- v
303
- select deterministic filter
304
- |
305
- +--> git status: group files by state
306
- +--> git diff: retain changed lines, drop metadata/context
307
- +--> git log: retain short hash, refs, subject, author, date,
308
- | and up to three useful body lines
309
- +--> tests: collapse passes, retain failures and summaries
310
- +--> logs: collapse progress and repeated lines
311
- |
312
- v
313
- compact output + optional metrics + meaningful-omission recovery hint
314
- ```
315
-
316
- Filters are pure functions, so the same pipeline can later sit behind a GitHub Copilot hook or MCP server without rewriting the compression logic.
317
-
318
- ## Safety and limitations
319
-
320
- - The tool does not execute through a shell. Compound shell expressions and interactive commands are out of scope.
321
- - Stdout and stderr are captured separately and presented as stdout followed by stderr; exact interleaving is not preserved.
322
- - Filtering is conservative, but any lossy transform can hide useful context. The recovery file and `--raw` are escape hatches.
323
- - Git log patch/stat/name-list flags and explicit custom formats are preserved rather than destructively reinterpreted.
324
- - Git log does not impose hidden commit limits or suppress merge commits.
325
- - This measures command-output reduction, not total Copilot usage, total conversation context, or billing.
326
- - Streaming, agent hooks, MCP, telemetry, dashboards, custom configuration, and a broad command registry are deliberately deferred.
327
-
328
- ## Validation
329
-
330
- ```powershell
331
- npm test
332
- ```
333
-
334
- Tests cover information retention, reduction targets, ANSI cleanup, filter selection, command capture, and non-zero exit-code propagation.
335
-
336
- ## Release to npm
337
-
338
- A GitHub Actions workflow publishes this CLI to npm:
339
-
340
- - Workflow file: `.github/workflows/publish-npm.yml`
341
- - Triggers:
342
- - Tag push matching `v*` (for example `v0.2.0`)
343
- - Manual run via workflow_dispatch
344
- - Pipeline steps:
345
- - `npm ci`
346
- - `npm test`
347
- - `npm publish` to `https://registry.npmjs.org`
348
-
349
- How to publish:
350
-
351
- 1. Push your changes to GitHub.
352
- 2. Push a version tag (or run the workflow manually):
353
- - `git tag v0.2.0`
354
- - `git push origin v0.2.0`
355
- 3. After the workflow succeeds, install from npm:
356
- - `npm install -g shrinker-ai`
357
-
358
- ## Suggested roadmap
359
-
360
- 1. Validate the POC with real Copilot/Agency workflows and identify the highest-volume commands.
361
- 2. Add a GitHub Copilot pre-tool hook for transparent rewriting.
362
- 3. Expose the executor and filters through MCP for other agents.
363
- 4. Add filters only when measured usage justifies them.
1
+ # shrinker
2
+
3
+ A small local CLI proof of concept that removes noise from command output before a coding agent or LLM reads it.
4
+
5
+ this POC proves that a few conservative, deterministic filters can save useful context without requiring an API key, service, UI, database, or agent-specific integration.
6
+
7
+ ## What the POC demonstrates
8
+
9
+ - Explicit cross-agent command wrapping: `shrinker exec -- <command>`.
10
+ - Filters for Git status, Git diff, test output, and generic logs.
11
+ - Failures, warnings, changed paths, and command exit codes are preserved.
12
+ - Omitted raw output is saved locally for recovery.
13
+ - Optional per-run metrics report bytes and approximate before/after tokens.
14
+ - Local SQLite statistics accumulate savings across runs.
15
+ - No command output leaves the machine.
16
+
17
+ ## Quick start
18
+
19
+ The recommended customer install downloads a standalone binary from GitHub Releases. It does not require npm registry access or a local Node.js installation.
20
+
21
+ Contributor and npm-based installs still require Node.js 22.13 or newer. This is the first Node 22 release where the built-in SQLite module no longer requires an experimental flag.
22
+
23
+ ### One-command install (macOS zsh)
24
+
25
+ ```bash
26
+ curl -fsSL https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/macos/install.sh | bash
27
+ ```
28
+
29
+ To pin a version:
30
+
31
+ ```bash
32
+ curl -fsSL https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/macos/install.sh | bash -s -- --version 0.4.0
33
+ ```
34
+
35
+ ### One-command install (Windows PowerShell)
36
+
37
+ ```powershell
38
+ irm https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/windows/install.ps1 | iex
39
+ ```
40
+
41
+ To pin a version:
42
+
43
+ ```powershell
44
+ & ([scriptblock]::Create((irm https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/windows/install.ps1))) -Version 0.4.0
45
+ ```
46
+
47
+ The installer downloads these anonymous GitHub Release assets by default:
48
+
49
+ - `shrinker-win-x64.zip`
50
+ - `shrinker-macos-arm64.tar.gz`
51
+ - `shrinker-macos-x64.tar.gz`
52
+ - `shrinker-linux-x64.tar.gz`
53
+
54
+ Network allowlists need access to `raw.githubusercontent.com` for the installer script and `github.com/ivanduplenskikh/shrinker/releases/download/...` for release assets.
55
+
56
+ ### Optional npm package install
57
+
58
+ Use this only when npm registry access is available or preferred.
59
+
60
+ Windows PowerShell:
61
+
62
+ ```powershell
63
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -UseNpm
64
+
65
+ # Or manually:
66
+ npm install --global shrinker-ai --registry=https://registry.npmjs.org
67
+ $pkg = Join-Path ((npm root --global).Trim()) "shrinker-ai"
68
+ pwsh -ExecutionPolicy Bypass -File (Join-Path $pkg "integrations\\windows\\install.ps1") -Local -SkipNpmInstall -SkipBuild -SkipLink
69
+ ```
70
+
71
+ To enable automatic PowerShell routing, add `-EnableProfileRouting` to the final command.
72
+
73
+ macOS zsh:
74
+
75
+ ```bash
76
+ bash ./integrations/macos/install.sh --use-npm
77
+
78
+ # Or manually:
79
+ npm install --global shrinker-ai --registry=https://registry.npmjs.org
80
+ pkg="$(npm root --global)/shrinker-ai"
81
+ bash "$pkg/integrations/macos/install.sh" --local --skip-npm-install --skip-build --skip-link --enable-profile-routing
82
+ ```
83
+
84
+ ### Install from local checkout
85
+
86
+ Windows PowerShell:
87
+
88
+ ```powershell
89
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Local
90
+ ```
91
+
92
+ macOS zsh:
93
+
94
+ ```bash
95
+ bash ./integrations/macos/install.sh --local
96
+ ```
97
+
98
+ This writes managed guidance blocks globally to:
99
+
100
+ - `~/.copilot/copilot-instructions.md`
101
+ - `~/.claude/CLAUDE.md`
102
+
103
+ The shared guidance source is `templates/agent-rules.md`; the files above are created in the corresponding global agent directory.
104
+
105
+ The rules tell agents to prefer `shrinker <command>` for high-volume commands while leaving native commands untouched.
106
+
107
+ ### Uninstall
108
+
109
+ GitHub Release binary install:
110
+
111
+ Windows PowerShell:
112
+
113
+ ```powershell
114
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\uninstall.ps1
115
+ ```
116
+
117
+ macOS zsh:
118
+
119
+ ```bash
120
+ bash ./integrations/macos/uninstall.sh
121
+ ```
122
+
123
+ If you installed from npm, use npm mode:
124
+
125
+ ```bash
126
+ npm uninstall --global shrinker-ai --registry=https://registry.npmjs.org
127
+ ```
128
+
129
+ If you also installed profile/rules through the package scripts, run the matching local uninstaller from the installed package before uninstalling:
130
+
131
+ Windows PowerShell:
132
+
133
+ ```powershell
134
+ $pkg = Join-Path ((npm root --global).Trim()) "shrinker-ai"
135
+ pwsh -ExecutionPolicy Bypass -File (Join-Path $pkg "integrations\\windows\\uninstall.ps1") -SkipUnlink
136
+ ```
137
+
138
+ macOS zsh:
139
+
140
+ ```bash
141
+ pkg="$(npm root --global)/shrinker-ai"
142
+ bash "$pkg/integrations/macos/uninstall.sh" --skip-unlink
143
+ ```
144
+
145
+ macOS one-liner uninstall:
146
+
147
+ ```bash
148
+ curl -fsSL https://raw.githubusercontent.com/ivanduplenskikh/shrinker/main/integrations/macos/uninstall.sh | bash
149
+ ```
150
+
151
+ ### Local repo install/uninstall (contributors)
152
+
153
+ If you cloned this repository and want to run scripts directly from the local path:
154
+
155
+ ```powershell
156
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Local
157
+ ```
158
+
159
+ Or on macOS:
160
+
161
+ ```bash
162
+ bash ./integrations/macos/install.sh --local
163
+ ```
164
+
165
+ To uninstall:
166
+
167
+ ```powershell
168
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Uninstall
169
+ ```
170
+
171
+ Or on macOS:
172
+
173
+ ```bash
174
+ bash ./integrations/macos/install.sh --uninstall
175
+ ```
176
+
177
+ Uninstall options:
178
+
179
+ ```powershell
180
+ # Keep shrinker command installed, but remove profile integration and managed rules
181
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Uninstall -SkipUnlink
182
+
183
+ # Keep managed rules files unchanged while uninstalling command/profile hooks
184
+ pwsh -ExecutionPolicy Bypass -File .\integrations\windows\install.ps1 -Uninstall -SkipAgentRules
185
+ ```
186
+
187
+ macOS uninstall options:
188
+
189
+ ```bash
190
+ # Keep shrinker command installed, but remove profile integration and managed rules
191
+ bash ./integrations/macos/install.sh --uninstall --skip-unlink
192
+
193
+ # Keep managed rules files unchanged while uninstalling command/profile hooks
194
+ bash ./integrations/macos/install.sh --uninstall --skip-agent-rules
195
+ ```
196
+
197
+ If your current terminal had already loaded `shrinker-profile.ps1` or `shrinker-profile.zsh`, restart terminal (or remove loaded wrapper functions) to fully return to native command behavior.
198
+
199
+ ```powershell
200
+ npm install
201
+ npm run build
202
+ node dist\src\cli.js exec -- git status
203
+ node dist\src\cli.js exec -- git diff
204
+ node dist\src\cli.js exec -- git log -n 10
205
+ node dist\src\cli.js exec -- npm test
206
+ Get-Content .\tests\fixtures\generic-log.txt -Raw |
207
+ node dist\src\cli.js pipe --kind log
208
+ ```
209
+
210
+ To install the `shrinker` command locally:
211
+
212
+ ```powershell
213
+ npm link
214
+ shrinker git status
215
+ shrinker git log -n 10
216
+ shrinker npm test
217
+ ```
218
+
219
+ ## CLI
220
+
221
+ ```text
222
+ shrinker <command> [args...]
223
+ shrinker exec [options] [--] <command> [args...]
224
+ shrinker pipe [options]
225
+ shrinker stats [--json]
226
+ shrinker last [--path]
227
+ shrinker raw <capture-id> [--path]
228
+ shrinker track --executable <name> [--subcommand <name>] [--bytes <number>] [--exit-code <number>]
229
+ shrinker help
230
+
231
+ --kind <auto|git-status|git-diff|git-log|test|log>
232
+ --max-lines <number> default: 120
233
+ --per-file-lines <number> default: 40
234
+ --raw bypass filtering
235
+ --metrics print per-run savings and duration
236
+ --no-save do not save omitted raw output
237
+ --no-stats do not record this run
238
+ --coverage list commands shrinker does not cover yet
239
+ ```
240
+
241
+ `help`, `stats`, `last`, `raw`, `track`, `pipe`, and `exec` are reserved shrinker commands. Every other top-level token starts a wrapped command, so `shrinker git log` is equivalent to `shrinker exec git log`. The `--` separator remains optional because npm's PowerShell shim may consume it. `pipe` reads existing text from stdin and defaults to the generic log filter unless `--kind` is specified. `track` is used by the shell integrations to record coverage gaps and prints nothing.
242
+
243
+ ## Automatic PowerShell routing
244
+
245
+ The optional profile integration routes allowlisted commands through `shrinker` and invokes the native executable for everything else. Install it after `npm link`:
246
+
247
+ ```powershell
248
+ if (!(Test-Path $PROFILE)) {
249
+ New-Item -ItemType File -Path $PROFILE -Force | Out-Null
250
+ }
251
+
252
+ $integration = (Resolve-Path .\integrations\windows\shrinker-profile.ps1).Path
253
+ Add-Content $PROFILE "`n. `"$integration`""
254
+ . $PROFILE
255
+ ```
256
+
257
+ macOS zsh profile integration:
258
+
259
+ ```bash
260
+ echo '' >> ~/.zshrc
261
+ echo '# >>> shrinker integration >>>' >> ~/.zshrc
262
+ echo 'source "'"$(pwd)/integrations/macos/shrinker-profile.zsh"'"' >> ~/.zshrc
263
+ echo '# <<< shrinker integration <<<' >> ~/.zshrc
264
+ source ~/.zshrc
265
+ ```
266
+
267
+ The default rules are:
268
+
269
+ ```text
270
+ git status -> shrinker git status
271
+ git diff -> shrinker git diff
272
+ git log -> shrinker git log
273
+ npm test -> shrinker npm test
274
+ docker ps -> shrinker docker ps
275
+ kubectl get -> shrinker kubectl get
276
+ gh pr list -> shrinker gh pr list
277
+ rg/find/tail/cat/ls/dir -> shrinker <command>
278
+
279
+ git push, git fetch, and all other commands -> native executable
280
+ ```
281
+
282
+ Edit `$global:ShrinkPowerShellRules` in `integrations\windows\shrinker-profile.ps1` to change the allowlist. The router is now option-aware for common global flags, so forms like `git -C <path> log` and `kubectl --context prod get pods` are routed correctly.
283
+
284
+ ## Savings statistics
285
+
286
+ Filtered runs are recorded locally in `~/.shrinker/stats.db`. The database stores only measurements, filter kind, executable basename, duration, omission state, and exit code. It does **not** store command arguments or command output.
287
+
288
+ ```powershell
289
+ node dist\src\cli.js stats
290
+ node dist\src\cli.js stats --json
291
+ node dist\src\cli.js stats --chart
292
+ node dist\src\cli.js stats --dashboard
293
+ node dist\src\cli.js stats --dashboard --port 4318
294
+ node dist\src\cli.js stats --dashboard --restart
295
+ ```
296
+
297
+ The summary shows all-time and last-seven-day savings plus a breakdown by filter. Use `--no-stats` before `--` to opt out for an individual run:
298
+
299
+ `stats --coverage` lists commands shrinker does not cover yet; see [Coverage gaps](#coverage-gaps).
300
+ `stats --chart` shows daily runs, estimated tokens saved, reduction percentage, and an activity bar for the last 30 days.
301
+ `stats --dashboard` starts the local dashboard server in the background at `http://127.0.0.1:4317` and opens it in your browser, then returns to the terminal. The page reads the latest local stats whenever it is refreshed; use `--port` to choose another port. The same command also refreshes the standalone copy at `~/.shrinker/dashboard.html`, which can be opened directly without a server running.
302
+
303
+ Use `stats --dashboard --restart` after rebuilding to replace an already-running dashboard server with the current code.
304
+
305
+ The dashboard estimates input API cost saved from the recorded token savings. Set the input price directly in the dashboard; it is retained in that browser. It defaults to `$5.00` per million input tokens, or `SHRINKER_INPUT_COST_PER_MILLION_TOKENS` when set before starting the dashboard:
306
+
307
+ ```powershell
308
+ $env:SHRINKER_INPUT_COST_PER_MILLION_TOKENS = "2.50"
309
+ shrinker stats --dashboard
310
+ ```
311
+
312
+ ```powershell
313
+ node dist\src\cli.js exec --no-stats -- git log -n 10
314
+ ```
315
+
316
+ Detailed per-run measurements are hidden by default so agents do not spend tokens reading wrapper telemetry. Enable them for benchmarking or demos:
317
+
318
+ ```powershell
319
+ shrinker --metrics git log -n 10
320
+ ```
321
+
322
+ When meaningful content is omitted, the full capture is saved under `~/.shrinker/raw` and a compact exact-recovery hint such as `[full: shrinker raw ab12cd34]` is printed instead of an absolute path. Retrieve it only when needed:
323
+
324
+ ```powershell
325
+ shrinker raw ab12cd34
326
+ shrinker raw ab12cd34 --path
327
+ shrinker last
328
+ shrinker last --path
329
+ ```
330
+
331
+ `raw` retrieves the exact capture referenced by a hint; `last` is a convenience for human use. The cache uses atomic publication and best-effort rotation to retain up to 20 recent files. File names contain only the executable name, not command arguments. Wrapped `git log` output never creates a recovery file or hint because the full history can be reproduced by rerunning Git; piped Git-log text still gets a recovery hint when meaningful content is omitted. Use `--no-save` for other output that should not be persisted.
332
+
333
+ ## Coverage gaps
334
+
335
+ Shrinker only measures what it filters. Coverage tracking answers the opposite question: **which commands does an agent run that shrinker does not cover yet?** It ranks them by the estimated tokens a dedicated filter could have seen, so the top row is the next filter worth writing.
336
+
337
+ The installer asks whether to enable it and stores the answer in `~/.shrinker/config`:
338
+
339
+ ```text
340
+ SHRINKER_TRACK_UNCOVERED=1
341
+ ```
342
+
343
+ Pass `--enable-uncovered-tracking` / `--disable-uncovered-tracking` (macOS) or `-EnableUncoveredTracking` / `-DisableUncoveredTracking` (Windows) to answer ahead of time. Non-interactive installs skip the prompt and enable tracking.
344
+
345
+ The environment variable still wins for a single shell or command, in either direction:
346
+
347
+ ```bash
348
+ SHRINKER_TRACK_UNCOVERED=0 shrinker git status # off for one command
349
+ export SHRINKER_TRACK_UNCOVERED=1 # on for this shell
350
+ ```
351
+
352
+ ```powershell
353
+ $env:SHRINKER_TRACK_UNCOVERED = "1"
354
+ ```
355
+
356
+ Both the CLI and the shell integration read `~/.shrinker/config`; the shell profile reads it once at load, so change it and restart the shell (or export the variable) to take effect immediately. Set `SHRINKER_CONFIG_PATH` to relocate the file.
357
+
358
+ Two kinds of gaps are recorded:
359
+
360
+ - `no-filter` / `low-reduction` — the command ran through shrinker, but no filter matched it, or the matching filter barely reduced the output.
361
+ - `unlisted-subcommand` the shell integration shadows the executable, but the subcommand is outside the routing allowlist, so the native binary ran instead (`git blame`, `docker inspect`, `npm run build`).
362
+
363
+ Read the results with:
364
+
365
+ ```powershell
366
+ shrinker stats --coverage
367
+ ```
368
+
369
+ ```text
370
+ Ranked by estimated tokens a dedicated filter could see:
371
+ Command Runs Est. tokens Avg Reason Source Last seen
372
+ ------------------------- ---------- ----------- ---------- --------------------- --------------- -------------------
373
+ docker inspect 12 runs 148,204 12,350 unlisted-subcommand shell 2025-05-14 09:22:41
374
+ ```
375
+
376
+ The same data is included in `stats --json` and appears as a "Coverage gaps" panel in the dashboard.
377
+
378
+ **What is stored:** the executable name and its subcommand only, plus an occurrence count, output size, and exit code — for example `docker inspect`. Command arguments, flag values, paths, and command output are never stored. Tokens that are not bare command names are dropped rather than written, so a misfiring hook cannot leak a path or secret into the database. Everything stays in `~/.shrinker/stats.db` on this machine; nothing is uploaded.
379
+
380
+ Runs with small outputs (under ~200 estimated tokens) are ignored so the table stays focused on real savings. Adjust the low-reduction threshold with `SHRINKER_LOW_REDUCTION_PERCENT` (default `10`).
381
+
382
+ Output volume is measured in the shell integration only when stdout is redirected — which is the agent case. Interactive terminal sessions run the native command completely untouched and are recorded with a size of zero, so pagers, colours, and prompts still behave normally.
383
+
384
+ ## Demo
385
+
386
+ ```powershell
387
+ npm run demo
388
+ ```
389
+
390
+ Current representative fixtures:
391
+
392
+ | Output | Estimated token reduction |
393
+ |---|---:|
394
+ | Git status | 62% |
395
+ | Git diff | 26% |
396
+ | Git log with commit bodies | 39% |
397
+ | Git log with one short commit | 69%, but only 27 estimated tokens |
398
+ | Test failure | 51% |
399
+ | Noisy log | 39% |
400
+ | **Average** | **48%** |
401
+
402
+ The token estimate uses `ceil(characters / 4)`. It is suitable for relative before/after comparisons, not billing claims. Byte counts and absolute estimated tokens saved are also reported; gains below 50 tokens are labeled as small.
403
+
404
+ ## Architecture
405
+
406
+ ```text
407
+ command/stdin
408
+ |
409
+ v
410
+ capture output + exit code
411
+ |
412
+ v
413
+ select deterministic filter
414
+ |
415
+ +--> git status: group files by state
416
+ +--> git diff: retain changed lines, drop metadata/context
417
+ +--> git log: retain short hash, refs, subject, author, date,
418
+ | and up to three useful body lines
419
+ +--> tests: collapse passes, retain failures and summaries
420
+ +--> logs: collapse progress and repeated lines
421
+ |
422
+ v
423
+ compact output + optional metrics + meaningful-omission recovery hint
424
+ ```
425
+
426
+ Filters are pure functions, so the same pipeline can later sit behind a GitHub Copilot hook or MCP server without rewriting the compression logic.
427
+
428
+ ### Workspace layout
429
+
430
+ The repository is an npm workspace. The CLI lives at the root; the stats dashboard is a separate React + HeroUI app.
431
+
432
+ ```text
433
+ .
434
+ ├── src/ CLI (TypeScript, ESM, zero runtime dependencies)
435
+ ├── tests/ node:test suites
436
+ └── packages/dashboard-ui/ React + HeroUI dashboard, bundled by Vite
437
+ ```
438
+
439
+ `packages/dashboard-ui` builds to a single self-contained HTML file (`vite-plugin-singlefile`), which `scripts/emit-template.mjs` then bakes into `src/metrics/dashboard-template.generated.ts`. The CLI injects the current `StatsSummary` into that template as an embedded JSON blob, so the published package still has no runtime dependencies and the dashboard works from `file://` with no server.
440
+
441
+ | Command | Purpose |
442
+ | --- | --- |
443
+ | `npm run dev:ui` | Vite dev server with hot reload (renders empty-state data) |
444
+ | `npm run build:ui` | Build the dashboard and regenerate the baked template |
445
+ | `npm run build` | `build:ui`, then `tsc` |
446
+
447
+ `npm run build:ui` is a prerequisite for `tsc`, because the generated template module is a compiled source file. `npm run build`, `npm test`, `npm run demo`, and `npm run pack` all chain it automatically.
448
+
449
+ ## Safety and limitations
450
+
451
+ - The tool does not execute through a shell. Compound shell expressions and interactive commands are out of scope.
452
+ - Stdout and stderr are captured separately and presented as stdout followed by stderr; exact interleaving is not preserved.
453
+ - Filtering is conservative, but any lossy transform can hide useful context. The recovery file and `--raw` are escape hatches.
454
+ - Git log patch/stat/name-list flags and explicit custom formats are preserved rather than destructively reinterpreted.
455
+ - Git log does not impose hidden commit limits or suppress merge commits.
456
+ - This measures command-output reduction, not total Copilot usage, total conversation context, or billing.
457
+ - Streaming, agent hooks, MCP, telemetry, dashboards, custom configuration, and a broad command registry are deliberately deferred.
458
+
459
+ ## Validation
460
+
461
+ ```powershell
462
+ npm test
463
+ ```
464
+
465
+ Tests cover information retention, reduction targets, ANSI cleanup, filter selection, command capture, and non-zero exit-code propagation.
466
+
467
+ ## Release to npm
468
+
469
+ A GitHub Actions workflow publishes this CLI to npm:
470
+
471
+ - Workflow file: `.github/workflows/publish-npm.yml`
472
+ - Triggers:
473
+ - Tag push matching `v*` (for example `v0.2.0`)
474
+ - Manual run via workflow_dispatch
475
+ - Pipeline steps:
476
+ - `npm ci`
477
+ - `npm test`
478
+ - `npm publish` to `https://registry.npmjs.org`
479
+
480
+ How to publish:
481
+
482
+ 1. Push your changes to GitHub.
483
+ 2. Push a version tag (or run the workflow manually):
484
+ - `git tag v0.2.0`
485
+ - `git push origin v0.2.0`
486
+ 3. After the workflow succeeds, install from npm:
487
+ - `npm install -g shrinker-ai`
488
+
489
+ ## Suggested roadmap
490
+
491
+ 1. Validate the POC with real Copilot/Agency workflows and identify the highest-volume commands.
492
+ 2. Add a GitHub Copilot pre-tool hook for transparent rewriting.
493
+ 3. Expose the executor and filters through MCP for other agents.
494
+ 4. Add filters only when measured usage justifies them.