@swttch/extend-kit 0.3.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.
Files changed (42) hide show
  1. package/README.ko.md +445 -0
  2. package/README.md +445 -0
  3. package/dist/battery/api/client.d.ts +12 -0
  4. package/dist/battery/api/client.js +54 -0
  5. package/dist/battery/api/client.js.map +1 -0
  6. package/dist/battery/api/index.d.ts +3 -0
  7. package/dist/battery/api/index.js +3 -0
  8. package/dist/battery/api/index.js.map +1 -0
  9. package/dist/battery/api/oauth.d.ts +8 -0
  10. package/dist/battery/api/oauth.js +22 -0
  11. package/dist/battery/api/oauth.js.map +1 -0
  12. package/dist/battery/api/types.d.ts +49 -0
  13. package/dist/battery/api/types.js +2 -0
  14. package/dist/battery/api/types.js.map +1 -0
  15. package/dist/battery/auth/file-store.d.ts +2 -0
  16. package/dist/battery/auth/file-store.js +21 -0
  17. package/dist/battery/auth/file-store.js.map +1 -0
  18. package/dist/battery/auth/index.d.ts +6 -0
  19. package/dist/battery/auth/index.js +23 -0
  20. package/dist/battery/auth/index.js.map +1 -0
  21. package/dist/battery/auth/keychain.d.ts +2 -0
  22. package/dist/battery/auth/keychain.js +21 -0
  23. package/dist/battery/auth/keychain.js.map +1 -0
  24. package/dist/battery/auth/types.d.ts +16 -0
  25. package/dist/battery/auth/types.js +2 -0
  26. package/dist/battery/auth/types.js.map +1 -0
  27. package/dist/battery/errors.d.ts +12 -0
  28. package/dist/battery/errors.js +20 -0
  29. package/dist/battery/errors.js.map +1 -0
  30. package/dist/battery/index.d.ts +14 -0
  31. package/dist/battery/index.js +13 -0
  32. package/dist/battery/index.js.map +1 -0
  33. package/dist/cli/index.d.ts +2 -0
  34. package/dist/cli/index.js +79 -0
  35. package/dist/cli/index.js.map +1 -0
  36. package/dist/cli/oauth.d.ts +2 -0
  37. package/dist/cli/oauth.js +63 -0
  38. package/dist/cli/oauth.js.map +1 -0
  39. package/dist/index.d.ts +15 -0
  40. package/dist/index.js +18 -0
  41. package/dist/index.js.map +1 -0
  42. package/package.json +57 -0
package/README.md ADDED
@@ -0,0 +1,445 @@
1
+ # @swttch/extend-kit
2
+
3
+ [한국어](README.ko.md)
4
+
5
+ The companion tools [Swttch](https://github.com/Swttch/swttch) needs but cannot ship inside the plugin bundle, so they install on your machine instead. Each one is usable on its own — from a terminal or as a library — and the plugin is simply one caller among others.
6
+
7
+ | Tool | Why it lives outside the bundle |
8
+ | --- | --- |
9
+ | **battery** | Reads the Claude Code login stored on *your* machine (keychain, or a credentials file) |
10
+ | **stt** | Planned. Needs native binaries the plugin cannot carry |
11
+
12
+ ## battery
13
+
14
+ A TypeScript SDK and CLI that wraps the internal API of Claude Code. This allows programmatic access to API usage metrics and account information for Claude Code users.
15
+
16
+ > **Moving from `claude-code-battery`?** Change the import to `@swttch/extend-kit` and everything else stays the same — the exports and the `ccb` command are unchanged. The old package still works; it now re-exports this one.
17
+
18
+ ## Important Notes
19
+
20
+ - **Unofficial API**: This package uses the unofficial internal API of the Claude Code client. Anthropic does not officially support it, so it may change in the future.
21
+ - **Claude Code Login Required**: To use this SDK, you must have Claude Code installed and logged in on your local machine.
22
+ - **API Key Support**: You can also authenticate using Anthropic API Key. However, some OAuth-exclusive features (`getUsage()`, `getProfile()`) are not available with API Key authentication.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install @swttch/extend-kit
28
+ ```
29
+
30
+ Node.js version 20 or higher is required.
31
+
32
+ ## Quick Start
33
+
34
+ ### SDK Usage
35
+
36
+ ```typescript
37
+ import { ClaudeCodeClient } from '@swttch/extend-kit';
38
+
39
+ // No token needed — credentials are resolved automatically on first API call
40
+ const client = new ClaudeCodeClient();
41
+
42
+ const usage = await client.oauth.getUsage();
43
+ console.log(usage);
44
+
45
+ const profile = await client.oauth.getProfile();
46
+ console.log(profile);
47
+ ```
48
+
49
+ You can also pass a token explicitly if needed:
50
+
51
+ ```typescript
52
+ // With OAuth access token explicitly
53
+ const client = new ClaudeCodeClient(myOAuthAccessToken);
54
+ ```
55
+
56
+ If you prefer using Anthropic API Key:
57
+
58
+ ```typescript
59
+ // With Anthropic API Key
60
+ const client = new ClaudeCodeClient({ apiKey: process.env.ANTHROPIC_API_KEY });
61
+ ```
62
+
63
+ ### CLI Usage
64
+
65
+ After building, you can use the `ccb` command.
66
+
67
+ ```bash
68
+ # Build
69
+ npm run build
70
+
71
+ # Install globally (optional)
72
+ npm install -g .
73
+
74
+ # Get usage information
75
+ ccb oauth usage
76
+
77
+ # Get profile information
78
+ ccb oauth profile
79
+
80
+ # Output in JSON format
81
+ ccb oauth usage --json
82
+ ```
83
+
84
+ ## API Documentation
85
+
86
+ ### Authentication Functions
87
+
88
+ #### `getCredentials(): Promise<ClaudeCredentials>`
89
+
90
+ Reads credentials from the Claude Code storage.
91
+
92
+ - **macOS**: Reads from Keychain
93
+ - **Windows/Linux**: Reads from `~/.claude/.credentials.json` file
94
+ - **Customization**: Specify path with `CLAUDE_CONFIG_DIR` environment variable
95
+
96
+ ```typescript
97
+ const credentials = await getCredentials();
98
+ ```
99
+
100
+ #### `getAccessToken(credentials: ClaudeCredentials): string`
101
+
102
+ Extracts the access token from credentials.
103
+
104
+ ```typescript
105
+ const token = getAccessToken(credentials);
106
+ ```
107
+
108
+ #### `isTokenExpired(credentials: ClaudeCredentials): boolean`
109
+
110
+ Checks if the token has expired.
111
+
112
+ ```typescript
113
+ if (isTokenExpired(credentials)) {
114
+ console.log('Token has expired');
115
+ }
116
+ ```
117
+
118
+ ### Authentication Methods
119
+
120
+ | Method | Header | Use Case |
121
+ |--------|--------|----------|
122
+ | OAuth (auto) | `Authorization: Bearer {token}` | Claude Code logged-in users |
123
+ | OAuth (explicit) | `Authorization: Bearer {token}` | Manual OAuth token |
124
+ | API Key | `x-api-key: {key}` | Anthropic API users |
125
+
126
+ **Note**: OAuth-exclusive features (`getUsage()`, `getProfile()`) are not available with API Key authentication.
127
+
128
+ ### ClaudeCodeClient
129
+
130
+ A client class for making API calls. Access API endpoints through sub-modules.
131
+
132
+ #### `constructor(auth?: string | { apiKey: string })`
133
+
134
+ Initializes the client with OAuth access token or API Key. If no argument is provided, credentials are resolved automatically.
135
+
136
+ ```typescript
137
+ // Auto-resolve credentials
138
+ const client = new ClaudeCodeClient();
139
+
140
+ // Explicit OAuth token
141
+ const client = new ClaudeCodeClient(myAccessToken);
142
+
143
+ // API Key
144
+ const client = new ClaudeCodeClient({ apiKey: process.env.ANTHROPIC_API_KEY });
145
+ ```
146
+
147
+ #### `oauth: OAuthApi`
148
+
149
+ A sub-module that provides OAuth-related API methods.
150
+
151
+ ##### `oauth.getUsage(): Promise<UsageResponse>`
152
+
153
+ Retrieves usage information. Returns utilization data for 5-hour and 7-day buckets.
154
+
155
+ ```typescript
156
+ const usage = await client.oauth.getUsage();
157
+ // {
158
+ // five_hour: { utilization: 45, resets_at: '2024-01-01T12:00:00Z' },
159
+ // seven_day: { utilization: 62, resets_at: '2024-01-08T00:00:00Z' },
160
+ // seven_day_opus: { utilization: 30, resets_at: '2024-01-08T00:00:00Z' },
161
+ // seven_day_sonnet: { utilization: 55, resets_at: '2024-01-08T00:00:00Z' },
162
+ // extra_usage: { is_enabled: true, monthly_limit: 1000, ... }
163
+ // }
164
+ ```
165
+
166
+ ##### `oauth.getProfile(): Promise<ProfileResponse>`
167
+
168
+ Retrieves account and organization profile information.
169
+
170
+ ```typescript
171
+ const profile = await client.oauth.getProfile();
172
+ // {
173
+ // account: {
174
+ // uuid: '...',
175
+ // display_name: 'John Doe',
176
+ // email: 'john@example.com',
177
+ // has_claude_pro: true,
178
+ // ...
179
+ // },
180
+ // organization: {
181
+ // name: 'My Org',
182
+ // organization_type: 'free',
183
+ // subscription_status: 'active',
184
+ // ...
185
+ // },
186
+ // application: { ... }
187
+ // }
188
+ ```
189
+
190
+ ### Error Handling
191
+
192
+ All errors thrown by the SDK are instances of `CcbError`, which includes a machine-readable `code` and optional `hint`.
193
+
194
+ ```typescript
195
+ import { ClaudeCodeClient, CcbError } from '@swttch/extend-kit';
196
+
197
+ try {
198
+ const usage = await client.oauth.getUsage();
199
+ } catch (err) {
200
+ if (err instanceof CcbError) {
201
+ console.log(err.code); // 'unsupported_auth'
202
+ console.log(err.hint); // 'Check usage at console.anthropic.com, ...'
203
+ console.log(err.toJSON()); // { error: { code, message, hint } }
204
+ }
205
+ }
206
+ ```
207
+
208
+ #### Error Codes
209
+
210
+ | Code | Description | Hint |
211
+ |------|-------------|------|
212
+ | `unsupported_auth` | API Key does not support this operation | Check usage at console.anthropic.com, or use OAuth login |
213
+ | `credentials_not_found` | Credentials file not found | Run `claude login` to authenticate |
214
+ | `token_expired` | OAuth token has expired | Run `claude login` to refresh your token |
215
+ | `api_error` | API request failed (includes HTTP status) | — |
216
+ | `unsupported_platform` | Platform not supported | — |
217
+
218
+ ## Type Definitions
219
+
220
+ ### Authentication Types
221
+
222
+ ```typescript
223
+ interface ApiKeyAuth {
224
+ apiKey: string;
225
+ }
226
+
227
+ type ClientAuth = string | ApiKeyAuth;
228
+ ```
229
+
230
+ ### UsageResponse
231
+
232
+ ```typescript
233
+ interface UsageResponse {
234
+ five_hour: UsageBucket | null;
235
+ seven_day: UsageBucket | null;
236
+ seven_day_oauth_apps: UsageBucket | null;
237
+ seven_day_opus: UsageBucket | null;
238
+ seven_day_sonnet: UsageBucket | null;
239
+ seven_day_cowork: UsageBucket | null;
240
+ extra_usage: ExtraUsage | null;
241
+ }
242
+ ```
243
+
244
+ ### UsageBucket
245
+
246
+ ```typescript
247
+ interface UsageBucket {
248
+ utilization: number; // 0-100%
249
+ resets_at: string | null; // ISO 8601 format reset time
250
+ }
251
+ ```
252
+
253
+ ### ExtraUsage
254
+
255
+ ```typescript
256
+ interface ExtraUsage {
257
+ is_enabled: boolean;
258
+ monthly_limit: number | null;
259
+ used_credits: number | null;
260
+ utilization: number | null;
261
+ }
262
+ ```
263
+
264
+ ### ProfileResponse
265
+
266
+ ```typescript
267
+ interface ProfileResponse {
268
+ account: AccountInfo;
269
+ organization: OrganizationInfo;
270
+ application: ApplicationInfo;
271
+ }
272
+ ```
273
+
274
+ ### AccountInfo
275
+
276
+ ```typescript
277
+ interface AccountInfo {
278
+ uuid: string;
279
+ full_name: string;
280
+ display_name: string;
281
+ email: string;
282
+ has_claude_max: boolean;
283
+ has_claude_pro: boolean;
284
+ created_at: string;
285
+ }
286
+ ```
287
+
288
+ ### OrganizationInfo
289
+
290
+ ```typescript
291
+ interface OrganizationInfo {
292
+ uuid: string;
293
+ name: string;
294
+ organization_type: string;
295
+ billing_type: string;
296
+ rate_limit_tier: string;
297
+ has_extra_usage_enabled: boolean;
298
+ subscription_status: string;
299
+ subscription_created_at: string;
300
+ }
301
+ ```
302
+
303
+ ### ApplicationInfo
304
+
305
+ ```typescript
306
+ interface ApplicationInfo {
307
+ uuid: string;
308
+ name: string;
309
+ slug: string;
310
+ }
311
+ ```
312
+
313
+ ### ClaudeCredentials
314
+
315
+ ```typescript
316
+ interface ClaudeCredentials {
317
+ claudeAiOauth: ClaudeOAuthCredentials;
318
+ organizationUuid: string;
319
+ }
320
+
321
+ interface ClaudeOAuthCredentials {
322
+ accessToken: string;
323
+ refreshToken: string;
324
+ expiresAt: number;
325
+ scopes: string[];
326
+ subscriptionType: string;
327
+ rateLimitTier: string;
328
+ }
329
+ ```
330
+
331
+ ## CLI Commands
332
+
333
+ ### usage
334
+
335
+ Retrieves usage limit information.
336
+
337
+ ```bash
338
+ ccb oauth usage
339
+
340
+ # Output example:
341
+ # Usage:
342
+ # five hour: 45%
343
+ # seven day: 62% (resets 2024-01-08T00:00:00)
344
+ # seven day opus: 30% (resets 2024-01-08T00:00:00)
345
+ # seven day sonnet: 55% (resets 2024-01-08T00:00:00)
346
+ # extra usage: enabled
347
+ ```
348
+
349
+ ### profile
350
+
351
+ Retrieves account and organization profile.
352
+
353
+ ```bash
354
+ ccb oauth profile
355
+
356
+ # Output example:
357
+ # Profile:
358
+ # name: John Doe
359
+ # email: john@example.com
360
+ # plan: free
361
+ # org: My Organization
362
+ # status: active
363
+ ```
364
+
365
+ ### Options
366
+
367
+ - `--json`: Output in JSON format
368
+ - `-h, --help`: Show help
369
+ - `-v, --version`: Show version information
370
+
371
+ ```bash
372
+ ccb oauth usage --json
373
+ ccb oauth profile --json
374
+ ccb --version
375
+ ccb --help
376
+ ```
377
+
378
+ ### Error Output
379
+
380
+ Errors respect the `--json` flag:
381
+
382
+ ```bash
383
+ $ ccb oauth usage
384
+ Error: API Key authentication does not support usage/profile queries.
385
+ Hint: Check usage at console.anthropic.com, or use OAuth login (claude login)
386
+ ```
387
+
388
+ ```bash
389
+ $ ccb oauth usage --json
390
+ {
391
+ "error": {
392
+ "code": "unsupported_auth",
393
+ "message": "API Key authentication does not support usage/profile queries.",
394
+ "hint": "Check usage at console.anthropic.com, or use OAuth login (claude login)"
395
+ }
396
+ }
397
+ ```
398
+
399
+ ## Development
400
+
401
+ ### Installation
402
+
403
+ ```bash
404
+ npm install
405
+ ```
406
+
407
+ ### Build
408
+
409
+ ```bash
410
+ npm run build
411
+ ```
412
+
413
+ Compiles TypeScript to JavaScript. Output is saved in the `dist/` directory.
414
+
415
+ ### Watch Mode
416
+
417
+ ```bash
418
+ npm run dev
419
+ ```
420
+
421
+ Automatically compiles on file changes.
422
+
423
+ ### Type Checking
424
+
425
+ ```bash
426
+ npm run lint
427
+ ```
428
+
429
+ Runs TypeScript type checking.
430
+
431
+ ### Testing
432
+
433
+ ```bash
434
+ npm test
435
+ ```
436
+
437
+ Runs test files in `dist/**/*.test.js`.
438
+
439
+ ## License
440
+
441
+ MIT
442
+
443
+ ## Author
444
+
445
+ yhk1038
@@ -0,0 +1,12 @@
1
+ import { OAuthApi } from './oauth.js';
2
+ import type { ClientAuth } from '../auth/index.js';
3
+ export declare class ClaudeCodeClient {
4
+ private auth?;
5
+ private accessToken?;
6
+ private _oauth?;
7
+ constructor(auth?: ClientAuth);
8
+ get isApiKeyMode(): boolean;
9
+ get oauth(): OAuthApi;
10
+ private resolveToken;
11
+ _request<T>(path: string, headers?: Record<string, string>): Promise<T>;
12
+ }
@@ -0,0 +1,54 @@
1
+ import { OAuthApi } from './oauth.js';
2
+ import { getCredentials, getAccessToken, isApiKeyAuth } from '../auth/index.js';
3
+ import { CcbError } from '../errors.js';
4
+ const BASE_URL = 'https://api.anthropic.com';
5
+ export class ClaudeCodeClient {
6
+ auth;
7
+ accessToken;
8
+ _oauth;
9
+ constructor(auth) {
10
+ this.auth = auth;
11
+ if (typeof auth === 'string') {
12
+ this.accessToken = auth;
13
+ }
14
+ }
15
+ get isApiKeyMode() {
16
+ return isApiKeyAuth(this.auth);
17
+ }
18
+ get oauth() {
19
+ return this._oauth ??= new OAuthApi(this);
20
+ }
21
+ async resolveToken() {
22
+ if (!this.accessToken) {
23
+ const credentials = await getCredentials();
24
+ this.accessToken = getAccessToken(credentials);
25
+ }
26
+ return this.accessToken;
27
+ }
28
+ async _request(path, headers) {
29
+ let requestHeaders;
30
+ if (this.auth !== undefined && isApiKeyAuth(this.auth)) {
31
+ requestHeaders = {
32
+ 'x-api-key': this.auth.apiKey,
33
+ 'anthropic-version': '2023-06-01',
34
+ ...headers,
35
+ };
36
+ }
37
+ else {
38
+ const token = await this.resolveToken();
39
+ requestHeaders = {
40
+ Authorization: `Bearer ${token}`,
41
+ ...headers,
42
+ };
43
+ }
44
+ const response = await fetch(`${BASE_URL}${path}`, {
45
+ method: 'GET',
46
+ headers: requestHeaders,
47
+ });
48
+ if (!response.ok) {
49
+ throw new CcbError(`API error ${response.status}: ${response.statusText}`, 'api_error');
50
+ }
51
+ return response.json();
52
+ }
53
+ }
54
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/battery/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAE7C,MAAM,OAAO,gBAAgB;IACnB,IAAI,CAAc;IAClB,WAAW,CAAU;IACrB,MAAM,CAAY;IAE1B,YAAY,IAAiB;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,YAAY;QACd,OAAO,YAAY,CAAC,IAAI,CAAC,IAAkB,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;YAC3C,IAAI,CAAC,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAI,IAAY,EAAE,OAAgC;QAC9D,IAAI,cAAsC,CAAC;QAE3C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,cAAc,GAAG;gBACf,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;gBAC7B,mBAAmB,EAAE,YAAY;gBACjC,GAAG,OAAO;aACX,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,cAAc,GAAG;gBACf,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,GAAG,OAAO;aACX,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,EAAE;YACjD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,cAAc;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,QAAQ,CAAC,aAAa,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,EAAE,WAAW,CAAC,CAAC;QAC1F,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export { ClaudeCodeClient } from './client.js';
2
+ export { OAuthApi } from './oauth.js';
3
+ export type { UsageResponse, UsageBucket, ExtraUsage, ProfileResponse, AccountInfo, OrganizationInfo, ApplicationInfo, } from './types.js';
@@ -0,0 +1,3 @@
1
+ export { ClaudeCodeClient } from './client.js';
2
+ export { OAuthApi } from './oauth.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/battery/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ClaudeCodeClient } from './client.js';
2
+ import type { UsageResponse, ProfileResponse } from './types.js';
3
+ export declare class OAuthApi {
4
+ private readonly client;
5
+ constructor(client: ClaudeCodeClient);
6
+ getUsage(): Promise<UsageResponse>;
7
+ getProfile(): Promise<ProfileResponse>;
8
+ }
@@ -0,0 +1,22 @@
1
+ import { CcbError } from '../errors.js';
2
+ export class OAuthApi {
3
+ client;
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ async getUsage() {
8
+ if (this.client.isApiKeyMode) {
9
+ throw new CcbError('API Key authentication does not support usage/profile queries.', 'unsupported_auth', 'Check usage at console.anthropic.com, or use OAuth login (claude login)');
10
+ }
11
+ return this.client._request('/api/oauth/usage', {
12
+ 'anthropic-beta': 'oauth-2025-04-20',
13
+ });
14
+ }
15
+ async getProfile() {
16
+ if (this.client.isApiKeyMode) {
17
+ throw new CcbError('API Key authentication does not support usage/profile queries.', 'unsupported_auth', 'Check usage at console.anthropic.com, or use OAuth login (claude login)');
18
+ }
19
+ return this.client._request('/api/oauth/profile');
20
+ }
21
+ }
22
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/battery/api/oauth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,OAAO,QAAQ;IACU;IAA7B,YAA6B,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;IAAG,CAAC;IAEzD,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,MAAM,IAAI,QAAQ,CAChB,gEAAgE,EAChE,kBAAkB,EAClB,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAgB,kBAAkB,EAAE;YAC7D,gBAAgB,EAAE,kBAAkB;SACrC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,MAAM,IAAI,QAAQ,CAChB,gEAAgE,EAChE,kBAAkB,EAClB,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAkB,oBAAoB,CAAC,CAAC;IACrE,CAAC;CACF"}
@@ -0,0 +1,49 @@
1
+ export interface UsageBucket {
2
+ utilization: number;
3
+ resets_at: string | null;
4
+ }
5
+ export interface ExtraUsage {
6
+ is_enabled: boolean;
7
+ monthly_limit: number | null;
8
+ used_credits: number | null;
9
+ utilization: number | null;
10
+ }
11
+ export interface UsageResponse {
12
+ five_hour: UsageBucket | null;
13
+ seven_day: UsageBucket | null;
14
+ seven_day_oauth_apps: UsageBucket | null;
15
+ seven_day_opus: UsageBucket | null;
16
+ seven_day_sonnet: UsageBucket | null;
17
+ seven_day_cowork: UsageBucket | null;
18
+ iguana_necktie: unknown | null;
19
+ extra_usage: ExtraUsage | null;
20
+ }
21
+ export interface AccountInfo {
22
+ uuid: string;
23
+ full_name: string;
24
+ display_name: string;
25
+ email: string;
26
+ has_claude_max: boolean;
27
+ has_claude_pro: boolean;
28
+ created_at: string;
29
+ }
30
+ export interface OrganizationInfo {
31
+ uuid: string;
32
+ name: string;
33
+ organization_type: string;
34
+ billing_type: string;
35
+ rate_limit_tier: string;
36
+ has_extra_usage_enabled: boolean;
37
+ subscription_status: string;
38
+ subscription_created_at: string;
39
+ }
40
+ export interface ApplicationInfo {
41
+ uuid: string;
42
+ name: string;
43
+ slug: string;
44
+ }
45
+ export interface ProfileResponse {
46
+ account: AccountInfo;
47
+ organization: OrganizationInfo;
48
+ application: ApplicationInfo;
49
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/battery/api/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ import type { ClaudeCredentials } from './types.js';
2
+ export declare function readFileCredentials(): Promise<ClaudeCredentials>;
@@ -0,0 +1,21 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { CcbError } from '../errors.js';
5
+ function getCredentialsFilePath() {
6
+ const configDir = process.env['CLAUDE_CONFIG_DIR'] ?? path.join(os.homedir(), '.claude');
7
+ return path.join(configDir, '.credentials.json');
8
+ }
9
+ export async function readFileCredentials() {
10
+ const filePath = getCredentialsFilePath();
11
+ let raw;
12
+ try {
13
+ raw = await readFile(filePath, 'utf-8');
14
+ }
15
+ catch (err) {
16
+ throw new CcbError(`Failed to read credentials file at ${filePath}: ${err.message}`, 'credentials_not_found', "Run 'claude login' to authenticate");
17
+ }
18
+ const parsed = JSON.parse(raw);
19
+ return parsed;
20
+ }
21
+ //# sourceMappingURL=file-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-store.js","sourceRoot":"","sources":["../../../src/battery/auth/file-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,SAAS,sBAAsB;IAC7B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACzF,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;IAE1C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,QAAQ,CAChB,sCAAsC,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,EAC3E,uBAAuB,EACvB,oCAAoC,CACrC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;IACpD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ClaudeCredentials, ClientAuth, ApiKeyAuth } from './types.js';
2
+ export type { ClaudeCredentials, ClaudeOAuthCredentials, ApiKeyAuth, ClientAuth } from './types.js';
3
+ export declare function isApiKeyAuth(auth: ClientAuth): auth is ApiKeyAuth;
4
+ export declare function getCredentials(): Promise<ClaudeCredentials>;
5
+ export declare function getAccessToken(credentials: ClaudeCredentials): string;
6
+ export declare function isTokenExpired(credentials: ClaudeCredentials): boolean;
@@ -0,0 +1,23 @@
1
+ import { readKeychainCredentials } from './keychain.js';
2
+ import { readFileCredentials } from './file-store.js';
3
+ import { CcbError } from '../errors.js';
4
+ export function isApiKeyAuth(auth) {
5
+ return typeof auth === 'object' && 'apiKey' in auth;
6
+ }
7
+ export async function getCredentials() {
8
+ const platform = process.platform;
9
+ if (platform === 'darwin') {
10
+ return readKeychainCredentials();
11
+ }
12
+ if (platform === 'win32' || platform === 'linux') {
13
+ return readFileCredentials();
14
+ }
15
+ throw new CcbError(`Unsupported platform: ${platform}.`, 'unsupported_platform');
16
+ }
17
+ export function getAccessToken(credentials) {
18
+ return credentials.claudeAiOauth.accessToken;
19
+ }
20
+ export function isTokenExpired(credentials) {
21
+ return Date.now() >= credentials.claudeAiOauth.expiresAt;
22
+ }
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/battery/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAElC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,uBAAuB,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjD,OAAO,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,IAAI,QAAQ,CAAC,yBAAyB,QAAQ,GAAG,EAAE,sBAAsB,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA8B;IAC3D,OAAO,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA8B;IAC3D,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC;AAC3D,CAAC"}