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.
- {kompactor-0.7.8 → kompactor-0.8.0}/PKG-INFO +17 -17
- {kompactor-0.7.8 → kompactor-0.8.0}/README.md +16 -16
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/__init__.py +1 -1
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/cli.py +32 -38
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/hooks.py +2 -1
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/installer.py +42 -4
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/prove.py +1 -1
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/usage.html +7 -7
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/ui.html +3 -3
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/PKG-INFO +17 -17
- {kompactor-0.7.8 → kompactor-0.8.0}/pyproject.toml +1 -1
- {kompactor-0.7.8 → kompactor-0.8.0}/tests/test_graph.py +2 -1
- {kompactor-0.7.8 → kompactor-0.8.0}/tests/test_kompactor.py +19 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/tests/test_shell.py +1 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/LICENSE +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/__main__.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/_launch.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/config.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/estimate.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/filters.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/graph.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/langs.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/outline.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/rules.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/samples.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/server.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/shellwrap.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/OFL.txt +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-mono-400.woff2 +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-mono-500.woff2 +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-sans-400.woff2 +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-sans-500.woff2 +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/fonts/plex-sans-600.woff2 +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/static/logo-mark.svg +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/store.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor/tokens.py +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/SOURCES.txt +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/dependency_links.txt +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/entry_points.txt +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/requires.txt +0 -0
- {kompactor-0.7.8 → kompactor-0.8.0}/kompactor.egg-info/top_level.txt +0 -0
- {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.
|
|
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
|
|
115
|
+
/kompactor start
|
|
116
116
|
```
|
|
117
|
-
The last step adds the status line and the shell prefix that compacts failing commands
|
|
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
|
|
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.
|
|
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.
|
|
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. **
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
|
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
|
|
82
|
+
/kompactor start
|
|
83
83
|
```
|
|
84
|
-
The last step adds the status line and the shell prefix that compacts failing commands
|
|
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
|
|
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.
|
|
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.
|
|
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. **
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
|
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/).
|
|
@@ -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
|
|
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
|
|
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
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
|
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
|
|
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 (
|
|
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
|
-
|
|
198
|
-
/kompactor stop: `{cmd} stop` (pauses compaction, closes the dashboard). /kompactor
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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">
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
727
|
-
group("pip, pipx or uv (from PyPI)", code("pipx install kompactor"), code("kompactor
|
|
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.
|
|
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
|
|
115
|
+
/kompactor start
|
|
116
116
|
```
|
|
117
|
-
The last step adds the status line and the shell prefix that compacts failing commands
|
|
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
|
|
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.
|
|
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.
|
|
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. **
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
|
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
|
+
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
|
|
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
|
|
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
|
|
File without changes
|