kompactor 0.7.8__tar.gz → 0.8.0__tar.gz

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.

Potentially problematic release.


This version of kompactor might be problematic. Click here for more details.

Files changed (42) hide show
  1. {kompactor-0.7.8 → kompactor-0.8.0}/PKG-INFO +17 -17
  2. {kompactor-0.7.8 → kompactor-0.8.0}/README.md +16 -16
  3. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/__init__.py +1 -1
  4. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/cli.py +32 -38
  5. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/hooks.py +2 -1
  6. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/installer.py +42 -4
  7. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/prove.py +1 -1
  8. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/usage.html +7 -7
  9. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/ui.html +3 -3
  10. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/PKG-INFO +17 -17
  11. {kompactor-0.7.8 → kompactor-0.8.0}/pyproject.toml +1 -1
  12. {kompactor-0.7.8 → kompactor-0.8.0}/tests/test_graph.py +2 -1
  13. {kompactor-0.7.8 → kompactor-0.8.0}/tests/test_kompactor.py +19 -0
  14. {kompactor-0.7.8 → kompactor-0.8.0}/tests/test_shell.py +1 -0
  15. {kompactor-0.7.8 → kompactor-0.8.0}/LICENSE +0 -0
  16. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/__main__.py +0 -0
  17. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/_launch.py +0 -0
  18. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/config.py +0 -0
  19. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/estimate.py +0 -0
  20. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/filters.py +0 -0
  21. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/graph.py +0 -0
  22. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/langs.py +0 -0
  23. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/outline.py +0 -0
  24. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/rules.py +0 -0
  25. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/samples.py +0 -0
  26. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/server.py +0 -0
  27. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/shellwrap.py +0 -0
  28. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/OFL.txt +0 -0
  29. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-mono-400.woff2 +0 -0
  30. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-mono-500.woff2 +0 -0
  31. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-sans-400.woff2 +0 -0
  32. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-sans-500.woff2 +0 -0
  33. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-sans-600.woff2 +0 -0
  34. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/logo-mark.svg +0 -0
  35. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/store.py +0 -0
  36. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/tokens.py +0 -0
  37. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/SOURCES.txt +0 -0
  38. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/dependency_links.txt +0 -0
  39. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/entry_points.txt +0 -0
  40. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/requires.txt +0 -0
  41. {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/top_level.txt +0 -0
  42. {kompactor-0.7.8 → kompactor-0.8.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kompactor
3
- Version: 0.7.8
3
+ Version: 0.8.0
4
4
  Summary: Cut the tokens Claude Code spends on noise: compacted command output (failing runs included), outline-first reads, a local code graph, and per-turn savings.
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/amarkum/kompactor
@@ -112,17 +112,18 @@ Pick one. All of them set up the same thing, and the Claude Code CLI and VS Code
112
112
  ```
113
113
  /plugin marketplace add amarkum/kompactor
114
114
  /plugin install amarkum@kompactor
115
- /kompactor setup
115
+ /kompactor start
116
116
  ```
117
- The last step adds the status line and the shell prefix that compacts failing commands, which a plugin can't set itself. Then restart Claude Code.
117
+ The last step turns Kompactor on: it adds the status line and the shell prefix that compacts failing commands (a plugin can't set those itself) and opens the dashboard. Then restart Claude Code.
118
118
 
119
119
  **pip / pipx / uv** (macOS, Linux, Windows):
120
120
  ```bash
121
121
  pipx install kompactor # or: pip install kompactor · uv tool install kompactor
122
- kompactor setup
122
+ kompactor start
123
123
  ```
124
+ If your shell says `kompactor: command not found` (pip put the command in a folder that isn't on your PATH), run `python3 -m kompactor start` once. It links `kompactor` into a folder that is already on your PATH, such as `~/.local/bin`, so the command works in every terminal from then on.
124
125
 
125
- **VS Code.** Download `kompactor-0.7.8.vsix` from [Releases](https://github.com/amarkum/kompactor/releases), install it (Extensions › `⋯` › *Install from VSIX…*), and click **Enable** when Kompactor asks.
126
+ **VS Code.** Download `kompactor-0.8.0.vsix` from [Releases](https://github.com/amarkum/kompactor/releases), install it (Extensions › `⋯` › *Install from VSIX…*), and click **Enable** when Kompactor asks.
126
127
 
127
128
  **From source:**
128
129
  ```bash
@@ -135,12 +136,12 @@ git clone https://github.com/amarkum/kompactor.git && ./kompactor/install.sh
135
136
  2. **Work as usual.** You don't call Kompactor; it acts on Claude's tool calls by itself. After each reply you'll see a line like `Kompactor: −8.2k tokens this turn`, and the status line shows the running total.
136
137
  3. **Check it's on:** run `kompactor` in a terminal (or `/kompactor` in Claude Code):
137
138
  ```
138
- Kompactor 0.7.8: ON
139
+ Kompactor 0.8.0: ON
139
140
  Connected via the Claude Code plugin. New Claude Code sessions are compacted.
140
141
  Level: Balanced (level 3 of 5). Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced
141
142
  Saved so far: 41.3k tokens (−38%) over 52 tool calls. Details: `kompactor gain`
142
143
  ```
143
- 4. **Open the dashboard:** `kompactor start` runs it in the background on a free port and prints the address.
144
+ 4. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
144
145
 
145
146
  ## How it works
146
147
 
@@ -186,10 +187,10 @@ Ask Claude Code the way you normally would. These prompts come from the [evidenc
186
187
 
187
188
  | Command | What it does |
188
189
  |---|---|
190
+ | `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code) and open the dashboard on a free port |
191
+ | `kompactor stop` | Pause it and close the dashboard; settings are kept |
192
+ | `kompactor uninstall [--purge]` | Remove it from Claude Code (`--purge` also deletes `~/.kompactor`) |
189
193
  | `kompactor` / `kompactor status` | On or off, level, savings, how it works |
190
- | `kompactor setup` | Connect to Claude Code (CLI + VS Code) and open the dashboard |
191
- | `kompactor start` / `kompactor stop` | Turn on (dashboard in the background, free port) / pause |
192
- | `kompactor uninstall [--purge]` | Remove from Claude Code (`--purge` also deletes `~/.kompactor`) |
193
194
  | `kompactor presets` · `kompactor config preset 4` | List levels · change level |
194
195
  | `kompactor config <setting> <value>` | Change one [setting](#settings) |
195
196
  | `kompactor gain` | Savings so far |
@@ -224,7 +225,7 @@ Settings come from, in increasing priority: the level → your global choices
224
225
  | Setting | Type | What it does |
225
226
  |---|---|---|
226
227
  | `bash` | bool | Compact command output |
227
- | `bash_wrap` | bool | Compact failing commands too (needs the shell prefix from `kompactor setup`) |
228
+ | `bash_wrap` | bool | Compact failing commands too (needs the shell prefix that `kompactor start` adds) |
228
229
  | `bash_plain` | bool | Ask Claude to run commands without `\| head`, `\| tail` or `\| grep`, since Kompactor keeps every failure |
229
230
  | `bash_min_tokens` | int | Leave outputs smaller than this untouched |
230
231
  | `bash_max_lines` | int | Max lines kept per output (head and tail kept; error lines from the middle always kept) |
@@ -306,7 +307,7 @@ kompactor graph unused dead-code candidates
306
307
  "enabledPlugins": { "amarkum@kompactor": true }
307
308
  }
308
309
  ```
309
- When a teammate trusts the folder, Claude Code installs the plugin; each person then runs `/kompactor setup` once. `autoUpdate` keeps everyone on the latest release. Admins can put the same keys in Claude Code's managed settings to roll it out to every machine, and a team that runs its own fork sets `KOMPACTOR_REPO` so the dashboard shows the fork's commands.
310
+ When a teammate trusts the folder, Claude Code installs the plugin; each person then runs `/kompactor start` once. `autoUpdate` keeps everyone on the latest release. Admins can put the same keys in Claude Code's managed settings to roll it out to every machine, and a team that runs its own fork sets `KOMPACTOR_REPO` so the dashboard shows the fork's commands.
310
311
 
311
312
  ## Evidence
312
313
 
@@ -369,13 +370,13 @@ Command output from any language is compacted. These languages also get language
369
370
 
370
371
  Everything below happens on your machine. Kompactor makes no network requests of its own and has no telemetry. (If you install the optional `tiktoken` package for exact token counts, tiktoken downloads its token table once, on first use.)
371
372
 
372
- **What it runs.** Python hooks that Claude Code calls (`python3 kompactor/_launch.py hook <name>` from the plugin folder): after Bash, Read, Grep, Glob and edit tool calls; before Read; at session start, subagent start and before compaction; and when a turn ends. After `/kompactor setup` on macOS and Linux, Claude's Bash commands run through Kompactor's shell prefix (`~/.kompactor/bin/kompactor-shell`) so failing runs can be compacted too. The prefix runs after Claude Code's permission check, on Claude's original command, and returns its exit code unchanged.
373
+ **What it runs.** Python hooks that Claude Code calls (`python3 kompactor/_launch.py hook <name>` from the plugin folder): after Bash, Read, Grep, Glob and edit tool calls; before Read; at session start, subagent start and before compaction; and when a turn ends. After `kompactor start` on macOS and Linux, Claude's Bash commands run through Kompactor's shell prefix (`~/.kompactor/bin/kompactor-shell`) so failing runs can be compacted too. The prefix runs after Claude Code's permission check, on Claude's original command, and returns its exit code unchanged.
373
374
 
374
375
  **What it adds to Claude's context.** Compacted tool output, outlines in place of large file reads, a code map once per session, a one-line savings note after each turn, and short reply rules at session start and for subagents. The rules are plain text you can read in [`kompactor/rules.py`](https://github.com/amarkum/kompactor/blob/main/kompactor/rules.py).
375
376
 
376
377
  **What it reads.** The tool output Claude Code passes to its hooks, the files Claude reads (to outline them), your project's source (for the code graph), and the context size Claude Code gives the status line. Hooks never read your session transcripts. `kompactor estimate` and the dashboard's **Replay your history** panel read your local Claude Code session logs in `~/.claude/projects` only when you run them; the result isn't stored or sent anywhere.
377
378
 
378
- **What it writes.** `~/.kompactor/`: settings, the savings ledger, raw copies of shortened output (for `kompactor show`), the code graph index and the `~/.kompactor/bin/` launchers. History is deleted after 30 days by default. Setup edits `~/.claude/settings.json` to add Kompactor's hooks (non-plugin installs), a status line (only if you have none) and `CLAUDE_CODE_SHELL_PREFIX` (only if it isn't set), keeping a backup in `settings.json.kompactor-backup`; non-plugin installs also get the `/kompactor` skill in `~/.claude/skills`. Nothing is written to your repositories.
379
+ **What it writes.** `~/.kompactor/`: settings, the savings ledger, raw copies of shortened output (for `kompactor show`), the code graph index and the `~/.kompactor/bin/` launchers. When `kompactor` isn't on your PATH, it adds one link to that launcher in a writable folder that already is (`~/.local/bin`, `~/bin`, `/opt/homebrew/bin` or `/usr/local/bin`); it never edits shell files or replaces an existing command, and `kompactor uninstall` removes the link. History is deleted after 30 days by default. `kompactor start` edits `~/.claude/settings.json` to add Kompactor's hooks (non-plugin installs), a status line (only if you have none) and `CLAUDE_CODE_SHELL_PREFIX` (only if it isn't set), keeping a backup in `settings.json.kompactor-backup`; non-plugin installs also get the `/kompactor` skill in `~/.claude/skills`. Nothing is written to your repositories.
379
380
 
380
381
  **What it never does.** Change your permission rules or sandbox settings, change what a command does, or send your code or output anywhere. Details: [privacy policy](https://github.com/amarkum/kompactor/blob/main/PRIVACY.md).
381
382
 
@@ -383,7 +384,8 @@ Everything below happens on your machine. Kompactor makes no network requests of
383
384
 
384
385
  | Problem | What to do |
385
386
  |---|---|
386
- | No savings line after replies | Restart Claude Code after setup, then run `kompactor doctor`: it checks the installation and shows recent hook errors. The dashboard's **Self-test** panel runs every hook once. |
387
+ | `kompactor: command not found` | pip put the command in a folder that isn't on your PATH. Run `python3 -m kompactor start` once: it links `kompactor` into a writable folder already on your PATH, such as `~/.local/bin`. Claude Code plugin installs do this at the first session. |
388
+ | No savings line after replies | Restart Claude Code after `kompactor start`, then run `kompactor doctor`: it checks the installation and shows recent hook errors. The dashboard's **Self-test** panel runs every hook once. |
387
389
  | An output looks too short | Claude can fetch the original with `kompactor show <id>`, or search earlier outputs with `kompactor search "text"`. |
388
390
  | A command should never be shortened | Add it to **Never compact these commands** on the dashboard, or to `never_compact` in `.kompactor.json`. For a single run, start the command with `KOMPACTOR_RAW=1`. |
389
391
  | Something seems off | `kompactor stop` turns Kompactor off at once; every hook also lets the original output through if it hits an error. Errors are logged to `~/.kompactor/hook-errors.log`. |
@@ -455,5 +457,3 @@ Bug reports, ideas and pull requests are welcome. See [CONTRIBUTING.md](https://
455
457
  ## License
456
458
 
457
459
  [MIT](https://github.com/amarkum/kompactor/blob/main/LICENSE) © The Kompactor authors. The dashboard uses the IBM Plex fonts under the [SIL Open Font License](https://github.com/amarkum/kompactor/blob/main/kompactor/static/fonts/OFL.txt).
458
-
459
- Built by [stackcone](https://stackcone.com). Read the story behind it: [Kompactor: Cut the Tokens Claude Code Spends on Noise](https://stackcone.com/blog/posts/kompactor-claude-code-token-saver/).
@@ -79,17 +79,18 @@ Pick one. All of them set up the same thing, and the Claude Code CLI and VS Code
79
79
  ```
80
80
  /plugin marketplace add amarkum/kompactor
81
81
  /plugin install amarkum@kompactor
82
- /kompactor setup
82
+ /kompactor start
83
83
  ```
84
- The last step adds the status line and the shell prefix that compacts failing commands, which a plugin can't set itself. Then restart Claude Code.
84
+ The last step turns Kompactor on: it adds the status line and the shell prefix that compacts failing commands (a plugin can't set those itself) and opens the dashboard. Then restart Claude Code.
85
85
 
86
86
  **pip / pipx / uv** (macOS, Linux, Windows):
87
87
  ```bash
88
88
  pipx install kompactor # or: pip install kompactor · uv tool install kompactor
89
- kompactor setup
89
+ kompactor start
90
90
  ```
91
+ If your shell says `kompactor: command not found` (pip put the command in a folder that isn't on your PATH), run `python3 -m kompactor start` once. It links `kompactor` into a folder that is already on your PATH, such as `~/.local/bin`, so the command works in every terminal from then on.
91
92
 
92
- **VS Code.** Download `kompactor-0.7.8.vsix` from [Releases](https://github.com/amarkum/kompactor/releases), install it (Extensions › `⋯` › *Install from VSIX…*), and click **Enable** when Kompactor asks.
93
+ **VS Code.** Download `kompactor-0.8.0.vsix` from [Releases](https://github.com/amarkum/kompactor/releases), install it (Extensions › `⋯` › *Install from VSIX…*), and click **Enable** when Kompactor asks.
93
94
 
94
95
  **From source:**
95
96
  ```bash
@@ -102,12 +103,12 @@ git clone https://github.com/amarkum/kompactor.git && ./kompactor/install.sh
102
103
  2. **Work as usual.** You don't call Kompactor; it acts on Claude's tool calls by itself. After each reply you'll see a line like `Kompactor: −8.2k tokens this turn`, and the status line shows the running total.
103
104
  3. **Check it's on:** run `kompactor` in a terminal (or `/kompactor` in Claude Code):
104
105
  ```
105
- Kompactor 0.7.8: ON
106
+ Kompactor 0.8.0: ON
106
107
  Connected via the Claude Code plugin. New Claude Code sessions are compacted.
107
108
  Level: Balanced (level 3 of 5). Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced
108
109
  Saved so far: 41.3k tokens (−38%) over 52 tool calls. Details: `kompactor gain`
109
110
  ```
110
- 4. **Open the dashboard:** `kompactor start` runs it in the background on a free port and prints the address.
111
+ 4. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
111
112
 
112
113
  ## How it works
113
114
 
@@ -153,10 +154,10 @@ Ask Claude Code the way you normally would. These prompts come from the [evidenc
153
154
 
154
155
  | Command | What it does |
155
156
  |---|---|
157
+ | `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code) and open the dashboard on a free port |
158
+ | `kompactor stop` | Pause it and close the dashboard; settings are kept |
159
+ | `kompactor uninstall [--purge]` | Remove it from Claude Code (`--purge` also deletes `~/.kompactor`) |
156
160
  | `kompactor` / `kompactor status` | On or off, level, savings, how it works |
157
- | `kompactor setup` | Connect to Claude Code (CLI + VS Code) and open the dashboard |
158
- | `kompactor start` / `kompactor stop` | Turn on (dashboard in the background, free port) / pause |
159
- | `kompactor uninstall [--purge]` | Remove from Claude Code (`--purge` also deletes `~/.kompactor`) |
160
161
  | `kompactor presets` · `kompactor config preset 4` | List levels · change level |
161
162
  | `kompactor config <setting> <value>` | Change one [setting](#settings) |
162
163
  | `kompactor gain` | Savings so far |
@@ -191,7 +192,7 @@ Settings come from, in increasing priority: the level → your global choices
191
192
  | Setting | Type | What it does |
192
193
  |---|---|---|
193
194
  | `bash` | bool | Compact command output |
194
- | `bash_wrap` | bool | Compact failing commands too (needs the shell prefix from `kompactor setup`) |
195
+ | `bash_wrap` | bool | Compact failing commands too (needs the shell prefix that `kompactor start` adds) |
195
196
  | `bash_plain` | bool | Ask Claude to run commands without `\| head`, `\| tail` or `\| grep`, since Kompactor keeps every failure |
196
197
  | `bash_min_tokens` | int | Leave outputs smaller than this untouched |
197
198
  | `bash_max_lines` | int | Max lines kept per output (head and tail kept; error lines from the middle always kept) |
@@ -273,7 +274,7 @@ kompactor graph unused dead-code candidates
273
274
  "enabledPlugins": { "amarkum@kompactor": true }
274
275
  }
275
276
  ```
276
- When a teammate trusts the folder, Claude Code installs the plugin; each person then runs `/kompactor setup` once. `autoUpdate` keeps everyone on the latest release. Admins can put the same keys in Claude Code's managed settings to roll it out to every machine, and a team that runs its own fork sets `KOMPACTOR_REPO` so the dashboard shows the fork's commands.
277
+ When a teammate trusts the folder, Claude Code installs the plugin; each person then runs `/kompactor start` once. `autoUpdate` keeps everyone on the latest release. Admins can put the same keys in Claude Code's managed settings to roll it out to every machine, and a team that runs its own fork sets `KOMPACTOR_REPO` so the dashboard shows the fork's commands.
277
278
 
278
279
  ## Evidence
279
280
 
@@ -336,13 +337,13 @@ Command output from any language is compacted. These languages also get language
336
337
 
337
338
  Everything below happens on your machine. Kompactor makes no network requests of its own and has no telemetry. (If you install the optional `tiktoken` package for exact token counts, tiktoken downloads its token table once, on first use.)
338
339
 
339
- **What it runs.** Python hooks that Claude Code calls (`python3 kompactor/_launch.py hook <name>` from the plugin folder): after Bash, Read, Grep, Glob and edit tool calls; before Read; at session start, subagent start and before compaction; and when a turn ends. After `/kompactor setup` on macOS and Linux, Claude's Bash commands run through Kompactor's shell prefix (`~/.kompactor/bin/kompactor-shell`) so failing runs can be compacted too. The prefix runs after Claude Code's permission check, on Claude's original command, and returns its exit code unchanged.
340
+ **What it runs.** Python hooks that Claude Code calls (`python3 kompactor/_launch.py hook <name>` from the plugin folder): after Bash, Read, Grep, Glob and edit tool calls; before Read; at session start, subagent start and before compaction; and when a turn ends. After `kompactor start` on macOS and Linux, Claude's Bash commands run through Kompactor's shell prefix (`~/.kompactor/bin/kompactor-shell`) so failing runs can be compacted too. The prefix runs after Claude Code's permission check, on Claude's original command, and returns its exit code unchanged.
340
341
 
341
342
  **What it adds to Claude's context.** Compacted tool output, outlines in place of large file reads, a code map once per session, a one-line savings note after each turn, and short reply rules at session start and for subagents. The rules are plain text you can read in [`kompactor/rules.py`](https://github.com/amarkum/kompactor/blob/main/kompactor/rules.py).
342
343
 
343
344
  **What it reads.** The tool output Claude Code passes to its hooks, the files Claude reads (to outline them), your project's source (for the code graph), and the context size Claude Code gives the status line. Hooks never read your session transcripts. `kompactor estimate` and the dashboard's **Replay your history** panel read your local Claude Code session logs in `~/.claude/projects` only when you run them; the result isn't stored or sent anywhere.
344
345
 
345
- **What it writes.** `~/.kompactor/`: settings, the savings ledger, raw copies of shortened output (for `kompactor show`), the code graph index and the `~/.kompactor/bin/` launchers. History is deleted after 30 days by default. Setup edits `~/.claude/settings.json` to add Kompactor's hooks (non-plugin installs), a status line (only if you have none) and `CLAUDE_CODE_SHELL_PREFIX` (only if it isn't set), keeping a backup in `settings.json.kompactor-backup`; non-plugin installs also get the `/kompactor` skill in `~/.claude/skills`. Nothing is written to your repositories.
346
+ **What it writes.** `~/.kompactor/`: settings, the savings ledger, raw copies of shortened output (for `kompactor show`), the code graph index and the `~/.kompactor/bin/` launchers. When `kompactor` isn't on your PATH, it adds one link to that launcher in a writable folder that already is (`~/.local/bin`, `~/bin`, `/opt/homebrew/bin` or `/usr/local/bin`); it never edits shell files or replaces an existing command, and `kompactor uninstall` removes the link. History is deleted after 30 days by default. `kompactor start` edits `~/.claude/settings.json` to add Kompactor's hooks (non-plugin installs), a status line (only if you have none) and `CLAUDE_CODE_SHELL_PREFIX` (only if it isn't set), keeping a backup in `settings.json.kompactor-backup`; non-plugin installs also get the `/kompactor` skill in `~/.claude/skills`. Nothing is written to your repositories.
346
347
 
347
348
  **What it never does.** Change your permission rules or sandbox settings, change what a command does, or send your code or output anywhere. Details: [privacy policy](https://github.com/amarkum/kompactor/blob/main/PRIVACY.md).
348
349
 
@@ -350,7 +351,8 @@ Everything below happens on your machine. Kompactor makes no network requests of
350
351
 
351
352
  | Problem | What to do |
352
353
  |---|---|
353
- | No savings line after replies | Restart Claude Code after setup, then run `kompactor doctor`: it checks the installation and shows recent hook errors. The dashboard's **Self-test** panel runs every hook once. |
354
+ | `kompactor: command not found` | pip put the command in a folder that isn't on your PATH. Run `python3 -m kompactor start` once: it links `kompactor` into a writable folder already on your PATH, such as `~/.local/bin`. Claude Code plugin installs do this at the first session. |
355
+ | No savings line after replies | Restart Claude Code after `kompactor start`, then run `kompactor doctor`: it checks the installation and shows recent hook errors. The dashboard's **Self-test** panel runs every hook once. |
354
356
  | An output looks too short | Claude can fetch the original with `kompactor show <id>`, or search earlier outputs with `kompactor search "text"`. |
355
357
  | A command should never be shortened | Add it to **Never compact these commands** on the dashboard, or to `never_compact` in `.kompactor.json`. For a single run, start the command with `KOMPACTOR_RAW=1`. |
356
358
  | Something seems off | `kompactor stop` turns Kompactor off at once; every hook also lets the original output through if it hits an error. Errors are logged to `~/.kompactor/hook-errors.log`. |
@@ -422,5 +424,3 @@ Bug reports, ideas and pull requests are welcome. See [CONTRIBUTING.md](https://
422
424
  ## License
423
425
 
424
426
  [MIT](https://github.com/amarkum/kompactor/blob/main/LICENSE) © The Kompactor authors. The dashboard uses the IBM Plex fonts under the [SIL Open Font License](https://github.com/amarkum/kompactor/blob/main/kompactor/static/fonts/OFL.txt).
425
-
426
- Built by [stackcone](https://stackcone.com). Read the story behind it: [Kompactor: Cut the Tokens Claude Code Spends on Noise](https://stackcone.com/blog/posts/kompactor-claude-code-token-saver/).
@@ -1,3 +1,3 @@
1
1
  """Kompactor: cut the tokens Claude Code spends on noise."""
2
2
 
3
- __version__ = "0.7.8"
3
+ __version__ = "0.8.0"
@@ -189,7 +189,7 @@ def cmd_status(a):
189
189
  state = ("ON" if on else "STOPPED" if store.paused() else "NOT SET UP")
190
190
  print(f"Kompactor {__version__}: {state}")
191
191
  if not (st["plugin_enabled"] or st["hooks_installed"]):
192
- print(" Run `kompactor setup` to connect it to Claude Code (CLI and VS Code).")
192
+ print(" Run `kompactor start` to connect it to Claude Code (CLI and VS Code).")
193
193
  elif store.paused():
194
194
  print(" Claude Code output passes through untouched. Turn it back on: `kompactor start`")
195
195
  else:
@@ -282,27 +282,15 @@ def _prefix_note(st):
282
282
  note = {"kompactor": "Shell prefix: on (failing tests and builds are compacted too)",
283
283
  "other": "Shell prefix: another tool already sets CLAUDE_CODE_SHELL_PREFIX, so failing commands are "
284
284
  "not compacted",
285
- "missing": "Shell prefix: its script is missing; run `kompactor setup` again",
285
+ "missing": "Shell prefix: its script is missing; run `kompactor start` again",
286
286
  "none": "Shell prefix: off (only commands that succeed are compacted)"}[st["shell_prefix"]]
287
287
  print(f" {note}")
288
288
 
289
289
 
290
- def cmd_setup(a):
291
- """One-step setup: enable hooks for CLI + VS Code, then open the dashboard."""
292
- target = installer.install(statusline=config.read_file()["general"].get("statusline", True))
293
- st = installer.status()
294
- print("✓ Kompactor plugin is enabled; hooks are active." if st["plugin_enabled"] else f"✓ Hooks installed in {target}")
295
- print(f" Claude Code CLI: {'found' if st['claude_cli'] else 'not found'}")
296
- print(f" VS Code extension: {st['vscode_extension'] or 'not found'} (uses the same settings)")
297
- _prefix_note(st)
298
- print("\nNext: restart Claude Code, then work as usual. The status line shows what each turn saved.")
299
- print(" `kompactor` shows status and how it works · `kompactor stop` turns it off · "
300
- "`kompactor uninstall` removes it")
301
- if a.no_ui:
302
- return 0
303
- print("Opening the dashboard to choose your quality level…")
304
- a.no_browser = False
305
- return cmd_start(a)
290
+ def _path_note(link):
291
+ if link:
292
+ where = os.path.dirname(link).replace(os.path.expanduser("~"), "~", 1)
293
+ print(f" Added the `kompactor` command to {where}, so it works in any terminal.")
306
294
 
307
295
 
308
296
  def _pidfile():
@@ -336,12 +324,19 @@ def _kill_dashboard() -> bool:
336
324
 
337
325
 
338
326
  def cmd_start(a):
339
- """Turn compaction on and run the dashboard in the background on a free port; returns at once."""
327
+ """Turn Kompactor on: connect it to Claude Code (hooks, status line, shell prefix), make the
328
+ `kompactor` command reachable, and run the dashboard in the background on a free port.
329
+ Returns at once; running it again is safe."""
340
330
  (store.home() / "paused").unlink(missing_ok=True)
331
+ before = installer.status()
332
+ was_connected = before["plugin_enabled"] or before["hooks_installed"]
333
+ installer.install(statusline=config.read_file()["general"].get("statusline", True))
341
334
  st = installer.status()
342
- if not st["plugin_enabled"] and not st["hooks_installed"]:
343
- installer.install(statusline=config.read_file()["general"].get("statusline", True))
344
335
  print("✓ Kompactor is on: new Claude Code sessions are compacted.")
336
+ where = st["settings_file"].replace(os.path.expanduser("~"), "~", 1)
337
+ print(f" Connected via {'the Claude Code plugin' if st['plugin_enabled'] else where}")
338
+ _prefix_note(st)
339
+ _path_note(installer.link_on_path())
345
340
  d = _dashboard()
346
341
  if not d:
347
342
  from . import server
@@ -361,6 +356,8 @@ def cmd_start(a):
361
356
  d = {"pid": proc.pid, "url": f"http://127.0.0.1:{port}/"}
362
357
  _pidfile().write_text(json.dumps(d))
363
358
  print(f" Dashboard: {d['url']} (stop with `kompactor stop`)")
359
+ if not was_connected:
360
+ print(" Restart Claude Code so sessions that are already open use it too.")
364
361
  if not a.no_browser:
365
362
  import webbrowser
366
363
  webbrowser.open(d["url"])
@@ -478,6 +475,8 @@ def cmd_doctor(a):
478
475
 
479
476
  def main(argv=None):
480
477
  argv = sys.argv[1:] if argv is None else argv
478
+ if argv[:1] == ["setup"]: # the old name for `start`; older docs still say it
479
+ argv = ["start"] + ["--no-browser" if x == "--no-ui" else x for x in argv[1:]]
481
480
  if argv[:1] == ["prove"]: # has its own parser
482
481
  from . import prove
483
482
  return prove.main(argv[1:])
@@ -488,6 +487,18 @@ def main(argv=None):
488
487
  p = sp.add_parser("status", help="is it on, your level, savings so far, and how to use it (also: plain `kompactor`)")
489
488
  p.set_defaults(fn=cmd_status)
490
489
 
490
+ p = sp.add_parser("start", help="turn Kompactor on: connect it to Claude Code and open the dashboard")
491
+ p.add_argument("--port", type=int, default=0, help="preferred port (default: any free port)")
492
+ p.add_argument("--no-browser", action="store_true")
493
+ p.set_defaults(fn=cmd_start)
494
+
495
+ p = sp.add_parser("stop", help="pause Kompactor and close the dashboard (settings are kept)")
496
+ p.set_defaults(fn=cmd_stop)
497
+
498
+ p = sp.add_parser("uninstall", help="stop and remove Kompactor from Claude Code settings")
499
+ p.add_argument("--purge", action="store_true", help="also delete ~/.kompactor (history and config)")
500
+ p.set_defaults(fn=cmd_uninstall)
501
+
491
502
  p = sp.add_parser("estimate", help="replay past Claude Code sessions and show %% Kompactor would save")
492
503
  p.add_argument("--root", help="transcripts dir (default ~/.claude/projects)")
493
504
  p.add_argument("--project", help="only this project folder under the root")
@@ -499,29 +510,12 @@ def main(argv=None):
499
510
  p = sp.add_parser("gain", help="live savings recorded by the hooks")
500
511
  p.set_defaults(fn=cmd_gain)
501
512
 
502
- p = sp.add_parser("setup", help="one-step setup: enable for Claude Code (CLI + VS Code) and open the dashboard")
503
- p.add_argument("--no-ui", action="store_true")
504
- p.add_argument("--port", type=int, default=0)
505
- p.set_defaults(fn=cmd_setup)
506
-
507
513
  p = sp.add_parser("ui", help="open the settings & savings dashboard (foreground; see `start`)")
508
514
  p.add_argument("--port", type=int, default=7420)
509
515
  p.add_argument("--no-browser", action="store_true")
510
516
  p.add_argument("--exact-port", action="store_true", help=argparse.SUPPRESS)
511
517
  p.set_defaults(fn=cmd_ui)
512
518
 
513
- p = sp.add_parser("start", help="turn compaction on and run the dashboard in the background")
514
- p.add_argument("--port", type=int, default=0, help="preferred port (default: any free port)")
515
- p.add_argument("--no-browser", action="store_true")
516
- p.set_defaults(fn=cmd_start)
517
-
518
- p = sp.add_parser("stop", help="pause compaction and stop the background dashboard")
519
- p.set_defaults(fn=cmd_stop)
520
-
521
- p = sp.add_parser("uninstall", help="stop and remove Kompactor from Claude Code settings")
522
- p.add_argument("--purge", action="store_true", help="also delete ~/.kompactor (history and config)")
523
- p.set_defaults(fn=cmd_uninstall)
524
-
525
519
  p = sp.add_parser("install", help="add Kompactor hooks to Claude Code settings")
526
520
  p.add_argument("--project", action="store_true", help="write .claude/settings.json instead of ~/.claude")
527
521
  p.add_argument("--uninstall", action="store_true")
@@ -264,8 +264,9 @@ def pre_compact(event: dict, cfg: dict) -> None:
264
264
 
265
265
 
266
266
  def session_start(event: dict, cfg: dict) -> None:
267
- try: # so outputs can point at `~/.kompactor/bin/kompactor` even before `kompactor setup` (plugin installs)
267
+ try: # so outputs can point at `~/.kompactor/bin/kompactor` even before `kompactor start` (plugin installs)
268
268
  installer.write_shim(only_if_changed=True)
269
+ installer.link_on_path() # and so `kompactor` works in the user's own terminal too
269
270
  except OSError:
270
271
  pass
271
272
  if event.get("source") in ("compact", "clear"):
@@ -64,6 +64,43 @@ def write_shim(only_if_changed: bool = False) -> Path:
64
64
  f.chmod(0o755)
65
65
  return d / "kompactor"
66
66
 
67
+
68
+ # Where a `kompactor` command can be linked when pip put it in a folder that isn't on PATH.
69
+ PATH_DIRS = ("~/.local/bin", "~/bin", "/opt/homebrew/bin", "/usr/local/bin")
70
+
71
+
72
+ def link_on_path(path=None, dirs=None) -> str:
73
+ """Make `kompactor` work in any terminal. A pip install into a Python whose scripts folder isn't on
74
+ PATH leaves the command unreachable, so link the stable launcher into the first writable folder of
75
+ `dirs` that is already on PATH. Never edits shell files or replaces an existing command.
76
+ Returns the link it made, or ""."""
77
+ path = os.environ.get("PATH", "") if path is None else path
78
+ dirs = PATH_DIRS if dirs is None else dirs
79
+ if os.name == "nt" or shutil.which("kompactor", path=path):
80
+ return ""
81
+ on_path = {os.path.realpath(p) for p in path.split(os.pathsep) if p}
82
+ target = write_shim(only_if_changed=True)
83
+ for d in dirs:
84
+ d = os.path.expanduser(d)
85
+ link = Path(d, "kompactor")
86
+ if os.path.realpath(d) not in on_path or not os.access(d, os.W_OK) or link.exists() or link.is_symlink():
87
+ continue
88
+ try:
89
+ link.symlink_to(target)
90
+ except OSError:
91
+ continue
92
+ return str(link)
93
+ return ""
94
+
95
+
96
+ def unlink_from_path(dirs=None) -> None:
97
+ """Remove the links link_on_path made, and only those."""
98
+ target = str(shim_dir() / "kompactor")
99
+ for d in PATH_DIRS if dirs is None else dirs:
100
+ link = Path(os.path.expanduser(d), "kompactor")
101
+ if link.is_symlink() and os.readlink(link) == target:
102
+ link.unlink()
103
+
67
104
  PREFIX_ENV = "CLAUDE_CODE_SHELL_PREFIX"
68
105
  # Claude Code runs every Bash command as `kompactor-shell '<command>'`. Only commands that look like
69
106
  # tests, builds, linters or installs start Python; the rest (and everything, if Kompactor is gone)
@@ -186,16 +223,16 @@ PLUGIN_SKILL = {"cmd": "~/.kompactor/bin/kompactor",
186
223
 
187
224
  SKILL = """---
188
225
  name: kompactor
189
- description: Kompactor token saver and code graph. Use when the user says /kompactor (setup, start, stop, uninstall, status, a level name, review, audit, debt, graph), asks about token savings, or when you need to find code by topic, see who uses something, or check what a change affects.
226
+ description: Kompactor token saver and code graph. Use when the user says /kompactor (start, stop, uninstall, status, a level name, review, audit, debt, graph), asks about token savings, or when you need to find code by topic, see who uses something, or check what a change affects.
190
227
  ---
191
228
 
192
229
  Run these with Bash and report briefly. Kompactor token saver.{note}
193
230
 
194
231
  /kompactor status (or just /kompactor): run `{cmd} status` and summarise it in a few lines.
195
- /kompactor setup: run `{cmd} setup --no-ui` (adds the status line and the shell prefix that compacts failing commands, which a plugin can't set itself), report what it printed, and tell the user to restart Claude Code.
196
232
  Levels: `{cmd} presets`; change with `{cmd} config preset <N>` (1 Max quality, 2 Quality, 3 Balanced, 4 Savings, 5 Max savings; map words like "balanced" or "more savings").
197
- Savings: `{cmd} gain`. Dashboard: run `{cmd} start --no-browser` (returns at once, picks a free port) and give the user the URL it prints.
198
- /kompactor stop: `{cmd} stop` (pauses compaction, closes the dashboard). /kompactor start: `{cmd} start --no-browser`. /kompactor uninstall: `{cmd} uninstall`, then relay any extra command it prints.
233
+ /kompactor start: run `{cmd} start --no-browser` (turns Kompactor on: hooks, status line and the shell prefix that compacts failing commands, plus the dashboard on a free port), give the user the dashboard URL it prints, and if it says so, tell them to restart Claude Code.
234
+ /kompactor stop: `{cmd} stop` (pauses compaction, closes the dashboard). /kompactor uninstall: `{cmd} uninstall`, then relay any extra command it prints.
235
+ Savings: `{cmd} gain`.
199
236
 
200
237
  Code graph (local, instant):
201
238
  - `{cmd} graph query "words"` find code by topic; `{cmd} graph explain Name` one symbol, its users and tests
@@ -270,6 +307,7 @@ def install(scope: str = "user", project: str = "", statusline: bool = True, uni
270
307
  pass
271
308
  skill = skill_path(scope, project)
272
309
  if uninstall:
310
+ unlink_from_path()
273
311
  if skill.exists() and "Kompactor token saver" in skill.read_text():
274
312
  skill.unlink()
275
313
  try:
@@ -111,7 +111,7 @@ def run_once(task: dict, repo: Path, condition: str, work: Path, preset: int, mo
111
111
  settings.write_text(json.dumps(hook_settings()))
112
112
  args += ["--settings", str(settings)]
113
113
  tools += sorted({"Bash(kompactor:*)", f"Bash({installer.cli_name()}:*)"})
114
- prefix = run_dir / "kompactor-shell" # what `kompactor setup` installs as ~/.kompactor/bin/kompactor-shell
114
+ prefix = run_dir / "kompactor-shell" # what `kompactor start` installs as ~/.kompactor/bin/kompactor-shell
115
115
  prefix.write_text(installer.SHELL_PREFIX.format(py=shlex.quote(sys.executable or "python3"),
116
116
  script=shlex.quote(str(Path(installer.__file__).with_name("_launch.py")))))
117
117
  prefix.chmod(0o755)
@@ -134,15 +134,15 @@ svg.chev { width: 11px; height: 11px; stroke: var(--ink-3); fill: none; stroke-w
134
134
  <div class="card"><b>Claude Code plugin</b><span class="muted">Recommended. Run these in any Claude Code session, one at a time. The last one adds the status line and the shell prefix, which a plugin can't set itself.</span>
135
135
  <pre><code>/plugin marketplace add <span data-repo>your-org/kompactor</span>
136
136
  /plugin install amarkum@kompactor
137
- /kompactor setup</code></pre></div>
137
+ /kompactor start</code></pre></div>
138
138
  <div class="card"><b>pip / pipx / uv</b><span class="muted">macOS, Linux and Windows. Needs Python 3.9 or newer and nothing else.</span>
139
139
  <pre><code>pipx install kompactor
140
- kompactor setup</code></pre></div>
140
+ kompactor start</code></pre></div>
141
141
  <div class="card"><b>VS Code</b><span class="muted">Download the extension file from the repo's Releases page, then click <b>Enable</b> when Kompactor asks.</span>
142
- <pre><code>code --install-extension kompactor-0.7.8.vsix</code></pre></div>
142
+ <pre><code>code --install-extension kompactor-0.8.0.vsix</code></pre></div>
143
143
  </div>
144
144
  <p class="muted">Windows: run <code>.\kompactor\install.ps1</code> from a clone, or use the VS Code extension. The CLI and the VS Code extension read the same <code>~/.claude/settings.json</code>, so one install covers both. A backup of that file is kept as <code>settings.json.kompactor-backup</code>.</p>
145
- <p class="muted">Setup adds hooks, a status line (if you don't have one) and, on macOS and Linux, Claude Code's <code>CLAUDE_CODE_SHELL_PREFIX</code> setting pointing at <code>~/.kompactor/bin/kompactor-shell</code>, which is what lets Kompactor compact failing commands. It never replaces a status line or shell prefix you already have. Restart open Claude Code sessions after setup.</p>
145
+ <p class="muted"><code>kompactor start</code> adds hooks, a status line (if you don't have one) and, on macOS and Linux, Claude Code's <code>CLAUDE_CODE_SHELL_PREFIX</code> setting pointing at <code>~/.kompactor/bin/kompactor-shell</code>, which is what lets Kompactor compact failing commands. It never replaces a status line or shell prefix you already have. Restart open Claude Code sessions after setup.</p>
146
146
  <p>Open the dashboard any time with <code>kompactor start</code> (it runs in the background; <code>kompactor stop</code> turns Kompactor off), or <b>Kompactor: Open Dashboard</b> in VS Code. Its <b>Setup</b> page shows these commands with your repo filled in, ready to copy.</p>
147
147
  </section>
148
148
 
@@ -152,8 +152,8 @@ kompactor setup</code></pre></div>
152
152
  <div class="tbl"><table>
153
153
  <tr><th>Way</th><th>Who it's for</th><th>What each person does</th><th>Updating</th></tr>
154
154
  <tr><td><b>Plugin</b></td><td>Everyone on Claude Code, CLI or VS Code</td><td>The three plugin commands under Install, once</td><td>Automatic with <code>autoUpdate</code> (below); or <code>claude plugin marketplace update kompactor</code>, then <code>claude plugin update amarkum@kompactor</code></td></tr>
155
- <tr><td><b>Project settings</b></td><td>Everyone who works in a given repo</td><td>Trust the project folder when Claude Code asks, then <code>/kompactor setup</code> once; you commit the snippet below</td><td>Same as the plugin</td></tr>
156
- <tr><td><b>pip / pipx / uv</b></td><td>People who manage Python tools that way</td><td><code>pipx install kompactor</code>, then <code>kompactor setup</code></td><td><code>pipx upgrade kompactor</code></td></tr>
155
+ <tr><td><b>Project settings</b></td><td>Everyone who works in a given repo</td><td>Trust the project folder when Claude Code asks, then <code>/kompactor start</code> once; you commit the snippet below</td><td>Same as the plugin</td></tr>
156
+ <tr><td><b>pip / pipx / uv</b></td><td>People who manage Python tools that way</td><td><code>pipx install kompactor</code>, then <code>kompactor start</code></td><td><code>pipx upgrade kompactor</code></td></tr>
157
157
  <tr><td><b>Terminal install</b></td><td>Scripted machine setup, or people who don't use plugins</td><td><code>git clone</code>, then <code>./kompactor/install.sh</code></td><td><code>git pull</code>, then run <code>./install.sh</code> again</td></tr>
158
158
  <tr><td><b>VS Code extension file</b></td><td>VS Code users who want the status bar and dashboard inside VS Code</td><td>Install the <code>.vsix</code> from Releases</td><td>Install the newer <code>.vsix</code></td></tr>
159
159
  </table></div>
@@ -165,7 +165,7 @@ kompactor setup</code></pre></div>
165
165
  },
166
166
  "enabledPlugins": { "amarkum@kompactor": true }
167
167
  }</code></pre>
168
- <p class="muted">When a teammate opens the project and accepts Claude Code's prompt to trust the folder, Claude Code adds the marketplace and turns the plugin on. Each person then runs <code>/kompactor setup</code> once (plugins can't set the status line or the shell prefix themselves). <code>autoUpdate</code> keeps everyone on your latest release: teammates get a new version when <code>version</code> in <code>.claude-plugin/plugin.json</code> changes, and <code>python scripts/bump_version.py 0.4.1</code> bumps it everywhere.</p>
168
+ <p class="muted">When a teammate opens the project and accepts Claude Code's prompt to trust the folder, Claude Code adds the marketplace and turns the plugin on. Each person then runs <code>/kompactor start</code> once (plugins can't set the status line or the shell prefix themselves). <code>autoUpdate</code> keeps everyone on your latest release: teammates get a new version when <code>version</code> in <code>.claude-plugin/plugin.json</code> changes, and <code>python scripts/bump_version.py 0.4.1</code> bumps it everywhere.</p>
169
169
  <h3>Private-repo access</h3>
170
170
  <p>Claude Code uses each person's existing git login and can't prompt for a password. An SSH key that works with GitHub is enough. Without one, run <code>gh auth login</code> and <code>gh auth setup-git</code>, and set <code>CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1</code>.</p>
171
171
  <h3>Set the team's level for a repo</h3>
@@ -722,9 +722,9 @@ function renderSetup() {
722
722
  const group = (label, ...codes) => `<div class="share-group"><div class="lbl">${label}</div>${codes.join("")}</div>`;
723
723
  const teamSettings = JSON.stringify({ extraKnownMarketplaces: { kompactor: { source: m.includes("://") ? { source: "git", url: clone } : { source: "github", repo: m }, autoUpdate: true } }, enabledPlugins: { "amarkum@kompactor": true } }, null, 2);
724
724
  $("snips").innerHTML =
725
- group("Claude Code plugin: run these in any Claude Code session, one at a time", code(`/plugin marketplace add ${m}`), code("/plugin install amarkum@kompactor"), code("/kompactor setup")) +
726
- group(`Everyone on a project: commit this as <span class="mono">.claude/settings.json</span>; Claude Code turns the plugin on once a teammate trusts the folder, then they run <span class="mono">/kompactor setup</span>`, code(teamSettings, true)) +
727
- group("pip, pipx or uv (from PyPI)", code("pipx install kompactor"), code("kompactor setup")) +
725
+ group("Claude Code plugin: run these in any Claude Code session, one at a time", code(`/plugin marketplace add ${m}`), code("/plugin install amarkum@kompactor"), code("/kompactor start")) +
726
+ group(`Everyone on a project: commit this as <span class="mono">.claude/settings.json</span>; Claude Code turns the plugin on once a teammate trusts the folder, then they run <span class="mono">/kompactor start</span>`, code(teamSettings, true)) +
727
+ group("pip, pipx or uv (from PyPI)", code("pipx install kompactor"), code("kompactor start")) +
728
728
  group("Terminal (macOS, Linux), from a clone", code(`git clone ${clone} && ./${dir}/install.sh`)) +
729
729
  group(`VS Code: download the <span class="mono">.vsix</span> from the repo's GitHub Releases, then click Enable`, code(`code --install-extension kompactor-${S.version}.vsix`));
730
730
  $("snips").querySelectorAll("[data-copy]").forEach((b) => (b.onclick = async () => { try { await navigator.clipboard.writeText(b.dataset.copy); toast("Copied"); } catch (e) { toast("Select the text to copy it"); } }));
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kompactor
3
- Version: 0.7.8
3
+ Version: 0.8.0
4
4
  Summary: Cut the tokens Claude Code spends on noise: compacted command output (failing runs included), outline-first reads, a local code graph, and per-turn savings.
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/amarkum/kompactor
@@ -112,17 +112,18 @@ Pick one. All of them set up the same thing, and the Claude Code CLI and VS Code
112
112
  ```
113
113
  /plugin marketplace add amarkum/kompactor
114
114
  /plugin install amarkum@kompactor
115
- /kompactor setup
115
+ /kompactor start
116
116
  ```
117
- The last step adds the status line and the shell prefix that compacts failing commands, which a plugin can't set itself. Then restart Claude Code.
117
+ The last step turns Kompactor on: it adds the status line and the shell prefix that compacts failing commands (a plugin can't set those itself) and opens the dashboard. Then restart Claude Code.
118
118
 
119
119
  **pip / pipx / uv** (macOS, Linux, Windows):
120
120
  ```bash
121
121
  pipx install kompactor # or: pip install kompactor · uv tool install kompactor
122
- kompactor setup
122
+ kompactor start
123
123
  ```
124
+ If your shell says `kompactor: command not found` (pip put the command in a folder that isn't on your PATH), run `python3 -m kompactor start` once. It links `kompactor` into a folder that is already on your PATH, such as `~/.local/bin`, so the command works in every terminal from then on.
124
125
 
125
- **VS Code.** Download `kompactor-0.7.8.vsix` from [Releases](https://github.com/amarkum/kompactor/releases), install it (Extensions › `⋯` › *Install from VSIX…*), and click **Enable** when Kompactor asks.
126
+ **VS Code.** Download `kompactor-0.8.0.vsix` from [Releases](https://github.com/amarkum/kompactor/releases), install it (Extensions › `⋯` › *Install from VSIX…*), and click **Enable** when Kompactor asks.
126
127
 
127
128
  **From source:**
128
129
  ```bash
@@ -135,12 +136,12 @@ git clone https://github.com/amarkum/kompactor.git && ./kompactor/install.sh
135
136
  2. **Work as usual.** You don't call Kompactor; it acts on Claude's tool calls by itself. After each reply you'll see a line like `Kompactor: −8.2k tokens this turn`, and the status line shows the running total.
136
137
  3. **Check it's on:** run `kompactor` in a terminal (or `/kompactor` in Claude Code):
137
138
  ```
138
- Kompactor 0.7.8: ON
139
+ Kompactor 0.8.0: ON
139
140
  Connected via the Claude Code plugin. New Claude Code sessions are compacted.
140
141
  Level: Balanced (level 3 of 5). Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced
141
142
  Saved so far: 41.3k tokens (−38%) over 52 tool calls. Details: `kompactor gain`
142
143
  ```
143
- 4. **Open the dashboard:** `kompactor start` runs it in the background on a free port and prints the address.
144
+ 4. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
144
145
 
145
146
  ## How it works
146
147
 
@@ -186,10 +187,10 @@ Ask Claude Code the way you normally would. These prompts come from the [evidenc
186
187
 
187
188
  | Command | What it does |
188
189
  |---|---|
190
+ | `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code) and open the dashboard on a free port |
191
+ | `kompactor stop` | Pause it and close the dashboard; settings are kept |
192
+ | `kompactor uninstall [--purge]` | Remove it from Claude Code (`--purge` also deletes `~/.kompactor`) |
189
193
  | `kompactor` / `kompactor status` | On or off, level, savings, how it works |
190
- | `kompactor setup` | Connect to Claude Code (CLI + VS Code) and open the dashboard |
191
- | `kompactor start` / `kompactor stop` | Turn on (dashboard in the background, free port) / pause |
192
- | `kompactor uninstall [--purge]` | Remove from Claude Code (`--purge` also deletes `~/.kompactor`) |
193
194
  | `kompactor presets` · `kompactor config preset 4` | List levels · change level |
194
195
  | `kompactor config <setting> <value>` | Change one [setting](#settings) |
195
196
  | `kompactor gain` | Savings so far |
@@ -224,7 +225,7 @@ Settings come from, in increasing priority: the level → your global choices
224
225
  | Setting | Type | What it does |
225
226
  |---|---|---|
226
227
  | `bash` | bool | Compact command output |
227
- | `bash_wrap` | bool | Compact failing commands too (needs the shell prefix from `kompactor setup`) |
228
+ | `bash_wrap` | bool | Compact failing commands too (needs the shell prefix that `kompactor start` adds) |
228
229
  | `bash_plain` | bool | Ask Claude to run commands without `\| head`, `\| tail` or `\| grep`, since Kompactor keeps every failure |
229
230
  | `bash_min_tokens` | int | Leave outputs smaller than this untouched |
230
231
  | `bash_max_lines` | int | Max lines kept per output (head and tail kept; error lines from the middle always kept) |
@@ -306,7 +307,7 @@ kompactor graph unused dead-code candidates
306
307
  "enabledPlugins": { "amarkum@kompactor": true }
307
308
  }
308
309
  ```
309
- When a teammate trusts the folder, Claude Code installs the plugin; each person then runs `/kompactor setup` once. `autoUpdate` keeps everyone on the latest release. Admins can put the same keys in Claude Code's managed settings to roll it out to every machine, and a team that runs its own fork sets `KOMPACTOR_REPO` so the dashboard shows the fork's commands.
310
+ When a teammate trusts the folder, Claude Code installs the plugin; each person then runs `/kompactor start` once. `autoUpdate` keeps everyone on the latest release. Admins can put the same keys in Claude Code's managed settings to roll it out to every machine, and a team that runs its own fork sets `KOMPACTOR_REPO` so the dashboard shows the fork's commands.
310
311
 
311
312
  ## Evidence
312
313
 
@@ -369,13 +370,13 @@ Command output from any language is compacted. These languages also get language
369
370
 
370
371
  Everything below happens on your machine. Kompactor makes no network requests of its own and has no telemetry. (If you install the optional `tiktoken` package for exact token counts, tiktoken downloads its token table once, on first use.)
371
372
 
372
- **What it runs.** Python hooks that Claude Code calls (`python3 kompactor/_launch.py hook <name>` from the plugin folder): after Bash, Read, Grep, Glob and edit tool calls; before Read; at session start, subagent start and before compaction; and when a turn ends. After `/kompactor setup` on macOS and Linux, Claude's Bash commands run through Kompactor's shell prefix (`~/.kompactor/bin/kompactor-shell`) so failing runs can be compacted too. The prefix runs after Claude Code's permission check, on Claude's original command, and returns its exit code unchanged.
373
+ **What it runs.** Python hooks that Claude Code calls (`python3 kompactor/_launch.py hook <name>` from the plugin folder): after Bash, Read, Grep, Glob and edit tool calls; before Read; at session start, subagent start and before compaction; and when a turn ends. After `kompactor start` on macOS and Linux, Claude's Bash commands run through Kompactor's shell prefix (`~/.kompactor/bin/kompactor-shell`) so failing runs can be compacted too. The prefix runs after Claude Code's permission check, on Claude's original command, and returns its exit code unchanged.
373
374
 
374
375
  **What it adds to Claude's context.** Compacted tool output, outlines in place of large file reads, a code map once per session, a one-line savings note after each turn, and short reply rules at session start and for subagents. The rules are plain text you can read in [`kompactor/rules.py`](https://github.com/amarkum/kompactor/blob/main/kompactor/rules.py).
375
376
 
376
377
  **What it reads.** The tool output Claude Code passes to its hooks, the files Claude reads (to outline them), your project's source (for the code graph), and the context size Claude Code gives the status line. Hooks never read your session transcripts. `kompactor estimate` and the dashboard's **Replay your history** panel read your local Claude Code session logs in `~/.claude/projects` only when you run them; the result isn't stored or sent anywhere.
377
378
 
378
- **What it writes.** `~/.kompactor/`: settings, the savings ledger, raw copies of shortened output (for `kompactor show`), the code graph index and the `~/.kompactor/bin/` launchers. History is deleted after 30 days by default. Setup edits `~/.claude/settings.json` to add Kompactor's hooks (non-plugin installs), a status line (only if you have none) and `CLAUDE_CODE_SHELL_PREFIX` (only if it isn't set), keeping a backup in `settings.json.kompactor-backup`; non-plugin installs also get the `/kompactor` skill in `~/.claude/skills`. Nothing is written to your repositories.
379
+ **What it writes.** `~/.kompactor/`: settings, the savings ledger, raw copies of shortened output (for `kompactor show`), the code graph index and the `~/.kompactor/bin/` launchers. When `kompactor` isn't on your PATH, it adds one link to that launcher in a writable folder that already is (`~/.local/bin`, `~/bin`, `/opt/homebrew/bin` or `/usr/local/bin`); it never edits shell files or replaces an existing command, and `kompactor uninstall` removes the link. History is deleted after 30 days by default. `kompactor start` edits `~/.claude/settings.json` to add Kompactor's hooks (non-plugin installs), a status line (only if you have none) and `CLAUDE_CODE_SHELL_PREFIX` (only if it isn't set), keeping a backup in `settings.json.kompactor-backup`; non-plugin installs also get the `/kompactor` skill in `~/.claude/skills`. Nothing is written to your repositories.
379
380
 
380
381
  **What it never does.** Change your permission rules or sandbox settings, change what a command does, or send your code or output anywhere. Details: [privacy policy](https://github.com/amarkum/kompactor/blob/main/PRIVACY.md).
381
382
 
@@ -383,7 +384,8 @@ Everything below happens on your machine. Kompactor makes no network requests of
383
384
 
384
385
  | Problem | What to do |
385
386
  |---|---|
386
- | No savings line after replies | Restart Claude Code after setup, then run `kompactor doctor`: it checks the installation and shows recent hook errors. The dashboard's **Self-test** panel runs every hook once. |
387
+ | `kompactor: command not found` | pip put the command in a folder that isn't on your PATH. Run `python3 -m kompactor start` once: it links `kompactor` into a writable folder already on your PATH, such as `~/.local/bin`. Claude Code plugin installs do this at the first session. |
388
+ | No savings line after replies | Restart Claude Code after `kompactor start`, then run `kompactor doctor`: it checks the installation and shows recent hook errors. The dashboard's **Self-test** panel runs every hook once. |
387
389
  | An output looks too short | Claude can fetch the original with `kompactor show <id>`, or search earlier outputs with `kompactor search "text"`. |
388
390
  | A command should never be shortened | Add it to **Never compact these commands** on the dashboard, or to `never_compact` in `.kompactor.json`. For a single run, start the command with `KOMPACTOR_RAW=1`. |
389
391
  | Something seems off | `kompactor stop` turns Kompactor off at once; every hook also lets the original output through if it hits an error. Errors are logged to `~/.kompactor/hook-errors.log`. |
@@ -455,5 +457,3 @@ Bug reports, ideas and pull requests are welcome. See [CONTRIBUTING.md](https://
455
457
  ## License
456
458
 
457
459
  [MIT](https://github.com/amarkum/kompactor/blob/main/LICENSE) © The Kompactor authors. The dashboard uses the IBM Plex fonts under the [SIL Open Font License](https://github.com/amarkum/kompactor/blob/main/kompactor/static/fonts/OFL.txt).
458
-
459
- Built by [stackcone](https://stackcone.com). Read the story behind it: [Kompactor: Cut the Tokens Claude Code Spends on Noise](https://stackcone.com/blog/posts/kompactor-claude-code-token-saver/).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kompactor"
7
- version = "0.7.8"
7
+ version = "0.8.0"
8
8
  description = "Cut the tokens Claude Code spends on noise: compacted command output (failing runs included), outline-first reads, a local code graph, and per-turn savings."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -11,7 +11,8 @@ from pathlib import Path
11
11
 
12
12
  os.environ.setdefault("KOMPACTOR_HOME", tempfile.mkdtemp())
13
13
 
14
- from kompactor import config, graph, hooks # noqa: E402
14
+ from kompactor import config, graph, hooks, installer # noqa: E402
15
+ installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from tests
15
16
 
16
17
 
17
18
  def make_repo(files: dict) -> str:
@@ -12,6 +12,7 @@ TMP = tempfile.mkdtemp()
12
12
  os.environ["KOMPACTOR_HOME"] = os.path.join(TMP, "home")
13
13
 
14
14
  from kompactor import config, estimate, filters, hooks, installer, langs, outline, server, store, tokens # noqa: E402
15
+ installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from tests
15
16
 
16
17
 
17
18
  def run_hook(name, event):
@@ -565,6 +566,24 @@ class SourceTests(unittest.TestCase):
565
566
  self.assertEqual(installer.parse_source(ssh)["clone"], ssh)
566
567
  self.assertEqual(installer.parse_source(""), {})
567
568
 
569
+ def test_command_linked_onto_path_when_missing(self):
570
+ from unittest import mock
571
+ tmp = Path(tempfile.mkdtemp())
572
+ on_path, off_path, shim = tmp / "bin", tmp / "elsewhere", tmp / "shim"
573
+ on_path.mkdir(); off_path.mkdir()
574
+ with mock.patch.object(installer, "shim_dir", return_value=shim):
575
+ # only a writable folder that is already on PATH gets the link
576
+ link = installer.link_on_path(path=str(on_path), dirs=(str(off_path), str(on_path)))
577
+ self.assertEqual(link, str(on_path / "kompactor"))
578
+ self.assertEqual(os.readlink(link), str(shim / "kompactor"))
579
+ self.assertEqual(installer.link_on_path(path=str(on_path), dirs=(str(on_path),)), "") # already there
580
+ installer.unlink_from_path(dirs=(str(on_path),))
581
+ self.assertFalse(Path(link).is_symlink())
582
+ (on_path / "kompactor").write_text("someone else's") # never replaced
583
+ self.assertEqual(installer.link_on_path(path=str(on_path), dirs=(str(on_path),)), "")
584
+ installer.unlink_from_path(dirs=(str(on_path),))
585
+ self.assertTrue((on_path / "kompactor").exists())
586
+
568
587
  def test_source_defaults_to_the_public_repo(self):
569
588
  self.assertEqual(installer.source("")["marketplace"], "amarkum/kompactor")
570
589
  self.assertEqual(installer.source("acme/kompactor")["clone"], "https://github.com/acme/kompactor.git") # a fork
@@ -20,6 +20,7 @@ ROOT = Path(__file__).resolve().parent.parent
20
20
  sys.path.insert(0, str(ROOT))
21
21
 
22
22
  from kompactor import filters, hooks, installer, shellwrap, tokens # noqa: E402
23
+ installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from tests
23
24
 
24
25
  PASSING = "".join(f"tests/test_mod.py::test_case_{i} PASSED{' ' * 30}[{i // 5:3d}%]\n" for i in range(500))
25
26
  FAILURE = ("=================================== FAILURES ===================================\n"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes