cc-cream 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,24 @@ All notable changes to cc-cream are documented here. Format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.3] — 2026-05-30
10
+
11
+ ### Changed
12
+ - **The post-publish `npx` smoke test now uses `--safe-chain-skip-minimum-package-age`** so the `@manual` "npm indexing" scenario works immediately after a release without waiting for the package-age guard to lift (CREAM-elrbkfot).
13
+ - **TTL segment now displays minutes only** (`ttl:60`, `ttl:8`, `ttl:0`) instead of the previous `HH:MM` format (`ttl:01:00`). Simpler to read at a glance; matches the 60-second refresh cadence (CREAM-vhhdhydn).
14
+
15
+ ### Documentation
16
+ - **The `cache` segment's `drop` / `drop_recover` config keys are now documented.** They've been live since cache drop-detection shipped but never appeared in the README — the segment catalog listed `cache` as "neutral" with no mention that it turns red on a sharp hit-rate drop, nor that the trip/recover thresholds are configurable. Added a "`cache` drop detection" subsection, surfaced the keys in the example config, and corrected the catalog color note. This is the documentation outcome of CREAM-wwsdavum (configure-via-`/cc-cream:` command), which is otherwise declined as a dup of the deliberately-closed CREAM-udibxkch.
17
+
18
+ ## [0.3.2] — 2026-05-30
19
+
20
+ ### Fixed
21
+ - **`npm run coverage` (and the pre-push hook) no longer crash on Node ≥ 26.** `c8@11` does `require('yargs/yargs')`, and yargs 17's `exports` map resolves that to an **extensionless** CJS file; under Node 26's `require(ESM)` loader an extensionless file in a `"type": "module"` package is parsed as ESM, throwing `ReferenceError: require is not defined in ES module scope`. This broke the `simple-git-hooks` pre-push gate, forcing `SKIP_SIMPLE_GIT_HOOKS=1` on every push. Pinned yargs to `^18.0.0` via `overrides` — its `./yargs` export is a proper `.mjs` that Node 26 loads cleanly, and `c8@11` works against it unchanged (all 248 scenarios green under coverage). Dev-only; no runtime-dependency or published-package impact.
22
+ - **The uninstall receipt's cache-path escape hatch is now copy-pasteable.** It printed `…/cc-cream/cc-cream/<version>/src/install.js`, but the receipt reaches the user through the `/cc-cream:uninstall` slash command, whose output Claude Code renders as **markdown — which strips `<version>` as an HTML-like tag**. The user saw `cc-cream//src` (empty version) and pasting it failed with `MODULE_NOT_FOUND`, breaking the documented npm-free recovery path exactly when it's needed. The receipt now prints install.js's own resolved absolute path — via the slash command that's the real versioned cache copy — so it's both version-accurate and free of any stripped placeholder. The README uses a markdown-safe `VERSION` placeholder with an `ls` hint to read off the real one (CREAM-rhtrzwss).
23
+
24
+ ### Internal
25
+ - **Internal spec/working docs and the fp-managed `FP_CLAUDE.md` are no longer tracked in git.** `docs/` (PRD, release plan, code-review notes, install-lifecycle notes) and `FP_CLAUDE.md` are local working references, now gitignored and removed from the repo to keep the public tree focused on shipped code. No effect on the published npm package — its `files` allowlist (`src/`, `LICENSE`, `README.md`, `CHANGELOG.md`) never included them.
26
+
9
27
  ## [0.3.1] — 2026-05-30
10
28
 
11
29
  ### Fixed
package/README.md CHANGED
@@ -151,14 +151,17 @@ message — restart an already-open session to drop it immediately.
151
151
  > `statusLine` line still lingers in `settings.json`.
152
152
  >
153
153
  > To clear that leftover line once the plugin is gone, the **guaranteed** route is
154
- > the copy of the uninstaller still in the cache — npm-free and always present:
154
+ > the copy of the uninstaller still in the cache — npm-free and always present.
155
+ > `VERSION` is the single directory under that path (run the `ls` first to read it
156
+ > off); `/cc-cream:uninstall` also prints the fully-resolved command:
155
157
  > ```bash
156
- > node ~/.claude/plugins/cache/cc-cream/cc-cream/<version>/src/install.js --uninstall
158
+ > ls ~/.claude/plugins/cache/cc-cream/cc-cream/ # e.g. 0.3.1
159
+ > node ~/.claude/plugins/cache/cc-cream/cc-cream/VERSION/src/install.js --uninstall
157
160
  > # add --purge to also remove your config
158
161
  > ```
159
162
  > The npm bin does the same job, but **not always**: a *freshly published* version
160
- > is blocked by npm's min-package-age safe-chain guard (it reports "command not
161
- > found") until it ages in, so use it only if the cache route isn't handy:
163
+ > is blocked by npm's min-package-age safe-chain guard (it reports "No versions
164
+ > available") until it ages in, so use it only if the cache route isn't handy:
162
165
  > ```bash
163
166
  > npx -y -p cc-cream cc-cream-setup --uninstall
164
167
  > ```
@@ -207,7 +210,7 @@ cc-cream-setup --check-config # reports unknown keys / out-of-domain values; e
207
210
  "percentage": "consumed",
208
211
  "segments": {
209
212
  "ctx": { "on": true, "row": 1, "order": 2, "amber": 30, "orange": 40, "red": 50, "basis": "window", "ceiling": 200000, "display": "basis" },
210
- "cache": { "on": true, "row": 1, "order": 3 },
213
+ "cache": { "on": true, "row": 1, "order": 3, "drop": 20, "drop_recover": 80 },
211
214
  "write": { "on": false, "row": 1, "order": 3.5 },
212
215
  "ttl": { "on": true, "row": 1, "order": 4, "amber": 50, "red": 80 },
213
216
  "cost": { "on": true, "row": 1, "order": 5 },
@@ -251,7 +254,7 @@ Colored segments additionally accept threshold keys. Thresholds mark the
251
254
  | Segment | Default | Example | Meaning | Color |
252
255
  |---|---|---|---|---|
253
256
  | `ctx` | on, row 1 | `ctx:19% [38k]` | context-window occupancy + input-token magnitude | `<30` green · `30–40` amber · `40–50` orange · `≥50` red |
254
- | `cache` | on, row 1 | `cache:95%` | last-turn cache hit rate (reads / total tokens) | neutral |
257
+ | `cache` | on, row 1 | `cache:95%` | last-turn cache hit rate (reads / total tokens) | neutral; **red** on a sharp drop (see below) |
255
258
  | `write` | **off**, row 1 | `write:4%` | last-turn cache creation rate (new writes / total tokens) | neutral |
256
259
  | `ttl` | on, row 1 | `ttl:00:52` | time remaining before cache expires (counts down to 00:00) | `<50%` green · `50–80%` amber · `≥80%` red |
257
260
  | `cost` | on, row 1 | `~$4.50` | session cost incl. subagents; `~` = CC's estimate | neutral; hidden when zero |
@@ -298,6 +301,18 @@ default row via config must land in a zone to appear on row 1.
298
301
 
299
302
  Default: `amber: 30`, `orange: 40`, `red: 50` (percent consumed).
300
303
 
304
+ ### `cache` drop detection
305
+
306
+ The `cache` segment stays neutral while the hit rate is healthy, but turns **red**
307
+ when it falls sharply from one turn to the next — a cue that the prompt cache was
308
+ just invalidated (e.g. an edit far back in context forced a re-read). This relies
309
+ on per-session state, so it only fires when `session_id` is present in stdin.
310
+
311
+ - `drop`: percentage-point fall from the previous turn that trips red. Default `20`
312
+ (95% → 74% trips; 95% → 80% does not).
313
+ - `drop_recover`: once tripped, the segment stays red until the hit rate climbs
314
+ back to at least this value. Default `80`.
315
+
301
316
  ### `ttl` thresholds
302
317
 
303
318
  Default: `amber: 50`, `red: 80` (percent of the resolved TTL consumed).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-cream",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Claude Code cache/context/cost status-line tool",
5
5
  "directories": {
6
6
  "doc": "docs"
@@ -60,5 +60,8 @@
60
60
  "c8": "^11.0.0",
61
61
  "knip": "^6.14.2",
62
62
  "simple-git-hooks": "^2.13.1"
63
+ },
64
+ "overrides": {
65
+ "yargs": "^18.0.0"
63
66
  }
64
67
  }
package/src/install.js CHANGED
@@ -21,6 +21,12 @@ import { isEntrypoint } from './utils.js';
21
21
 
22
22
  export { writeFileAtomic } from './settings.js';
23
23
 
24
+ // Absolute path of THIS install.js. When the /cc-cream:uninstall slash command
25
+ // runs it, that's the versioned plugin-cache copy — the durable, npm-free
26
+ // escape hatch we advertise in the uninstall receipt (resolved, not guessed, so
27
+ // it carries the real version and no markdown-stripped placeholder).
28
+ const SELF_PATH = fileURLToPath(import.meta.url);
29
+
24
30
  const TRUST_NOTE =
25
31
  'The bar appears on your next message — restart only an already-open session, and the workspace must be trusted.';
26
32
 
@@ -255,18 +261,32 @@ async function uninstall({ purge }) {
255
261
  printUninstallReceipt();
256
262
  }
257
263
 
264
+ // Shorten an absolute path under $HOME to a `~/…` form for display. The shell
265
+ // still expands `~`, so the result stays copy-pasteable.
266
+ function tildeify(p) {
267
+ const home = os.homedir();
268
+ return p === home || p.startsWith(`${home}/`) ? `~${p.slice(home.length)}` : p;
269
+ }
270
+
258
271
  // The closing receipt. No Claude Code host removal path drops our statusLine OR
259
272
  // the version cache, so spell out what's gone, what the host leaves behind, and
260
273
  // the npm-free escape hatch (the lingering cache always has a working install.js).
261
274
  // See project memory cc-cream-plugin-lifecycle-findings.
275
+ //
276
+ // The escape-hatch line prints SELF_PATH — this install.js's real, resolved
277
+ // location — NOT a `<version>` placeholder. The receipt reaches the user through
278
+ // the slash command, whose output Claude Code renders as markdown; `<version>`
279
+ // was silently stripped to an empty segment (cc-cream//src), breaking copy-paste
280
+ // exactly when it's needed (CREAM-rhtrzwss). Via the slash command SELF_PATH IS
281
+ // the versioned cache copy, so the path is both accurate and markdown-safe.
262
282
  function printUninstallReceipt() {
263
283
  console.log('\nDone — the bar disappears on your next message (restart an already-open session to drop it now).');
264
284
  console.log('The host leaves the rest behind; to fully remove cc-cream:');
265
285
  console.log(' • Plugin: /plugin uninstall cc-cream then /plugin marketplace remove cc-cream');
266
286
  console.log(' • Version cache (never auto-removed): rm -rf ~/.claude/plugins/cache/cc-cream');
267
287
  console.log(' • The /cc-cream:* slash commands linger in this session until you restart Claude Code.');
268
- console.log('Already removed the plugin? This same uninstall lives in the cache:');
269
- console.log(' node ~/.claude/plugins/cache/cc-cream/cc-cream/<version>/src/install.js --uninstall [--purge]');
288
+ console.log('Re-run this uninstall later (e.g. the plugin is gone but the bar lingers) — it lives at:');
289
+ console.log(` node ${tildeify(SELF_PATH)} --uninstall [--purge]`);
270
290
  }
271
291
 
272
292
  // `cc-cream-setup --check-config`: lint ~/.claude/cc-cream.json against the
package/src/segments.js CHANGED
@@ -63,7 +63,7 @@ function segTtl(cfg, ttlMin, now, anchorMs) {
63
63
  if (!isNum(anchorMs)) return null;
64
64
  const elapsedMin = Math.floor(Math.max(0, now - anchorMs) / 60000);
65
65
  const remainingMin = Math.max(0, ttlMin - elapsedMin);
66
- const text = `ttl:${pad2(Math.floor(remainingMin / 60))}:${pad2(remainingMin % 60)}`;
66
+ const text = `ttl:${remainingMin}`;
67
67
  const s = cfg.segments.ttl;
68
68
  const pctTtl = ttlMin > 0 ? (elapsedMin / ttlMin) * 100 : 0;
69
69
  return { text, color: band(pctTtl, s.amber, s.red) };