kompactor 0.8.2__tar.gz → 0.8.3__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.2 → kompactor-0.8.3}/PKG-INFO +10 -7
- {kompactor-0.8.2 → kompactor-0.8.3}/README.md +9 -6
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/__init__.py +1 -1
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/cli.py +77 -38
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/usage.html +1 -1
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/store.py +18 -2
- kompactor-0.8.2/kompactor/vsix/kompactor-0.8.2.vsix → kompactor-0.8.3/kompactor/vsix/kompactor-0.8.3.vsix +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor.egg-info/PKG-INFO +10 -7
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor.egg-info/SOURCES.txt +1 -1
- {kompactor-0.8.2 → kompactor-0.8.3}/pyproject.toml +1 -1
- {kompactor-0.8.2 → kompactor-0.8.3}/tests/test_kompactor.py +19 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/LICENSE +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/__main__.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/_launch.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/config.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/estimate.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/filters.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/graph.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/hooks.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/installer.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/langs.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/outline.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/prove.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/rules.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/samples.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/server.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/shellwrap.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/fonts/OFL.txt +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/fonts/plex-mono-400.woff2 +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/fonts/plex-mono-500.woff2 +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/fonts/plex-sans-400.woff2 +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/fonts/plex-sans-500.woff2 +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/fonts/plex-sans-600.woff2 +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/static/logo-mark.svg +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/tokens.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor/ui.html +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor.egg-info/dependency_links.txt +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor.egg-info/entry_points.txt +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor.egg-info/requires.txt +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/kompactor.egg-info/top_level.txt +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/setup.cfg +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/tests/test_graph.py +0 -0
- {kompactor-0.8.2 → kompactor-0.8.3}/tests/test_shell.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kompactor
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
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
|
|
@@ -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 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.
|
|
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.3.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,15 @@ 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.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Kompactor 0.8.3 is on
|
|
140
|
+
|
|
141
|
+
Claude Code connected
|
|
142
|
+
Level Balanced (3 of 5)
|
|
143
|
+
Saved 41.3k tokens (−38%) in 52 tool calls
|
|
144
|
+
Dashboard http://127.0.0.1:56710/
|
|
143
145
|
```
|
|
144
|
-
|
|
146
|
+
`kompactor help` lists every command.
|
|
147
|
+
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 Kompactor shortened in each of Claude's recent replies.
|
|
145
148
|
5. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
|
|
146
149
|
|
|
147
150
|
## How it works
|
|
@@ -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 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.
|
|
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.3.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,15 @@ 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.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
Kompactor 0.8.3 is on
|
|
107
|
+
|
|
108
|
+
Claude Code connected
|
|
109
|
+
Level Balanced (3 of 5)
|
|
110
|
+
Saved 41.3k tokens (−38%) in 52 tool calls
|
|
111
|
+
Dashboard http://127.0.0.1:56710/
|
|
110
112
|
```
|
|
111
|
-
|
|
113
|
+
`kompactor help` lists every command.
|
|
114
|
+
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 Kompactor shortened in each of Claude's recent replies.
|
|
112
115
|
5. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
|
|
113
116
|
|
|
114
117
|
## How it works
|
|
@@ -190,47 +190,36 @@ def cmd_status(a):
|
|
|
190
190
|
"""What Kompactor is doing right now, and what to do next. Also what plain `kompactor` prints."""
|
|
191
191
|
st = installer.status()
|
|
192
192
|
cfg = config.load(os.getcwd())
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if not (st["plugin_enabled"] or st["hooks_installed"]):
|
|
198
|
-
print(" Run `kompactor start` to connect it to Claude Code (CLI and VS Code).")
|
|
193
|
+
connected = st["plugin_enabled"] or st["hooks_installed"]
|
|
194
|
+
state = "on" if connected and not store.paused() else "stopped" if connected else "not set up"
|
|
195
|
+
if not connected:
|
|
196
|
+
claude = "not connected; run 'kompactor start'"
|
|
199
197
|
elif store.paused():
|
|
200
|
-
|
|
198
|
+
claude = "paused; run 'kompactor start' to resume"
|
|
201
199
|
else:
|
|
202
|
-
|
|
203
|
-
" New Claude Code sessions are compacted.")
|
|
204
|
-
print(f" Level: {level}. Change it: `kompactor config preset 1-5`, the dashboard, or /kompactor balanced")
|
|
200
|
+
claude = "connected (plugin)" if st["plugin_enabled"] else "connected"
|
|
205
201
|
with store.connect() as db:
|
|
206
202
|
raw, kept, n = db.execute("SELECT COALESCE(SUM(raw_tokens),0), COALESCE(SUM(kept_tokens),0), COUNT(*) "
|
|
207
203
|
"FROM events").fetchone()
|
|
208
|
-
if n
|
|
209
|
-
print(f" Saved so far: {_fmt(raw - kept)} tokens ({_pct(raw - kept, raw)}) over {n} tool calls."
|
|
210
|
-
" Details: `kompactor gain`")
|
|
211
|
-
else:
|
|
212
|
-
print(" Saved so far: nothing yet. Use Claude Code as usual; the status line shows savings per turn.")
|
|
204
|
+
saved = f"{_fmt(raw - kept)} tokens ({_pct(raw - kept, raw)}) in {n} tool calls" if n else "nothing yet"
|
|
213
205
|
d = _dashboard()
|
|
214
|
-
print(f"
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
Your own sessions: `kompactor estimate` replays them and shows what it would have saved.
|
|
232
|
-
|
|
233
|
-
All commands: kompactor --help""")
|
|
206
|
+
print(f"""Kompactor {__version__} is {state}
|
|
207
|
+
|
|
208
|
+
Claude Code {claude}
|
|
209
|
+
Level {config.PRESETS[cfg['preset']]['name']} ({cfg['preset']} of 5)
|
|
210
|
+
Saved {saved}
|
|
211
|
+
Dashboard {d['url'] if d else "not running"}
|
|
212
|
+
|
|
213
|
+
Commands:
|
|
214
|
+
start Turn Kompactor on and open the dashboard
|
|
215
|
+
stop Pause Kompactor (settings are kept)
|
|
216
|
+
uninstall Remove Kompactor and delete its data
|
|
217
|
+
gain Show what it saved, command by command
|
|
218
|
+
help List all commands
|
|
219
|
+
|
|
220
|
+
Kompactor shortens test runs, installs, logs and big file reads
|
|
221
|
+
before Claude reads them, keeping every error, failure and summary.
|
|
222
|
+
Evidence: {EVIDENCE_URL}""")
|
|
234
223
|
return 0
|
|
235
224
|
|
|
236
225
|
|
|
@@ -486,16 +475,59 @@ def cmd_doctor(a):
|
|
|
486
475
|
return 0
|
|
487
476
|
|
|
488
477
|
|
|
478
|
+
HELP = """Kompactor {version}: cut the tokens Claude Code spends on noise
|
|
479
|
+
|
|
480
|
+
Usage:
|
|
481
|
+
kompactor <command> [options]
|
|
482
|
+
|
|
483
|
+
Getting started:
|
|
484
|
+
start Turn Kompactor on and open the dashboard
|
|
485
|
+
stop Pause Kompactor (settings are kept)
|
|
486
|
+
uninstall Remove Kompactor and delete its data
|
|
487
|
+
status Show whether it's on and what it saved
|
|
488
|
+
|
|
489
|
+
Savings:
|
|
490
|
+
gain Show what it saved, command by command
|
|
491
|
+
estimate Estimate savings on your past sessions
|
|
492
|
+
ui Open the dashboard in this terminal
|
|
493
|
+
|
|
494
|
+
Settings:
|
|
495
|
+
presets List the quality-vs-tokens levels
|
|
496
|
+
config Show or change settings
|
|
497
|
+
|
|
498
|
+
Code:
|
|
499
|
+
graph Find code, callers and the impact of a change
|
|
500
|
+
outline List a file's symbols with line ranges
|
|
501
|
+
symbol Print one definition
|
|
502
|
+
show Print an output Kompactor shortened
|
|
503
|
+
search Search outputs Kompactor shortened
|
|
504
|
+
|
|
505
|
+
Other:
|
|
506
|
+
run Run a command and print its compacted output
|
|
507
|
+
doctor Check the installation
|
|
508
|
+
prove A/B test Kompactor in Claude Code sessions
|
|
509
|
+
|
|
510
|
+
Options:
|
|
511
|
+
-h, --help Show this help
|
|
512
|
+
--version Show the version
|
|
513
|
+
|
|
514
|
+
Run 'kompactor <command> --help' for details on a command.
|
|
515
|
+
Docs: https://github.com/amarkum/kompactor"""
|
|
516
|
+
|
|
517
|
+
|
|
489
518
|
def main(argv=None):
|
|
490
519
|
argv = sys.argv[1:] if argv is None else argv
|
|
491
520
|
if argv[:1] == ["setup"]: # the old name for `start`; older docs still say it
|
|
492
521
|
argv = ["start"] + ["--no-browser" if x == "--no-ui" else x for x in argv[1:]]
|
|
522
|
+
if argv[:1] in (["help"], ["-h"], ["--help"]):
|
|
523
|
+
print(HELP.format(version=__version__))
|
|
524
|
+
return 0
|
|
493
525
|
if argv[:1] == ["prove"]: # has its own parser
|
|
494
526
|
from . import prove
|
|
495
527
|
return prove.main(argv[1:])
|
|
496
528
|
ap = argparse.ArgumentParser(prog="kompactor", description="Cut the tokens Claude Code spends on noise.")
|
|
497
529
|
ap.add_argument("--version", action="version", version=__version__)
|
|
498
|
-
sp = ap.add_subparsers(dest="cmd")
|
|
530
|
+
sp = ap.add_subparsers(dest="cmd", metavar="<command>")
|
|
499
531
|
|
|
500
532
|
p = sp.add_parser("status", help="is it on, your level, savings so far, and how to use it (also: plain `kompactor`)")
|
|
501
533
|
p.set_defaults(fn=cmd_status)
|
|
@@ -543,7 +575,7 @@ def main(argv=None):
|
|
|
543
575
|
help="don't set CLAUDE_CODE_SHELL_PREFIX (then commands that fail are not compacted)")
|
|
544
576
|
p.set_defaults(fn=cmd_install)
|
|
545
577
|
|
|
546
|
-
p = sp.add_parser("statusline"
|
|
578
|
+
p = sp.add_parser("statusline") # internal: Claude Code's status line
|
|
547
579
|
p.set_defaults(fn=cmd_statusline)
|
|
548
580
|
|
|
549
581
|
p = sp.add_parser("map", help="ranked repo skeleton within a token budget")
|
|
@@ -606,13 +638,20 @@ def main(argv=None):
|
|
|
606
638
|
p.add_argument("--json", action="store_true")
|
|
607
639
|
p.set_defaults(fn=cmd_presets)
|
|
608
640
|
|
|
609
|
-
p = sp.add_parser("hook"
|
|
641
|
+
p = sp.add_parser("hook") # internal: Claude Code hook entry point
|
|
610
642
|
p.add_argument("name", choices=list(hooks.HANDLERS))
|
|
611
643
|
p.set_defaults(fn=cmd_hook)
|
|
612
644
|
|
|
613
645
|
p = sp.add_parser("doctor", help="check installation")
|
|
614
646
|
p.set_defaults(fn=cmd_doctor)
|
|
615
647
|
|
|
648
|
+
if argv and not argv[0].startswith("-") and argv[0] not in sp.choices:
|
|
649
|
+
import difflib
|
|
650
|
+
near = difflib.get_close_matches(argv[0], [c for c in sp.choices if c not in ("hook", "statusline")], n=1)
|
|
651
|
+
print(f"kompactor: unknown command '{argv[0]}'" + (f"\n\nDid you mean this?\n kompactor {near[0]}" if near else ""),
|
|
652
|
+
file=sys.stderr)
|
|
653
|
+
print("\nRun 'kompactor help' for a list of commands.", file=sys.stderr)
|
|
654
|
+
return 2
|
|
616
655
|
a = ap.parse_args(argv)
|
|
617
656
|
if not a.cmd:
|
|
618
657
|
a.fn = cmd_status
|
|
@@ -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.3.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>
|
|
@@ -160,8 +160,18 @@ def savings(price_per_mtok: float = 3.0, session: str = "", project: str = "") -
|
|
|
160
160
|
if project:
|
|
161
161
|
periods["project"] = total("project = ?", (project,))
|
|
162
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
|
|
163
|
+
"WHERE project = ? OR (? = '' AND session = ?) ORDER BY ts DESC LIMIT 30",
|
|
164
164
|
(project, project, session)).fetchall()
|
|
165
|
+
shortened = {} # what each recent reply shortened: its commands and files, biggest first
|
|
166
|
+
for s, idx, ts, *_ in recent:
|
|
167
|
+
prev = db.execute("SELECT COALESCE(MAX(ts), 0) FROM turns WHERE session = ? AND idx < ?", (s, idx)).fetchone()[0]
|
|
168
|
+
items = {}
|
|
169
|
+
for f, d, r, k in db.execute("SELECT feature, detail, raw_tokens, kept_tokens FROM events WHERE session = ? "
|
|
170
|
+
"AND ts > ? AND ts <= ? AND raw_tokens > kept_tokens", (s, prev, ts)):
|
|
171
|
+
it = items.setdefault(_label(f, d), {"what": _label(f, d), "saved": 0, "times": 0})
|
|
172
|
+
it["saved"] += r - k
|
|
173
|
+
it["times"] += 1
|
|
174
|
+
shortened[(s, idx)] = sorted(items.values(), key=lambda it: -it["saved"])[:3]
|
|
165
175
|
turns = db.execute("SELECT session, ts, raw_tokens - kept_tokens, project FROM turns "
|
|
166
176
|
"ORDER BY session, idx").fetchall()
|
|
167
177
|
top = db.execute("SELECT detail, COUNT(*), SUM(raw_tokens), SUM(kept_tokens) FROM events WHERE feature='bash' "
|
|
@@ -183,7 +193,13 @@ def savings(price_per_mtok: float = 3.0, session: str = "", project: str = "") -
|
|
|
183
193
|
return {"price_per_mtok": price_per_mtok, "sessions": sessions, **periods,
|
|
184
194
|
"top": [{"cmd": t[0], "runs": t[1], "raw": t[2], "kept": t[3]} for t in top],
|
|
185
195
|
"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]}
|
|
196
|
+
"features": json.loads(t[5] or "{}"), "shortened": shortened[(t[0], t[1])]} for t in recent]}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _label(feature: str, detail: str) -> str:
|
|
200
|
+
"""How a saving reads in a list: the command, or the file that was outlined or not re-read."""
|
|
201
|
+
name = os.path.basename((detail or "").split(" (")[0])
|
|
202
|
+
return {"read_outline": f"read {name}", "read_dedupe": f"re-read {name}"}.get(feature, detail or feature)
|
|
187
203
|
|
|
188
204
|
|
|
189
205
|
def prune(retention_days: float) -> None:
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kompactor
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
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
|
|
@@ -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 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.
|
|
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.3.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,15 @@ 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.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Kompactor 0.8.3 is on
|
|
140
|
+
|
|
141
|
+
Claude Code connected
|
|
142
|
+
Level Balanced (3 of 5)
|
|
143
|
+
Saved 41.3k tokens (−38%) in 52 tool calls
|
|
144
|
+
Dashboard http://127.0.0.1:56710/
|
|
143
145
|
```
|
|
144
|
-
|
|
146
|
+
`kompactor help` lists every command.
|
|
147
|
+
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 Kompactor shortened in each of Claude's recent replies.
|
|
145
148
|
5. **Three commands to remember:** `kompactor start` turns it on and opens the dashboard, `kompactor stop` pauses it, `kompactor uninstall` removes it.
|
|
146
149
|
|
|
147
150
|
## How it works
|
|
@@ -35,7 +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.
|
|
38
|
+
kompactor/vsix/kompactor-0.8.3.vsix
|
|
39
39
|
tests/test_graph.py
|
|
40
40
|
tests/test_kompactor.py
|
|
41
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.3"
|
|
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"
|
|
@@ -16,6 +16,11 @@ installer.PATH_DIRS = () # never link `kompactor` into real PATH folders from t
|
|
|
16
16
|
installer.EDITORS = () # never install or remove the real VS Code / Cursor extension from tests
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def mock_stderr(buf):
|
|
20
|
+
from contextlib import redirect_stderr
|
|
21
|
+
return redirect_stderr(buf)
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
def run_hook(name, event):
|
|
20
25
|
sys.stdin = io.StringIO(json.dumps(event))
|
|
21
26
|
buf = io.StringIO()
|
|
@@ -608,6 +613,20 @@ exit 0
|
|
|
608
613
|
self.assertEqual(log.read_text().split("\n")[:2],
|
|
609
614
|
[f"--install-extension {vsix} --force", "--uninstall-extension kompactor.kompactor"])
|
|
610
615
|
|
|
616
|
+
def test_help_and_mistyped_commands(self):
|
|
617
|
+
from kompactor import cli
|
|
618
|
+
out = io.StringIO()
|
|
619
|
+
with redirect_stdout(out):
|
|
620
|
+
self.assertEqual(cli.main(["help"]), 0)
|
|
621
|
+
self.assertIn("Usage:\n kompactor <command> [options]", out.getvalue())
|
|
622
|
+
self.assertIn(" start Turn Kompactor on", out.getvalue())
|
|
623
|
+
self.assertLessEqual(max(len(line) for line in out.getvalue().splitlines()), 80) # fits a normal terminal
|
|
624
|
+
self.assertNotIn("statusline", out.getvalue()) # internal commands stay out of the help
|
|
625
|
+
err = io.StringIO()
|
|
626
|
+
with mock_stderr(err):
|
|
627
|
+
self.assertEqual(cli.main(["strt"]), 2)
|
|
628
|
+
self.assertIn("Did you mean this?\n kompactor start", err.getvalue())
|
|
629
|
+
|
|
611
630
|
def test_source_defaults_to_the_public_repo(self):
|
|
612
631
|
self.assertEqual(installer.source("")["marketplace"], "amarkum/kompactor")
|
|
613
632
|
self.assertEqual(installer.source("acme/kompactor")["clone"], "https://github.com/acme/kompactor.git") # a fork
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|