claudemon 0.2.0 → 0.2.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 +43 -8
- package/dist/api.d.ts +0 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -4
- package/dist/api.js.map +1 -1
- package/dist/auth.d.ts +3 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +123 -53
- package/dist/auth.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +32 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +41 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Claudemon
|
|
2
2
|
|
|
3
3
|
Claude Usage Monitor TUI - monitor your Claude Pro/Max plan quota in real-time.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
[](https://www.npmjs.com/package/claudemon)
|
|
6
8
|
[](https://www.npmjs.com/package/claudemon)
|
|
7
9
|
[](https://github.com/anistark/claudemon)
|
|
8
10
|

|
|
9
11
|
[](https://opensource.org/licenses/MIT)
|
|
10
12
|
|
|
13
|
+

|
|
14
|
+
|
|
11
15
|
## Install
|
|
12
16
|
|
|
13
17
|
```sh
|
|
@@ -29,20 +33,47 @@ claudemon setup
|
|
|
29
33
|
|
|
30
34
|
This detects your Claude Code OAuth credentials automatically. If you haven't logged in to Claude Code yet, it will guide you through the process.
|
|
31
35
|
|
|
32
|
-
##
|
|
36
|
+
## Commands
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
claudemon
|
|
37
|
-
|
|
38
|
+
| Command | Description |
|
|
39
|
+
|---------|-------------|
|
|
40
|
+
| `claudemon` | Launch the TUI dashboard |
|
|
41
|
+
| `claudemon setup` | Interactive OAuth setup (skips if already authenticated) |
|
|
42
|
+
| `claudemon setup --re` | Force re-authentication, overwriting existing token |
|
|
43
|
+
| `claudemon --help`, `-h` | Show help message |
|
|
44
|
+
| `claudemon --version` | Show version |
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
## Keybindings (in TUI)
|
|
40
47
|
|
|
41
48
|
| Key | Action |
|
|
42
49
|
|-----|--------|
|
|
43
50
|
| `q` | Quit |
|
|
44
51
|
| `r` | Force refresh |
|
|
45
|
-
| `?` |
|
|
52
|
+
| `?` | Toggle help |
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
Config file: `~/.config/claudemon/config.toml`
|
|
57
|
+
|
|
58
|
+
| Key | Type | Default | Description |
|
|
59
|
+
|-----|------|---------|-------------|
|
|
60
|
+
| `plan_type` | string | `"pro"` | Claude plan type (`pro` or `max`) |
|
|
61
|
+
| `refresh_interval` | number | `5` | Auto-refresh interval in seconds |
|
|
62
|
+
|
|
63
|
+
<details>
|
|
64
|
+
<summary>Advanced OAuth settings (usually no need to change)</summary>
|
|
65
|
+
|
|
66
|
+
| Key | Type | Default | Description |
|
|
67
|
+
|-----|------|---------|-------------|
|
|
68
|
+
| `oauth_client_id` | string | `"9d1c250a-..."` | Public OAuth client ID for Anthropic PKCE flow |
|
|
69
|
+
| `oauth_authorize_url` | string | `"https://claude.ai/oauth/authorize"` | Authorization endpoint |
|
|
70
|
+
| `oauth_token_url` | string | `"https://console.anthropic.com/v1/oauth/token"` | Token exchange endpoint |
|
|
71
|
+
| `oauth_redirect_uri` | string | `"https://console.anthropic.com/oauth/code/callback"` | OAuth redirect URI |
|
|
72
|
+
| `oauth_scopes` | string | `"org:create_api_key user:profile user:inference"` | OAuth scopes |
|
|
73
|
+
| `oauth_usage_url` | string | `"https://api.anthropic.com/api/oauth/usage"` | Usage/quota API endpoint |
|
|
74
|
+
| `oauth_beta_header` | string | `"oauth-2025-04-20"` | Required beta header for the usage API |
|
|
75
|
+
|
|
76
|
+
</details>
|
|
46
77
|
|
|
47
78
|
## Development
|
|
48
79
|
|
|
@@ -64,3 +95,7 @@ just dev
|
|
|
64
95
|
# Type check
|
|
65
96
|
just lint
|
|
66
97
|
```
|
|
98
|
+
|
|
99
|
+
<img width="1906" height="1017" alt="claudemon-ss" src="https://github.com/user-attachments/assets/f1b818e1-f34b-4703-8cfb-cd630342b1b5" />
|
|
100
|
+
|
|
101
|
+
[MIT License](./LICENSE)
|
package/dist/api.d.ts
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* API client for Claude OAuth usage endpoint.
|
|
3
3
|
*/
|
|
4
4
|
import { type QuotaData } from "./models.js";
|
|
5
|
-
export declare const OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
|
|
6
|
-
export declare const OAUTH_BETA_HEADER = "oauth-2025-04-20";
|
|
7
5
|
export declare class QuotaFetchError extends Error {
|
|
8
6
|
constructor(message: string);
|
|
9
7
|
}
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAmB,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAmB,KAAK,SAAS,EAAmB,MAAM,aAAa,CAAC;AAG/E,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,eAAe;gBAC1C,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAuCvE"}
|
package/dist/api.js
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* API client for Claude OAuth usage endpoint.
|
|
3
3
|
*/
|
|
4
4
|
import { createQuotaData } from "./models.js";
|
|
5
|
-
|
|
6
|
-
export const OAUTH_BETA_HEADER = "oauth-2025-04-20";
|
|
5
|
+
import { loadConfig } from "./config.js";
|
|
7
6
|
export class QuotaFetchError extends Error {
|
|
8
7
|
constructor(message) {
|
|
9
8
|
super(message);
|
|
@@ -17,13 +16,16 @@ export class AuthenticationError extends QuotaFetchError {
|
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
18
|
export async function fetchQuota(oauthToken) {
|
|
19
|
+
const config = loadConfig();
|
|
20
|
+
const usageUrl = config["oauth_usage_url"];
|
|
21
|
+
const betaHeader = config["oauth_beta_header"];
|
|
20
22
|
const headers = {
|
|
21
23
|
Authorization: `Bearer ${oauthToken}`,
|
|
22
|
-
"anthropic-beta":
|
|
24
|
+
"anthropic-beta": betaHeader,
|
|
23
25
|
};
|
|
24
26
|
let resp;
|
|
25
27
|
try {
|
|
26
|
-
resp = await fetch(
|
|
28
|
+
resp = await fetch(usageUrl, {
|
|
27
29
|
headers,
|
|
28
30
|
signal: AbortSignal.timeout(15000),
|
|
29
31
|
});
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAmC,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Reads Claude Code's OAuth credentials from:
|
|
5
5
|
* 1. macOS Keychain ("Claude Code-credentials")
|
|
6
6
|
* 2. ~/.claude/.credentials.json (Linux / older versions)
|
|
7
|
+
*
|
|
8
|
+
* Can also perform its own OAuth PKCE flow against Anthropic's endpoints.
|
|
7
9
|
*/
|
|
8
10
|
export declare function storeToken(tokenData: Record<string, unknown>): void;
|
|
9
11
|
export declare function loadToken(): Record<string, unknown> | null;
|
|
@@ -13,5 +15,5 @@ export declare function isAuthenticated(): boolean;
|
|
|
13
15
|
export declare function clearToken(): void;
|
|
14
16
|
export declare function openBrowser(url: string): boolean;
|
|
15
17
|
export declare function detectPlanType(): string;
|
|
16
|
-
export declare function interactiveSetup(): Promise<void>;
|
|
18
|
+
export declare function interactiveSetup(forceReauth?: boolean): Promise<void>;
|
|
17
19
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmFH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAInE;AAED,wBAAgB,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAU1D;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAc7C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAoBhD;AAYD,wBAAgB,cAAc,IAAI,MAAM,CAUvC;AA+GD,wBAAsB,gBAAgB,CAAC,WAAW,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEzE"}
|
package/dist/auth.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Reads Claude Code's OAuth credentials from:
|
|
5
5
|
* 1. macOS Keychain ("Claude Code-credentials")
|
|
6
6
|
* 2. ~/.claude/.credentials.json (Linux / older versions)
|
|
7
|
+
*
|
|
8
|
+
* Can also perform its own OAuth PKCE flow against Anthropic's endpoints.
|
|
7
9
|
*/
|
|
8
10
|
import { execFileSync, spawn } from "node:child_process";
|
|
9
11
|
import { chmodSync, existsSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
@@ -11,6 +13,7 @@ import { homedir, platform } from "node:os";
|
|
|
11
13
|
import { join } from "node:path";
|
|
12
14
|
import { createInterface } from "node:readline/promises";
|
|
13
15
|
import { stdin, stdout } from "node:process";
|
|
16
|
+
import { webcrypto } from "node:crypto";
|
|
14
17
|
import { CONFIG_DIR, ensureConfigDir, loadConfig, saveConfig } from "./config.js";
|
|
15
18
|
const TOKEN_FILE = join(CONFIG_DIR, "token.json");
|
|
16
19
|
const CLAUDE_CREDENTIALS_FILE = join(homedir(), ".claude", ".credentials.json");
|
|
@@ -48,8 +51,12 @@ function getClaudeCodeCredentials() {
|
|
|
48
51
|
const data = reader();
|
|
49
52
|
if (data) {
|
|
50
53
|
const oauth = data["claudeAiOauth"];
|
|
51
|
-
if (oauth?.accessToken)
|
|
54
|
+
if (oauth?.accessToken) {
|
|
55
|
+
// Skip expired credentials
|
|
56
|
+
if (oauth.expiresAt && oauth.expiresAt < Date.now())
|
|
57
|
+
continue;
|
|
52
58
|
return oauth;
|
|
59
|
+
}
|
|
53
60
|
}
|
|
54
61
|
}
|
|
55
62
|
return null;
|
|
@@ -73,14 +80,18 @@ export function loadToken() {
|
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
export function getOAuthToken() {
|
|
76
|
-
// Prefer Claude Code's live credentials (
|
|
83
|
+
// Prefer Claude Code's live credentials (skips expired ones)
|
|
77
84
|
const creds = getClaudeCodeCredentials();
|
|
78
85
|
if (creds?.accessToken)
|
|
79
86
|
return creds.accessToken;
|
|
80
|
-
// Fallback to
|
|
87
|
+
// Fallback to claudemon's own stored token
|
|
81
88
|
const tokenData = loadToken();
|
|
82
89
|
if (!tokenData)
|
|
83
90
|
return null;
|
|
91
|
+
// Check expiry on stored token
|
|
92
|
+
const expiresAt = tokenData["expires_at"];
|
|
93
|
+
if (expiresAt && expiresAt < Date.now())
|
|
94
|
+
return null;
|
|
84
95
|
return tokenData["oauth_token"] ?? null;
|
|
85
96
|
}
|
|
86
97
|
export function getSubscriptionType() {
|
|
@@ -144,9 +155,92 @@ export function detectPlanType() {
|
|
|
144
155
|
return "pro";
|
|
145
156
|
}
|
|
146
157
|
// ---------------------------------------------------------------------------
|
|
158
|
+
// PKCE OAuth flow
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
function base64urlEncode(bytes) {
|
|
161
|
+
let binary = "";
|
|
162
|
+
for (const byte of bytes) {
|
|
163
|
+
binary += String.fromCharCode(byte);
|
|
164
|
+
}
|
|
165
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
166
|
+
}
|
|
167
|
+
async function generatePKCE() {
|
|
168
|
+
const crypto = webcrypto;
|
|
169
|
+
const verifierBytes = new Uint8Array(32);
|
|
170
|
+
crypto.getRandomValues(verifierBytes);
|
|
171
|
+
const verifier = base64urlEncode(verifierBytes);
|
|
172
|
+
const encoder = new TextEncoder();
|
|
173
|
+
const data = encoder.encode(verifier);
|
|
174
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
175
|
+
const challenge = base64urlEncode(new Uint8Array(hashBuffer));
|
|
176
|
+
return { verifier, challenge };
|
|
177
|
+
}
|
|
178
|
+
async function oauthLogin() {
|
|
179
|
+
const config = loadConfig();
|
|
180
|
+
const clientId = config["oauth_client_id"];
|
|
181
|
+
const authorizeUrl = config["oauth_authorize_url"];
|
|
182
|
+
const tokenUrl = config["oauth_token_url"];
|
|
183
|
+
const redirectUri = config["oauth_redirect_uri"];
|
|
184
|
+
const scopes = config["oauth_scopes"];
|
|
185
|
+
const { verifier, challenge } = await generatePKCE();
|
|
186
|
+
const authParams = new URLSearchParams({
|
|
187
|
+
code: "true",
|
|
188
|
+
client_id: clientId,
|
|
189
|
+
response_type: "code",
|
|
190
|
+
redirect_uri: redirectUri,
|
|
191
|
+
scope: scopes,
|
|
192
|
+
code_challenge: challenge,
|
|
193
|
+
code_challenge_method: "S256",
|
|
194
|
+
state: verifier,
|
|
195
|
+
});
|
|
196
|
+
const authUrl = `${authorizeUrl}?${authParams.toString()}`;
|
|
197
|
+
console.log("Opening Anthropic OAuth page in your browser...");
|
|
198
|
+
console.log();
|
|
199
|
+
openBrowser(authUrl);
|
|
200
|
+
console.log(`If the browser didn't open, visit this URL:`);
|
|
201
|
+
console.log(` ${authUrl}`);
|
|
202
|
+
console.log();
|
|
203
|
+
console.log("After authorizing, you'll be redirected to a page with a code.");
|
|
204
|
+
console.log("Copy the full authorization code (in the format: code#state).");
|
|
205
|
+
console.log();
|
|
206
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
207
|
+
const authCode = await rl.question("Paste the authorization code here: ");
|
|
208
|
+
rl.close();
|
|
209
|
+
if (!authCode.trim()) {
|
|
210
|
+
throw new Error("No authorization code provided.");
|
|
211
|
+
}
|
|
212
|
+
const splits = authCode.trim().split("#");
|
|
213
|
+
const code = splits[0];
|
|
214
|
+
const state = splits[1];
|
|
215
|
+
// Exchange code for tokens
|
|
216
|
+
const tokenResponse = await fetch(tokenUrl, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: { "Content-Type": "application/json" },
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
grant_type: "authorization_code",
|
|
221
|
+
client_id: clientId,
|
|
222
|
+
code,
|
|
223
|
+
state,
|
|
224
|
+
redirect_uri: redirectUri,
|
|
225
|
+
code_verifier: verifier,
|
|
226
|
+
}),
|
|
227
|
+
});
|
|
228
|
+
if (!tokenResponse.ok) {
|
|
229
|
+
const error = await tokenResponse.text();
|
|
230
|
+
throw new Error(`Token exchange failed: ${error}`);
|
|
231
|
+
}
|
|
232
|
+
const tokenData = (await tokenResponse.json());
|
|
233
|
+
const expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;
|
|
234
|
+
return {
|
|
235
|
+
accessToken: tokenData.access_token,
|
|
236
|
+
refreshToken: tokenData.refresh_token,
|
|
237
|
+
expiresAt,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
147
241
|
// Interactive setup
|
|
148
242
|
// ---------------------------------------------------------------------------
|
|
149
|
-
export async function interactiveSetup() {
|
|
243
|
+
export async function interactiveSetup(forceReauth = false) {
|
|
150
244
|
const config = loadConfig();
|
|
151
245
|
console.log("=".repeat(50));
|
|
152
246
|
console.log(" Claudemon Setup — OAuth Authentication");
|
|
@@ -154,7 +248,7 @@ export async function interactiveSetup() {
|
|
|
154
248
|
console.log();
|
|
155
249
|
// Check if Claude Code credentials already exist
|
|
156
250
|
const creds = getClaudeCodeCredentials();
|
|
157
|
-
if (creds) {
|
|
251
|
+
if (creds && !forceReauth) {
|
|
158
252
|
console.log("Found existing Claude Code credentials.");
|
|
159
253
|
const token = creds.accessToken ?? "";
|
|
160
254
|
if (token.length > 16) {
|
|
@@ -174,61 +268,37 @@ export async function interactiveSetup() {
|
|
|
174
268
|
console.log("Setup complete! Run 'claudemon' to launch the dashboard.");
|
|
175
269
|
return;
|
|
176
270
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
console.log("Claude Code first.");
|
|
181
|
-
console.log();
|
|
182
|
-
console.log("Run the following command to log in:");
|
|
183
|
-
console.log(" claude /login");
|
|
184
|
-
console.log();
|
|
185
|
-
const rl = createInterface({ input: stdin, output: stdout });
|
|
186
|
-
const answer = await rl.question("Open Claude Code login in browser? [Y/n]: ");
|
|
187
|
-
if (["", "y", "yes"].includes(answer.trim().toLowerCase())) {
|
|
188
|
-
openBrowser("https://claude.ai/login");
|
|
271
|
+
if (forceReauth) {
|
|
272
|
+
console.log("Re-authenticating (overwriting existing credentials)...");
|
|
273
|
+
clearToken();
|
|
189
274
|
console.log();
|
|
190
|
-
|
|
191
|
-
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
console.log("No Claude Code credentials found.");
|
|
192
278
|
console.log();
|
|
193
279
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
280
|
+
// OAuth PKCE flow
|
|
281
|
+
try {
|
|
282
|
+
const tokens = await oauthLogin();
|
|
283
|
+
storeToken({
|
|
284
|
+
oauth_token: tokens.accessToken,
|
|
285
|
+
refresh_token: tokens.refreshToken,
|
|
286
|
+
expires_at: tokens.expiresAt,
|
|
287
|
+
});
|
|
288
|
+
console.log();
|
|
289
|
+
console.log("Token saved.");
|
|
290
|
+
console.log("Detecting plan type...");
|
|
291
|
+
const detectedPlan = detectPlanType();
|
|
292
|
+
config["plan_type"] = detectedPlan;
|
|
293
|
+
console.log(` Plan: ${detectedPlan.toUpperCase()}`);
|
|
206
294
|
saveConfig(config);
|
|
207
295
|
console.log();
|
|
208
296
|
console.log("Setup complete! Run 'claudemon' to launch the dashboard.");
|
|
209
297
|
}
|
|
210
|
-
|
|
211
|
-
console.
|
|
212
|
-
console.
|
|
213
|
-
console.log("
|
|
214
|
-
console.log();
|
|
215
|
-
console.log("You can also paste your OAuth token manually.");
|
|
216
|
-
const token = await rl.question("OAuth token (or Enter to skip): ");
|
|
217
|
-
if (token.trim()) {
|
|
218
|
-
storeToken({ oauth_token: token.trim() });
|
|
219
|
-
console.log("Token saved.");
|
|
220
|
-
console.log("Detecting plan type...");
|
|
221
|
-
const detectedPlan = detectPlanType();
|
|
222
|
-
config["plan_type"] = detectedPlan;
|
|
223
|
-
console.log(` Plan: ${detectedPlan.toUpperCase()}`);
|
|
224
|
-
saveConfig(config);
|
|
225
|
-
console.log();
|
|
226
|
-
console.log("Setup complete! Run 'claudemon' to launch the dashboard.");
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
console.log("Setup incomplete. Run 'claudemon setup' again after logging in.");
|
|
230
|
-
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
console.error();
|
|
300
|
+
console.error(`OAuth login failed: ${err instanceof Error ? err.message : err}`);
|
|
301
|
+
console.log("Run 'claudemon setup' to try again.");
|
|
231
302
|
}
|
|
232
|
-
rl.close();
|
|
233
303
|
}
|
|
234
304
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAElF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAClD,MAAM,uBAAuB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;AAehF,SAAS,uBAAuB;IAC9B,IAAI,QAAQ,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CACtB,mBAAmB,EACnB;YACE,uBAAuB;YACvB,IAAI;YACJ,yBAAyB;YACzB,IAAI;SACL,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CACtE,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAA4B,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,IAAI,CAAC,UAAU,CAAC,uBAAuB,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB;IAC/B,KAAK,MAAM,MAAM,IAAI,CAAC,uBAAuB,EAAE,mBAAmB,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC;QACtB,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAiC,CAAC;YACpE,IAAI,KAAK,EAAE,WAAW,EAAE,CAAC;gBACvB,2BAA2B;gBAC3B,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;oBAAE,SAAS;gBAC9D,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,wCAAwC;AACxC,8EAA8E;AAE9E,MAAM,UAAU,UAAU,CAAC,SAAkC;IAC3D,eAAe,EAAE,CAAC;IAClB,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9D,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAGlD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,6DAA6D;IAC7D,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC;IACzC,IAAI,KAAK,EAAE,WAAW;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC;IAEjD,2CAA2C;IAC3C,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;IAC9B,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5B,+BAA+B;IAC/B,MAAM,SAAS,GAAG,SAAS,CAAC,YAAY,CAAuB,CAAC;IAChE,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAErD,OAAQ,SAAS,CAAC,aAAa,CAAY,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC;IACzC,OAAO,KAAK,EAAE,gBAAgB,IAAI,IAAI,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,EAAE,KAAK,IAAI,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,UAAU,CAAC,UAAU,CAAC;QAAE,UAAU,CAAC,UAAU,CAAC,CAAC;AACrD,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE;gBACjC,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,MAAM,UAAU,GAA2B;IACzC,kBAAkB,EAAE,KAAK;IACzB,qBAAqB,EAAE,KAAK;IAC5B,sBAAsB,EAAE,KAAK;CAC9B,CAAC;AAEF,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAC1C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,SAAS,eAAe,CAAC,KAAiB;IACxC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,KAAK,UAAU,YAAY;IACzB,MAAM,MAAM,GAAG,SAA8B,CAAC;IAC9C,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAW,CAAC;IACrD,MAAM,YAAY,GAAG,MAAM,CAAC,qBAAqB,CAAW,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAW,CAAC;IACrD,MAAM,WAAW,GAAG,MAAM,CAAC,oBAAoB,CAAW,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAW,CAAC;IAEhD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;IAErD,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC;QACrC,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,QAAQ;QACnB,aAAa,EAAE,MAAM;QACrB,YAAY,EAAE,WAAW;QACzB,KAAK,EAAE,MAAM;QACb,cAAc,EAAE,SAAS;QACzB,qBAAqB,EAAE,MAAM;QAC7B,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,GAAG,YAAY,IAAI,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC;IAE3D,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,WAAW,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC,CAAC;IAC1E,EAAE,CAAC,KAAK,EAAE,CAAC;IAEX,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAExB,2BAA2B;IAC3B,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;QAC1C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,QAAQ;YACnB,IAAI;YACJ,KAAK;YACL,YAAY,EAAE,WAAW;YACzB,aAAa,EAAE,QAAQ;SACxB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,CAI5C,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAE3E,OAAO;QACL,WAAW,EAAE,SAAS,CAAC,YAAY;QACnC,YAAY,EAAE,SAAS,CAAC,aAAa;QACrC,SAAS;KACV,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAW,GAAG,KAAK;IACxD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,iDAAiD;IACjD,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC;IACzC,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC;QAC5C,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;YACtE,OAAO,CAAC,GAAG,CAAC,YAAa,IAAe,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;QACvE,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,kBAAkB;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,UAAU,CAAC;YACT,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,aAAa,EAAE,MAAM,CAAC,YAAY;YAClC,UAAU,EAAE,MAAM,CAAC,SAAS;SAC7B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE5B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,MAAM,YAAY,GAAG,cAAc,EAAE,CAAC;QACtC,MAAM,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,WAAW,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAErD,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IAC1E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,eAAO,MAAM,UAAU,QAA0C,CAAC;AAClE,eAAO,MAAM,WAAW,QAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,eAAO,MAAM,UAAU,QAA0C,CAAC;AAClE,eAAO,MAAM,WAAW,QAAkC,CAAC;AAuC3D,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAWtE;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAChD,IAAI,CAaN;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAGvC;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAC/B,IAAI,CAIN"}
|
package/dist/config.js
CHANGED
|
@@ -7,9 +7,41 @@ import { join } from "node:path";
|
|
|
7
7
|
import { parse as parseTOML } from "smol-toml";
|
|
8
8
|
export const CONFIG_DIR = join(homedir(), ".config", "claudemon");
|
|
9
9
|
export const CONFIG_FILE = join(CONFIG_DIR, "config.toml");
|
|
10
|
+
/**
|
|
11
|
+
* Default configuration values.
|
|
12
|
+
*
|
|
13
|
+
* General:
|
|
14
|
+
* plan_type - Claude subscription plan: "pro" or "max"
|
|
15
|
+
* refresh_interval - Auto-refresh interval in seconds for the TUI dashboard
|
|
16
|
+
*
|
|
17
|
+
* OAuth (Anthropic PKCE flow):
|
|
18
|
+
* These are the public OAuth parameters used by Claude Code and other
|
|
19
|
+
* third-party tools to authenticate with Anthropic. The client_id is a
|
|
20
|
+
* public identifier for the OAuth application (not user-specific) — this
|
|
21
|
+
* is standard for PKCE flows which don't require a client secret.
|
|
22
|
+
*
|
|
23
|
+
* oauth_client_id - Public OAuth client ID for the Anthropic PKCE flow
|
|
24
|
+
* oauth_authorize_url - Authorization endpoint (user grants consent here)
|
|
25
|
+
* oauth_token_url - Token exchange endpoint (code → access/refresh tokens)
|
|
26
|
+
* oauth_redirect_uri - Redirect URI registered with the OAuth application
|
|
27
|
+
* oauth_scopes - OAuth scopes requested during authorization
|
|
28
|
+
*
|
|
29
|
+
* API:
|
|
30
|
+
* oauth_usage_url - Anthropic API endpoint for fetching quota/usage data
|
|
31
|
+
* oauth_beta_header - Required beta header for the usage API
|
|
32
|
+
*
|
|
33
|
+
* All values can be overridden in ~/.config/claudemon/config.toml
|
|
34
|
+
*/
|
|
10
35
|
const DEFAULT_CONFIG = {
|
|
11
36
|
plan_type: "pro",
|
|
12
37
|
refresh_interval: 5,
|
|
38
|
+
oauth_client_id: "9d1c250a-e61b-44d9-88ed-5944d1962f5e",
|
|
39
|
+
oauth_authorize_url: "https://claude.ai/oauth/authorize",
|
|
40
|
+
oauth_token_url: "https://console.anthropic.com/v1/oauth/token",
|
|
41
|
+
oauth_redirect_uri: "https://console.anthropic.com/oauth/code/callback",
|
|
42
|
+
oauth_scopes: "org:create_api_key user:profile user:inference",
|
|
43
|
+
oauth_usage_url: "https://api.anthropic.com/api/oauth/usage",
|
|
44
|
+
oauth_beta_header: "oauth-2025-04-20",
|
|
13
45
|
};
|
|
14
46
|
export function ensureConfigDir() {
|
|
15
47
|
if (!existsSync(CONFIG_DIR)) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAE3D,MAAM,cAAc,GAA8C;IAChE,SAAS,EAAE,KAAK;IAChB,gBAAgB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,40 @@ import { render } from "ink";
|
|
|
8
8
|
import { App } from "./app.js";
|
|
9
9
|
const require = createRequire(import.meta.url);
|
|
10
10
|
const { version: VERSION } = require("../package.json");
|
|
11
|
+
const LOGO = `
|
|
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
|
+
`;
|
|
11
45
|
function main() {
|
|
12
46
|
const args = process.argv.slice(2);
|
|
13
47
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -15,11 +49,13 @@ function main() {
|
|
|
15
49
|
return;
|
|
16
50
|
}
|
|
17
51
|
if (args.includes("--version")) {
|
|
52
|
+
console.log(LOGO);
|
|
18
53
|
console.log(`claudemon ${VERSION}`);
|
|
19
54
|
return;
|
|
20
55
|
}
|
|
21
56
|
if (args[0] === "setup") {
|
|
22
|
-
|
|
57
|
+
const forceReauth = args.includes("--re");
|
|
58
|
+
runSetup(forceReauth);
|
|
23
59
|
return;
|
|
24
60
|
}
|
|
25
61
|
// Launch TUI (full-screen alternate screen)
|
|
@@ -30,16 +66,18 @@ function main() {
|
|
|
30
66
|
process.stdout.write("\x1b[?1049l"); // restore main screen
|
|
31
67
|
});
|
|
32
68
|
}
|
|
33
|
-
async function runSetup() {
|
|
69
|
+
async function runSetup(forceReauth = false) {
|
|
34
70
|
const { interactiveSetup } = await import("./auth.js");
|
|
35
|
-
await interactiveSetup();
|
|
71
|
+
await interactiveSetup(forceReauth);
|
|
36
72
|
}
|
|
37
73
|
function printHelp() {
|
|
74
|
+
console.log(LOGO);
|
|
38
75
|
console.log(`claudemon — Claude Usage Monitor TUI
|
|
39
76
|
|
|
40
77
|
Usage:
|
|
41
78
|
claudemon Launch the TUI dashboard
|
|
42
79
|
claudemon setup Interactive OAuth setup
|
|
80
|
+
claudemon setup --re Force re-authentication (overwrite existing token)
|
|
43
81
|
|
|
44
82
|
Options:
|
|
45
83
|
--help, -h Show this help message
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";;AAEA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAExD,SAAS,IAAI;IACX,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACxB,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";;AAEA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAExD,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCZ,CAAC;AAEF,SAAS,IAAI;IACX,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC1C,QAAQ,CAAC,WAAW,CAAC,CAAC;QACtB,OAAO;IACT,CAAC;IAED,4CAA4C;IAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,yBAAyB;IAC9D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe;IACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAC,GAAG,IAAC,OAAO,EAAE,OAAO,GAAI,CAAC,CAAC;IACnD,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,sBAAsB;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,WAAW,GAAG,KAAK;IACzC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;iBAcG,CAAC,CAAC;AACnB,CAAC;AAED,IAAI,EAAE,CAAC"}
|