agent-limit 0.3.0 → 0.4.1

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,6 +1,6 @@
1
1
  # agent-limit
2
2
 
3
- Terminal dashboard to monitor Claude Code, Codex, and Gemini CLI usage limits.
3
+ Terminal dashboard to monitor Claude Code and Codex usage limits.
4
4
 
5
5
  ## Install
6
6
 
@@ -46,7 +46,7 @@ agent-limit usage
46
46
 
47
47
  ## Features
48
48
 
49
- - Real-time usage tracking for Claude Code, Codex, and Gemini CLI
49
+ - Real-time usage tracking for Claude Code and Codex
50
50
  - Trajectory markers showing if you're ahead or behind your usage pace
51
51
  - Auto-refresh every 60 seconds
52
52
  - Color-coded usage indicators
@@ -57,7 +57,6 @@ agent-limit usage
57
57
  |----------|--------|-------------|
58
58
  | Claude Code | Full support | macOS Keychain + Anthropic API |
59
59
  | Codex | Full support | `~/.codex/auth.json` + OpenAI API |
60
- | Gemini CLI | Static limits | `~/.gemini/settings.json` |
61
60
 
62
61
  ## Development
63
62
 
@@ -102,7 +101,6 @@ agent-limit reads credentials from standard locations:
102
101
 
103
102
  - **Claude Code**: macOS Keychain (`Claude Code-credentials`)
104
103
  - **Codex**: `~/.codex/auth.json`
105
- - **Gemini**: `~/.gemini/settings.json`
106
104
 
107
105
  It then fetches usage data from each provider's API and displays it in a unified dashboard.
108
106
 
package/bin/cli.js ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execFileSync } from "child_process";
4
+ import { dirname, join } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { existsSync } from "fs";
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ const bunPath = join(__dirname, "..", "node_modules", ".bin", "bun");
10
+ const cliPath = join(__dirname, "cli.tsx");
11
+
12
+ if (!existsSync(bunPath)) {
13
+ console.error("Error: bun not found at", bunPath);
14
+ console.error("Try running: npm install");
15
+ process.exit(1);
16
+ }
17
+
18
+ try {
19
+ execFileSync(bunPath, [cliPath, ...process.argv.slice(2)], {
20
+ stdio: "inherit",
21
+ env: { ...process.env, FORCE_COLOR: "1" },
22
+ });
23
+ } catch (err) {
24
+ process.exit(err.status ?? 1);
25
+ }
package/bin/cli.tsx CHANGED
@@ -1,54 +1,44 @@
1
1
  #!/usr/bin/env bun
2
2
  /** @jsxImportSource @opentui/react */
3
3
 
4
+ import { createCliRenderer } from "@opentui/core";
4
5
  import { createRoot } from "@opentui/react";
5
6
  import { App } from "../src/App";
6
7
 
7
- function resetTerminal() {
8
- process.stdout.write("\x1b[?1049l");
9
- process.stdout.write("\x1b[?25h");
10
- process.stdout.write("\x1b[0m");
11
- process.stdout.write("\x1b[?1000l");
12
- process.stdout.write("\x1b[?1002l");
13
- process.stdout.write("\x1b[?1003l");
14
- process.stdout.write("\x1b[?1006l");
15
- process.stdout.write("\x1b[?2004l");
16
- }
17
-
18
8
  const command = process.argv[2];
19
9
 
20
10
  if (command === "usage") {
21
- let root: ReturnType<typeof createRoot> | null = null;
11
+ const renderer = await createCliRenderer({
12
+ exitOnCtrlC: false,
13
+ });
14
+
15
+ const root = createRoot(renderer);
22
16
 
23
17
  const cleanup = () => {
24
- if (root) {
25
- root.unmount();
26
- }
27
- resetTerminal();
18
+ root.unmount();
19
+ renderer.destroy();
28
20
  process.exit(0);
29
21
  };
30
22
 
31
23
  process.on("SIGINT", cleanup);
32
24
  process.on("SIGTERM", cleanup);
33
- process.on("exit", resetTerminal);
34
25
 
35
- root = createRoot(process.stdout, { hideCursor: true });
36
26
  root.render(<App onExit={cleanup} />);
37
27
  } else if (command === "help" || command === "--help" || command === "-h" || !command) {
38
28
  console.log(`
39
- agent-monitor
29
+ agent-limit
40
30
 
41
31
  Monitor AI agent CLI usage limits in real-time.
42
32
 
43
33
  Install:
44
- npm install -g agent-monitor
34
+ npm install -g agent-limit
45
35
 
46
36
  Quick Start:
47
- agent-monitor usage
37
+ agent-limit usage
48
38
 
49
39
  CLI:
50
- agent-monitor usage Show usage dashboard
51
- agent-monitor help Show this help message
40
+ agent-limit usage Show usage dashboard
41
+ agent-limit help Show this help message
52
42
 
53
43
  Dashboard Controls:
54
44
  q Quit
@@ -56,6 +46,6 @@ Dashboard Controls:
56
46
  `);
57
47
  } else {
58
48
  console.error(`Unknown command: ${command}`);
59
- console.error(`Run 'agent-monitor help' for usage.`);
49
+ console.error(`Run 'agent-limit help' for usage.`);
60
50
  process.exit(1);
61
51
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "agent-limit",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Terminal dashboard to monitor Claude Code, Codex, and other agent usage limits",
5
5
  "type": "module",
6
6
  "main": "src/index.tsx",
7
7
  "bin": {
8
- "agent-limit": "./bin/cli.tsx"
8
+ "agent-limit": "bin/cli.js"
9
9
  },
10
10
  "scripts": {
11
11
  "start": "bun run src/index.tsx",
@@ -24,7 +24,6 @@
24
24
  "dashboard",
25
25
  "claude",
26
26
  "codex",
27
- "gemini",
28
27
  "ai",
29
28
  "agent",
30
29
  "usage",
@@ -43,7 +42,7 @@
43
42
  },
44
43
  "homepage": "https://github.com/AgentWorkforce/limit",
45
44
  "engines": {
46
- "bun": ">=1.0.0"
45
+ "node": ">=18.0.0"
47
46
  },
48
47
  "os": [
49
48
  "darwin"
@@ -51,6 +50,7 @@
51
50
  "dependencies": {
52
51
  "@opentui/core": "^0.1.67",
53
52
  "@opentui/react": "^0.1.63",
53
+ "bun": "^1.2.0",
54
54
  "react": "^19.0.0"
55
55
  },
56
56
  "devDependencies": {
package/src/App.tsx CHANGED
@@ -13,7 +13,6 @@ export function App({ onExit }: AppProps) {
13
13
  const [providers, setProviders] = useState<ProviderStatus[]>([
14
14
  { provider: "claude", status: "loading", metrics: [] },
15
15
  { provider: "codex", status: "loading", metrics: [] },
16
- { provider: "gemini", status: "loading", metrics: [] },
17
16
  ]);
18
17
  const [lastRefresh, setLastRefresh] = useState<Date | null>(null);
19
18
  const [isLoading, setIsLoading] = useState(true);
@@ -10,7 +10,6 @@ function getProviderDisplayName(provider: string): string {
10
10
  switch (provider) {
11
11
  case "claude": return "CLAUDE CODE";
12
12
  case "codex": return "CODEX";
13
- case "gemini": return "GEMINI CLI";
14
13
  default: return provider.toUpperCase();
15
14
  }
16
15
  }
@@ -1,19 +1,16 @@
1
1
  export * from "./types";
2
2
  export { fetchClaudeUsage } from "./claude";
3
3
  export { fetchCodexUsage } from "./codex";
4
- export { fetchGeminiUsage } from "./gemini";
5
4
 
6
5
  import { fetchClaudeUsage } from "./claude";
7
6
  import { fetchCodexUsage } from "./codex";
8
- import { fetchGeminiUsage } from "./gemini";
9
7
  import type { ProviderStatus } from "./types";
10
8
 
11
9
  export async function fetchAllProviders(): Promise<ProviderStatus[]> {
12
- const [claude, codex, gemini] = await Promise.all([
10
+ const [claude, codex] = await Promise.all([
13
11
  fetchClaudeUsage(),
14
12
  fetchCodexUsage(),
15
- fetchGeminiUsage(),
16
13
  ]);
17
14
 
18
- return [claude, codex, gemini];
15
+ return [claude, codex];
19
16
  }
@@ -1,4 +1,4 @@
1
- export type ProviderName = "claude" | "codex" | "gemini";
1
+ export type ProviderName = "claude" | "codex";
2
2
 
3
3
  export type ProviderStatusType = "ok" | "warning" | "error" | "unavailable" | "loading" | "limited";
4
4
 
@@ -18,7 +18,6 @@ export function getStatusColor(status: string): string {
18
18
  export const PROVIDER_COLORS = {
19
19
  claude: "#d97706",
20
20
  codex: "#10b981",
21
- gemini: "#3b82f6",
22
21
  } as const;
23
22
 
24
23
  export const UI_COLORS = {
@@ -82,25 +82,3 @@ export async function getCodexCredentials(): Promise<CodexCredentials | null> {
82
82
  return null;
83
83
  }
84
84
  }
85
-
86
- export interface GeminiSettings {
87
- authType?: "google" | "api_key" | "vertex";
88
- apiKey?: string;
89
- project?: string;
90
- }
91
-
92
- export async function getGeminiSettings(): Promise<GeminiSettings | null> {
93
- try {
94
- const homedir = process.env.HOME || "~";
95
- const file = Bun.file(`${homedir}/.gemini/settings.json`);
96
-
97
- if (!(await file.exists())) {
98
- return null;
99
- }
100
-
101
- const content = await file.json();
102
- return content;
103
- } catch {
104
- return null;
105
- }
106
- }
@@ -1,63 +0,0 @@
1
- import { getGeminiSettings } from "../utils/keychain";
2
- import type { ProviderStatus, UsageMetric } from "./types";
3
-
4
- interface GeminiLimits {
5
- requestsPerDay: number;
6
- requestsPerMinute: number;
7
- plan: string;
8
- }
9
-
10
- function getLimitsForAuthType(authType?: string): GeminiLimits {
11
- switch (authType) {
12
- case "google":
13
- return { requestsPerDay: 1000, requestsPerMinute: 60, plan: "Google (Free)" };
14
- case "api_key":
15
- return { requestsPerDay: 250, requestsPerMinute: 10, plan: "API Key (Free)" };
16
- case "vertex":
17
- return { requestsPerDay: -1, requestsPerMinute: -1, plan: "Vertex AI" };
18
- default:
19
- return { requestsPerDay: 1000, requestsPerMinute: 60, plan: "Unknown" };
20
- }
21
- }
22
-
23
- export async function fetchGeminiUsage(): Promise<ProviderStatus> {
24
- const settings = await getGeminiSettings();
25
-
26
- if (!settings) {
27
- return {
28
- provider: "gemini",
29
- status: "unavailable",
30
- metrics: [],
31
- message: "Not configured. Run 'gemini' to set up.",
32
- };
33
- }
34
-
35
- const limits = getLimitsForAuthType(settings.authType);
36
- const metrics: UsageMetric[] = [];
37
-
38
- if (limits.requestsPerDay > 0) {
39
- metrics.push({
40
- name: "Daily Limit",
41
- percentage: -1,
42
- resetsAt: null,
43
- resetsIn: `${limits.requestsPerDay} req/day`,
44
- });
45
- }
46
-
47
- if (limits.requestsPerMinute > 0) {
48
- metrics.push({
49
- name: "Per-Minute",
50
- percentage: -1,
51
- resetsAt: null,
52
- resetsIn: `${limits.requestsPerMinute} req/min`,
53
- });
54
- }
55
-
56
- return {
57
- provider: "gemini",
58
- status: "limited",
59
- plan: limits.plan,
60
- metrics,
61
- message: "Live usage not available. Run /stats in Gemini CLI.",
62
- };
63
- }