@inbrace-tech/tokenline 1.2.1 → 1.2.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.
Files changed (3) hide show
  1. package/README.md +6 -7
  2. package/package.json +12 -11
  3. package/tokenline.sh +28 -3
package/README.md CHANGED
@@ -12,18 +12,17 @@
12
12
 
13
13
  Run the installer for your AI coding CLI:
14
14
 
15
- **Claude Code**
15
+ **Claude Code Per-project installation (`./.claude/settings.json`)**
16
16
  ```bash
17
- # Per-project installation (./.claude/settings.json)
18
17
  npx @inbrace-tech/tokenline init
19
-
20
- # Global installation (~/.claude/settings.json)
18
+ ```
19
+ **Claude Code Global installation (`~/.claude/settings.json`)**
20
+ ```bash
21
21
  npx @inbrace-tech/tokenline init --global
22
22
  ```
23
23
 
24
- **Antigravity CLI**
24
+ **Antigravity CLI Global installation (`~/.gemini/antigravity-cli/settings.json`)**
25
25
  ```bash
26
- # Global installation (~/.gemini/antigravity-cli/settings.json)
27
26
  npx @inbrace-tech/tokenline init --antigravity
28
27
  ```
29
28
 
@@ -68,7 +67,7 @@ LLMs are stateless — by default, they must reread your entire codebase context
68
67
 
69
68
  **Prompt Caching** solves this by saving that processed state in the provider's memory:
70
69
  - **Cache Write (Cold):** The model reads everything and stores the state. This costs slightly more than base tokens.
71
- - **Cache Hit (Warm):** If your prompt prefix matches the cached state exactly, the model skips the reading phase. This is **~90% cheaper** and starts responding almost instantly.
70
+ - **Cache Hit (Warm):** If your prompt prefix matches the cached state exactly, the model skips the reading phase. This is **~90% cheaper** (**97.5%** on Claude Fable 5.1 / Mythos 5.1, which bill cache hits at 0.025x base input) and starts responding almost instantly. `tokenline` picks the right multiplier from the active model.
72
71
  - **TTL (Time-To-Live):** The cache operates as a **sliding window**. Every cache hit resets the countdown to its full duration for free. The secret to minimizing rate-limit drain is adjusting your workflow pace to keep the cache continuously **HOT**.
73
72
 
74
73
  ### 💡 Pro-tip: Forcing a 5m TTL to save rate limits
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inbrace-tech/tokenline",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "A cache-aware statusline for AI coding CLIs — installs tokenline.sh and wires it into your Claude Code settings.",
5
5
  "bin": {
6
6
  "tokenline": "dist/cli.js"
@@ -37,29 +37,30 @@
37
37
  "access": "public"
38
38
  },
39
39
  "devDependencies": {
40
- "@changesets/cli": "^2.31.0",
40
+ "@changesets/cli": "^3.0.2",
41
41
  "@eslint/js": "10.0.1",
42
- "@types/node": "24.13.3",
43
- "@vitest/eslint-plugin": "1.6.23",
44
- "eslint": "10.7.0",
42
+ "@types/node": "24.13.4",
43
+ "@vitest/eslint-plugin": "1.6.27",
44
+ "eslint": "10.10.0",
45
45
  "eslint-config-prettier": "10.1.8",
46
- "eslint-plugin-n": "18.2.2",
46
+ "eslint-plugin-n": "18.3.0",
47
47
  "eslint-plugin-prettier": "5.5.6",
48
48
  "eslint-plugin-simple-import-sort": "13.0.0",
49
- "globals": "17.7.0",
50
- "prettier": "3.9.5",
49
+ "globals": "17.12.0",
50
+ "prettier": "3.9.6",
51
51
  "tsup": "^8.5.1",
52
52
  "typescript": "5.9.3",
53
- "typescript-eslint": "8.64.0",
54
- "vitest": "4.1.10"
53
+ "typescript-eslint": "8.70.0",
54
+ "vitest": "4.1.11"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "tsup",
58
- "typecheck": "tsc --noEmit -p tsconfig.json",
58
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p scripts/tsconfig.json",
59
59
  "lint": "eslint . --cache --cache-location node_modules/.cache/.eslintcache --fix",
60
60
  "format": "prettier --write \"src/**/*.ts\"",
61
61
  "format:check": "prettier --check \"src/**/*.ts\"",
62
62
  "test": "vitest run",
63
+ "audit:lockfile": "node --experimental-strip-types scripts/check-lockfile-release-age.mts",
63
64
  "test:watch": "vitest",
64
65
  "changeset": "changeset",
65
66
  "release": "pnpm build && changeset publish"
package/tokenline.sh CHANGED
@@ -56,6 +56,19 @@ epoch_from_iso() {
56
56
  fi
57
57
  }
58
58
 
59
+ epoch_from_reset() {
60
+ # rate_limits.*.resets_at -> epoch seconds; empty on failure.
61
+ # Claude Code sends Unix epoch seconds, which `date` cannot parse as a date
62
+ # (GNU needs '@<n>', BSD needs '-r <n>'), so an integer is taken as-is and
63
+ # never reaches `date`. Anything else is tried as ISO-8601.
64
+ local value="$1"
65
+ if [[ "$value" =~ ^[0-9]+$ ]]; then
66
+ printf '%s' "$value"
67
+ elif [ -n "$value" ]; then
68
+ epoch_from_iso "$value"
69
+ fi
70
+ }
71
+
59
72
  file_mtime() {
60
73
  local f="$1"
61
74
  if [ "$_stat_gnu" -eq 1 ]; then
@@ -95,7 +108,8 @@ parse_and_prepare_paths() {
95
108
  (.context_window.current_usage.input_tokens // 0),
96
109
  (.context_window.current_usage.output_tokens // 0),
97
110
  (.context_window.current_usage.cache_creation_input_tokens // 0),
98
- (.context_window.current_usage.cache_read_input_tokens // 0)' 2>/dev/null)
111
+ (.context_window.current_usage.cache_read_input_tokens // 0),
112
+ (.model.id // "")' 2>/dev/null)
99
113
 
100
114
  # Malformed or empty stdin: jq emits nothing, so the array is empty. Degrade to
101
115
  # a silent no-op render rather than leaking parse errors or rendering garbage —
@@ -108,13 +122,14 @@ parse_and_prepare_paths() {
108
122
  transcript_path="${_f[3]}"
109
123
  session_id="${_f[4]}"
110
124
  rl_5h_pct="${_f[5]}"
111
- rl_5h_reset=$(epoch_from_iso "${_f[6]}")
125
+ rl_5h_reset=$(epoch_from_reset "${_f[6]}")
112
126
  rl_7d_pct="${_f[7]}"
113
- rl_7d_reset=$(epoch_from_iso "${_f[8]}")
127
+ rl_7d_reset=$(epoch_from_reset "${_f[8]}")
114
128
  cur_input="${_f[9]}"
115
129
  cur_output="${_f[10]}"
116
130
  cur_cwrite="${_f[11]}"
117
131
  cur_cread="${_f[12]}"
132
+ model_id="${_f[13]}"
118
133
 
119
134
  # Computed: total input-only tokens used in the current context window
120
135
  tokens_used=$((cur_input + cur_cwrite + cur_cread))
@@ -141,6 +156,15 @@ parse_and_prepare_paths() {
141
156
  is_gemini=true
142
157
  fi
143
158
 
159
+ # Claude Fable 5.1 and Mythos 5.1 bill cache hits at 0.025x base input instead of
160
+ # the standard 0.1x. Match the API id (claude-fable-5-1[1m]) or the display name
161
+ # (Fable 5.1) so either field alone is enough.
162
+ discounted_cache_read=false
163
+ local discounted_re='(fable|mythos)[- ]5[-.]1([^0-9]|$)'
164
+ if [[ "${model_id,,}" =~ $discounted_re ]] || [[ "${model,,}" =~ $discounted_re ]]; then
165
+ discounted_cache_read=true
166
+ fi
167
+
144
168
  # Get the current epoch timestamp once to be reused across all calculations
145
169
  now=$(date +%s)
146
170
  }
@@ -402,6 +426,7 @@ compute_turn_breakdown() {
402
426
  output_mult="4"
403
427
  else
404
428
  read_mult="0.1"
429
+ [ "$discounted_cache_read" = true ] && read_mult="0.025"
405
430
  write_mult="1.25"
406
431
  [ "${ttl_label:-5m}" = "1h" ] && write_mult="2"
407
432
  input_mult="1"