kompactor 0.8.1__tar.gz → 0.8.2__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.
- {kompactor-0.8.1 → kompactor-0.8.2}/PKG-INFO +15 -10
- {kompactor-0.8.1 → kompactor-0.8.2}/README.md +14 -9
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/__init__.py +1 -1
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/cli.py +27 -8
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/installer.py +62 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/usage.html +1 -1
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/store.py +43 -0
- kompactor-0.8.2/kompactor/vsix/kompactor-0.8.2.vsix +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor.egg-info/PKG-INFO +15 -10
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor.egg-info/SOURCES.txt +1 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/pyproject.toml +3 -2
- {kompactor-0.8.1 → kompactor-0.8.2}/tests/test_graph.py +1 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/tests/test_kompactor.py +24 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/tests/test_shell.py +1 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/LICENSE +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/__main__.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/_launch.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/config.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/estimate.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/filters.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/graph.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/hooks.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/langs.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/outline.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/prove.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/rules.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/samples.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/server.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/shellwrap.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/fonts/OFL.txt +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/fonts/plex-mono-400.woff2 +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/fonts/plex-mono-500.woff2 +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/fonts/plex-sans-400.woff2 +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/fonts/plex-sans-500.woff2 +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/fonts/plex-sans-600.woff2 +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/static/logo-mark.svg +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/tokens.py +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor/ui.html +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor.egg-info/dependency_links.txt +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor.egg-info/entry_points.txt +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor.egg-info/requires.txt +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/kompactor.egg-info/top_level.txt +0 -0
- {kompactor-0.8.1 → kompactor-0.8.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kompactor
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
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
|
|
@@ -98,7 +98,7 @@ Measured in 54 real Claude Code sessions on Flask, Cobra, SWR, ky and zustand at
|
|
|
98
98
|
- **Outline-first file reads.** Big source files arrive as an outline (symbols, line ranges, who imports the file, which tests cover it). Claude reads just the ranges it needs; repeating the read returns the whole file.
|
|
99
99
|
- **Local code graph.** Find code by topic, see callers, the impact of a change and the tests to run, for Python, Go, TypeScript, JavaScript and React.
|
|
100
100
|
- **Terse replies and lean code.** Short, readable rules for answer-first prose and smallest-diff code, from 0 to 177 tokens depending on the level.
|
|
101
|
-
- **Per-turn savings.** In the reply, the status line,
|
|
101
|
+
- **Per-turn savings, in tokens and dollars.** In the reply, the status line, a VS Code / Cursor sidebar (per session, per project and per turn) and a local dashboard. Numbers are conservative and never count output Claude wouldn't have read.
|
|
102
102
|
- **One dial for quality vs tokens.** Five levels, every option adjustable, per project, with a live preview of exactly what Claude would see.
|
|
103
103
|
- **Nothing is lost.** Every shortened output keeps a raw copy (`kompactor show <id>`), and every hook fails open.
|
|
104
104
|
- **Private and dependency-free.** Python 3.9+ standard library only. Runs locally, sends nothing anywhere, no telemetry.
|
|
@@ -123,7 +123,7 @@ kompactor start
|
|
|
123
123
|
```
|
|
124
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.
|
|
125
125
|
|
|
126
|
-
**VS Code.**
|
|
126
|
+
**VS Code and Cursor.** `kompactor start` adds the Kompactor extension to VS Code and Cursor automatically when they're installed (skip it with `--no-editor`); reload the window and a **Kompactor** icon appears in the activity bar. To install it by hand, download `kompactor-0.8.2.vsix` from [Releases](https://github.com/amarkum/kompactor/releases) and use Extensions › `⋯` › *Install from VSIX…*.
|
|
127
127
|
|
|
128
128
|
**From source:**
|
|
129
129
|
```bash
|
|
@@ -136,12 +136,13 @@ git clone https://github.com/amarkum/kompactor.git && ./kompactor/install.sh
|
|
|
136
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.
|
|
137
137
|
3. **Check it's on:** run `kompactor` in a terminal (or `/kompactor` in Claude Code):
|
|
138
138
|
```
|
|
139
|
-
Kompactor 0.8.
|
|
139
|
+
Kompactor 0.8.2: ON
|
|
140
140
|
Connected via the Claude Code plugin. New Claude Code sessions are compacted.
|
|
141
141
|
Level: Balanced (level 3 of 5). Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced
|
|
142
142
|
Saved so far: 41.3k tokens (−38%) over 52 tool calls. Details: `kompactor gain`
|
|
143
143
|
```
|
|
144
|
-
4. **
|
|
144
|
+
4. **In VS Code or Cursor:** click the **Kompactor** icon in the activity bar for tokens and estimated dollars saved this session, in this project, today and over 30 days, plus what every recent turn saved.
|
|
145
|
+
5. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
|
|
145
146
|
|
|
146
147
|
## How it works
|
|
147
148
|
|
|
@@ -187,9 +188,9 @@ Ask Claude Code the way you normally would. These prompts come from the [evidenc
|
|
|
187
188
|
|
|
188
189
|
| Command | What it does |
|
|
189
190
|
|---|---|
|
|
190
|
-
| `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code) and open the dashboard on a free port |
|
|
191
|
+
| `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code), add the extension to VS Code and Cursor, and open the dashboard on a free port |
|
|
191
192
|
| `kompactor stop` | Pause it and close the dashboard; settings are kept |
|
|
192
|
-
| `kompactor uninstall
|
|
193
|
+
| `kompactor uninstall` | Remove it from Claude Code and from VS Code / Cursor, and delete its data (`--keep-data` keeps `~/.kompactor`) |
|
|
193
194
|
| `kompactor` / `kompactor status` | On or off, level, savings, how it works |
|
|
194
195
|
| `kompactor presets` · `kompactor config preset 4` | List levels · change level |
|
|
195
196
|
| `kompactor config <setting> <value>` | Change one [setting](#settings) |
|
|
@@ -272,7 +273,8 @@ Commit a `.kompactor.json` next to the code to give everyone the same level and
|
|
|
272
273
|
|---|---|
|
|
273
274
|
| After each reply | `Kompactor: −8.2k tokens this turn (13.1k › 4.9k, −63%) · session −41k · context ≈31% smaller` |
|
|
274
275
|
| CLI status line | `Kompactor −41.3k · ctx −31% · last turn −8.2k · Balanced` |
|
|
275
|
-
| VS Code status bar |
|
|
276
|
+
| VS Code / Cursor status bar | Tokens and ≈ dollars saved this session; hover for details |
|
|
277
|
+
| VS Code / Cursor sidebar | Kompactor icon in the activity bar: this session, this project, today and 30 days in tokens and dollars, recent turns (saved or "nothing to trim"), biggest wins |
|
|
276
278
|
| Dashboard (`kompactor start`) | Per-turn chart, biggest wins, savings by feature and by project |
|
|
277
279
|
| `kompactor gain` | The same numbers in the terminal |
|
|
278
280
|
| `kompactor estimate` | Replays your **past** sessions and shows what Kompactor would have saved |
|
|
@@ -376,7 +378,7 @@ Everything below happens on your machine. Kompactor makes no network requests of
|
|
|
376
378
|
|
|
377
379
|
**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.
|
|
378
380
|
|
|
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.
|
|
381
|
+
**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`. When VS Code or Cursor is installed, `kompactor start` adds the Kompactor extension to them with their own `code` / `cursor` command (from a copy inside the package; nothing is downloaded), and `kompactor uninstall` removes it and deletes `~/.kompactor`. Nothing is written to your repositories.
|
|
380
382
|
|
|
381
383
|
**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).
|
|
382
384
|
|
|
@@ -395,7 +397,7 @@ Everything below happens on your machine. Kompactor makes no network requests of
|
|
|
395
397
|
```bash
|
|
396
398
|
kompactor stop # pause: output passes through untouched; settings are kept
|
|
397
399
|
kompactor start # turn it back on
|
|
398
|
-
kompactor uninstall # remove hooks, status line, shell prefix and
|
|
400
|
+
kompactor uninstall # remove hooks, status line, shell prefix, skill and editor extension, and delete ~/.kompactor
|
|
399
401
|
```
|
|
400
402
|
Then remove the package the way you installed it: `claude plugin uninstall amarkum@kompactor`, `pipx uninstall kompactor`, or uninstall the extension in VS Code.
|
|
401
403
|
|
|
@@ -419,6 +421,9 @@ The hooks are Claude Code-specific, but `kompactor run -- <command>` and `kompac
|
|
|
419
421
|
**How much latency does it add?**
|
|
420
422
|
About 50–100 ms per hook, because the filters run in Python.
|
|
421
423
|
|
|
424
|
+
**How are the dollar figures worked out?**
|
|
425
|
+
They're estimates at an input-token price you set (`kompactor.pricePerMillionTokens` in VS Code, default $3 per million). Each token kept out of the context is counted once as a prompt-cache write (1.25× the input price) and once more at the cache-read price (0.1×) for every later turn in that session that would have re-read it.
|
|
426
|
+
|
|
422
427
|
**Is it free?**
|
|
423
428
|
Yes. MIT-licensed, no account, no paid tier.
|
|
424
429
|
|
|
@@ -65,7 +65,7 @@ Measured in 54 real Claude Code sessions on Flask, Cobra, SWR, ky and zustand at
|
|
|
65
65
|
- **Outline-first file reads.** Big source files arrive as an outline (symbols, line ranges, who imports the file, which tests cover it). Claude reads just the ranges it needs; repeating the read returns the whole file.
|
|
66
66
|
- **Local code graph.** Find code by topic, see callers, the impact of a change and the tests to run, for Python, Go, TypeScript, JavaScript and React.
|
|
67
67
|
- **Terse replies and lean code.** Short, readable rules for answer-first prose and smallest-diff code, from 0 to 177 tokens depending on the level.
|
|
68
|
-
- **Per-turn savings.** In the reply, the status line,
|
|
68
|
+
- **Per-turn savings, in tokens and dollars.** In the reply, the status line, a VS Code / Cursor sidebar (per session, per project and per turn) and a local dashboard. Numbers are conservative and never count output Claude wouldn't have read.
|
|
69
69
|
- **One dial for quality vs tokens.** Five levels, every option adjustable, per project, with a live preview of exactly what Claude would see.
|
|
70
70
|
- **Nothing is lost.** Every shortened output keeps a raw copy (`kompactor show <id>`), and every hook fails open.
|
|
71
71
|
- **Private and dependency-free.** Python 3.9+ standard library only. Runs locally, sends nothing anywhere, no telemetry.
|
|
@@ -90,7 +90,7 @@ kompactor start
|
|
|
90
90
|
```
|
|
91
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.
|
|
92
92
|
|
|
93
|
-
**VS Code.**
|
|
93
|
+
**VS Code and Cursor.** `kompactor start` adds the Kompactor extension to VS Code and Cursor automatically when they're installed (skip it with `--no-editor`); reload the window and a **Kompactor** icon appears in the activity bar. To install it by hand, download `kompactor-0.8.2.vsix` from [Releases](https://github.com/amarkum/kompactor/releases) and use Extensions › `⋯` › *Install from VSIX…*.
|
|
94
94
|
|
|
95
95
|
**From source:**
|
|
96
96
|
```bash
|
|
@@ -103,12 +103,13 @@ git clone https://github.com/amarkum/kompactor.git && ./kompactor/install.sh
|
|
|
103
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.
|
|
104
104
|
3. **Check it's on:** run `kompactor` in a terminal (or `/kompactor` in Claude Code):
|
|
105
105
|
```
|
|
106
|
-
Kompactor 0.8.
|
|
106
|
+
Kompactor 0.8.2: ON
|
|
107
107
|
Connected via the Claude Code plugin. New Claude Code sessions are compacted.
|
|
108
108
|
Level: Balanced (level 3 of 5). Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced
|
|
109
109
|
Saved so far: 41.3k tokens (−38%) over 52 tool calls. Details: `kompactor gain`
|
|
110
110
|
```
|
|
111
|
-
4. **
|
|
111
|
+
4. **In VS Code or Cursor:** click the **Kompactor** icon in the activity bar for tokens and estimated dollars saved this session, in this project, today and over 30 days, plus what every recent turn saved.
|
|
112
|
+
5. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
|
|
112
113
|
|
|
113
114
|
## How it works
|
|
114
115
|
|
|
@@ -154,9 +155,9 @@ Ask Claude Code the way you normally would. These prompts come from the [evidenc
|
|
|
154
155
|
|
|
155
156
|
| Command | What it does |
|
|
156
157
|
|---|---|
|
|
157
|
-
| `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code) and open the dashboard on a free port |
|
|
158
|
+
| `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code), add the extension to VS Code and Cursor, and open the dashboard on a free port |
|
|
158
159
|
| `kompactor stop` | Pause it and close the dashboard; settings are kept |
|
|
159
|
-
| `kompactor uninstall
|
|
160
|
+
| `kompactor uninstall` | Remove it from Claude Code and from VS Code / Cursor, and delete its data (`--keep-data` keeps `~/.kompactor`) |
|
|
160
161
|
| `kompactor` / `kompactor status` | On or off, level, savings, how it works |
|
|
161
162
|
| `kompactor presets` · `kompactor config preset 4` | List levels · change level |
|
|
162
163
|
| `kompactor config <setting> <value>` | Change one [setting](#settings) |
|
|
@@ -239,7 +240,8 @@ Commit a `.kompactor.json` next to the code to give everyone the same level and
|
|
|
239
240
|
|---|---|
|
|
240
241
|
| After each reply | `Kompactor: −8.2k tokens this turn (13.1k › 4.9k, −63%) · session −41k · context ≈31% smaller` |
|
|
241
242
|
| CLI status line | `Kompactor −41.3k · ctx −31% · last turn −8.2k · Balanced` |
|
|
242
|
-
| VS Code status bar |
|
|
243
|
+
| VS Code / Cursor status bar | Tokens and ≈ dollars saved this session; hover for details |
|
|
244
|
+
| VS Code / Cursor sidebar | Kompactor icon in the activity bar: this session, this project, today and 30 days in tokens and dollars, recent turns (saved or "nothing to trim"), biggest wins |
|
|
243
245
|
| Dashboard (`kompactor start`) | Per-turn chart, biggest wins, savings by feature and by project |
|
|
244
246
|
| `kompactor gain` | The same numbers in the terminal |
|
|
245
247
|
| `kompactor estimate` | Replays your **past** sessions and shows what Kompactor would have saved |
|
|
@@ -343,7 +345,7 @@ Everything below happens on your machine. Kompactor makes no network requests of
|
|
|
343
345
|
|
|
344
346
|
**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.
|
|
345
347
|
|
|
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.
|
|
348
|
+
**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`. When VS Code or Cursor is installed, `kompactor start` adds the Kompactor extension to them with their own `code` / `cursor` command (from a copy inside the package; nothing is downloaded), and `kompactor uninstall` removes it and deletes `~/.kompactor`. Nothing is written to your repositories.
|
|
347
349
|
|
|
348
350
|
**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).
|
|
349
351
|
|
|
@@ -362,7 +364,7 @@ Everything below happens on your machine. Kompactor makes no network requests of
|
|
|
362
364
|
```bash
|
|
363
365
|
kompactor stop # pause: output passes through untouched; settings are kept
|
|
364
366
|
kompactor start # turn it back on
|
|
365
|
-
kompactor uninstall # remove hooks, status line, shell prefix and
|
|
367
|
+
kompactor uninstall # remove hooks, status line, shell prefix, skill and editor extension, and delete ~/.kompactor
|
|
366
368
|
```
|
|
367
369
|
Then remove the package the way you installed it: `claude plugin uninstall amarkum@kompactor`, `pipx uninstall kompactor`, or uninstall the extension in VS Code.
|
|
368
370
|
|
|
@@ -386,6 +388,9 @@ The hooks are Claude Code-specific, but `kompactor run -- <command>` and `kompac
|
|
|
386
388
|
**How much latency does it add?**
|
|
387
389
|
About 50–100 ms per hook, because the filters run in Python.
|
|
388
390
|
|
|
391
|
+
**How are the dollar figures worked out?**
|
|
392
|
+
They're estimates at an input-token price you set (`kompactor.pricePerMillionTokens` in VS Code, default $3 per million). Each token kept out of the context is counted once as a prompt-cache write (1.25× the input price) and once more at the cache-read price (0.1×) for every later turn in that session that would have re-read it.
|
|
393
|
+
|
|
389
394
|
**Is it free?**
|
|
390
395
|
Yes. MIT-licensed, no account, no paid tier.
|
|
391
396
|
|
|
@@ -151,6 +151,12 @@ def cmd_hook(a):
|
|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
def cmd_gain(a):
|
|
154
|
+
if a.json:
|
|
155
|
+
project = config.project_root(a.project) if a.project else ""
|
|
156
|
+
print(json.dumps({**store.savings(a.price, a.session or "", project), "project_path": project,
|
|
157
|
+
"paused": store.paused(),
|
|
158
|
+
"version": __version__}))
|
|
159
|
+
return 0
|
|
154
160
|
with store.connect() as db:
|
|
155
161
|
rows = db.execute("SELECT feature, COUNT(*), SUM(raw_tokens), SUM(kept_tokens) FROM events GROUP BY feature "
|
|
156
162
|
"ORDER BY SUM(raw_tokens) - SUM(kept_tokens) DESC").fetchall()
|
|
@@ -218,7 +224,7 @@ Use it from Claude Code
|
|
|
218
224
|
|
|
219
225
|
Turn it off
|
|
220
226
|
kompactor stop pause it (settings kept); `kompactor start` resumes
|
|
221
|
-
kompactor uninstall remove it from Claude Code
|
|
227
|
+
kompactor uninstall remove it from Claude Code, VS Code and Cursor, and delete its data
|
|
222
228
|
|
|
223
229
|
Evidence
|
|
224
230
|
Measured A/B runs of real Claude Code tasks: {EVIDENCE_URL}
|
|
@@ -337,6 +343,10 @@ def cmd_start(a):
|
|
|
337
343
|
print(f" Connected via {'the Claude Code plugin' if st['plugin_enabled'] else where}")
|
|
338
344
|
_prefix_note(st)
|
|
339
345
|
_path_note(installer.link_on_path())
|
|
346
|
+
if not a.no_editor:
|
|
347
|
+
added = installer.install_editor_extension()
|
|
348
|
+
if added:
|
|
349
|
+
print(f" Added the Kompactor extension to {' and '.join(added)}: reload the window to see its sidebar.")
|
|
340
350
|
d = _dashboard()
|
|
341
351
|
if not d:
|
|
342
352
|
from . import server
|
|
@@ -375,17 +385,20 @@ def cmd_stop(a):
|
|
|
375
385
|
|
|
376
386
|
|
|
377
387
|
def cmd_uninstall(a):
|
|
378
|
-
"""Stop, remove hooks / status line / shell prefix / skill, and
|
|
388
|
+
"""Stop, remove hooks / status line / shell prefix / skill / editor extension, and delete Kompactor's data."""
|
|
379
389
|
_kill_dashboard()
|
|
380
390
|
target = installer.install(uninstall=True)
|
|
381
391
|
print(f"✓ Removed Kompactor from {target}")
|
|
382
|
-
|
|
392
|
+
removed = installer.uninstall_editor_extension()
|
|
393
|
+
if removed:
|
|
394
|
+
print(f" Removed the Kompactor extension from {' and '.join(removed)}.")
|
|
395
|
+
if a.keep_data:
|
|
396
|
+
(store.home() / "paused").unlink(missing_ok=True)
|
|
397
|
+
print(" Kept savings history and settings in ~/.kompactor.")
|
|
398
|
+
else:
|
|
383
399
|
import shutil
|
|
384
400
|
shutil.rmtree(store.home(), ignore_errors=True)
|
|
385
|
-
print(" Deleted savings history and
|
|
386
|
-
else:
|
|
387
|
-
(store.home() / "paused").unlink(missing_ok=True)
|
|
388
|
-
print(" Kept savings history and config in ~/.kompactor (add --purge to delete).")
|
|
401
|
+
print(" Deleted Kompactor's data: savings history, settings, code graphs and saved outputs (~/.kompactor).")
|
|
389
402
|
if installer.status()["plugin_enabled"]:
|
|
390
403
|
print(" The Claude Code plugin is still enabled; run: claude plugin uninstall amarkum@kompactor")
|
|
391
404
|
print(" Installed it as a Python package? Remove that too, with the tool you installed it with (pip, pipx or uv).")
|
|
@@ -490,13 +503,15 @@ def main(argv=None):
|
|
|
490
503
|
p = sp.add_parser("start", help="turn Kompactor on: connect it to Claude Code and open the dashboard")
|
|
491
504
|
p.add_argument("--port", type=int, default=0, help="preferred port (default: any free port)")
|
|
492
505
|
p.add_argument("--no-browser", action="store_true")
|
|
506
|
+
p.add_argument("--no-editor", action="store_true", help="don't add the extension to VS Code or Cursor")
|
|
493
507
|
p.set_defaults(fn=cmd_start)
|
|
494
508
|
|
|
495
509
|
p = sp.add_parser("stop", help="pause Kompactor and close the dashboard (settings are kept)")
|
|
496
510
|
p.set_defaults(fn=cmd_stop)
|
|
497
511
|
|
|
498
512
|
p = sp.add_parser("uninstall", help="stop and remove Kompactor from Claude Code settings")
|
|
499
|
-
p.add_argument("--
|
|
513
|
+
p.add_argument("--keep-data", action="store_true", help="keep ~/.kompactor (history and settings)")
|
|
514
|
+
p.add_argument("--purge", action="store_true", help=argparse.SUPPRESS) # the default now; kept for old docs
|
|
500
515
|
p.set_defaults(fn=cmd_uninstall)
|
|
501
516
|
|
|
502
517
|
p = sp.add_parser("estimate", help="replay past Claude Code sessions and show %% Kompactor would save")
|
|
@@ -508,6 +523,10 @@ def main(argv=None):
|
|
|
508
523
|
p.set_defaults(fn=cmd_estimate)
|
|
509
524
|
|
|
510
525
|
p = sp.add_parser("gain", help="live savings recorded by the hooks")
|
|
526
|
+
p.add_argument("--json", action="store_true", help="machine-readable totals with a dollar estimate")
|
|
527
|
+
p.add_argument("--price", type=float, default=3.0, help="input-token price in USD per million (default 3)")
|
|
528
|
+
p.add_argument("--session", help="also report this Claude Code session")
|
|
529
|
+
p.add_argument("--project", help="also report this project folder, with its recent turns")
|
|
511
530
|
p.set_defaults(fn=cmd_gain)
|
|
512
531
|
|
|
513
532
|
p = sp.add_parser("ui", help="open the settings & savings dashboard (foreground; see `start`)")
|
|
@@ -65,6 +65,68 @@ def write_shim(only_if_changed: bool = False) -> Path:
|
|
|
65
65
|
return d / "kompactor"
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
# The VS Code extension ships inside the Python package (kompactor/vsix/, built by scripts/build-vsix.sh),
|
|
69
|
+
# so `kompactor start` can add it to VS Code and Cursor without downloading anything.
|
|
70
|
+
EXTENSION_ID = "kompactor.kompactor"
|
|
71
|
+
EDITORS = (("VS Code", "code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", ".vscode"),
|
|
72
|
+
("Cursor", "cursor", "/Applications/Cursor.app/Contents/Resources/app/bin/cursor", ".cursor"))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def bundled_vsix():
|
|
76
|
+
from . import __version__
|
|
77
|
+
p = Path(__file__).with_name("vsix") / f"kompactor-{__version__}.vsix"
|
|
78
|
+
return p if p.exists() else None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def editors() -> list:
|
|
82
|
+
"""(name, command-line tool, extensions folder) for each VS Code-family editor on this machine."""
|
|
83
|
+
found = []
|
|
84
|
+
for name, cmd, mac_path, home_dir in EDITORS:
|
|
85
|
+
cli = shutil.which(cmd) or (mac_path if os.path.exists(mac_path) else "")
|
|
86
|
+
if cli:
|
|
87
|
+
found.append((name, cli, Path.home() / home_dir / "extensions"))
|
|
88
|
+
return found
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _has_extension(ext_dir: Path, version: str = "") -> bool:
|
|
92
|
+
return any(ext_dir.glob(f"{EXTENSION_ID}-{version or '*'}"))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def install_editor_extension() -> list:
|
|
96
|
+
"""Add the bundled extension to each editor that doesn't have this version yet; returns the editor names."""
|
|
97
|
+
import subprocess
|
|
98
|
+
from . import __version__
|
|
99
|
+
vsix = bundled_vsix()
|
|
100
|
+
done = []
|
|
101
|
+
for name, cli, ext_dir in editors() if vsix else []:
|
|
102
|
+
if _has_extension(ext_dir, __version__):
|
|
103
|
+
continue
|
|
104
|
+
try:
|
|
105
|
+
r = subprocess.run([cli, "--install-extension", str(vsix), "--force"], capture_output=True, text=True,
|
|
106
|
+
timeout=180)
|
|
107
|
+
except (OSError, subprocess.SubprocessError):
|
|
108
|
+
continue
|
|
109
|
+
if r.returncode == 0:
|
|
110
|
+
done.append(name)
|
|
111
|
+
return done
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def uninstall_editor_extension() -> list:
|
|
115
|
+
"""Remove the extension from every editor that has it; returns the editor names."""
|
|
116
|
+
import subprocess
|
|
117
|
+
done = []
|
|
118
|
+
for name, cli, ext_dir in editors():
|
|
119
|
+
if not _has_extension(ext_dir):
|
|
120
|
+
continue
|
|
121
|
+
try:
|
|
122
|
+
r = subprocess.run([cli, "--uninstall-extension", EXTENSION_ID], capture_output=True, text=True, timeout=180)
|
|
123
|
+
except (OSError, subprocess.SubprocessError):
|
|
124
|
+
continue
|
|
125
|
+
if r.returncode == 0:
|
|
126
|
+
done.append(name)
|
|
127
|
+
return done
|
|
128
|
+
|
|
129
|
+
|
|
68
130
|
# Where a `kompactor` command can be linked when pip put it in a folder that isn't on PATH.
|
|
69
131
|
PATH_DIRS = ("~/.local/bin", "~/bin", "/opt/homebrew/bin", "/usr/local/bin")
|
|
70
132
|
|
|
@@ -139,7 +139,7 @@ svg.chev { width: 11px; height: 11px; stroke: var(--ink-3); fill: none; stroke-w
|
|
|
139
139
|
<pre><code>pipx install kompactor
|
|
140
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.8.
|
|
142
|
+
<pre><code>code --install-extension kompactor-0.8.2.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
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>
|
|
@@ -143,6 +143,49 @@ def session_totals(session: str) -> dict:
|
|
|
143
143
|
"context": last[2] if last else 0, "last_turn_saved": (last[0] - last[1]) if last else 0}
|
|
144
144
|
|
|
145
145
|
|
|
146
|
+
def savings(price_per_mtok: float = 3.0, session: str = "", project: str = "") -> dict:
|
|
147
|
+
"""Tokens kept out of Claude's context, with a dollar estimate at `price_per_mtok` (the input-token
|
|
148
|
+
price). A kept-out token would have been written to the prompt cache once (1.25x) and re-read on every
|
|
149
|
+
later turn of its session (0.1x each), the same weights `kompactor estimate` uses."""
|
|
150
|
+
now = time.time()
|
|
151
|
+
day = now - 86400
|
|
152
|
+
with connect() as db:
|
|
153
|
+
def total(where="1", args=()):
|
|
154
|
+
r = db.execute(f"SELECT COUNT(*), COALESCE(SUM(raw_tokens),0), COALESCE(SUM(kept_tokens),0) FROM events "
|
|
155
|
+
f"WHERE {where}", args).fetchone()
|
|
156
|
+
return {"events": r[0], "raw": r[1], "kept": r[2], "saved": r[1] - r[2]}
|
|
157
|
+
periods = {"all": total(), "today": total("ts > ?", (day,))}
|
|
158
|
+
if session:
|
|
159
|
+
periods["session"] = total("session = ?", (session,))
|
|
160
|
+
if project:
|
|
161
|
+
periods["project"] = total("project = ?", (project,))
|
|
162
|
+
recent = db.execute("SELECT session, idx, ts, raw_tokens, kept_tokens, features FROM turns "
|
|
163
|
+
"WHERE project = ? OR (? = '' AND session = ?) ORDER BY ts DESC LIMIT 12",
|
|
164
|
+
(project, project, session)).fetchall()
|
|
165
|
+
turns = db.execute("SELECT session, ts, raw_tokens - kept_tokens, project FROM turns "
|
|
166
|
+
"ORDER BY session, idx").fetchall()
|
|
167
|
+
top = db.execute("SELECT detail, COUNT(*), SUM(raw_tokens), SUM(kept_tokens) FROM events WHERE feature='bash' "
|
|
168
|
+
"GROUP BY detail ORDER BY SUM(raw_tokens) - SUM(kept_tokens) DESC LIMIT 5").fetchall()
|
|
169
|
+
sessions = db.execute("SELECT COUNT(DISTINCT session) FROM events").fetchone()[0]
|
|
170
|
+
rereads = {"all": 0.0, "today": 0.0, "session": 0.0, "project": 0.0}
|
|
171
|
+
by_session = {}
|
|
172
|
+
for s, ts, saved, proj in turns:
|
|
173
|
+
by_session.setdefault(s, []).append((ts, saved, proj))
|
|
174
|
+
for s, rows in by_session.items():
|
|
175
|
+
for i, (ts, saved, proj) in enumerate(rows):
|
|
176
|
+
later = (len(rows) - i - 1) * saved * 0.1
|
|
177
|
+
rereads["all"] += later
|
|
178
|
+
rereads["today"] += later if ts > day else 0
|
|
179
|
+
rereads["session"] += later if s == session else 0
|
|
180
|
+
rereads["project"] += later if project and proj == project else 0
|
|
181
|
+
for k, p in periods.items():
|
|
182
|
+
p["usd"] = round((p["saved"] * 1.25 + rereads[k]) * price_per_mtok / 1e6, 4)
|
|
183
|
+
return {"price_per_mtok": price_per_mtok, "sessions": sessions, **periods,
|
|
184
|
+
"top": [{"cmd": t[0], "runs": t[1], "raw": t[2], "kept": t[3]} for t in top],
|
|
185
|
+
"turns": [{"session": t[0], "idx": t[1], "ts": t[2], "raw": t[3], "kept": t[4], "saved": t[3] - t[4],
|
|
186
|
+
"features": json.loads(t[5] or "{}")} for t in recent]}
|
|
187
|
+
|
|
188
|
+
|
|
146
189
|
def prune(retention_days: float) -> None:
|
|
147
190
|
"""Drop data older than the retention window (called at session start)."""
|
|
148
191
|
cutoff = time.time() - retention_days * 86400
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kompactor
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
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
|
|
@@ -98,7 +98,7 @@ Measured in 54 real Claude Code sessions on Flask, Cobra, SWR, ky and zustand at
|
|
|
98
98
|
- **Outline-first file reads.** Big source files arrive as an outline (symbols, line ranges, who imports the file, which tests cover it). Claude reads just the ranges it needs; repeating the read returns the whole file.
|
|
99
99
|
- **Local code graph.** Find code by topic, see callers, the impact of a change and the tests to run, for Python, Go, TypeScript, JavaScript and React.
|
|
100
100
|
- **Terse replies and lean code.** Short, readable rules for answer-first prose and smallest-diff code, from 0 to 177 tokens depending on the level.
|
|
101
|
-
- **Per-turn savings.** In the reply, the status line,
|
|
101
|
+
- **Per-turn savings, in tokens and dollars.** In the reply, the status line, a VS Code / Cursor sidebar (per session, per project and per turn) and a local dashboard. Numbers are conservative and never count output Claude wouldn't have read.
|
|
102
102
|
- **One dial for quality vs tokens.** Five levels, every option adjustable, per project, with a live preview of exactly what Claude would see.
|
|
103
103
|
- **Nothing is lost.** Every shortened output keeps a raw copy (`kompactor show <id>`), and every hook fails open.
|
|
104
104
|
- **Private and dependency-free.** Python 3.9+ standard library only. Runs locally, sends nothing anywhere, no telemetry.
|
|
@@ -123,7 +123,7 @@ kompactor start
|
|
|
123
123
|
```
|
|
124
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.
|
|
125
125
|
|
|
126
|
-
**VS Code.**
|
|
126
|
+
**VS Code and Cursor.** `kompactor start` adds the Kompactor extension to VS Code and Cursor automatically when they're installed (skip it with `--no-editor`); reload the window and a **Kompactor** icon appears in the activity bar. To install it by hand, download `kompactor-0.8.2.vsix` from [Releases](https://github.com/amarkum/kompactor/releases) and use Extensions › `⋯` › *Install from VSIX…*.
|
|
127
127
|
|
|
128
128
|
**From source:**
|
|
129
129
|
```bash
|
|
@@ -136,12 +136,13 @@ git clone https://github.com/amarkum/kompactor.git && ./kompactor/install.sh
|
|
|
136
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.
|
|
137
137
|
3. **Check it's on:** run `kompactor` in a terminal (or `/kompactor` in Claude Code):
|
|
138
138
|
```
|
|
139
|
-
Kompactor 0.8.
|
|
139
|
+
Kompactor 0.8.2: ON
|
|
140
140
|
Connected via the Claude Code plugin. New Claude Code sessions are compacted.
|
|
141
141
|
Level: Balanced (level 3 of 5). Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced
|
|
142
142
|
Saved so far: 41.3k tokens (−38%) over 52 tool calls. Details: `kompactor gain`
|
|
143
143
|
```
|
|
144
|
-
4. **
|
|
144
|
+
4. **In VS Code or Cursor:** click the **Kompactor** icon in the activity bar for tokens and estimated dollars saved this session, in this project, today and over 30 days, plus what every recent turn saved.
|
|
145
|
+
5. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
|
|
145
146
|
|
|
146
147
|
## How it works
|
|
147
148
|
|
|
@@ -187,9 +188,9 @@ Ask Claude Code the way you normally would. These prompts come from the [evidenc
|
|
|
187
188
|
|
|
188
189
|
| Command | What it does |
|
|
189
190
|
|---|---|
|
|
190
|
-
| `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code) and open the dashboard on a free port |
|
|
191
|
+
| `kompactor start` | Turn Kompactor on: connect it to Claude Code (CLI + VS Code), add the extension to VS Code and Cursor, and open the dashboard on a free port |
|
|
191
192
|
| `kompactor stop` | Pause it and close the dashboard; settings are kept |
|
|
192
|
-
| `kompactor uninstall
|
|
193
|
+
| `kompactor uninstall` | Remove it from Claude Code and from VS Code / Cursor, and delete its data (`--keep-data` keeps `~/.kompactor`) |
|
|
193
194
|
| `kompactor` / `kompactor status` | On or off, level, savings, how it works |
|
|
194
195
|
| `kompactor presets` · `kompactor config preset 4` | List levels · change level |
|
|
195
196
|
| `kompactor config <setting> <value>` | Change one [setting](#settings) |
|
|
@@ -272,7 +273,8 @@ Commit a `.kompactor.json` next to the code to give everyone the same level and
|
|
|
272
273
|
|---|---|
|
|
273
274
|
| After each reply | `Kompactor: −8.2k tokens this turn (13.1k › 4.9k, −63%) · session −41k · context ≈31% smaller` |
|
|
274
275
|
| CLI status line | `Kompactor −41.3k · ctx −31% · last turn −8.2k · Balanced` |
|
|
275
|
-
| VS Code status bar |
|
|
276
|
+
| VS Code / Cursor status bar | Tokens and ≈ dollars saved this session; hover for details |
|
|
277
|
+
| VS Code / Cursor sidebar | Kompactor icon in the activity bar: this session, this project, today and 30 days in tokens and dollars, recent turns (saved or "nothing to trim"), biggest wins |
|
|
276
278
|
| Dashboard (`kompactor start`) | Per-turn chart, biggest wins, savings by feature and by project |
|
|
277
279
|
| `kompactor gain` | The same numbers in the terminal |
|
|
278
280
|
| `kompactor estimate` | Replays your **past** sessions and shows what Kompactor would have saved |
|
|
@@ -376,7 +378,7 @@ Everything below happens on your machine. Kompactor makes no network requests of
|
|
|
376
378
|
|
|
377
379
|
**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.
|
|
378
380
|
|
|
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.
|
|
381
|
+
**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`. When VS Code or Cursor is installed, `kompactor start` adds the Kompactor extension to them with their own `code` / `cursor` command (from a copy inside the package; nothing is downloaded), and `kompactor uninstall` removes it and deletes `~/.kompactor`. Nothing is written to your repositories.
|
|
380
382
|
|
|
381
383
|
**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).
|
|
382
384
|
|
|
@@ -395,7 +397,7 @@ Everything below happens on your machine. Kompactor makes no network requests of
|
|
|
395
397
|
```bash
|
|
396
398
|
kompactor stop # pause: output passes through untouched; settings are kept
|
|
397
399
|
kompactor start # turn it back on
|
|
398
|
-
kompactor uninstall # remove hooks, status line, shell prefix and
|
|
400
|
+
kompactor uninstall # remove hooks, status line, shell prefix, skill and editor extension, and delete ~/.kompactor
|
|
399
401
|
```
|
|
400
402
|
Then remove the package the way you installed it: `claude plugin uninstall amarkum@kompactor`, `pipx uninstall kompactor`, or uninstall the extension in VS Code.
|
|
401
403
|
|
|
@@ -419,6 +421,9 @@ The hooks are Claude Code-specific, but `kompactor run -- <command>` and `kompac
|
|
|
419
421
|
**How much latency does it add?**
|
|
420
422
|
About 50–100 ms per hook, because the filters run in Python.
|
|
421
423
|
|
|
424
|
+
**How are the dollar figures worked out?**
|
|
425
|
+
They're estimates at an input-token price you set (`kompactor.pricePerMillionTokens` in VS Code, default $3 per million). Each token kept out of the context is counted once as a prompt-cache write (1.25× the input price) and once more at the cache-read price (0.1×) for every later turn in that session that would have re-read it.
|
|
426
|
+
|
|
422
427
|
**Is it free?**
|
|
423
428
|
Yes. MIT-licensed, no account, no paid tier.
|
|
424
429
|
|
|
@@ -35,6 +35,7 @@ kompactor/static/fonts/plex-mono-500.woff2
|
|
|
35
35
|
kompactor/static/fonts/plex-sans-400.woff2
|
|
36
36
|
kompactor/static/fonts/plex-sans-500.woff2
|
|
37
37
|
kompactor/static/fonts/plex-sans-600.woff2
|
|
38
|
+
kompactor/vsix/kompactor-0.8.2.vsix
|
|
38
39
|
tests/test_graph.py
|
|
39
40
|
tests/test_kompactor.py
|
|
40
41
|
tests/test_shell.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "kompactor"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.2"
|
|
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"
|
|
@@ -44,9 +44,10 @@ exact = ["tiktoken>=0.7"]
|
|
|
44
44
|
kompactor = "kompactor.cli:main"
|
|
45
45
|
|
|
46
46
|
[tool.setuptools]
|
|
47
|
-
packages = ["kompactor", "kompactor.static", "kompactor.static.fonts"]
|
|
47
|
+
packages = ["kompactor", "kompactor.static", "kompactor.static.fonts", "kompactor.vsix"]
|
|
48
48
|
|
|
49
49
|
[tool.setuptools.package-data]
|
|
50
50
|
kompactor = ["ui.html"]
|
|
51
51
|
"kompactor.static" = ["*.html", "*.svg"]
|
|
52
52
|
"kompactor.static.fonts" = ["*.woff2", "*.txt"]
|
|
53
|
+
"kompactor.vsix" = ["*.vsix"]
|
|
@@ -13,6 +13,7 @@ os.environ.setdefault("KOMPACTOR_HOME", tempfile.mkdtemp())
|
|
|
13
13
|
|
|
14
14
|
from kompactor import config, graph, hooks, installer # noqa: E402
|
|
15
15
|
installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from tests
|
|
16
|
+
installer.EDITORS = () # never install or remove the real VS Code / Cursor extension from tests
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def make_repo(files: dict) -> str:
|
|
@@ -13,6 +13,7 @@ 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
15
|
installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from tests
|
|
16
|
+
installer.EDITORS = () # never install or remove the real VS Code / Cursor extension from tests
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def run_hook(name, event):
|
|
@@ -584,6 +585,29 @@ class SourceTests(unittest.TestCase):
|
|
|
584
585
|
installer.unlink_from_path(dirs=(str(on_path),))
|
|
585
586
|
self.assertTrue((on_path / "kompactor").exists())
|
|
586
587
|
|
|
588
|
+
@unittest.skipIf(os.name == "nt", "uses a POSIX shell script as the fake editor")
|
|
589
|
+
def test_editor_extension_added_once_and_removed(self):
|
|
590
|
+
from unittest import mock
|
|
591
|
+
from kompactor import __version__
|
|
592
|
+
tmp = Path(tempfile.mkdtemp())
|
|
593
|
+
ext, log, cli, vsix = tmp / "extensions", tmp / "log", tmp / "code", tmp / "k.vsix"
|
|
594
|
+
ext.mkdir(); vsix.write_text("x")
|
|
595
|
+
cli.write_text(f"""#!/bin/sh
|
|
596
|
+
echo "$@" >> '{log}'
|
|
597
|
+
[ "$1" = --install-extension ] && mkdir -p '{ext}/kompactor.kompactor-{__version__}'
|
|
598
|
+
[ "$1" = --uninstall-extension ] && rm -rf '{ext}'/kompactor.kompactor-*
|
|
599
|
+
exit 0
|
|
600
|
+
""")
|
|
601
|
+
cli.chmod(0o755)
|
|
602
|
+
fake = (("VS Code", "no-such-editor-command", str(cli), str(tmp)),)
|
|
603
|
+
with mock.patch.object(installer, "EDITORS", fake), mock.patch.object(installer, "bundled_vsix", return_value=vsix):
|
|
604
|
+
self.assertEqual(installer.install_editor_extension(), ["VS Code"])
|
|
605
|
+
self.assertEqual(installer.install_editor_extension(), []) # this version is already there
|
|
606
|
+
self.assertEqual(installer.uninstall_editor_extension(), ["VS Code"])
|
|
607
|
+
self.assertEqual(installer.uninstall_editor_extension(), []) # nothing left to remove
|
|
608
|
+
self.assertEqual(log.read_text().split("\n")[:2],
|
|
609
|
+
[f"--install-extension {vsix} --force", "--uninstall-extension kompactor.kompactor"])
|
|
610
|
+
|
|
587
611
|
def test_source_defaults_to_the_public_repo(self):
|
|
588
612
|
self.assertEqual(installer.source("")["marketplace"], "amarkum/kompactor")
|
|
589
613
|
self.assertEqual(installer.source("acme/kompactor")["clone"], "https://github.com/acme/kompactor.git") # a fork
|
|
@@ -21,6 +21,7 @@ sys.path.insert(0, str(ROOT))
|
|
|
21
21
|
|
|
22
22
|
from kompactor import filters, hooks, installer, shellwrap, tokens # noqa: E402
|
|
23
23
|
installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from tests
|
|
24
|
+
installer.EDITORS = () # never install or remove the real VS Code / Cursor extension from tests
|
|
24
25
|
|
|
25
26
|
PASSING = "".join(f"tests/test_mod.py::test_case_{i} PASSED{' ' * 30}[{i // 5:3d}%]\n" for i in range(500))
|
|
26
27
|
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
|
|
File without changes
|