Skip to content

Commit df0a751

Browse files
authored
feat!: web dashboard, analytics, and CLIProxy multi-account support
2 parents b321edd + 0075afa commit df0a751

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3910
-259
lines changed

CLAUDE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ bun run format # Auto-fix formatting
4040
- `lib/` - Native shell scripts (bash, PowerShell)
4141
- `ui/` - React dashboard (Vite + React 19 + shadcn/ui)
4242

43+
**Development server (ALWAYS use for testing UI changes):**
44+
```bash
45+
bun run dev # Start dev server with hot reload (http://localhost:3000)
46+
```
47+
**IMPORTANT:** Use `bun run dev` at CCS root level for always up-to-date code. Do NOT use `ccs config` during development as it uses the globally installed (outdated) version.
48+
4349
## UI Quality Gates (React Dashboard)
4450

4551
**The ui/ directory has IDENTICAL quality gates to the main project.**

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ Features a modern React 19 dashboard with real-time updates.
1212

1313
[![License](https://img.shields.io/badge/license-MIT-C15F3C?style=for-the-badge)](LICENSE)
1414
[![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey?style=for-the-badge)]()
15+
[![PoweredBy](https://img.shields.io/badge/PoweredBy-ClaudeKit-C15F3C?style=for-the-badge)](https://claudekit.cc?ref=HMNKXOHN)
16+
1517
[![npm](https://img.shields.io/npm/v/@kaitranntt/ccs?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@kaitranntt/ccs)
1618
[![React](https://img.shields.io/badge/React-19-61DAFB?style=for-the-badge&logo=react)](https://react.dev/)
1719
[![TypeScript](https://img.shields.io/badge/TypeScript-100%25-3178C6?style=for-the-badge&logo=typescript)](https://www.typescriptlang.org/)
18-
[![PoweredBy](https://img.shields.io/badge/PoweredBy-ClaudeKit-C15F3C?style=for-the-badge)](https://claudekit.cc?ref=HMNKXOHN)
1920

2021
**Languages**: [English](README.md) | [Tiếng Việt](docs/vi/README.md) | [日本語](docs/ja/README.md)
2122

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.11.0
1+
5.11.0-dev.8

bun.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"": {
55
"name": "@kaitranntt/ccs",
66
"dependencies": {
7+
"better-ccusage": "^1.2.6",
78
"boxen": "^8.0.1",
89
"chalk": "^5.6.2",
910
"chokidar": "^5.0.0",
@@ -445,6 +446,8 @@
445446

446447
"before-after-hook": ["[email protected]", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="],
447448

449+
"better-ccusage": ["[email protected]", "", { "bin": { "better-ccusage": "dist/index.js" } }, "sha512-IZCYBX1kF0IfJ6ho9JMwLKn2o820WRiVGZ+2tVS2olODU5J7Np5mJ1j1i5HtazZPNo2S9wKU9C9iysc0f8Cjqw=="],
450+
448451
"body-parser": ["[email protected]", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="],
449452

450453
"bottleneck": ["[email protected]", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="],

docs/project-roadmap.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ src/types/
440440
- Intelligent profile selection algorithms
441441
- Cost estimation with typed calculation models
442442
- Performance optimization through type-aware caching
443+
- Recently implemented significant UI improvements for analytics dashboard, enhancing data presentation.
443444

444445
2. **Enhanced Session Management**
445446
- Type-safe session persistence with serialization
@@ -584,21 +585,29 @@ src/types/
584585
- **User Experience**: One-command channel switching without data loss
585586
- **Backward Compatibility**: Zero breaking changes, existing workflows preserved
586587

587-
### Version 4.5.1 - UI Layout Improvements
588+
### Version 4.5.1 - UI Quality Gate Fixes & Layout Improvements
588589
**Release Date**: 2025-12-08
589590

590591
#### UI Fixes & Improvements
592+
-**Auto-formatting**: 31 UI files auto-formatted for consistent styling.
593+
-**Fast Refresh Exports**: Resolved `react-refresh/only-export-components` by extracting `buttonVariants`, `useSidebar`, and `useWebSocketContext` to separate files.
594+
-**React Hooks Issues**: Fixed `react-hooks/purity` (`Math.random()` in `useMemo` for `sidebar.tsx`) and `react-hooks/set-state-in-effect` (`use-theme.ts`, `settings.tsx`).
595+
-**useWebSocket Hook Restructure**: Addressed `react-hooks/immutability` errors and dependency array warnings in `use-websocket.ts`.
596+
-**TypeScript Strict Mode**: Implemented null-check for `document.getElementById('root')` in `src/main.tsx` for strict mode compliance.
597+
-**Duplicate Directory Removal**: Cleaned up extraneous `ui/@/` directory.
591598
-**CLIProxy Card Padding**: Removed excessive padding from CLIProxy cards for better visual integration.
592-
-**CLIProxy Dashboard Layout**: Improved overall layout and styling of the CLIProxy dashboard for enhanced user experience.
593-
-**Dropdown Styling**: Refined dropdown component styling for consistency and readability.
599+
-**CLIProxy Dashboard Layout**: Improved overall layout and styling of the CLIProxy dashboard.
600+
-**Dropdown Styling**: Refined dropdown component styling.
601+
-**Model Usage Card**: Corrected icon display and refined donut chart styling.
594602

595603
#### Technical Improvements
596604
- **Improved UI Responsiveness**: Adjustments ensure better display across various screen sizes.
597605
- **Enhanced User Experience**: Minor visual tweaks lead to a more polished and intuitive interface.
598606

599607
#### Validation Results
600-
- **UI Rendering**: ✅ All UI components render correctly after layout adjustments.
608+
- **UI Rendering**: ✅ All UI components render correctly after adjustments and fixes.
601609
- **Functional Impact**: ✅ No regressions introduced, core functionality remains stable.
610+
- **Code Quality**: ✅ All ESLint and TypeScript quality gates passed after fixes.
602611

603612
---
604613

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kaitranntt/ccs",
3-
"version": "5.11.0",
3+
"version": "5.11.0-dev.8",
44
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
55
"keywords": [
66
"cli",
@@ -79,6 +79,7 @@
7979
"postinstall": "node scripts/postinstall.js"
8080
},
8181
"dependencies": {
82+
"better-ccusage": "^1.2.6",
8283
"boxen": "^8.0.1",
8384
"chalk": "^5.6.2",
8485
"chokidar": "^5.0.0",

src/cliproxy/model-catalog.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,27 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
4848
agy: {
4949
provider: 'agy',
5050
displayName: 'Antigravity',
51-
defaultModel: 'gemini-3-pro-preview',
51+
defaultModel: 'gemini-claude-opus-4-5-thinking',
5252
models: [
53-
{
54-
id: 'gemini-claude-sonnet-4-5',
55-
name: 'Claude Sonnet 4.5',
56-
description: 'Fast and capable',
57-
},
58-
{
59-
id: 'gemini-3-pro-preview',
60-
name: 'Gemini 3 Pro',
61-
description: 'Google latest model via Antigravity',
62-
},
6353
{
6454
id: 'gemini-claude-opus-4-5-thinking',
6555
name: 'Claude Opus 4.5 Thinking',
6656
description: 'Most capable, extended thinking',
67-
deprecated: true,
68-
deprecationReason:
69-
'Thinking models are deprecated due to compatibility issues with Antigravity',
7057
},
7158
{
7259
id: 'gemini-claude-sonnet-4-5-thinking',
7360
name: 'Claude Sonnet 4.5 Thinking',
7461
description: 'Balanced with extended thinking',
75-
deprecated: true,
76-
deprecationReason:
77-
'Thinking models are deprecated due to compatibility issues with Antigravity',
62+
},
63+
{
64+
id: 'gemini-claude-sonnet-4-5',
65+
name: 'Claude Sonnet 4.5',
66+
description: 'Fast and capable',
67+
},
68+
{
69+
id: 'gemini-3-pro-preview',
70+
name: 'Gemini 3 Pro',
71+
description: 'Google latest model via Antigravity',
7872
},
7973
],
8074
},

src/commands/update-command.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
*/
77

88
import { spawn } from 'child_process';
9-
import * as path from 'path';
10-
import * as fs from 'fs';
119
import { colored } from '../utils/helpers';
1210
import { detectInstallationMethod, detectPackageManager } from '../utils/package-manager-detector';
1311
import { compareVersionsWithPrerelease } from '../utils/update-checker';
12+
import { getVersion } from '../utils/version';
1413

1514
/**
1615
* Options for the update command
@@ -20,10 +19,8 @@ export interface UpdateOptions {
2019
beta?: boolean;
2120
}
2221

23-
// Version (sync with package.json)
24-
const CCS_VERSION = JSON.parse(
25-
fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8')
26-
).version;
22+
// Version (from centralized utility)
23+
const CCS_VERSION = getVersion();
2724

2825
/**
2926
* Handle the update command
@@ -169,19 +166,17 @@ function handleCheckFailed(
169166
* Handle no update available
170167
*/
171168
function handleNoUpdate(reason: string | undefined): void {
172-
const CCS_VERSION_LOCAL = JSON.parse(
173-
fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8')
174-
).version;
169+
const version = getVersion();
175170

176-
let message = `You are already on the latest version (${CCS_VERSION_LOCAL})`;
171+
let message = `You are already on the latest version (${version})`;
177172

178173
switch (reason) {
179174
case 'dismissed':
180-
message = `Update dismissed. You are on version ${CCS_VERSION_LOCAL}`;
175+
message = `Update dismissed. You are on version ${version}`;
181176
console.log(colored(`[i] ${message}`, 'yellow'));
182177
break;
183178
case 'cached':
184-
message = `No updates available (cached result). You are on version ${CCS_VERSION_LOCAL}`;
179+
message = `No updates available (cached result). You are on version ${version}`;
185180
console.log(colored(`[i] ${message}`, 'cyan'));
186181
break;
187182
default:

src/commands/version-command.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,13 @@ import * as fs from 'fs';
99
import * as os from 'os';
1010
import { colored } from '../utils/helpers';
1111
import { getConfigPath } from '../utils/config-manager';
12-
13-
// Get version from package.json
14-
const CCS_VERSION = JSON.parse(
15-
fs.readFileSync(path.join(__dirname, '../../package.json'), 'utf8')
16-
).version;
12+
import { getVersion } from '../utils/version';
1713

1814
/**
1915
* Handle version command
2016
*/
2117
export function handleVersionCommand(): void {
22-
console.log(colored(`CCS (Claude Code Switch) v${CCS_VERSION}`, 'bold'));
18+
console.log(colored(`CCS (Claude Code Switch) v${getVersion()}`, 'bold'));
2319
console.log('');
2420

2521
console.log(colored('Installation:', 'cyan'));

src/types/external.d.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,81 @@
22
* Type shims for incomplete external dependencies
33
*/
44

5+
// better-ccusage types (package has JS exports but incomplete TS subpath support)
6+
declare module 'better-ccusage/data-loader' {
7+
export interface ModelBreakdown {
8+
modelName: string;
9+
inputTokens: number;
10+
outputTokens: number;
11+
cacheCreationTokens: number;
12+
cacheReadTokens: number;
13+
cost: number;
14+
}
15+
16+
export interface DailyUsage {
17+
date: string;
18+
source: string;
19+
inputTokens: number;
20+
outputTokens: number;
21+
cacheCreationTokens: number;
22+
cacheReadTokens: number;
23+
cost: number;
24+
totalCost: number;
25+
modelsUsed: string[];
26+
modelBreakdowns: ModelBreakdown[];
27+
}
28+
29+
export interface MonthlyUsage {
30+
month: string;
31+
source: string;
32+
inputTokens: number;
33+
outputTokens: number;
34+
cacheCreationTokens: number;
35+
cacheReadTokens: number;
36+
totalCost: number;
37+
modelsUsed: string[];
38+
modelBreakdowns: ModelBreakdown[];
39+
}
40+
41+
export interface SessionUsage {
42+
sessionId: string;
43+
projectPath: string;
44+
inputTokens: number;
45+
outputTokens: number;
46+
cacheCreationTokens: number;
47+
cacheReadTokens: number;
48+
cost: number;
49+
totalCost: number;
50+
lastActivity: string;
51+
versions: string[];
52+
modelsUsed: string[];
53+
modelBreakdowns: ModelBreakdown[];
54+
source: string;
55+
}
56+
57+
export interface DataLoaderOptions {
58+
mode?: 'calculate' | 'cached';
59+
claudePaths?: string[];
60+
}
61+
62+
export function loadDailyUsageData(options?: DataLoaderOptions): Promise<DailyUsage[]>;
63+
export function loadMonthlyUsageData(options?: DataLoaderOptions): Promise<MonthlyUsage[]>;
64+
export function loadSessionData(options?: DataLoaderOptions): Promise<SessionUsage[]>;
65+
}
66+
67+
declare module 'better-ccusage/calculate-cost' {
68+
export interface Totals {
69+
inputTokens: number;
70+
outputTokens: number;
71+
cacheCreationTokens: number;
72+
cacheReadTokens: number;
73+
costUSD: number;
74+
}
75+
76+
export function calculateTotals(entries: unknown[]): Totals;
77+
export function getTotalTokens(entries: unknown[]): number;
78+
}
79+
580
declare module 'cli-table3' {
681
interface TableOptions {
782
head?: string[];

0 commit comments

Comments
 (0)