claudemon 0.2.1 → 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.
package/README.md CHANGED
@@ -1,13 +1,17 @@
1
- # claudemon
1
+ # Claudemon
2
2
 
3
3
  Claude Usage Monitor TUI - monitor your Claude Pro/Max plan quota in real-time.
4
4
 
5
+ ![claudemon-demo](assets/claudemon.gif)
6
+
5
7
  [![npm version](https://img.shields.io/npm/v/claudemon)](https://www.npmjs.com/package/claudemon)
6
8
  [![npm downloads](https://img.shields.io/npm/dm/claudemon)](https://www.npmjs.com/package/claudemon)
7
9
  [![Open Source](https://img.shields.io/badge/open-source-brightgreen)](https://github.com/anistark/claudemon)
8
10
  ![maintenance-status](https://img.shields.io/badge/maintenance-actively--developed-brightgreen.svg)
9
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
10
12
 
13
+ ![claudemon-demo](https://github.com/user-attachments/assets/7acff469-ac72-4de5-8a50-b9231667fbf4)
14
+
11
15
  ## Install
12
16
 
13
17
  ```sh
@@ -56,6 +60,52 @@ Config file: `~/.config/claudemon/config.toml`
56
60
  | `plan_type` | string | `"pro"` | Claude plan type (`pro` or `max`) |
57
61
  | `refresh_interval` | number | `5` | Auto-refresh interval in seconds |
58
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>
77
+
78
+ ## Pi Integration
79
+
80
+ Claudemon is also available as a [pi](https://github.com/badlogic/pi-mono) extension, so you can check your Claude quota without leaving your coding session.
81
+
82
+ ### Install
83
+
84
+ ```sh
85
+ # From npm
86
+ pi install npm:claudemon
87
+
88
+ # From git
89
+ pi install https://github.com/anistark/claudemon
90
+
91
+ # Try without installing
92
+ pi -e npm:claudemon
93
+ ```
94
+
95
+ ### Usage
96
+
97
+ | Command | Description |
98
+ |---------|-------------|
99
+ | `/claudemon` | Show quota usage inline (5-hour, 7-day windows, per-model breakdown) |
100
+ | `/claudemon --tui` | Launch the full TUI dashboard |
101
+ | *"Check my Claude usage"* | The LLM calls the `claudemon` tool automatically |
102
+
103
+ ### Uninstall
104
+
105
+ ```sh
106
+ pi remove npm:claudemon
107
+ ```
108
+
59
109
  ## Development
60
110
 
61
111
  ```sh
@@ -76,3 +126,7 @@ just dev
76
126
  # Type check
77
127
  just lint
78
128
  ```
129
+
130
+ <img width="1906" height="1017" alt="claudemon-ss" src="https://github.com/user-attachments/assets/f1b818e1-f34b-4703-8cfb-cd630342b1b5" />
131
+
132
+ [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
  }
@@ -11,4 +9,15 @@ export declare class AuthenticationError extends QuotaFetchError {
11
9
  constructor(message: string);
12
10
  }
13
11
  export declare function fetchQuota(oauthToken: string): Promise<QuotaData>;
12
+ /**
13
+ * Quick health-check: verifies that an OAuth token exists and is accepted
14
+ * by the API. Returns `{ ok: true }` on success, or `{ ok: false, reason }`
15
+ * on failure.
16
+ */
17
+ export declare function validateToken(): Promise<{
18
+ ok: true;
19
+ } | {
20
+ ok: false;
21
+ reason: string;
22
+ }>;
14
23
  //# sourceMappingURL=api.d.ts.map
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;AAE/E,eAAO,MAAM,eAAe,8CAA8C,CAAC;AAC3E,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD,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,CAmCvE"}
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;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAC5C;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAC7C,CAmDA"}
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
- export const OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
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": OAUTH_BETA_HEADER,
24
+ "anthropic-beta": betaHeader,
23
25
  };
24
26
  let resp;
25
27
  try {
26
- resp = await fetch(OAUTH_USAGE_URL, {
28
+ resp = await fetch(usageUrl, {
27
29
  headers,
28
30
  signal: AbortSignal.timeout(15000),
29
31
  });
@@ -44,6 +46,59 @@ export async function fetchQuota(oauthToken) {
44
46
  const data = (await resp.json());
45
47
  return parseQuotaResponse(data);
46
48
  }
49
+ /**
50
+ * Quick health-check: verifies that an OAuth token exists and is accepted
51
+ * by the API. Returns `{ ok: true }` on success, or `{ ok: false, reason }`
52
+ * on failure.
53
+ */
54
+ export async function validateToken() {
55
+ const { getOAuthToken } = await import("./auth.js");
56
+ const token = getOAuthToken();
57
+ if (!token) {
58
+ return {
59
+ ok: false,
60
+ reason: "No OAuth token found. Please run 'claudemon setup' first.",
61
+ };
62
+ }
63
+ const config = loadConfig();
64
+ const usageUrl = config["oauth_usage_url"];
65
+ const betaHeader = config["oauth_beta_header"];
66
+ try {
67
+ const resp = await fetch(usageUrl, {
68
+ headers: {
69
+ Authorization: `Bearer ${token}`,
70
+ "anthropic-beta": betaHeader,
71
+ },
72
+ signal: AbortSignal.timeout(10000),
73
+ });
74
+ if (resp.status === 401) {
75
+ return {
76
+ ok: false,
77
+ reason: "OAuth token is invalid or expired. Please run 'claudemon setup --re' to re-authenticate.",
78
+ };
79
+ }
80
+ if (resp.status === 403) {
81
+ return {
82
+ ok: false,
83
+ reason: "Access denied. Your token may lack the required permissions. Run 'claudemon setup --re'.",
84
+ };
85
+ }
86
+ if (resp.status !== 200) {
87
+ const text = await resp.text();
88
+ return {
89
+ ok: false,
90
+ reason: `API returned status ${resp.status}: ${text}`,
91
+ };
92
+ }
93
+ return { ok: true };
94
+ }
95
+ catch (e) {
96
+ return {
97
+ ok: false,
98
+ reason: `Network error while validating token: ${e}`,
99
+ };
100
+ }
101
+ }
47
102
  function parseQuotaResponse(data) {
48
103
  const quota = createQuotaData();
49
104
  // Parse 5-hour window
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
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;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4EH,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,CAS7C;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;AAMD,wBAAsB,gBAAgB,CAAC,WAAW,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAuGzE"}
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 (always fresh)
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 manually stored token
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,6 +155,89 @@ 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
243
  export async function interactiveSetup(forceReauth = false) {
@@ -179,61 +273,32 @@ export async function interactiveSetup(forceReauth = false) {
179
273
  clearToken();
180
274
  console.log();
181
275
  }
182
- // No Claude Code credentials — guide user through login
183
- console.log("Claudemon reads your Claude Code OAuth token to");
184
- console.log("monitor quota usage. You need to be logged in to");
185
- console.log("Claude Code first.");
186
- console.log();
187
- console.log("Run the following command to log in:");
188
- console.log(" claude /login");
189
- console.log();
190
- const rl = createInterface({ input: stdin, output: stdout });
191
- const answer = await rl.question("Open Claude Code login in browser? [Y/n]: ");
192
- if (["", "y", "yes"].includes(answer.trim().toLowerCase())) {
193
- openBrowser("https://claude.ai/login");
194
- console.log();
195
- console.log("Complete the login in your browser, then run:");
196
- console.log(" claude /login");
276
+ else {
277
+ console.log("No Claude Code credentials found.");
197
278
  console.log();
198
279
  }
199
- await rl.question("Press Enter after you've logged in to Claude Code...");
200
- console.log();
201
- // Re-check credentials
202
- const newCreds = getClaudeCodeCredentials();
203
- if (newCreds) {
204
- console.log("Credentials found!");
205
- const subType = newCreds.subscriptionType ?? "";
206
- const plan = PLAN_NAMES[subType] ?? subType;
207
- if (plan) {
208
- config["plan_type"] = plan === "pro" || plan === "max" ? plan : "pro";
209
- console.log(` Plan: ${plan.toUpperCase()}`);
210
- }
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()}`);
211
294
  saveConfig(config);
212
295
  console.log();
213
296
  console.log("Setup complete! Run 'claudemon' to launch the dashboard.");
214
297
  }
215
- else {
216
- console.log("Could not find Claude Code credentials.");
217
- console.log("Make sure Claude Code is installed and you've run:");
218
- console.log(" claude /login");
219
- console.log();
220
- console.log("You can also paste your OAuth token manually.");
221
- const token = await rl.question("OAuth token (or Enter to skip): ");
222
- if (token.trim()) {
223
- storeToken({ oauth_token: token.trim() });
224
- console.log("Token saved.");
225
- console.log("Detecting plan type...");
226
- const detectedPlan = detectPlanType();
227
- config["plan_type"] = detectedPlan;
228
- console.log(` Plan: ${detectedPlan.toUpperCase()}`);
229
- saveConfig(config);
230
- console.log();
231
- console.log("Setup complete! Run 'claudemon' to launch the dashboard.");
232
- }
233
- else {
234
- console.log("Setup incomplete. Run 'claudemon setup' again after logging in.");
235
- }
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.");
236
302
  }
237
- rl.close();
238
303
  }
239
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":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -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;AAO3D,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"}
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)) {
@@ -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;CACpB,CAAC;AAEF,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAA8C,CAAC;QAC3E,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,MAAiD;IAEjD,eAAe,EAAE,CAAC;IAClB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,OAAO,KAAK,GAAG,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,GAAW;IAEX,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,KAAgC;IAEhC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACpB,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,23 +6,67 @@ import { jsx as _jsx } from "react/jsx-runtime";
6
6
  import { createRequire } from "node:module";
7
7
  import { render } from "ink";
8
8
  import { App } from "./app.js";
9
+ import { validateToken } from "./api.js";
9
10
  const require = createRequire(import.meta.url);
10
11
  const { version: VERSION } = require("../package.json");
11
- function main() {
12
+ const LOGO = `
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
+ async function main() {
12
47
  const args = process.argv.slice(2);
13
48
  if (args.includes("--help") || args.includes("-h")) {
14
49
  printHelp();
15
50
  return;
16
51
  }
17
52
  if (args.includes("--version")) {
53
+ console.log(LOGO);
18
54
  console.log(`claudemon ${VERSION}`);
19
55
  return;
20
56
  }
21
57
  if (args[0] === "setup") {
22
58
  const forceReauth = args.includes("--re");
23
- runSetup(forceReauth);
59
+ await runSetup(forceReauth);
24
60
  return;
25
61
  }
62
+ // Validate token before launching the TUI
63
+ console.log("Validating OAuth token...");
64
+ const result = await validateToken();
65
+ if (!result.ok) {
66
+ console.error(`\n✗ ${result.reason}\n`);
67
+ process.exit(1);
68
+ }
69
+ console.log("✓ Token is valid.\n");
26
70
  // Launch TUI (full-screen alternate screen)
27
71
  process.stdout.write("\x1b[?1049h"); // enter alternate screen
28
72
  process.stdout.write("\x1b[2J\x1b[H"); // clear + home
@@ -36,6 +80,7 @@ async function runSetup(forceReauth = false) {
36
80
  await interactiveSetup(forceReauth);
37
81
  }
38
82
  function printHelp() {
83
+ console.log(LOGO);
39
84
  console.log(`claudemon — Claude Usage Monitor TUI
40
85
 
41
86
  Usage:
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,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;;;;;;;;;;;;;;iBAcG,CAAC,CAAC;AACnB,CAAC;AAED,IAAI,EAAE,CAAC"}
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;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,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,KAAK,UAAU,IAAI;IACjB,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,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,0CAA0C;IAC1C,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEnC,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"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Pi extension for claudemon - Claude Usage Monitor.
3
+ *
4
+ * Registers:
5
+ * /claudemon - Show quota usage inline (or launch TUI with --tui)
6
+ * claudemon tool - LLM-callable tool to check Claude quota
7
+ */
8
+
9
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ import { Type } from "@sinclair/typebox";
11
+ import { execFileSync } from "node:child_process";
12
+ import { existsSync, readFileSync } from "node:fs";
13
+ import { homedir, platform } from "node:os";
14
+ import { join } from "node:path";
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Token resolution (same logic as claudemon's auth.ts)
18
+ // ---------------------------------------------------------------------------
19
+
20
+ function readKeychainCredentials(): Record<string, unknown> | null {
21
+ if (platform() !== "darwin") return null;
22
+ try {
23
+ const raw = execFileSync(
24
+ "/usr/bin/security",
25
+ ["find-generic-password", "-s", "Claude Code-credentials", "-w"],
26
+ { timeout: 5000, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] },
27
+ );
28
+ if (!raw.trim()) return null;
29
+ return JSON.parse(raw.trim()) as Record<string, unknown>;
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ function readFileCredentials(): Record<string, unknown> | null {
36
+ const credFile = join(homedir(), ".claude", ".credentials.json");
37
+ if (!existsSync(credFile)) return null;
38
+ try {
39
+ return JSON.parse(readFileSync(credFile, "utf-8")) as Record<string, unknown>;
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+
45
+ function readClaudemonToken(): string | null {
46
+ const tokenFile = join(homedir(), ".config", "claudemon", "token.json");
47
+ if (!existsSync(tokenFile)) return null;
48
+ try {
49
+ const data = JSON.parse(readFileSync(tokenFile, "utf-8"));
50
+ if (data.expires_at && data.expires_at < Date.now()) return null;
51
+ return data.oauth_token ?? null;
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+
57
+ function getOAuthToken(): string | null {
58
+ // Prefer Claude Code's live credentials
59
+ for (const reader of [readKeychainCredentials, readFileCredentials]) {
60
+ const data = reader();
61
+ if (data) {
62
+ const oauth = data["claudeAiOauth"] as { accessToken?: string; expiresAt?: number } | undefined;
63
+ if (oauth?.accessToken) {
64
+ if (oauth.expiresAt && oauth.expiresAt < Date.now()) continue;
65
+ return oauth.accessToken;
66
+ }
67
+ }
68
+ }
69
+ // Fallback to claudemon's own stored token
70
+ return readClaudemonToken();
71
+ }
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Quota fetch (minimal inline version)
75
+ // ---------------------------------------------------------------------------
76
+
77
+ interface ModelQuota {
78
+ modelName: string;
79
+ usagePct: number;
80
+ }
81
+
82
+ interface QuotaData {
83
+ fiveHourUsagePct: number;
84
+ fiveHourResetTime: Date | null;
85
+ sevenDayUsagePct: number;
86
+ sevenDayResetTime: Date | null;
87
+ modelQuotas: ModelQuota[];
88
+ planType: string;
89
+ }
90
+
91
+ async function fetchQuota(token: string): Promise<QuotaData> {
92
+ const resp = await fetch("https://api.anthropic.com/api/oauth/usage", {
93
+ headers: {
94
+ Authorization: `Bearer ${token}`,
95
+ "anthropic-beta": "oauth-2025-04-20",
96
+ },
97
+ signal: AbortSignal.timeout(15000),
98
+ });
99
+
100
+ if (resp.status === 401 || resp.status === 403) {
101
+ throw new Error("OAuth token expired. Run `claudemon setup` to re-authenticate.");
102
+ }
103
+ if (resp.status !== 200) {
104
+ throw new Error(`API returned status ${resp.status}`);
105
+ }
106
+
107
+ const data = (await resp.json()) as Record<string, unknown>;
108
+ return parseQuotaResponse(data);
109
+ }
110
+
111
+ function parseQuotaResponse(data: Record<string, unknown>): QuotaData {
112
+ const fiveHour = (data["five_hour"] ?? data["fiveHour"] ?? {}) as Record<string, unknown>;
113
+ const sevenDay = (data["seven_day"] ?? data["sevenDay"] ?? {}) as Record<string, unknown>;
114
+ const models = (data["models"] ?? data["model_quotas"] ?? []) as Array<Record<string, unknown>>;
115
+
116
+ const fiveHourReset = (fiveHour["resets_at"] ?? fiveHour["reset_at"] ?? fiveHour["resetAt"]) as string | undefined;
117
+ const sevenDayReset = (sevenDay["resets_at"] ?? sevenDay["reset_at"] ?? sevenDay["resetAt"]) as string | undefined;
118
+
119
+ return {
120
+ fiveHourUsagePct: (fiveHour["utilization"] as number) ?? (fiveHour["usage_pct"] as number) ?? 0,
121
+ fiveHourResetTime: fiveHourReset ? new Date(fiveHourReset) : null,
122
+ sevenDayUsagePct: (sevenDay["utilization"] as number) ?? (sevenDay["usage_pct"] as number) ?? 0,
123
+ sevenDayResetTime: sevenDayReset ? new Date(sevenDayReset) : null,
124
+ modelQuotas: models.map((m) => ({
125
+ modelName: (m["model"] as string) ?? (m["name"] as string) ?? "unknown",
126
+ usagePct: (m["utilization"] as number) ?? (m["usage_pct"] as number) ?? 0,
127
+ })),
128
+ planType: (data["plan_type"] as string) ?? (data["planType"] as string) ?? "pro",
129
+ };
130
+ }
131
+
132
+ // ---------------------------------------------------------------------------
133
+ // Formatting helpers
134
+ // ---------------------------------------------------------------------------
135
+
136
+ function formatCountdown(totalSeconds: number): string {
137
+ if (totalSeconds <= 0) return "now";
138
+ const days = Math.floor(totalSeconds / 86400);
139
+ const hours = Math.floor((totalSeconds % 86400) / 3600);
140
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
141
+ if (days > 0) return `${days}d ${hours}h`;
142
+ if (hours > 0) return `${hours}h ${minutes}m`;
143
+ return `${minutes}m`;
144
+ }
145
+
146
+ function usageBar(pct: number, width = 20): string {
147
+ const filled = Math.round((pct / 100) * width);
148
+ const empty = width - filled;
149
+ return `[${"█".repeat(filled)}${"░".repeat(empty)}] ${pct.toFixed(1)}%`;
150
+ }
151
+
152
+ function formatQuota(q: QuotaData): string {
153
+ const lines: string[] = [];
154
+ lines.push(`📊 Claude Usage (${q.planType.toUpperCase()} plan)`);
155
+ lines.push("");
156
+
157
+ // 5-hour window
158
+ const fiveHourReset = q.fiveHourResetTime
159
+ ? formatCountdown(Math.max(0, (q.fiveHourResetTime.getTime() - Date.now()) / 1000))
160
+ : "—";
161
+ lines.push(`5-hour: ${usageBar(q.fiveHourUsagePct)} resets in ${fiveHourReset}`);
162
+
163
+ // 7-day window
164
+ const sevenDayReset = q.sevenDayResetTime
165
+ ? formatCountdown(Math.max(0, (q.sevenDayResetTime.getTime() - Date.now()) / 1000))
166
+ : "—";
167
+ lines.push(`7-day: ${usageBar(q.sevenDayUsagePct)} resets in ${sevenDayReset}`);
168
+
169
+ // Per-model breakdown
170
+ if (q.modelQuotas.length > 0) {
171
+ lines.push("");
172
+ lines.push("Per model:");
173
+ for (const m of q.modelQuotas) {
174
+ lines.push(` ${m.modelName.padEnd(30)} ${usageBar(m.usagePct)}`);
175
+ }
176
+ }
177
+
178
+ return lines.join("\n");
179
+ }
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // Extension entry point
183
+ // ---------------------------------------------------------------------------
184
+
185
+ export default function (pi: ExtensionAPI) {
186
+ // /claudemon command — show quota inline or launch TUI
187
+ pi.registerCommand("claudemon", {
188
+ description: "Show Claude usage quota (--tui to launch dashboard)",
189
+ handler: async (args, ctx) => {
190
+ const trimmed = (args ?? "").trim();
191
+
192
+ // --tui flag: launch the full TUI dashboard
193
+ if (trimmed === "--tui" || trimmed === "-t") {
194
+ const result = await pi.exec("npx", ["claudemon"], { timeout: 300000 });
195
+ if (result.code !== 0 && result.stderr) {
196
+ ctx.ui.notify(`claudemon exited with error: ${result.stderr.slice(0, 200)}`, "error");
197
+ }
198
+ return;
199
+ }
200
+
201
+ // Default: fetch and display inline
202
+ const token = getOAuthToken();
203
+ if (!token) {
204
+ ctx.ui.notify(
205
+ "Not authenticated. Run `claudemon setup` or `npx claudemon setup` first.",
206
+ "error",
207
+ );
208
+ return;
209
+ }
210
+
211
+ try {
212
+ ctx.ui.setStatus("claudemon", "Fetching quota…");
213
+ const quota = await fetchQuota(token);
214
+ ctx.ui.setStatus("claudemon", undefined);
215
+ ctx.ui.notify(formatQuota(quota), "info");
216
+ } catch (err) {
217
+ ctx.ui.setStatus("claudemon", undefined);
218
+ ctx.ui.notify(`Failed to fetch quota: ${err instanceof Error ? err.message : err}`, "error");
219
+ }
220
+ },
221
+ });
222
+
223
+ // LLM-callable tool
224
+ pi.registerTool({
225
+ name: "claudemon",
226
+ label: "Claude Usage Monitor",
227
+ description:
228
+ "Check the user's Claude Pro/Max plan quota usage including 5-hour and 7-day windows and per-model breakdown. Use when the user asks about their Claude usage, quota, or remaining capacity.",
229
+ parameters: Type.Object({}),
230
+ async execute(_toolCallId, _params, signal) {
231
+ const token = getOAuthToken();
232
+ if (!token) {
233
+ return {
234
+ content: [
235
+ {
236
+ type: "text" as const,
237
+ text: "Not authenticated. The user needs to run `claudemon setup` or `npx claudemon setup` to authenticate first.",
238
+ },
239
+ ],
240
+ isError: true,
241
+ };
242
+ }
243
+
244
+ try {
245
+ const quota = await fetchQuota(token);
246
+ return {
247
+ content: [{ type: "text" as const, text: formatQuota(quota) }],
248
+ details: {
249
+ fiveHourUsagePct: quota.fiveHourUsagePct,
250
+ sevenDayUsagePct: quota.sevenDayUsagePct,
251
+ planType: quota.planType,
252
+ modelQuotas: quota.modelQuotas,
253
+ },
254
+ };
255
+ } catch (err) {
256
+ return {
257
+ content: [
258
+ {
259
+ type: "text" as const,
260
+ text: `Failed to fetch quota: ${err instanceof Error ? err.message : err}`,
261
+ },
262
+ ],
263
+ isError: true,
264
+ };
265
+ }
266
+ },
267
+ });
268
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemon",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Claude Usage Monitor TUI - monitor your Claude usage in real-time",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,15 +8,22 @@
8
8
  "claudemon": "dist/index.js"
9
9
  },
10
10
  "files": [
11
- "dist"
11
+ "dist",
12
+ "extensions"
12
13
  ],
13
14
  "keywords": [
14
15
  "claude",
15
16
  "anthropic",
16
17
  "quota",
17
18
  "tui",
18
- "cli"
19
+ "cli",
20
+ "pi-package"
19
21
  ],
22
+ "pi": {
23
+ "extensions": [
24
+ "./extensions"
25
+ ]
26
+ },
20
27
  "license": "MIT",
21
28
  "dependencies": {
22
29
  "chalk": "^5.3.0",
@@ -24,6 +31,18 @@
24
31
  "react": "^18.3.1",
25
32
  "smol-toml": "^1.3.1"
26
33
  },
34
+ "peerDependencies": {
35
+ "@mariozechner/pi-coding-agent": "*",
36
+ "@sinclair/typebox": "*"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "@mariozechner/pi-coding-agent": {
40
+ "optional": true
41
+ },
42
+ "@sinclair/typebox": {
43
+ "optional": true
44
+ }
45
+ },
27
46
  "devDependencies": {
28
47
  "@types/node": "^25.2.3",
29
48
  "@types/react": "^18.3.12",