Skip to content

Commit 4137818

Browse files
author
libing
committed
chore: 准备开源发布 CodeFuel(重命名展示名、清理目录、MIT、重写 README)
1 parent caf9796 commit 4137818

16 files changed

Lines changed: 114 additions & 1701 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ dist/
77
*.spec.bak
88
.venv/
99
venv/
10+
11+
# internal design/plan notes — not part of the public repo
12+
docs/superpowers/

UsageTray.spec renamed to CodeFuel.spec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- mode: python ; coding: utf-8 -*-
2-
"""PyInstaller spec for UsageTray (single-file, windowed)."""
2+
"""PyInstaller spec for CodeFuel (single-file, windowed)."""
33

44
block_cipher = None
55

@@ -34,7 +34,7 @@ exe = EXE(
3434
a.zipfiles,
3535
a.datas,
3636
[],
37-
name="UsageTray",
37+
name="CodeFuel",
3838
debug=False,
3939
bootloader_ignore_signals=False,
4040
strip=False,

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 libing
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 83 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,50 @@
1-
# UsageTray
1+
# CodeFuel
22

3-
A Windows system-tray widget that shows your remaining **Claude Code** and
4-
**OpenAI Codex** usage at a glance — 5-hour session limits and weekly limits
5-
so you don't get cut off mid-task.
3+
A lightweight Windows system-tray widget that keeps your AI coding "fuel gauge"
4+
in view — the remaining **Claude Code** and **OpenAI Codex** usage limits plus
5+
your **DeepSeek** account balance — so you don't run dry mid-task.
66

7-
It reuses the login credentials your Claude Code / Codex CLIs already store on
8-
disk. No API keys to enter, zero configuration.
7+
For Claude and Codex it reuses the login credentials their CLIs already store on
8+
disk: no API keys to enter. DeepSeek uses a balance API key you supply.
9+
10+
> The interface is in Chinese (简体中文).
911
1012
## What it shows
1113

12-
- A tray icon with two horizontal bars: top = Claude (orange), bottom = Codex
13-
(grey). Each bar tracks the provider's most-used limit; it turns red above 90%
14-
and dims with a hatch pattern when that provider errors.
15-
- Hover over the icon for a dark popup panel: a card per provider with a
16-
progress bar, percentage, and reset countdown for each limit window. It
17-
hides by itself once the cursor leaves the icon and the panel (left-click
18-
also shows it, as a fallback).
19-
- Right-click menu: **Refresh now**, **Start at login** (off by default),
20-
**Quit**.
14+
- **Tray icon** — two stacked bars: top = Claude (orange), bottom = Codex
15+
(grey). Each bar tracks that provider's most-used limit, turns red above 90%,
16+
and dims with a hatch pattern when the provider errors.
17+
- **Hover panel** — a dark popup with one card per provider:
18+
- Claude / Codex: a progress bar, percentage, and reset countdown for each
19+
limit window (5-hour session, weekly, etc.).
20+
- DeepSeek: account balance as plain text — total, topped-up, and granted —
21+
per currency. No progress bar (a balance has no natural ceiling) and no tray
22+
glyph.
23+
24+
The panel appears on hover and hides itself once the cursor leaves both the
25+
icon and the panel. Left-click also opens it as a fallback.
26+
- **Right-click menu** — Refresh now · Start at login (off by default) · Quit.
27+
28+
Data is fetched on demand only — at startup, when you open the panel (throttled),
29+
and on manual refresh — so it never hammers the rate-limited usage endpoints.
2130

2231
## Requirements
2332

2433
- Windows 10/11 (64-bit) with the **WebView2 runtime** (preinstalled on current
25-
Windows 11; otherwise install from Microsoft's Evergreen WebView2 page).
26-
- Logged-in Claude Code (`~/.claude/.credentials.json`) and/or Codex
27-
(`~/.codex/auth.json`). If a credential is missing or expired, that card shows
28-
a fix hint; the other provider keeps working.
29-
- Python 3.11+ (only to run from source / build).
34+
Windows 11; otherwise install Microsoft's Evergreen WebView2 runtime).
35+
- For the Claude / Codex cards: a logged-in Claude Code
36+
(`~/.claude/.credentials.json`) and/or Codex (`~/.codex/auth.json`). If a
37+
credential is missing or expired, that card shows a fix hint; the others keep
38+
working.
39+
- For the DeepSeek card: a DeepSeek API key (see [Configuration](#configuration)).
40+
- Python 3.11+ — only needed to run from source or build the EXE.
41+
42+
## Install
43+
44+
Grab `CodeFuel.exe` from the [Releases](../../releases) page and run it — it's a
45+
single self-contained executable, no installer.
3046

31-
## Run from source
47+
Or run from source:
3248

3349
```powershell
3450
python -m pip install -r requirements.txt
@@ -40,61 +56,65 @@ python -m usagetray --cli
4056
python -m usagetray
4157
```
4258

59+
## Configuration
60+
61+
A config file is created on first run at `%APPDATA%\UsageTray\config.json`:
62+
63+
```json
64+
{
65+
"min_fetch_gap_seconds": 60,
66+
"providers": { "claude": true, "codex": true, "deepseek": true },
67+
"deepseek_api_key": ""
68+
}
69+
```
70+
71+
- `min_fetch_gap_seconds` — when you open the panel, a provider is re-fetched at
72+
most once per this many seconds (manual refresh bypasses it).
73+
- `providers` — toggle individual cards on/off.
74+
- `deepseek_api_key` — your DeepSeek balance key. Leave empty to fall back to the
75+
`DEEPSEEK_API_KEY` environment variable. With no key, the DeepSeek card shows a
76+
hint and the other providers are unaffected.
77+
78+
Logs live next to the config at `%APPDATA%\UsageTray\usagetray.log` (rotating,
79+
1 MB × 3). Credentials and tokens are never logged. A named mutex prevents a
80+
second instance from launching.
81+
4382
## How it works
4483

4584
```
4685
providers/ --fetch()--> poller (daemon thread) --writes--> state (locked cache)
4786
claude.py |
4887
codex.py tray (pystray) panel (pywebview)
88+
deepseek.py
4989
```
5090

51-
- **providers/** read local credentials and call each tool's private usage
52-
endpoint. `fetch()` never raises — on failure it returns a snapshot whose
53-
`error` carries a human-readable fix hint.
54-
- Claude: `GET https://api.anthropic.com/api/oauth/usage`
91+
- **providers/** read local credentials (or an API key) and call each tool's
92+
usage endpoint. `fetch()` never raises — on failure it returns a snapshot
93+
whose `error` carries a human-readable fix hint.
94+
- **Claude** `GET https://api.anthropic.com/api/oauth/usage`
5595
(`anthropic-beta: oauth-2025-04-20`). On a 401 it attempts one standard
5696
OAuth refresh using the local `refreshToken`; the refreshed token is kept in
5797
memory only and **never written back** to your credentials file.
58-
- Codex: `GET https://chatgpt.com/backend-api/wham/usage`
98+
- **Codex** `GET https://chatgpt.com/backend-api/wham/usage`
5999
(`Authorization: Bearer`, `ChatGPT-Account-Id`).
60-
- DeepSeek: `GET https://api.deepseek.com/user/balance`
61-
(`Authorization: Bearer`). Key comes from config.json `deepseek_api_key`,
62-
falling back to the `DEEPSEEK_API_KEY` env var. Shows account balance
63-
(total / topped-up / granted) as text, not a progress bar; no tray glyph.
64-
- **poller** fetches on demand only (no periodic polling): once at startup,
65-
when the panel is shown (throttled to one fetch per provider per
66-
`min_fetch_gap_seconds`), and on manual refresh (bypasses the throttle).
67-
One provider failing never blocks the other.
100+
- **DeepSeek**`GET https://api.deepseek.com/user/balance`
101+
(`Authorization: Bearer`).
102+
- **poller** fetches on demand only (no periodic polling): once at startup, when
103+
the panel is shown (throttled per `min_fetch_gap_seconds`), and on manual
104+
refresh. One provider failing never blocks the others.
68105
- **state** is a thread-safe snapshot cache; the UI only reads from it.
69106

70-
## Configuration
71-
72-
`%APPDATA%\UsageTray\config.json` (created on first run):
73-
74-
```json
75-
{
76-
"min_fetch_gap_seconds": 60,
77-
"providers": { "claude": true, "codex": true, "deepseek": true },
78-
"deepseek_api_key": ""
79-
}
80-
```
81-
82-
`deepseek_api_key` 留空时回退到环境变量 `DEEPSEEK_API_KEY`
83-
84-
Logs: `%APPDATA%\UsageTray\usagetray.log` (rotating, 1 MB × 3). Tokens are never
85-
logged. A named mutex prevents a second instance from launching.
86-
87107
## Build a single EXE
88108

89109
```powershell
90110
python -m pip install pyinstaller
91-
python -m PyInstaller --noconfirm UsageTray.spec
92-
# -> dist\UsageTray.exe
111+
python -m PyInstaller --noconfirm CodeFuel.spec
112+
# -> dist\CodeFuel.exe
93113
```
94114

95-
The `.spec` bundles `panel.html` as data and builds a windowed (no console)
96-
single-file executable. The autostart registry entry points at the EXE when
97-
frozen, or at `pythonw -m usagetray` when run from source.
115+
The `.spec` bundles `panel.html` as data and produces a windowed (no console)
116+
single-file executable. The "Start at login" entry points at the EXE when frozen,
117+
or at `pythonw -m usagetray` when run from source.
98118

99119
## Tests
100120

@@ -103,5 +123,10 @@ python -m pytest -q
103123
```
104124

105125
Covers each provider (real-response parsing via captured fixtures, missing
106-
credentials, 401 + refresh, timeouts, field changes), the poller (failure
107-
isolation, backoff, manual-refresh wake), and config loading.
126+
credentials, 401 + refresh, rate limits, timeouts, field changes), the data
127+
model, the poller (on-demand fetch, throttling, failure isolation), and config
128+
loading.
129+
130+
## License
131+
132+
[MIT](LICENSE) © 2026 libing

0 commit comments

Comments
 (0)