-
Notifications
You must be signed in to change notification settings - Fork 180
feat: Add Windows/Linux cross-platform Electron port with local CLI usage parsing #166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e009be8
c4d469c
8abdc4d
fffdd9d
bfdd91e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| node_modules/ | ||
| dist/ | ||
| release/ | ||
| *.log | ||
| .env | ||
| .env.local |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| # CodexBar for Windows/Linux | ||
|
|
||
| This is the cross-platform port of [CodexBar](https://github.com/steipete/CodexBar), originally a macOS menu bar app for monitoring AI provider API usage. | ||
|
|
||
| ## Features | ||
|
|
||
| - **System tray app** with usage menu (like macOS menu bar) | ||
| - **12 AI providers** supported: | ||
| - Codex (OpenAI) | ||
| - Claude (Anthropic) | ||
| - Cursor | ||
| - Gemini (Google) | ||
| - GitHub Copilot | ||
| - Antigravity | ||
| - Factory/Droid | ||
| - z.ai | ||
| - Kiro | ||
| - Vertex AI | ||
| - Augment | ||
| - MiniMax | ||
| - **Usage meters** with session + weekly + monthly tracking | ||
| - **Settings window** for provider toggles and preferences | ||
| - **Auto-updates** via electron-updater | ||
| - **CLI** for terminal usage | ||
|
|
||
| ## Installation | ||
|
|
||
| ### Download | ||
|
|
||
| Download the latest release from [GitHub Releases](https://github.com/steipete/CodexBar/releases). | ||
|
|
||
| - **Windows**: Download `CodexBar-Setup-x.x.x.exe` (installer) or `CodexBar-x.x.x-portable.exe` | ||
| - **Linux**: Download `CodexBar-x.x.x.AppImage` or `CodexBar-x.x.x.deb` | ||
|
|
||
| ### Build from Source | ||
|
|
||
| ```bash | ||
| cd codexbar-electron | ||
|
|
||
| # Install dependencies | ||
| npm install | ||
|
|
||
| # Development mode | ||
| npm run dev | ||
|
|
||
| # Build for production | ||
| npm run build | ||
|
|
||
| # Package for distribution | ||
| npm run dist:win # Windows | ||
| npm run dist:linux # Linux | ||
| ``` | ||
|
|
||
| ## Development | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| - Node.js 18+ | ||
| - npm 9+ | ||
|
|
||
| ### Project Structure | ||
|
|
||
| ``` | ||
| codexbar-electron/ | ||
| ├── src/ | ||
| │ ├── main/ # Electron main process | ||
| │ │ ├── providers/ # AI provider implementations | ||
| │ │ ├── store/ # Settings & usage persistence | ||
| │ │ ├── tray/ # System tray menu | ||
| │ │ └── utils/ # Utilities (logger, subprocess) | ||
| │ ├── renderer/ # React UI (settings window) | ||
| │ ├── cli/ # Command-line interface | ||
| │ └── shared/ # Shared types | ||
| ├── assets/ # Icons and images | ||
| ├── dist/ # Build output | ||
| └── release/ # Packaged apps | ||
| ``` | ||
|
|
||
| ### Scripts | ||
|
|
||
| ```bash | ||
| npm run dev # Start in development mode | ||
| npm run build # Build TypeScript | ||
| npm run start # Run built app | ||
| npm run dist # Package for current platform | ||
| npm run lint # Run ESLint | ||
| npm run typecheck # TypeScript check | ||
| npm run test # Run tests | ||
| ``` | ||
|
|
||
| ### Adding a New Provider | ||
|
|
||
| 1. Create a new directory under `src/main/providers/<name>/` | ||
| 2. Create `<Name>Provider.ts` extending `BaseProvider` | ||
| 3. Implement `isConfigured()` and `fetchUsage()` | ||
| 4. Register in `ProviderManager.ts` | ||
|
|
||
| Example: | ||
|
|
||
| ```typescript | ||
| import { BaseProvider, ProviderUsage } from '../BaseProvider'; | ||
|
|
||
| export class NewProvider extends BaseProvider { | ||
| readonly id = 'newprovider'; | ||
| readonly name = 'New Provider'; | ||
| readonly icon = '🆕'; | ||
| readonly websiteUrl = 'https://newprovider.ai'; | ||
|
|
||
| async isConfigured(): Promise<boolean> { | ||
| // Check if provider is set up | ||
| return true; | ||
| } | ||
|
|
||
| async fetchUsage(): Promise<ProviderUsage | null> { | ||
| // Fetch and return usage data | ||
| return null; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## CLI Usage | ||
|
|
||
| ```bash | ||
| # Show status for all providers | ||
| codexbar status | ||
|
|
||
| # Show status for specific provider | ||
| codexbar status -p claude | ||
|
|
||
| # Output as JSON | ||
| codexbar status -j | ||
|
|
||
| # List all providers | ||
| codexbar list | ||
|
|
||
| # Refresh data | ||
| codexbar refresh | ||
| ``` | ||
|
|
||
| ## Architecture | ||
|
|
||
| This port uses: | ||
|
|
||
| - **Electron** - Cross-platform desktop framework | ||
| - **React** - Settings UI | ||
| - **TypeScript** - Type safety | ||
| - **electron-store** - Settings persistence | ||
| - **electron-updater** - Auto-updates | ||
| - **winston** - Logging | ||
|
|
||
| The architecture mirrors the macOS app: | ||
| - Provider-based design for extensibility | ||
| - Background polling for usage updates | ||
| - System tray integration | ||
| - IPC for main/renderer communication | ||
|
|
||
| ## License | ||
|
|
||
| MIT License - see [LICENSE](../LICENSE) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| { | ||
| "name": "codexbar", | ||
| "version": "0.1.0", | ||
| "description": "Monitor API usage limits for AI providers - Windows/Linux port", | ||
| "main": "dist/main/index.js", | ||
| "author": "CodexBar Contributors", | ||
| "license": "MIT", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/steipete/CodexBar" | ||
| }, | ||
| "pnpm": { | ||
| "onlyBuiltDependencies": [ | ||
| "electron", | ||
| "esbuild", | ||
| "keytar", | ||
| "node-pty" | ||
| ] | ||
| }, | ||
| "scripts": { | ||
| "dev": "concurrently \"npm run dev:main\" \"npm run dev:renderer\"", | ||
| "dev:main": "tsc -p tsconfig.main.json --watch", | ||
| "dev:renderer": "vite", | ||
| "build": "npm run build:main && npm run build:renderer", | ||
| "build:main": "tsc -p tsconfig.main.json", | ||
| "build:renderer": "vite build", | ||
| "start": "electron .", | ||
| "pack": "electron-builder --dir", | ||
| "dist": "electron-builder", | ||
| "dist:win": "electron-builder --win", | ||
| "dist:linux": "electron-builder --linux", | ||
| "dist:mac": "electron-builder --mac", | ||
| "lint": "eslint src --ext .ts,.tsx", | ||
| "typecheck": "tsc --noEmit", | ||
| "test": "vitest", | ||
| "cli": "node dist/cli/index.js" | ||
| }, | ||
| "dependencies": { | ||
| "electron-store": "^8.1.0", | ||
| "electron-updater": "^6.1.7", | ||
| "node-fetch": "^3.3.2", | ||
| "keytar": "^7.9.0", | ||
| "tough-cookie": "^4.1.3", | ||
|
||
| "winston": "^3.11.0", | ||
| "commander": "^11.1.0", | ||
| "node-pty": "^1.0.0" | ||
|
||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^20.10.0", | ||
| "@types/react": "^18.2.45", | ||
| "@types/react-dom": "^18.2.18", | ||
| "@types/tough-cookie": "^4.0.5", | ||
| "@typescript-eslint/eslint-plugin": "^6.14.0", | ||
| "@typescript-eslint/parser": "^6.14.0", | ||
| "@vitejs/plugin-react": "^4.2.1", | ||
| "concurrently": "^8.2.2", | ||
| "electron": "^28.0.0", | ||
| "electron-builder": "^24.9.1", | ||
| "eslint": "^8.56.0", | ||
| "react": "^18.2.0", | ||
| "react-dom": "^18.2.0", | ||
| "typescript": "^5.3.3", | ||
| "vite": "^5.0.10", | ||
| "vitest": "^1.1.0" | ||
| }, | ||
| "build": { | ||
| "appId": "com.codexbar.app", | ||
| "productName": "CodexBar", | ||
| "directories": { | ||
| "output": "release" | ||
| }, | ||
| "files": [ | ||
| "dist/**/*", | ||
| "assets/**/*" | ||
| ], | ||
| "win": { | ||
| "target": ["nsis", "portable"], | ||
| "icon": "assets/icon.ico" | ||
| }, | ||
| "linux": { | ||
| "target": ["AppImage", "deb"], | ||
| "icon": "assets/icon.png", | ||
| "category": "Utility" | ||
| }, | ||
| "mac": { | ||
| "target": ["dmg"], | ||
| "icon": "assets/icon.icns" | ||
| }, | ||
| "nsis": { | ||
| "oneClick": false, | ||
| "allowToChangeInstallationDirectory": true | ||
| }, | ||
| "publish": { | ||
| "provider": "github", | ||
| "owner": "steipete", | ||
| "repo": "CodexBar" | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'keytar' package in dependencies is marked as a build dependency in pnpm config but is also in regular dependencies. Keytar is a native module that can be challenging to build. Verify if it's actually used in the codebase, as I don't see any imports for it. If unused, it should be removed to reduce installation complexity.