ccusage 20.0.11 → 20.0.12

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 CHANGED
@@ -23,6 +23,27 @@
23
23
 
24
24
  > Analyze coding (agent) CLI token usage and costs from local data.
25
25
 
26
+ ## Major Sponsors
27
+
28
+ <p align="center">
29
+ <a href="https://coderabbit.link/ryoppippi">
30
+ <picture>
31
+ <source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/ccusage/ccusage@main/docs/public/coderabbit-logo-dark.svg">
32
+ <img src="https://cdn.jsdelivr.net/gh/ccusage/ccusage@main/docs/public/coderabbit-logo.svg" alt="CodeRabbit" width="320">
33
+ </picture>
34
+ </a>
35
+ &nbsp;&nbsp;&nbsp;&nbsp;
36
+ <a href="https://blacksmith.sh">
37
+ <img src="https://cdn.jsdelivr.net/gh/ccusage/ccusage@main/docs/public/blacksmith.png" alt="Blacksmith" width="320">
38
+ </a>
39
+ </p>
40
+
41
+ ## Quick Start
42
+
43
+ ```bash
44
+ npx ccusage@latest
45
+ ```
46
+
26
47
  ## Supported Sources
27
48
 
28
49
  ccusage reads local usage data from coding agent CLIs and turns it into daily, weekly, monthly, and session reports.
@@ -49,21 +70,21 @@ Use `ccusage daily`, `ccusage weekly`, `ccusage monthly`, or `ccusage session` t
49
70
 
50
71
  ## Installation
51
72
 
52
- ### Quick Start (Recommended)
73
+ ### Package Runners
53
74
 
54
75
  You can run ccusage directly without a global installation:
55
76
 
56
77
  ```bash
57
- # Recommended
58
- bunx ccusage
78
+ # npm
79
+ npx ccusage@latest
59
80
 
60
81
  # Nix
61
82
  nix run github:ccusage/ccusage -- daily
62
83
 
63
84
  # Alternative package runners
85
+ bunx ccusage
64
86
  pnpm dlx ccusage
65
87
  pnpx ccusage
66
- npx ccusage@latest
67
88
 
68
89
  # PR preview builds
69
90
  bunx -p https://pkg.pr.new/ccusage/ccusage@<pr-number> ccusage --offline
@@ -166,7 +187,7 @@ cd ccusage
166
187
  direnv allow
167
188
  ```
168
189
 
169
- The dev shell provides the pinned `pnpm`, Rust toolchain, GitHub CLI, git hooks, generated local agent skills, and project utilities from `flake.nix`. It also installs package dependencies from `pnpm-lock.yaml` when needed.
190
+ The dev shell provides the pinned `pnpm`, Rust toolchain, GitHub CLI, git hooks, generated local agent skills, package tooling, and project utilities from `flake.nix`. Run `pnpm install --frozen-lockfile` only when a task needs workspace `node_modules`.
170
191
 
171
192
  Run project tasks with `just` from inside the Nix environment (`just --list` shows every recipe):
172
193
 
@@ -198,26 +219,7 @@ The scheduled `update pricing` workflow runs the same update and validation, the
198
219
 
199
220
  </details>
200
221
 
201
- ## Sponsors
202
-
203
- <p align="center">
204
- <strong>Sponsored by</strong>
205
- </p>
206
-
207
- <p align="center">
208
- <a href="https://coderabbit.link/ryoppippi">
209
- <picture>
210
- <source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/ccusage/ccusage@main/docs/public/coderabbit-logo-dark.svg">
211
- <img src="https://cdn.jsdelivr.net/gh/ccusage/ccusage@main/docs/public/coderabbit-logo.svg" alt="CodeRabbit" width="320">
212
- </picture>
213
- </a>
214
- </p>
215
-
216
- <p align="center">
217
- <a href="https://blacksmith.sh">
218
- <img src="https://cdn.jsdelivr.net/gh/ccusage/ccusage@main/docs/public/blacksmith.png" alt="Blacksmith" width="320">
219
- </a>
220
- </p>
222
+ ## GitHub Sponsors
221
223
 
222
224
  <p align="center">
223
225
  <a href="https://github.com/sponsors/ryoppippi">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccusage",
3
- "version": "20.0.11",
3
+ "version": "20.0.12",
4
4
  "description": "Analyze coding (agent) CLI token usage and costs from local data",
5
5
  "homepage": "https://github.com/ccusage/ccusage#readme",
6
6
  "bugs": {
@@ -15,19 +15,26 @@
15
15
  },
16
16
  "funding": "https://github.com/sponsors/ryoppippi",
17
17
  "bin": {
18
- "ccusage": "./dist/cli.js"
18
+ "ccusage": "./src/cli.js"
19
19
  },
20
20
  "files": [
21
21
  "config-schema.json",
22
- "dist/**/*.js"
22
+ "src/cli.js"
23
23
  ],
24
24
  "type": "module",
25
+ "devDependencies": {
26
+ "@types/node": "^24.10.1",
27
+ "publint": "^0.3.12"
28
+ },
25
29
  "optionalDependencies": {
26
- "@ccusage/ccusage-darwin-arm64": "20.0.11",
27
- "@ccusage/ccusage-darwin-x64": "20.0.11",
28
- "@ccusage/ccusage-linux-x64": "20.0.11",
29
- "@ccusage/ccusage-win32-arm64": "20.0.11",
30
- "@ccusage/ccusage-win32-x64": "20.0.11",
31
- "@ccusage/ccusage-linux-arm64": "20.0.11"
30
+ "@ccusage/ccusage-darwin-arm64": "20.0.12",
31
+ "@ccusage/ccusage-darwin-x64": "20.0.12",
32
+ "@ccusage/ccusage-linux-arm64": "20.0.12",
33
+ "@ccusage/ccusage-win32-arm64": "20.0.12",
34
+ "@ccusage/ccusage-linux-x64": "20.0.12",
35
+ "@ccusage/ccusage-win32-x64": "20.0.12"
36
+ },
37
+ "scripts": {
38
+ "build": "scripts/ensure-native-binary.nu && publint"
32
39
  }
33
40
  }
package/src/cli.js ADDED
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+ // @ts-check
3
+ import { spawn } from 'node:child_process';
4
+ import { chmodSync, realpathSync, statSync } from 'node:fs';
5
+ import { createRequire } from 'node:module';
6
+ import process from 'node:process';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const require = createRequire(import.meta.url);
10
+
11
+ /**
12
+ * @typedef {{ args: string[]; command: string } | { errorMessage: string }} CliRuntime
13
+ * @typedef {{ mode: number }} FileMode
14
+ * @typedef {{ error?: Error; signal?: NodeJS.Signals | null; status: number | null }} NativeSpawnResult
15
+ * @typedef {(command: string, args: string[]) => Promise<NativeSpawnResult>} NativeSpawner
16
+ * @typedef {{ argvEntry?: string; moduleUrl: string; realpathPath?: (path: string) => string }} MainModuleOptions
17
+ */
18
+
19
+ /**
20
+ * @param {string} [platform]
21
+ * @param {string} [arch]
22
+ * @returns {string | undefined}
23
+ */
24
+ function getNativePackageName(platform = process.platform, arch = process.arch) {
25
+ if (platform === 'darwin') {
26
+ if (arch === 'arm64') {
27
+ return '@ccusage/ccusage-darwin-arm64';
28
+ }
29
+ if (arch === 'x64') {
30
+ return '@ccusage/ccusage-darwin-x64';
31
+ }
32
+ return undefined;
33
+ }
34
+
35
+ if (platform === 'linux') {
36
+ if (arch === 'arm64') {
37
+ return '@ccusage/ccusage-linux-arm64';
38
+ }
39
+ if (arch === 'x64') {
40
+ return '@ccusage/ccusage-linux-x64';
41
+ }
42
+ return undefined;
43
+ }
44
+
45
+ if (platform === 'win32') {
46
+ if (arch === 'arm64') {
47
+ return '@ccusage/ccusage-win32-arm64';
48
+ }
49
+ if (arch === 'x64') {
50
+ return '@ccusage/ccusage-win32-x64';
51
+ }
52
+ }
53
+
54
+ return undefined;
55
+ }
56
+
57
+ /**
58
+ * @param {string} [platform]
59
+ * @returns {string}
60
+ */
61
+ function getNativeBinarySubpath(platform = process.platform) {
62
+ return platform === 'win32' ? 'bin/ccusage.exe' : 'bin/ccusage';
63
+ }
64
+
65
+ /**
66
+ * @param {{ arch?: string; platform?: string; resolvePath?: (id: string) => string }} [options]
67
+ * @returns {string | undefined}
68
+ */
69
+ function resolveNativeBinary({
70
+ arch = process.arch,
71
+ platform = process.platform,
72
+ resolvePath = (id) => require.resolve(id),
73
+ } = {}) {
74
+ const packageName = getNativePackageName(platform, arch);
75
+ if (packageName == null) {
76
+ return undefined;
77
+ }
78
+
79
+ try {
80
+ return resolvePath(`${packageName}/${getNativeBinarySubpath(platform)}`);
81
+ } catch {
82
+ return undefined;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * @param {{ arch?: string; argv: string[]; nativeBinaryPath?: string | null; platform?: string }} options
88
+ * @returns {CliRuntime}
89
+ */
90
+ function resolveCliRuntime({
91
+ argv,
92
+ arch = process.arch,
93
+ nativeBinaryPath = resolveNativeBinary(),
94
+ platform = process.platform,
95
+ }) {
96
+ if (nativeBinaryPath != null) {
97
+ return {
98
+ args: argv,
99
+ command: nativeBinaryPath,
100
+ };
101
+ }
102
+
103
+ return {
104
+ errorMessage: `ccusage native binary is not available for ${platform}-${arch}. Reinstall ccusage so optional native dependencies are installed.\n`,
105
+ };
106
+ }
107
+
108
+ /**
109
+ * @param {unknown} error
110
+ * @returns {string}
111
+ */
112
+ function errorMessage(error) {
113
+ return error instanceof Error ? error.message : String(error);
114
+ }
115
+
116
+ /**
117
+ * @param {{ binaryPath: string; chmodPath?: (path: string, mode: number) => void; platform?: string; statPath?: (path: string) => FileMode }} options
118
+ * @returns {string | undefined}
119
+ */
120
+ function ensureNativeBinaryExecutable({
121
+ binaryPath,
122
+ chmodPath = chmodSync,
123
+ platform = process.platform,
124
+ statPath = statSync,
125
+ }) {
126
+ if (platform === 'win32') {
127
+ return undefined;
128
+ }
129
+
130
+ try {
131
+ const mode = statPath(binaryPath).mode;
132
+ if ((mode & 0o111) !== 0) {
133
+ return undefined;
134
+ }
135
+ chmodPath(binaryPath, 0o755);
136
+ return undefined;
137
+ } catch (error) {
138
+ return `ccusage native binary is not executable: ${errorMessage(error)}\n`;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * @param {MainModuleOptions} options
144
+ * @returns {boolean}
145
+ */
146
+ function isMainModule({ argvEntry = process.argv[1], moduleUrl, realpathPath = realpathSync }) {
147
+ if (argvEntry == null) {
148
+ return false;
149
+ }
150
+
151
+ const modulePath = fileURLToPath(moduleUrl);
152
+ try {
153
+ return realpathPath(modulePath) === realpathPath(argvEntry);
154
+ } catch {
155
+ return modulePath === argvEntry;
156
+ }
157
+ }
158
+
159
+ /**
160
+ * @returns {NativeSpawner}
161
+ */
162
+ function createNativeSpawner() {
163
+ return async (command, args) =>
164
+ new Promise((resolve) => {
165
+ const child = spawn(command, args, { stdio: 'inherit' });
166
+ child.on('error', (error) => {
167
+ resolve({
168
+ error,
169
+ signal: null,
170
+ status: null,
171
+ });
172
+ });
173
+ child.on('exit', (status, signal) => {
174
+ resolve({
175
+ signal,
176
+ status,
177
+ });
178
+ });
179
+ });
180
+ }
181
+
182
+ /**
183
+ * @param {string[]} argv
184
+ * @param {NativeSpawner} [spawnNative]
185
+ * @returns {Promise<number>}
186
+ */
187
+ async function runCli(argv, spawnNative = createNativeSpawner()) {
188
+ const runtime = resolveCliRuntime({ argv });
189
+ if ('errorMessage' in runtime) {
190
+ process.stderr.write(runtime.errorMessage);
191
+ return 1;
192
+ }
193
+
194
+ const executableError = ensureNativeBinaryExecutable({
195
+ binaryPath: runtime.command,
196
+ });
197
+ if (executableError != null) {
198
+ process.stderr.write(executableError);
199
+ return 1;
200
+ }
201
+
202
+ const result = await spawnNative(runtime.command, runtime.args);
203
+ if (result.error != null) {
204
+ process.stderr.write(`${result.error.message}\n`);
205
+ return 1;
206
+ }
207
+ if (result.signal != null) {
208
+ process.kill(process.pid, result.signal);
209
+ return 1;
210
+ }
211
+ return result.status ?? 1;
212
+ }
213
+
214
+ if (isMainModule({ moduleUrl: import.meta.url })) {
215
+ process.exitCode = await runCli(process.argv.slice(2));
216
+ }
217
+
218
+ export { ensureNativeBinaryExecutable, isMainModule, resolveCliRuntime, resolveNativeBinary };
package/dist/cli.js DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- import{createRequire as e}from"node:module";import{spawn as t}from"node:child_process";import{chmodSync as n,statSync as r}from"node:fs";import i from"node:process";const a=e(import.meta.url);function o(e=i.platform,t=i.arch){if(e===`darwin`)return t===`arm64`?`@ccusage/ccusage-darwin-arm64`:t===`x64`?`@ccusage/ccusage-darwin-x64`:void 0;if(e===`linux`)return t===`arm64`?`@ccusage/ccusage-linux-arm64`:t===`x64`?`@ccusage/ccusage-linux-x64`:void 0;if(e===`win32`){if(t===`arm64`)return`@ccusage/ccusage-win32-arm64`;if(t===`x64`)return`@ccusage/ccusage-win32-x64`}}function s(e=i.platform){return e===`win32`?`bin/ccusage.exe`:`bin/ccusage`}function c({arch:e=i.arch,platform:t=i.platform,resolvePath:n=e=>a.resolve(e)}={}){let r=o(t,e);if(r!=null)try{return n(`${r}/${s(t)}`)}catch{return}}function l({argv:e,arch:t=i.arch,nativeBinaryPath:n=c(),platform:r=i.platform}){return n==null?{errorMessage:`ccusage native binary is not available for ${r}-${t}. Reinstall ccusage so optional native dependencies are installed.\n`}:{args:e,command:n}}function u(e){return e instanceof Error?e.message:String(e)}function d({binaryPath:e,chmodPath:t=n,platform:a=i.platform,statPath:o=r}){if(a!==`win32`)try{if(o(e).mode&73)return;t(e,493);return}catch(e){return`ccusage native binary is not executable: ${u(e)}\n`}}function f(){return async(e,n)=>new Promise(r=>{let i=t(e,n,{stdio:`inherit`});i.on(`error`,e=>{r({error:e,signal:null,status:null})}),i.on(`exit`,(e,t)=>{r({signal:t,status:e})})})}async function p(e,t=f()){let n=l({argv:e});if(`errorMessage`in n)return i.stderr.write(n.errorMessage),1;let r=d({binaryPath:n.command});if(r!=null)return i.stderr.write(r),1;let a=await t(n.command,n.args);return a.error==null?a.signal==null?a.status??1:(i.kill(i.pid,a.signal),1):(i.stderr.write(`${a.error.message}\n`),1)}i.exitCode=await p(i.argv.slice(2));export{};
3
- //# sourceMappingURL=cli.js.map