claude-usage-explorer 1.0.1 → 1.1.5
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/.claude-plugin/marketplace.json +5 -30
- package/.claude-plugin/plugin.json +5 -11
- package/README.md +125 -116
- package/bin/claude-usage.mjs +4 -1
- package/claude-usage +20 -0
- package/hooks/usage-explorer.mjs +200 -63
- package/package.json +18 -48
- package/src/core.mjs +9 -5
- package/src/snapshot.mjs +1 -2
- package/src/tui.mjs +39 -21
- package/tests/core.test.mjs +30 -0
- package/tests/launcher.test.mjs +12 -0
- package/tests/mod.test.mjs +177 -0
- package/tests/official-spend.test.mjs +17 -0
- package/tests/render.test.mjs +23 -0
- package/tests/snapshot.test.mjs +15 -0
- package/tests/statusline.test.mjs +19 -0
- package/tests/tui.test.mjs +104 -0
- package/commands/tui.md +0 -12
- package/src/plan-usage.mjs +0 -39
|
@@ -1,30 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claude-usage-explorer-marketplace",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
"url": "https://github.com/IliasPol"
|
|
7
|
-
},
|
|
8
|
-
"plugins": [
|
|
9
|
-
{
|
|
10
|
-
"name": "claude-usage",
|
|
11
|
-
"source": "./",
|
|
12
|
-
"description": "Explore Claude Code projects, sessions, token usage, model breakdowns and estimated costs locally",
|
|
13
|
-
"version": "1.0.0",
|
|
14
|
-
"author": {
|
|
15
|
-
"name": "IliasPol"
|
|
16
|
-
},
|
|
17
|
-
"homepage": "https://github.com/IliasPol/claude-usage",
|
|
18
|
-
"repository": "https://github.com/IliasPol/claude-usage",
|
|
19
|
-
"license": "MIT",
|
|
20
|
-
"category": "development",
|
|
21
|
-
"tags": [
|
|
22
|
-
"claude-code",
|
|
23
|
-
"usage",
|
|
24
|
-
"analytics",
|
|
25
|
-
"tokens",
|
|
26
|
-
"terminal"
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
]
|
|
30
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-usage-explorer-marketplace",
|
|
3
|
+
"owner": {"name": "Claude Usage Explorer contributors"},
|
|
4
|
+
"plugins": [{"name": "claude-usage", "source": "./", "description": "Local Claude Code usage explorer"}]
|
|
5
|
+
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claude-usage",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
|
|
6
|
-
"name": "IliasPol"
|
|
7
|
-
},
|
|
8
|
-
"homepage": "https://github.com/IliasPol/claude-usage",
|
|
9
|
-
"repository": "https://github.com/IliasPol/claude-usage",
|
|
10
|
-
"license": "MIT"
|
|
11
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-usage",
|
|
3
|
+
"description": "Interactive native Claude Code usage sidebar and standalone TUI",
|
|
4
|
+
"version": "1.0.11"
|
|
5
|
+
}
|
package/README.md
CHANGED
|
@@ -1,116 +1,125 @@
|
|
|
1
|
-
# Claude Usage Explorer
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
##
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
# Claude Usage Explorer v1.0.4
|
|
2
|
+
|
|
3
|
+
Local, read-only analytics for Claude Code sessions. No external npm dependencies and no tmux requirement.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 20 or newer (22 LTS recommended).
|
|
8
|
+
- Claude Code **2.1.287+** for native Mods (newer versions recommended).
|
|
9
|
+
- Access to the same machine/filesystem where Claude stores its JSONL transcripts.
|
|
10
|
+
|
|
11
|
+
## Install and run
|
|
12
|
+
|
|
13
|
+
1. Extract the ZIP into a permanent folder, e.g. `~/tools/claude-usage-explorer`.
|
|
14
|
+
2. Run `./claude-usage tui` in that folder for the standalone full-screen explorer. On macOS, optionally run `./scripts/install-command.sh` once, then use `claude-usage tui` from any folder (ensure `~/.local/bin` is on your PATH).
|
|
15
|
+
3. Start Claude with `claude --plugin-dir "$HOME/tools/claude-usage-explorer"`.
|
|
16
|
+
4. In Claude Code type **`/usage-explorer`** to open the **native interactive sidebar**. In CLI, run `/tui fullscreen` first and use a wide terminal (100+ columns). Claude Desktop Code may dock the pane automatically if mods are supported locally.
|
|
17
|
+
5. Optional: **`/claude-usage:open`** launches the standalone TUI in a separate terminal. This skill requires one model invocation; the native mod `/usage-explorer` is registered directly and does not need one.
|
|
18
|
+
|
|
19
|
+
**asdf users:** switch to a compatible Node before starting Claude, e.g. `asdf shell nodejs 22.22.2`, or `export ASDF_NODEJS_VERSION=22.22.2` if your asdf lacks `shell`. The native mod starts `node` from Claude's environment.
|
|
20
|
+
|
|
21
|
+
## Native sidebar
|
|
22
|
+
|
|
23
|
+
- Click projects → sessions → agents → models, and Back to return.
|
|
24
|
+
- Switch periods (including current/previous billing cycle), filter entries, sort by tokens/cost, refresh.
|
|
25
|
+
- Automatic refresh every five seconds while the pane is open.
|
|
26
|
+
- Shows model usage and API-equivalent estimated cost (not subscription billing).
|
|
27
|
+
- Billing renewal date/time/timezone and custom date ranges are configured in the standalone TUI (`B`); the sidebar reads those saved settings.
|
|
28
|
+
- Unknown model prices are displayed as N/A rather than $0.
|
|
29
|
+
|
|
30
|
+
## Standalone TUI
|
|
31
|
+
|
|
32
|
+
`./claude-usage tui`
|
|
33
|
+
|
|
34
|
+
Supports all original navigation, custom dates, settings, live refresh and model breakdowns. `./claude-usage open` opens another terminal window when supported. `split` and its Claude skill were removed.
|
|
35
|
+
|
|
36
|
+
## Notes and limitations
|
|
37
|
+
|
|
38
|
+
The mod is implemented against Anthropic's current Mod API (session.start, command.run, ui.render, ui.open, ui.invalidate, process.run, clock.every). **It has not been verified in a live Claude Code or Claude Desktop installation**, so treat this as an integration candidate and report any host API errors. The standalone TUI is independently tested. The native sidebar uses clickable rows; arrow-key selection parity with the standalone TUI is not yet complete. Native mod availability depends on the Claude Code version and host.
|
|
39
|
+
|
|
40
|
+
The plugin reads local Claude transcript files and does not send them to an external service. Costs are estimates based on configured per-model pricing, not actual Claude subscription charges. Pricing defaults may need verification or overrides.
|
|
41
|
+
|
|
42
|
+
## Validation
|
|
43
|
+
|
|
44
|
+
Run `npm test` and `npm run check`. For native mod validation on a machine with Claude Code installed: `claude plugin validate .`.
|
|
45
|
+
|
|
46
|
+
## v1.0.4 sidebar fix
|
|
47
|
+
|
|
48
|
+
Adds the required `onSubmit` handler as well as a stable `key` for the filter `<Input>` component in Claude Code 2.1.311. If the sidebar remains blank after upgrading, restart Claude Code with the updated plugin folder. The native mod still invokes `node` from Claude’s own environment, so start Claude under Node 20+ (e.g. Node 22).
|
|
49
|
+
|
|
50
|
+
## Fixing old asdf commands and terminal flashes (v1.0.4)
|
|
51
|
+
|
|
52
|
+
The installer now creates a small executable wrapper instead of a symlink. This avoids resolving `bin/claude-usage.mjs` relative to `~/.local/bin`.
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
./scripts/install-command.sh
|
|
56
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
57
|
+
hash -r
|
|
58
|
+
type -a claude-usage
|
|
59
|
+
claude-usage tui
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If an old asdf shim still appears first, ensure `~/.local/bin` is prepended *after* asdf initialization in your shell startup file. The standalone TUI now clips terminal output, reserves the last terminal row, and ignores duplicate resize events to reduce blank-screen flashes.
|
|
63
|
+
|
|
64
|
+
## Sidebar controls (v1.0.4)
|
|
65
|
+
|
|
66
|
+
The sidebar keeps its period picker collapsed by default, with the usage summary and drill-down list at the top and actions at the bottom. Click **◷ Period** (or use its host-supported `p` hotkey while the panel is focused) to choose a billing period. Other actions: Back (`h`), Refresh (`r`), Models (`m`), and Sort (`s`). Click a project or session to drill down. These shortcuts depend on Claude Code focus and hotkey handling.
|
|
67
|
+
|
|
68
|
+
### Native sidebar keyboard and exit (v1.0.6)
|
|
69
|
+
|
|
70
|
+
- **Esc** closes the pane and returns focus to Claude (native `closeOnEscape`).
|
|
71
|
+
- **X** or **× Exit** closes the pane; **H** or **← Back** navigates up one level.
|
|
72
|
+
- **Backspace cannot be registered as a custom pane shortcut** in the current Claude mod interface.
|
|
73
|
+
- **Ctrl+X, then X** is the host-level close shortcut.
|
|
74
|
+
- The action bar is placed after a flex-growing results area, to anchor it near the bottom where supported by the host layout. Terminal dimensions and host rendering may affect placement.
|
|
75
|
+
- Claude’s built-in **/usage** shows account plan usage limits; Usage Explorer shows local history and API-equivalent cost estimates.
|
|
76
|
+
|
|
77
|
+
### Install both native sidebar and standalone CLI (v1.0.7)
|
|
78
|
+
|
|
79
|
+
Extract the release archive into `~/claude-usage-explorer-1.0.7`, then:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
cd ~/claude-usage-explorer-1.0.7
|
|
83
|
+
./scripts/install-command.sh
|
|
84
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
85
|
+
hash -r
|
|
86
|
+
type -a claude-usage
|
|
87
|
+
claude-usage tui
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Place `export PATH="$HOME/.local/bin:$PATH"` **after asdf initialization** in your shell startup file to keep the CLI command ahead of old asdf shims. Run `claude --plugin-dir "$HOME/claude-usage-explorer-1.0.7"`, enter `/tui fullscreen` if needed, then `/usage-explorer` to open the native sidebar.
|
|
91
|
+
|
|
92
|
+
### v1.0.8 display updates
|
|
93
|
+
|
|
94
|
+
The selected period persists across standalone TUI and native sidebar launches in `~/.claude-usage-explorer/settings.json` (`lastPeriod`). Each usage row shows a token percentage of its parent scope; the standalone TUI reserves four terminal columns on the right. Enterprise plan limits remain unavailable when no supported source provides them; no estimated spend is misrepresented as an official limit.
|
|
95
|
+
|
|
96
|
+
### Experimental official usage diagnostic (v1.0.9)
|
|
97
|
+
|
|
98
|
+
Inside `/usage-explorer`, select **Check official limits (opt-in)**. It first reads `$.session.usage()` and then, if Claude supplies an opaque first-party authorization handle, calls Anthropic's undocumented OAuth usage endpoint through `$.http.fetch`. The mod never reads or stores the token and only renders allowlisted numeric usage fields and reset timestamps; no raw response is logged or persisted. Enterprise monthly spending limits may not be included. This is an experimental diagnostic, not a stable public API integration. No automatic polling.
|
|
99
|
+
|
|
100
|
+
### Official account usage (v1.0.10)
|
|
101
|
+
|
|
102
|
+
Native sidebar automatically loads official utilization through Claude-hosted authorization when available, refreshes no more often than every 3 minutes, and supports manual refresh. It shows a percentage bar for recognized limits (including Enterprise `extra_usage`) but does not infer a dollar amount or billing cap. The endpoint is undocumented and may change; credentials and raw responses are never stored. Standalone TUI remains local-only.
|
|
103
|
+
|
|
104
|
+
### Usage response schema diagnostic (v1.0.11)
|
|
105
|
+
|
|
106
|
+
The native sidebar displays official account spending and available limit bars without the developer-only response field diagnostic. No automatic billing-period override is applied.
|
|
107
|
+
|
|
108
|
+
## v1.1.0 changes
|
|
109
|
+
|
|
110
|
+
- Native sidebar now reads official `spend.used` and `spend.limit` in minor currency units, with `extra_usage` as a fallback, and displays actual used/limit/remaining amounts with a higher-contrast utilization bar. This is separate from estimated local API cost.
|
|
111
|
+
- Native sidebar has a `? Help` control, and the summary follows the selected project/session scope.
|
|
112
|
+
- Standalone TUI summary follows the selected scope; tiny nonzero shares display `<0.1%`.
|
|
113
|
+
- In the standalone macOS TUI, select a session and press `e` to open it in Terminal.app; press uppercase `C` to copy its ID. These actions do not call a model. Terminal.app is used even if the current terminal is PortX.
|
|
114
|
+
- Native in-place session resume is **not implemented** because a supported session-switching Mods API has not been verified. Official billing-cycle reset timestamps also remain unverified; locally configured dates are not represented as official.
|
|
115
|
+
- `stats-cache.json` versus transcript token reconciliation remains open. Local transcript counts should not be treated as official account totals.
|
|
116
|
+
|
|
117
|
+
## v1.1.1 hotfix
|
|
118
|
+
- Fix native sidebar render failure: Help uses `z` instead of unsupported `?` button hotkey. Standalone TUI still uses `?` for Help.
|
|
119
|
+
- Add a regression test for Mods UI hotkey restrictions.
|
|
120
|
+
|
|
121
|
+
### Native session actions (v1.1.2)
|
|
122
|
+
|
|
123
|
+
Drill into a project and select a session. Use **Open session in Terminal** to resume in a new macOS Terminal window from the original project directory, or **Copy session ID** to copy the identifier. In-place switching of the active Claude Code session is not supported.
|
|
124
|
+
|
|
125
|
+
Agent rows display a readable agent type when available in local transcripts, otherwise “Subagent”; raw subagent IDs appear only after opening an agent. Session shortcuts O/C apply inside a session, not to highlighted Sessions-list entries.
|
package/bin/claude-usage.mjs
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
2
5
|
import { main } from '../src/core.mjs';
|
|
3
6
|
import { launchTui } from '../src/tui.mjs';
|
|
4
7
|
import { snapshot } from '../src/snapshot.mjs';
|
|
5
8
|
import {runStatusLine,installStatusLine} from '../src/statusline.mjs';
|
|
6
9
|
import {launchSidecar} from '../src/launcher.mjs';
|
|
7
|
-
(process.argv[2] === 'open' ? Promise.resolve(launchSidecar({cwd:process.env.CLAUDE_PROJECT_DIR||process.cwd()})).then(()=>console.log('Opened Claude Usage Explorer in a separate terminal.')) : process.argv[2] === 'snapshot' ? Promise.resolve(snapshot(process.argv.slice(3))).then(data=>console.log(JSON.stringify(data))) : process.argv[2] === 'tui' ? launchTui(process.argv.slice(3)) : process.argv[2] === 'statusline' ? runStatusLine() : process.argv[2] === 'statusline-install' ? Promise.resolve(console.log('Installed status line in',installStatusLine({force:process.argv.includes('--force')}))) : main(process.argv.slice(2))).catch(err => { console.error('Error:', err.message); process.exitCode = 1; });
|
|
10
|
+
(process.argv[2] === 'preference' ? Promise.resolve().then(()=>{const file=path.join(os.homedir(),'.claude-usage-explorer','settings.json');let obj={};try{obj=JSON.parse(fs.readFileSync(file,'utf8'));}catch{}if(process.argv[3]==='period' && ['all','cycle','previous-cycle','today','yesterday','7d','30d','month','previous-month'].includes(process.argv[4])){obj.lastPeriod=process.argv[4];fs.mkdirSync(path.dirname(file),{recursive:true,mode:0o700});fs.writeFileSync(file,JSON.stringify(obj,null,2)+'\n',{mode:0o600});}else throw Error('Invalid preference');}) : process.argv[2] === 'open' ? Promise.resolve(launchSidecar({cwd:process.env.CLAUDE_PROJECT_DIR||process.cwd()})).then(()=>console.log('Opened Claude Usage Explorer in a separate terminal.')) : process.argv[2] === 'snapshot' ? Promise.resolve(snapshot(process.argv.slice(3))).then(data=>console.log(JSON.stringify(data))) : process.argv[2] === 'tui' ? launchTui(process.argv.slice(3)) : process.argv[2] === 'statusline' ? runStatusLine() : process.argv[2] === 'statusline-install' ? Promise.resolve(console.log('Installed status line in',installStatusLine({force:process.argv.includes('--force')}))) : main(process.argv.slice(2))).catch(err => { console.error('Error:', err.message); process.exitCode = 1; });
|
package/claude-usage
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Portable launcher: run directly from this folder, without npm global shims.
|
|
3
|
+
set -eu
|
|
4
|
+
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
5
|
+
if [ -n "${CLAUDE_USAGE_NODE:-}" ]; then
|
|
6
|
+
NODE="$CLAUDE_USAGE_NODE"
|
|
7
|
+
elif command -v node >/dev/null 2>&1 && node -e 'process.exit(Number(process.versions.node.split(".")[0]) < 20)' >/dev/null 2>&1; then
|
|
8
|
+
NODE=$(command -v node)
|
|
9
|
+
else
|
|
10
|
+
NODE=''
|
|
11
|
+
for candidate in "$HOME"/.asdf/installs/nodejs/22.22.2/bin/node "$HOME"/.asdf/installs/nodejs/22.22.1/bin/node "$HOME"/.asdf/installs/nodejs/24.18.0/bin/node "$HOME"/.asdf/installs/nodejs/20.19.5/bin/node; do
|
|
12
|
+
if [ -x "$candidate" ]; then NODE="$candidate"; break; fi
|
|
13
|
+
done
|
|
14
|
+
if [ -z "$NODE" ]; then
|
|
15
|
+
printf '%s\n' 'Claude Usage Explorer requires Node.js 20+. Set CLAUDE_USAGE_NODE to its executable path.' >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
fi
|
|
19
|
+
if [ "$#" -eq 0 ]; then set -- tui; fi
|
|
20
|
+
exec "$NODE" "$ROOT/bin/claude-usage.mjs" "$@"
|