claude-pace 0.7.1 → 0.7.2
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/README.md +8 -2
- package/claude-pace.sh +15 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,11 +80,17 @@ Claude Code polls the statusline every ~300ms:
|
|
|
80
80
|
|------|--------|-------|
|
|
81
81
|
| Model, context, cost | stdin JSON (single `jq` call) | None needed |
|
|
82
82
|
| Quota (5h, 7d, pace) | stdin `rate_limits` (CC >= 2.1.80) | None needed (real-time) |
|
|
83
|
-
| Quota fallback | Anthropic Usage API (CC < 2.1.80) |
|
|
84
|
-
| Git branch + diff | `git` commands |
|
|
83
|
+
| Quota fallback | Anthropic Usage API (CC < 2.1.80) | Private cache dir, 300s TTL, async background refresh |
|
|
84
|
+
| Git branch + diff | `git` commands | Private cache dir, 5s TTL |
|
|
85
85
|
|
|
86
86
|
On Claude Code >= 2.1.80, usage data comes directly from stdin. No network calls. On older versions, it falls back to the Usage API in a background subshell so the statusline never blocks.
|
|
87
87
|
|
|
88
|
+
Cache files live in a private per-user directory (`$XDG_RUNTIME_DIR/claude-pace` or `~/.cache/claude-pace`, mode 700). All cache reads are validated before use. No files are ever written to shared `/tmp`.
|
|
89
|
+
|
|
90
|
+
## Also by the Author
|
|
91
|
+
|
|
92
|
+
[**diffpane**](https://github.com/Astro-Han/diffpane) - Real-time TUI diff viewer for AI coding agents. See what Claude Code changes as it happens.
|
|
93
|
+
|
|
88
94
|
## License
|
|
89
95
|
|
|
90
96
|
MIT
|
package/claude-pace.sh
CHANGED
|
@@ -213,7 +213,7 @@ else
|
|
|
213
213
|
# Check in order: env var → macOS Keychain → credentials file → secret-tool (Linux).
|
|
214
214
|
_get_token() {
|
|
215
215
|
[ -n "$CLAUDE_CODE_OAUTH_TOKEN" ] && {
|
|
216
|
-
|
|
216
|
+
printf '%s' "$CLAUDE_CODE_OAUTH_TOKEN"
|
|
217
217
|
return
|
|
218
218
|
}
|
|
219
219
|
local b=""
|
|
@@ -222,18 +222,28 @@ else
|
|
|
222
222
|
[ -z "$b" ] && [ -f ~/.claude/.credentials.json ] && b=$(<~/.claude/.credentials.json)
|
|
223
223
|
[ -z "$b" ] && command -v secret-tool >/dev/null &&
|
|
224
224
|
b=$(timeout 2 secret-tool lookup service "Claude Code-credentials" 2>/dev/null)
|
|
225
|
-
[ -n "$b" ] && jq -
|
|
225
|
+
[ -n "$b" ] && jq -j '.claudeAiOauth.accessToken//empty' <<<"$b" 2>/dev/null
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
# ── _fetch_usage_api: direct API read into usage globals ──
|
|
229
229
|
# Used by both the cached background refresh path and the no-cache fallback.
|
|
230
230
|
_fetch_usage_api() {
|
|
231
231
|
local tk resp
|
|
232
|
-
|
|
232
|
+
# Command substitution strips trailing newlines. Append a sentinel byte only
|
|
233
|
+
# on success so malformed tokens with a trailing LF remain detectable here.
|
|
234
|
+
tk=$(_get_token && printf '\001') || return 1
|
|
235
|
+
[[ "$tk" == *$'\001' ]] || return 1
|
|
236
|
+
tk=${tk%$'\001'}
|
|
233
237
|
[ -n "$tk" ] || return 1
|
|
238
|
+
# OAuth bearer tokens must remain a single header line. Reject malformed
|
|
239
|
+
# credentials up front instead of letting curl parse injected CR/LF bytes.
|
|
240
|
+
case "$tk" in *$'\n'* | *$'\r'*) return 1 ;; esac
|
|
241
|
+
# Feed headers through process substitution so the bearer token stays out
|
|
242
|
+
# of curl argv while preserving literal bytes like quotes and backslashes.
|
|
234
243
|
resp=$(curl -s --max-time 3 \
|
|
235
|
-
-H
|
|
236
|
-
|
|
244
|
+
-H @<(printf 'Authorization: Bearer %s\n' "$tk"
|
|
245
|
+
printf '%s\n' 'anthropic-beta: oauth-2025-04-20'
|
|
246
|
+
printf '%s\n' 'Content-Type: application/json') \
|
|
237
247
|
"https://api.anthropic.com/api/oauth/usage" 2>/dev/null)
|
|
238
248
|
IFS=$'\t' read -r U5 U7 XO XU XL RM5 RM7 < <(jq -r '
|
|
239
249
|
def rmins: if . and . != "" then (sub("\\.[0-9]+"; "") | sub("\\+00:00$"; "Z") | fromdateiso8601) - (now|floor) | ./60|floor | if .<0 then 0 else . end else null end;
|