cc-api-statusline 0.1.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 +579 -0
- package/dist/cc-api-statusline.js +2257 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
# cc-api-statusline
|
|
2
|
+
|
|
3
|
+
> Claude Code statusline widget for monitoring API usage from third-party proxy backends
|
|
4
|
+
|
|
5
|
+
A high-performance TUI statusline tool that polls API usage data from Claude API proxy services (sub2api, claude-relay-service, or custom providers) and renders a configurable one-line status display.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- ⚡ **Fast piped mode** — <25ms warm cache, <100ms p95
|
|
10
|
+
- 🎨 **Highly configurable** — Layouts, colors, bar styles, display modes
|
|
11
|
+
- 🔌 **Provider autodetection** — Works with sub2api, claude-relay-service, custom providers
|
|
12
|
+
- 💾 **Smart caching** — Disk cache with atomic writes, TTL validation
|
|
13
|
+
- 🎯 **Claude Code integration** — Auto-setup with `--install` command
|
|
14
|
+
- 📊 **Multiple components** — Daily/weekly/monthly quotas, balance, tokens, rate limits
|
|
15
|
+
- 🐛 **Debug logging** — Detailed execution logs for troubleshooting
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Using npm
|
|
21
|
+
npm install -g cc-api-statusline
|
|
22
|
+
|
|
23
|
+
# Using bun
|
|
24
|
+
bun add -g cc-api-statusline
|
|
25
|
+
|
|
26
|
+
# From source
|
|
27
|
+
git clone https://github.com/liafonx/cc-api-statusline
|
|
28
|
+
cd cc-api-statusline
|
|
29
|
+
bun install
|
|
30
|
+
bun run build
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Claude Code Integration (Recommended)
|
|
36
|
+
|
|
37
|
+
The easiest way to use cc-api-statusline is with auto-setup:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Set required environment variables first
|
|
41
|
+
export ANTHROPIC_BASE_URL="https://your-proxy.example.com"
|
|
42
|
+
export ANTHROPIC_AUTH_TOKEN="your-api-token"
|
|
43
|
+
|
|
44
|
+
# Install as Claude Code statusline widget
|
|
45
|
+
npx cc-api-statusline --install
|
|
46
|
+
|
|
47
|
+
# Or with bunx (auto-detects if available)
|
|
48
|
+
bunx cc-api-statusline --install --runner bunx
|
|
49
|
+
|
|
50
|
+
# Uninstall
|
|
51
|
+
npx cc-api-statusline --uninstall
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This automatically adds to `~/.claude/settings.json`:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"statusLine": {
|
|
59
|
+
"type": "command",
|
|
60
|
+
"command": "bunx -y cc-api-statusline@latest",
|
|
61
|
+
"padding": 0
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Standalone Mode
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Set required environment variables
|
|
70
|
+
export ANTHROPIC_BASE_URL="https://your-proxy.example.com"
|
|
71
|
+
export ANTHROPIC_AUTH_TOKEN="your-api-token"
|
|
72
|
+
|
|
73
|
+
# Run once and exit
|
|
74
|
+
cc-api-statusline --once
|
|
75
|
+
|
|
76
|
+
# Run with custom config
|
|
77
|
+
cc-api-statusline --config ./my-config.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### ccstatusline Custom Command (Legacy)
|
|
81
|
+
|
|
82
|
+
Add to your `~/.claude/ccstatusline/config.json`:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"customCommands": {
|
|
87
|
+
"usage": {
|
|
88
|
+
"command": "cc-api-statusline",
|
|
89
|
+
"description": "API usage statusline",
|
|
90
|
+
"type": "piped"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"widgets": [
|
|
94
|
+
{
|
|
95
|
+
"type": "customCommand",
|
|
96
|
+
"command": "usage",
|
|
97
|
+
"refreshIntervalMs": 30000,
|
|
98
|
+
"maxWidth": 80,
|
|
99
|
+
"preserveColors": true
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Configuration
|
|
106
|
+
|
|
107
|
+
Configuration file: `~/.claude/cc-api-statusline/config.json`
|
|
108
|
+
|
|
109
|
+
### User-Agent Spoofing (Optional)
|
|
110
|
+
|
|
111
|
+
Some API providers restrict requests to only come from Claude Code clients. Enable User-Agent spoofing to bypass these restrictions:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"spoofClaudeCodeUA": true
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Options:**
|
|
120
|
+
- `false` / `undefined` — No User-Agent header (default)
|
|
121
|
+
- `true` — Auto-detect Claude Code version, fallback to `claude-cli/2.1.56 (external, cli)`
|
|
122
|
+
- `"string"` — Use custom User-Agent string
|
|
123
|
+
|
|
124
|
+
**Per-provider override (custom providers only):**
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"spoofClaudeCodeUA": true,
|
|
129
|
+
"customProviders": {
|
|
130
|
+
"my-provider": {
|
|
131
|
+
"spoofClaudeCodeUA": "custom-client/1.0.0"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Example Configuration
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"display": {
|
|
142
|
+
"layout": "standard",
|
|
143
|
+
"displayMode": "bar",
|
|
144
|
+
"barSize": "medium",
|
|
145
|
+
"barStyle": "classic",
|
|
146
|
+
"separator": " | ",
|
|
147
|
+
"maxWidth": 80,
|
|
148
|
+
"clockFormat": "24h"
|
|
149
|
+
},
|
|
150
|
+
"components": {
|
|
151
|
+
"daily": true,
|
|
152
|
+
"weekly": true,
|
|
153
|
+
"monthly": true,
|
|
154
|
+
"balance": true,
|
|
155
|
+
"tokens": false,
|
|
156
|
+
"rateLimit": false,
|
|
157
|
+
"plan": false
|
|
158
|
+
},
|
|
159
|
+
"colors": {
|
|
160
|
+
"auto": {
|
|
161
|
+
"low": "green",
|
|
162
|
+
"medium": "yellow",
|
|
163
|
+
"high": "red",
|
|
164
|
+
"lowThreshold": 50,
|
|
165
|
+
"highThreshold": 80
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"pollIntervalSeconds": 30,
|
|
169
|
+
"pipedRequestTimeoutMs": 800
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Display Options
|
|
174
|
+
|
|
175
|
+
#### Layouts
|
|
176
|
+
|
|
177
|
+
- `standard` — Full labels (e.g., "Daily 24%")
|
|
178
|
+
- `compact` — Single-letter labels (e.g., "D 24%")
|
|
179
|
+
- `minimal` — No labels (e.g., "24%")
|
|
180
|
+
- `percent-first` — Percentage before bar (e.g., "Daily 24% ━━──")
|
|
181
|
+
|
|
182
|
+
#### Display Modes
|
|
183
|
+
|
|
184
|
+
- `bar` — Progress bar visualization
|
|
185
|
+
- `percentage` — Percentage only (no bar)
|
|
186
|
+
- `icon-pct` — Nerd-font icon + percentage
|
|
187
|
+
|
|
188
|
+
#### Bar Styles
|
|
189
|
+
|
|
190
|
+
- `classic` — `━━━━────` (default)
|
|
191
|
+
- `block` — `████░░░░`
|
|
192
|
+
- `shade` — `▓▓▓▓░░░░`
|
|
193
|
+
- `pipe` — `||||····`
|
|
194
|
+
- `dot` — `●●●●○○○○`
|
|
195
|
+
- `braille` — `⣿⣿⣿⣿⠀⠀⠀⠀` (smooth gradients)
|
|
196
|
+
- `square` — `■■■■□□□□`
|
|
197
|
+
- `star` — `★★★★☆☆☆☆`
|
|
198
|
+
- Custom — `{"fill": "▰", "empty": "▱"}`
|
|
199
|
+
|
|
200
|
+
#### Bar Sizes
|
|
201
|
+
|
|
202
|
+
- `small` — 4 chars
|
|
203
|
+
- `small-medium` — 6 chars
|
|
204
|
+
- `medium` — 8 chars (default)
|
|
205
|
+
- `medium-large` — 10 chars
|
|
206
|
+
- `large` — 12 chars
|
|
207
|
+
|
|
208
|
+
### Per-Component Configuration
|
|
209
|
+
|
|
210
|
+
Override global settings per component:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"components": {
|
|
215
|
+
"daily": {
|
|
216
|
+
"barStyle": "dot",
|
|
217
|
+
"color": "chill",
|
|
218
|
+
"countdown": {
|
|
219
|
+
"format": "duration",
|
|
220
|
+
"divider": " · ",
|
|
221
|
+
"prefix": "⏱ "
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"weekly": {
|
|
225
|
+
"layout": "compact",
|
|
226
|
+
"displayMode": "icon-pct"
|
|
227
|
+
},
|
|
228
|
+
"balance": {
|
|
229
|
+
"label": "Credits"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Note:** Countdown divider defaults to ` · ` (space-dot-space) for clean spacing.
|
|
236
|
+
|
|
237
|
+
### Color Configuration
|
|
238
|
+
|
|
239
|
+
#### Named Colors
|
|
240
|
+
|
|
241
|
+
`black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `dim`, `bright-red`, `bright-green`, etc.
|
|
242
|
+
|
|
243
|
+
#### Hex Colors
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"components": {
|
|
248
|
+
"daily": {
|
|
249
|
+
"color": "#00ff00"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Dynamic Color Aliases
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"colors": {
|
|
260
|
+
"auto": {
|
|
261
|
+
"low": "green",
|
|
262
|
+
"medium": "yellow",
|
|
263
|
+
"high": "red",
|
|
264
|
+
"lowThreshold": 50,
|
|
265
|
+
"highThreshold": 80
|
|
266
|
+
},
|
|
267
|
+
"chill": {
|
|
268
|
+
"low": "cyan",
|
|
269
|
+
"medium": "blue",
|
|
270
|
+
"high": "magenta",
|
|
271
|
+
"lowThreshold": 60,
|
|
272
|
+
"highThreshold": 90
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
#### Per-Part Coloring
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"components": {
|
|
283
|
+
"daily": {
|
|
284
|
+
"colors": {
|
|
285
|
+
"label": "#8a8a8a",
|
|
286
|
+
"bar": "auto",
|
|
287
|
+
"value": "white",
|
|
288
|
+
"countdown": "#666666"
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Environment Variables
|
|
296
|
+
|
|
297
|
+
| Variable | Required | Description |
|
|
298
|
+
|----------|----------|-------------|
|
|
299
|
+
| `ANTHROPIC_BASE_URL` | Yes | API endpoint (e.g., `https://api.sub2api.com`) |
|
|
300
|
+
| `ANTHROPIC_AUTH_TOKEN` | Yes | API key or token |
|
|
301
|
+
| `CC_STATUSLINE_PROVIDER` | No | Override provider detection (`sub2api`, `claude-relay-service`, or custom) |
|
|
302
|
+
| `CC_STATUSLINE_POLL` | No | Override poll interval (seconds, min 5) |
|
|
303
|
+
| `CC_STATUSLINE_TIMEOUT` | No | Piped mode timeout (milliseconds, default 1000) |
|
|
304
|
+
| `DEBUG` or `CC_STATUSLINE_DEBUG` | No | Enable debug logging to `~/.claude/cc-api-statusline/debug.log` |
|
|
305
|
+
|
|
306
|
+
## Provider Setup
|
|
307
|
+
|
|
308
|
+
### sub2api
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
export ANTHROPIC_BASE_URL="https://api.sub2api.com"
|
|
312
|
+
export ANTHROPIC_AUTH_TOKEN="sk-sub2api-..."
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### claude-relay-service
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
export ANTHROPIC_BASE_URL="https://relay.example.com"
|
|
319
|
+
export ANTHROPIC_AUTH_TOKEN="your-relay-token"
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Custom Providers
|
|
323
|
+
|
|
324
|
+
Define custom providers in config.json:
|
|
325
|
+
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"customProviders": {
|
|
329
|
+
"my-provider": {
|
|
330
|
+
"urlPatterns": ["my-proxy.example.com"],
|
|
331
|
+
"endpoint": "/api/usage",
|
|
332
|
+
"method": "GET",
|
|
333
|
+
"authMode": "bearer",
|
|
334
|
+
"responseMapping": {
|
|
335
|
+
"billingMode": "$.mode",
|
|
336
|
+
"daily.used": "$.usage.daily",
|
|
337
|
+
"daily.limit": "$.limits.daily"
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## CLI Usage
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
# Show help
|
|
348
|
+
cc-api-statusline --help
|
|
349
|
+
|
|
350
|
+
# Show version
|
|
351
|
+
cc-api-statusline --version
|
|
352
|
+
|
|
353
|
+
# Fetch once and exit
|
|
354
|
+
cc-api-statusline --once
|
|
355
|
+
|
|
356
|
+
# Use custom config file
|
|
357
|
+
cc-api-statusline --config /path/to/config.json
|
|
358
|
+
|
|
359
|
+
# Install as Claude Code statusline widget
|
|
360
|
+
cc-api-statusline --install
|
|
361
|
+
cc-api-statusline --install --runner bunx
|
|
362
|
+
cc-api-statusline --install --force # Overwrite existing
|
|
363
|
+
|
|
364
|
+
# Uninstall from Claude Code
|
|
365
|
+
cc-api-statusline --uninstall
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Debug Logging
|
|
369
|
+
|
|
370
|
+
Enable detailed execution logs for troubleshooting:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
# Enable debug logging
|
|
374
|
+
DEBUG=1 cc-api-statusline --once
|
|
375
|
+
|
|
376
|
+
# For Claude Code widget, add to settings.json:
|
|
377
|
+
{
|
|
378
|
+
"statusLine": {
|
|
379
|
+
"type": "command",
|
|
380
|
+
"command": "DEBUG=1 bunx -y cc-api-statusline@latest",
|
|
381
|
+
"padding": 0
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
# View logs in real-time
|
|
386
|
+
tail -f ~/.claude/cc-api-statusline/debug.log
|
|
387
|
+
|
|
388
|
+
# View recent logs
|
|
389
|
+
tail -20 ~/.claude/cc-api-statusline/debug.log
|
|
390
|
+
|
|
391
|
+
# Search for errors
|
|
392
|
+
grep "ERROR" ~/.claude/cc-api-statusline/debug.log
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Debug logs include:
|
|
396
|
+
- Execution start/finish timestamps
|
|
397
|
+
- Mode detection (piped vs TTY)
|
|
398
|
+
- Environment variables (sanitized)
|
|
399
|
+
- Config and cache status
|
|
400
|
+
- Execution paths taken (A/B/C/D)
|
|
401
|
+
- Fetch timing and performance metrics
|
|
402
|
+
- Cache operations
|
|
403
|
+
- Error details with fallback behavior
|
|
404
|
+
|
|
405
|
+
## Performance
|
|
406
|
+
|
|
407
|
+
Piped mode performance targets (1000ms timeout):
|
|
408
|
+
|
|
409
|
+
- **Path A (warm cache)**: ≤25ms (p95 ≤100ms)
|
|
410
|
+
- **Path B (re-render)**: ≤55ms (p95 ≤100ms)
|
|
411
|
+
- **Path C (fetch)**: ≤840ms worst case
|
|
412
|
+
- **Path D (fallback)**: ≤25ms
|
|
413
|
+
|
|
414
|
+
Cache validation:
|
|
415
|
+
- TTL check
|
|
416
|
+
- Provider match
|
|
417
|
+
- Base URL match
|
|
418
|
+
- Version match
|
|
419
|
+
- Token hash match
|
|
420
|
+
|
|
421
|
+
Exit code behavior:
|
|
422
|
+
- Returns `0` when stale cache is shown with error indicators (output is still useful)
|
|
423
|
+
- Returns `1` only when no data can be shown (prevents confusing `[Exit: 1]` in widgets)
|
|
424
|
+
|
|
425
|
+
## Troubleshooting
|
|
426
|
+
|
|
427
|
+
### "Missing required environment variable"
|
|
428
|
+
|
|
429
|
+
Set `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN`:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
export ANTHROPIC_BASE_URL="https://your-proxy.example.com"
|
|
433
|
+
export ANTHROPIC_AUTH_TOKEN="your-token"
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Or add to `~/.claude/settings.json`:
|
|
437
|
+
|
|
438
|
+
```json
|
|
439
|
+
{
|
|
440
|
+
"env": {
|
|
441
|
+
"ANTHROPIC_BASE_URL": "https://your-proxy.example.com",
|
|
442
|
+
"ANTHROPIC_AUTH_TOKEN": "your-token"
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### "Unknown provider"
|
|
448
|
+
|
|
449
|
+
Provider autodetection failed. Explicitly set provider:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
export CC_STATUSLINE_PROVIDER="sub2api"
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Or define a custom provider in config.json.
|
|
456
|
+
|
|
457
|
+
### "[offline]" or "[stale]" indicator
|
|
458
|
+
|
|
459
|
+
Network error or cache staleness. Enable debug logging to investigate:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
DEBUG=1 cc-api-statusline --once
|
|
463
|
+
tail -f ~/.claude/cc-api-statusline/debug.log
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Check:
|
|
467
|
+
- Network connectivity to `ANTHROPIC_BASE_URL`
|
|
468
|
+
- API endpoint is responding
|
|
469
|
+
- Token is valid and not expired
|
|
470
|
+
|
|
471
|
+
### Slow performance in piped mode
|
|
472
|
+
|
|
473
|
+
Check cache validity:
|
|
474
|
+
- Run `cc-api-statusline --once` standalone to warm cache
|
|
475
|
+
- Verify `~/.claude/cc-api-statusline/cache-*.json` exists
|
|
476
|
+
- Check `pipedRequestTimeoutMs` config (default 800ms)
|
|
477
|
+
- Enable debug logging to see fetch timing
|
|
478
|
+
|
|
479
|
+
### Widget shows `[Exit: 1]` in Claude Code
|
|
480
|
+
|
|
481
|
+
This indicates the statusline command failed. Enable debug logging:
|
|
482
|
+
|
|
483
|
+
```json
|
|
484
|
+
{
|
|
485
|
+
"statusLine": {
|
|
486
|
+
"type": "command",
|
|
487
|
+
"command": "DEBUG=1 bunx -y cc-api-statusline@latest",
|
|
488
|
+
"padding": 0
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
Then check logs: `tail -f ~/.claude/cc-api-statusline/debug.log`
|
|
494
|
+
|
|
495
|
+
## Development
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
# Install dependencies
|
|
499
|
+
bun install
|
|
500
|
+
|
|
501
|
+
# Quick dev fetch (--once mode)
|
|
502
|
+
bun run start
|
|
503
|
+
|
|
504
|
+
# Simulate piped mode
|
|
505
|
+
bun run example
|
|
506
|
+
|
|
507
|
+
# Run tests
|
|
508
|
+
bun test
|
|
509
|
+
|
|
510
|
+
# Lint
|
|
511
|
+
bun run lint
|
|
512
|
+
|
|
513
|
+
# Build
|
|
514
|
+
bun run build
|
|
515
|
+
|
|
516
|
+
# Run all checks
|
|
517
|
+
bun run check
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
## Architecture
|
|
521
|
+
|
|
522
|
+
```
|
|
523
|
+
┌─────────────┐
|
|
524
|
+
│ main.ts │ ← Entry point, CLI orchestration, install/uninstall
|
|
525
|
+
└──────┬──────┘
|
|
526
|
+
│
|
|
527
|
+
├──────────────────────────────────────┐
|
|
528
|
+
│ │
|
|
529
|
+
┌──────▼────────┐ ┌────────▼────────┐
|
|
530
|
+
│ services/ │ │ providers/ │
|
|
531
|
+
│ - env │ │ - sub2api │
|
|
532
|
+
│ - cache │ │ - relay │
|
|
533
|
+
│ - config │ │ - custom │
|
|
534
|
+
│ - settings │ ← settings.json │ - autodetect │
|
|
535
|
+
│ - logger │ ← debug logging └────────┬────────┘
|
|
536
|
+
└──────┬────────┘ │
|
|
537
|
+
│ │
|
|
538
|
+
├──────────────────────────────────────┘
|
|
539
|
+
│
|
|
540
|
+
┌──────▼────────┐
|
|
541
|
+
│ execute-cycle │ ← Unified execution (Path A/B/C/D)
|
|
542
|
+
└──────┬────────┘
|
|
543
|
+
│
|
|
544
|
+
┌──────▼────────┐
|
|
545
|
+
│ renderer/ │
|
|
546
|
+
│ - component │ ← Per-component rendering
|
|
547
|
+
│ - bar │ ← Progress bars
|
|
548
|
+
│ - colors │ ← ANSI color system
|
|
549
|
+
│ - countdown │ ← Time-to-reset
|
|
550
|
+
│ - error │ ← Error states
|
|
551
|
+
│ - icons │ ← Nerd-font glyphs
|
|
552
|
+
│ - truncate │ ← Terminal width
|
|
553
|
+
│ - index │ ← Main pipeline
|
|
554
|
+
└───────────────┘
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Testing
|
|
558
|
+
|
|
559
|
+
- **356 tests** across **21 test files**
|
|
560
|
+
- Unit tests for all services and renderers
|
|
561
|
+
- Core execution path tests (A/B/C/D)
|
|
562
|
+
- E2E smoke tests with isolated environments
|
|
563
|
+
- Performance tests (p95 < 600ms verification)
|
|
564
|
+
- CI/CD via GitHub Actions
|
|
565
|
+
|
|
566
|
+
Run: `bun run check`
|
|
567
|
+
|
|
568
|
+
## License
|
|
569
|
+
|
|
570
|
+
MIT
|
|
571
|
+
|
|
572
|
+
## Links
|
|
573
|
+
|
|
574
|
+
- [Implementation Handbook](docs/implementation-handbook.md)
|
|
575
|
+
- [Current Implementation](docs/current-implementation.md)
|
|
576
|
+
- [TUI Style Spec](docs/spec-tui-style.md)
|
|
577
|
+
- [API Polling Spec](docs/spec-api-polling.md)
|
|
578
|
+
- [Custom Providers Spec](docs/spec-custom-providers.md)
|
|
579
|
+
- [AGENTS.md](AGENTS.md) - Development handoff guide
|