open-usage 0.3.2 → 0.5.0
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 +20 -1
- package/bin/open-usage.js +40 -9
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ open-usage --help
|
|
|
74
74
|
| `↵` | open the selected provider |
|
|
75
75
|
| `m` | overview mode: simplified / detailed |
|
|
76
76
|
| `w` | window: session / weekly (simplified mode only) |
|
|
77
|
-
| `t` | cycle range: today / 7d / 30d / month
|
|
77
|
+
| `t` | cycle range: today / 7d / 30d / month |
|
|
78
78
|
| `r` | refresh all providers |
|
|
79
79
|
| `/` | filter providers by name |
|
|
80
80
|
| `o` | re-run the setup wizard |
|
|
@@ -105,9 +105,28 @@ The check runs at most once a day, and [Configuration](#configuration) below cov
|
|
|
105
105
|
Those three are what ships today.
|
|
106
106
|
More providers are planned, so if a plan you pay for is missing, [open an issue](https://github.com/arionrefat/open-usage/issues) and say which one.
|
|
107
107
|
|
|
108
|
+
### Spend
|
|
109
|
+
|
|
110
|
+
The Claude Code screen also answers what a month cost, and where the money went.
|
|
111
|
+
|
|
112
|
+
Where Claude reports real money it is used as-is: `~/.claude.json` carries the account's credit spend, the monthly cap, and the remaining balance.
|
|
113
|
+
That figure is labelled `exact` and is never recomputed.
|
|
114
|
+
|
|
115
|
+
Where Claude reports no money - a subscription with usage credits switched off - the tokens are priced against a shipped rate table and the figure is labelled `est`, alongside the date the prices were taken.
|
|
116
|
+
Override any rate in `~/.config/open-usage/pricing.json`; a model with no published price is listed as unpriced rather than counted as free.
|
|
117
|
+
|
|
118
|
+
The per-model split is an apportionment, not a second opinion.
|
|
119
|
+
When an exact total covers the same window, each model's share is scaled to it, so the rows always add up to the headline and a stale price can move the split but never the total.
|
|
120
|
+
|
|
121
|
+
Claude keeps neither history: transcripts are pruned at `cleanupPeriodDays` (30 by default) and the account block reports only the window you are in.
|
|
122
|
+
So `open-usage` keeps its own record in `~/.config/open-usage/spend-history.json`, written from the day it is first run.
|
|
123
|
+
Month one answers this month; by month four it answers all four.
|
|
124
|
+
A month from before that file existed is shown as not recorded, never as zero.
|
|
125
|
+
|
|
108
126
|
`open-usage` is read-only, and there is no account to create and no key to paste.
|
|
109
127
|
It reuses the logins your CLIs already have: Claude and Codex limits come from their own signed-in CLIs, so their credentials are never read.
|
|
110
128
|
The one credential file it opens is OpenCode's `auth.json`, and only to show connection status - the key is masked on read and never displayed, logged, or sent anywhere.
|
|
129
|
+
It also reads `~/.claude.json`, but only the `cachedUsageUtilization` block Claude Code caches there, which is how the spend figures stay first-party; nothing else in that file is parsed, and no token in it is read.
|
|
111
130
|
|
|
112
131
|
Nothing is written outside its own config directory, and there is no telemetry or analytics of any kind.
|
|
113
132
|
It makes two outbound requests of its own accord.
|
package/bin/open-usage.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
// The binary embeds Bun, so nothing needs to be installed alongside it.
|
|
4
4
|
// Deliberately dependency-free and syntax-conservative so it runs on any Node.
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
-
import {
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { realpathSync } from "node:fs";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
7
9
|
|
|
8
10
|
const PLATFORM_PACKAGES = {
|
|
9
11
|
"darwin-arm64": "@open-usage/darwin-arm64",
|
|
@@ -44,13 +46,42 @@ function resolvePlatformBinary() {
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
export function launch(binary = resolvePlatformBinary(), args = process.argv.slice(2)) {
|
|
50
|
+
const child = spawn(binary, args, { stdio: "inherit" });
|
|
51
|
+
const signals = ["SIGTERM", "SIGINT", "SIGHUP"];
|
|
52
|
+
const handlers = new Map();
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
function cleanup() {
|
|
55
|
+
for (const [signal, handler] of handlers) process.off(signal, handler);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const signal of signals) {
|
|
59
|
+
const handler = () => {
|
|
60
|
+
try {
|
|
61
|
+
child.kill(signal);
|
|
62
|
+
} catch {
|
|
63
|
+
// The child may already be exiting; its exit event remains authoritative.
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
handlers.set(signal, handler);
|
|
67
|
+
process.on(signal, handler);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
child.once("error", (error) => {
|
|
71
|
+
cleanup();
|
|
72
|
+
fail("failed to start the platform binary", error.message);
|
|
73
|
+
});
|
|
74
|
+
child.once("exit", (code, signal) => {
|
|
75
|
+
cleanup();
|
|
76
|
+
if (signal) {
|
|
77
|
+
process.kill(process.pid, signal);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
process.exit(code ?? 1);
|
|
81
|
+
});
|
|
55
82
|
}
|
|
56
|
-
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
process.argv[1] &&
|
|
86
|
+
realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])
|
|
87
|
+
) launch();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-usage",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A terminal dashboard for unified AI plan usage across Claude Code, Codex, and OpenCode Go",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-only",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"shot": "bun scripts/shot.tsx",
|
|
42
42
|
"build": "bun build --compile --minify src/index.tsx --outfile dist/open-usage",
|
|
43
43
|
"build:npm": "bun scripts/build-npm-packages.ts",
|
|
44
|
+
"prepublishOnly": "bun scripts/check-prepublish.ts",
|
|
44
45
|
"version:set": "bun scripts/set-version.ts",
|
|
45
46
|
"test": "bun test",
|
|
46
47
|
"typecheck": "tsc --noEmit"
|
|
@@ -54,10 +55,10 @@
|
|
|
54
55
|
"typescript": "^5"
|
|
55
56
|
},
|
|
56
57
|
"optionalDependencies": {
|
|
57
|
-
"@open-usage/darwin-arm64": "0.
|
|
58
|
-
"@open-usage/linux-arm64": "0.
|
|
59
|
-
"@open-usage/linux-x64": "0.
|
|
60
|
-
"@open-usage/win32-arm64": "0.
|
|
61
|
-
"@open-usage/win32-x64": "0.
|
|
58
|
+
"@open-usage/darwin-arm64": "0.5.0",
|
|
59
|
+
"@open-usage/linux-arm64": "0.5.0",
|
|
60
|
+
"@open-usage/linux-x64": "0.5.0",
|
|
61
|
+
"@open-usage/win32-arm64": "0.5.0",
|
|
62
|
+
"@open-usage/win32-x64": "0.5.0"
|
|
62
63
|
}
|
|
63
64
|
}
|