@juliantanx/aiusage-widget 1.3.1 → 1.3.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 juliantanx
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.
package/README.md CHANGED
@@ -1,79 +1,81 @@
1
- # @juliantanx/aiusage-widget
2
-
3
- A lightweight system tray widget for [aiusage](https://github.com/juliantanx/aiusage) that shows your AI coding assistant token usage at a glance.
4
-
5
- English | [中文](./README_zh.md)
6
-
7
- ## Features
8
-
9
- - **System tray integration** — lives in your system tray, click to toggle a compact stats panel.
10
- - **Today's token usage** — total tokens with input/output breakdown.
11
- - **Monthly totals** — rolling token count for the current month.
12
- - **Top model** — your most-used model today and its share.
13
- - **Dashboard launcher** — one click to open the full aiusage web dashboard.
14
- - **Auto-refresh** — updates every 60 seconds automatically.
15
- - **Cross-platform** — Windows, macOS, and Linux.
16
-
17
- ## Prerequisites
18
-
19
- - [aiusage](https://github.com/juliantanx/aiusage) CLI installed and data parsed (`aiusage parse`)
20
- - Node.js >= 18
21
-
22
- ## Install
23
-
24
- ```bash
25
- npm install -g @juliantanx/aiusage-widget
26
- ```
27
-
28
- ## Usage
29
-
30
- ```bash
31
- # Start the widget (runs in background, adds a tray icon)
32
- aiusage-widget
33
- ```
34
-
35
- The widget reads from `~/.aiusage/cache.db`. Make sure you have run `aiusage parse` at least once so the database exists.
36
-
37
- ### Running with PM2
38
-
39
- To keep the widget running after closing the terminal and auto-start on boot:
40
-
41
- ```bash
42
- npm install -g pm2 pm2-startup
43
-
44
- pm2 start aiusage-widget -- --foreground
45
- pm2 save
46
- pm2-startup install
47
- ```
48
-
49
- PM2 works on Windows, macOS, and Linux.
50
-
51
- **Tray interactions:**
52
-
53
- - **Left-click** — toggle the stats panel.
54
- - **Right-click** — context menu with Show Panel, Refresh, and Quit.
55
-
56
- **Panel actions:**
57
-
58
- - Click **Open Full Dashboard** to launch `aiusage serve` and open the web dashboard in your browser.
59
-
60
- ## Build from Source
61
-
62
- ```bash
63
- git clone https://github.com/juliantanx/aiusage.git
64
- cd aiusage
65
- pnpm install
66
- pnpm build
67
- cd packages/widget
68
- pnpm dev
69
- ```
70
-
71
- ## Tech Stack
72
-
73
- - **Runtime:** Electron
74
- - **UI:** Svelte + Vite
75
- - **Database:** better-sqlite3 (reads aiusage's local SQLite database)
76
-
77
- ## License
78
-
79
- MIT
1
+ # @juliantanx/aiusage-widget
2
+
3
+ A lightweight system tray widget for [aiusage](https://github.com/juliantanx/aiusage) that shows your AI coding assistant token usage at a glance.
4
+
5
+ English | [中文](./README_zh.md)
6
+
7
+ ## Features
8
+
9
+ - **System tray integration** — lives in your system tray, click to toggle a compact stats panel.
10
+ - **Today's token usage** — total tokens with input/output breakdown.
11
+ - **Monthly totals** — rolling token count for the current month.
12
+ - **Top model** — your most-used model today and its share.
13
+ - **Dashboard launcher** — one click to open the full aiusage web dashboard.
14
+ - **Auto-refresh** — updates every 60 seconds automatically.
15
+ - **Cross-platform** — Windows, macOS, and Linux.
16
+
17
+ ## Prerequisites
18
+
19
+ - [aiusage](https://github.com/juliantanx/aiusage) CLI installed and data parsed (`aiusage parse`)
20
+ - Node.js >= 18
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install -g @juliantanx/aiusage-widget
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ```bash
31
+ # Start the widget (runs in background, adds a tray icon)
32
+ aiusage-widget
33
+ ```
34
+
35
+ The widget reads from `~/.aiusage/cache.db`. Make sure you have run `aiusage parse` at least once so the database exists.
36
+
37
+ ### Running with PM2
38
+
39
+ To keep the widget running after closing the terminal and auto-start on boot:
40
+
41
+ ```bash
42
+ npm install -g pm2
43
+
44
+ # Start aiusage server + widget as background services
45
+ aiusage pm2-start
46
+
47
+ # Linux / macOS: run directly; Windows: run the output command as Administrator
48
+ pm2 startup
49
+ ```
50
+
51
+ PM2 works on Windows, macOS, and Linux.
52
+
53
+ **Tray interactions:**
54
+
55
+ - **Left-click** — toggle the stats panel.
56
+ - **Right-click** — context menu with Show Panel, Refresh, and Quit.
57
+
58
+ **Panel actions:**
59
+
60
+ - Click **Open Full Dashboard** to launch `aiusage serve` and open the web dashboard in your browser.
61
+
62
+ ## Build from Source
63
+
64
+ ```bash
65
+ git clone https://github.com/juliantanx/aiusage.git
66
+ cd aiusage
67
+ pnpm install
68
+ pnpm build
69
+ cd packages/widget
70
+ pnpm dev
71
+ ```
72
+
73
+ ## Tech Stack
74
+
75
+ - **Runtime:** Electron
76
+ - **UI:** Svelte + Vite
77
+ - **Database:** better-sqlite3 (reads aiusage's local SQLite database)
78
+
79
+ ## License
80
+
81
+ MIT
package/README_zh.md CHANGED
@@ -1,79 +1,81 @@
1
- # @juliantanx/aiusage-widget
2
-
3
- 一个轻量级的系统托盘小组件,用于 [aiusage](https://github.com/juliantanx/aiusage),可以快速查看 AI 编程助手的 token 用量。
4
-
5
- [English](./README.md) | 中文
6
-
7
- ## 功能
8
-
9
- - **系统托盘集成** — 常驻系统托盘,点击即可弹出简洁的统计面板。
10
- - **今日 token 用量** — 总 token 数及输入/输出明细。
11
- - **月度总量** — 当月累计 token 数。
12
- - **热门模型** — 今日使用最多的模型及其占比。
13
- - **仪表盘启动** — 一键打开完整的 aiusage Web 仪表盘。
14
- - **自动刷新** — 每 60 秒自动更新数据。
15
- - **跨平台** — 支持 Windows、macOS 和 Linux。
16
-
17
- ## 前置条件
18
-
19
- - 已安装 [aiusage](https://github.com/juliantanx/aiusage) CLI 并完成数据解析(`aiusage parse`)
20
- - Node.js >= 18
21
-
22
- ## 安装
23
-
24
- ```bash
25
- npm install -g @juliantanx/aiusage-widget
26
- ```
27
-
28
- ## 使用
29
-
30
- ```bash
31
- # 启动组件(后台运行,添加系统托盘图标)
32
- aiusage-widget
33
- ```
34
-
35
- 组件会读取 `~/.aiusage/cache.db`。请确保至少执行过一次 `aiusage parse`,使数据库文件存在。
36
-
37
- ### 使用 PM2 后台运行
38
-
39
- 如需关闭终端后保持组件运行,并实现开机自启:
40
-
41
- ```bash
42
- npm install -g pm2 pm2-startup
43
-
44
- pm2 start aiusage-widget -- --foreground
45
- pm2 save
46
- pm2-startup install
47
- ```
48
-
49
- PM2 支持 Windows、macOS 和 Linux。
50
-
51
- **托盘操作:**
52
-
53
- - **左键点击** — 切换统计面板的显示/隐藏。
54
- - **右键点击** — 弹出上下文菜单,包含显示面板、刷新和退出。
55
-
56
- **面板操作:**
57
-
58
- - 点击 **Open Full Dashboard** 可启动 `aiusage serve` 并在浏览器中打开 Web 仪表盘。
59
-
60
- ## 从源码构建
61
-
62
- ```bash
63
- git clone https://github.com/juliantanx/aiusage.git
64
- cd aiusage
65
- pnpm install
66
- pnpm build
67
- cd packages/widget
68
- pnpm dev
69
- ```
70
-
71
- ## 技术栈
72
-
73
- - **运行时:** Electron
74
- - **UI:** Svelte + Vite
75
- - **数据库:** better-sqlite3(读取 aiusage 的本地 SQLite 数据库)
76
-
77
- ## 许可证
78
-
79
- MIT
1
+ # @juliantanx/aiusage-widget
2
+
3
+ 一个轻量级的系统托盘小组件,用于 [aiusage](https://github.com/juliantanx/aiusage),可以快速查看 AI 编程助手的 token 用量。
4
+
5
+ [English](./README.md) | 中文
6
+
7
+ ## 功能
8
+
9
+ - **系统托盘集成** — 常驻系统托盘,点击即可弹出简洁的统计面板。
10
+ - **今日 token 用量** — 总 token 数及输入/输出明细。
11
+ - **月度总量** — 当月累计 token 数。
12
+ - **热门模型** — 今日使用最多的模型及其占比。
13
+ - **仪表盘启动** — 一键打开完整的 aiusage Web 仪表盘。
14
+ - **自动刷新** — 每 60 秒自动更新数据。
15
+ - **跨平台** — 支持 Windows、macOS 和 Linux。
16
+
17
+ ## 前置条件
18
+
19
+ - 已安装 [aiusage](https://github.com/juliantanx/aiusage) CLI 并完成数据解析(`aiusage parse`)
20
+ - Node.js >= 18
21
+
22
+ ## 安装
23
+
24
+ ```bash
25
+ npm install -g @juliantanx/aiusage-widget
26
+ ```
27
+
28
+ ## 使用
29
+
30
+ ```bash
31
+ # 启动组件(后台运行,添加系统托盘图标)
32
+ aiusage-widget
33
+ ```
34
+
35
+ 组件会读取 `~/.aiusage/cache.db`。请确保至少执行过一次 `aiusage parse`,使数据库文件存在。
36
+
37
+ ### 使用 PM2 后台运行
38
+
39
+ 如需关闭终端后保持组件运行,并实现开机自启:
40
+
41
+ ```bash
42
+ npm install -g pm2
43
+
44
+ # 一条命令启动 aiusage 服务 + 托盘组件为后台服务
45
+ aiusage pm2-start
46
+
47
+ # Linux / macOS: 直接执行;Windows: 以管理员身份执行输出的命令
48
+ pm2 startup
49
+ ```
50
+
51
+ PM2 支持 Windows、macOS 和 Linux。
52
+
53
+ **托盘操作:**
54
+
55
+ - **左键点击** — 切换统计面板的显示/隐藏。
56
+ - **右键点击** — 弹出上下文菜单,包含显示面板、刷新和退出。
57
+
58
+ **面板操作:**
59
+
60
+ - 点击 **Open Full Dashboard** 可启动 `aiusage serve` 并在浏览器中打开 Web 仪表盘。
61
+
62
+ ## 从源码构建
63
+
64
+ ```bash
65
+ git clone https://github.com/juliantanx/aiusage.git
66
+ cd aiusage
67
+ pnpm install
68
+ pnpm build
69
+ cd packages/widget
70
+ pnpm dev
71
+ ```
72
+
73
+ ## 技术栈
74
+
75
+ - **运行时:** Electron
76
+ - **UI:** Svelte + Vite
77
+ - **数据库:** better-sqlite3(读取 aiusage 的本地 SQLite 数据库)
78
+
79
+ ## 许可证
80
+
81
+ MIT
package/bin/launcher.js CHANGED
@@ -1,40 +1,40 @@
1
- #!/usr/bin/env node
2
- const { spawn } = require('child_process')
3
- const { writeFileSync, mkdirSync } from 'fs'
4
- const { homedir } = require('os')
5
- const electron = require('electron')
6
- const path = require('path')
7
-
8
- const foreground = process.argv.includes('--foreground')
9
- const aiusageDir = path.join(homedir(), '.aiusage')
10
- const pidPath = path.join(aiusageDir, 'widget.pid')
11
-
12
- if (foreground) {
13
- // PM2 / service mode: run in foreground so the process manager can monitor it
14
- const child = spawn(
15
- String(electron),
16
- [path.join(__dirname, '..', 'dist', 'main.js')],
17
- { stdio: 'inherit' }
18
- )
19
- child.on('exit', (code) => process.exit(code ?? 0))
20
- process.on('SIGINT', () => child.kill('SIGINT'))
21
- process.on('SIGTERM', () => child.kill('SIGTERM'))
22
- } else {
23
- // Normal mode: detach so closing the terminal doesn't kill the widget
24
- const child = spawn(
25
- String(electron),
26
- [path.join(__dirname, '..', 'dist', 'main.js')],
27
- { detached: true, stdio: 'ignore' }
28
- )
29
-
30
- if (child.pid) {
31
- try {
32
- mkdirSync(aiusageDir, { recursive: true })
33
- writeFileSync(pidPath, String(child.pid), { encoding: 'utf-8' })
34
- } catch {
35
- // Non-fatal: widget still starts, deduplication just won't work
36
- }
37
- }
38
-
39
- child.unref()
40
- }
1
+ #!/usr/bin/env node
2
+ const { spawn } = require('child_process')
3
+ const { writeFileSync, mkdirSync } from 'fs'
4
+ const { homedir } = require('os')
5
+ const electron = require('electron')
6
+ const path = require('path')
7
+
8
+ const foreground = process.argv.includes('--foreground')
9
+ const aiusageDir = path.join(homedir(), '.aiusage')
10
+ const pidPath = path.join(aiusageDir, 'widget.pid')
11
+
12
+ if (foreground) {
13
+ // PM2 / service mode: run in foreground so the process manager can monitor it
14
+ const child = spawn(
15
+ String(electron),
16
+ [path.join(__dirname, '..', 'dist', 'main.js')],
17
+ { stdio: 'inherit' }
18
+ )
19
+ child.on('exit', (code) => process.exit(code ?? 0))
20
+ process.on('SIGINT', () => child.kill('SIGINT'))
21
+ process.on('SIGTERM', () => child.kill('SIGTERM'))
22
+ } else {
23
+ // Normal mode: detach so closing the terminal doesn't kill the widget
24
+ const child = spawn(
25
+ String(electron),
26
+ [path.join(__dirname, '..', 'dist', 'main.js')],
27
+ { detached: true, stdio: 'ignore' }
28
+ )
29
+
30
+ if (child.pid) {
31
+ try {
32
+ mkdirSync(aiusageDir, { recursive: true })
33
+ writeFileSync(pidPath, String(child.pid), { encoding: 'utf-8' })
34
+ } catch {
35
+ // Non-fatal: widget still starts, deduplication just won't work
36
+ }
37
+ }
38
+
39
+ child.unref()
40
+ }
package/dist/data.js CHANGED
@@ -6,27 +6,27 @@ function queryWidgetData(db) {
6
6
  const monthStart = getMonthStartMs();
7
7
  const tomorrow = todayStart + 86400000;
8
8
  const nextMonthStart = getNextMonthStartMs();
9
- const todayRow = db.prepare(`
10
- SELECT
11
- COALESCE(SUM(input_tokens), 0) AS input,
12
- COALESCE(SUM(output_tokens), 0) AS output,
13
- COALESCE(SUM(cache_read_tokens + cache_write_tokens + thinking_tokens), 0) AS other
14
- FROM records
15
- WHERE ts >= ? AND ts < ?
9
+ const todayRow = db.prepare(`
10
+ SELECT
11
+ COALESCE(SUM(input_tokens), 0) AS input,
12
+ COALESCE(SUM(output_tokens), 0) AS output,
13
+ COALESCE(SUM(cache_read_tokens + cache_write_tokens + thinking_tokens), 0) AS other
14
+ FROM records
15
+ WHERE ts >= ? AND ts < ?
16
16
  `).get(todayStart, tomorrow);
17
- const monthRow = db.prepare(`
18
- SELECT COALESCE(SUM(input_tokens + output_tokens + cache_read_tokens + cache_write_tokens + thinking_tokens), 0) AS total
19
- FROM records
20
- WHERE ts >= ? AND ts < ?
17
+ const monthRow = db.prepare(`
18
+ SELECT COALESCE(SUM(input_tokens + output_tokens + cache_read_tokens + cache_write_tokens + thinking_tokens), 0) AS total
19
+ FROM records
20
+ WHERE ts >= ? AND ts < ?
21
21
  `).get(monthStart, nextMonthStart);
22
- const modelRows = db.prepare(`
23
- SELECT
24
- model,
25
- SUM(input_tokens + output_tokens + cache_read_tokens + cache_write_tokens + thinking_tokens) AS tokens
26
- FROM records
27
- WHERE ts >= ? AND ts < ?
28
- GROUP BY model
29
- ORDER BY tokens DESC
22
+ const modelRows = db.prepare(`
23
+ SELECT
24
+ model,
25
+ SUM(input_tokens + output_tokens + cache_read_tokens + cache_write_tokens + thinking_tokens) AS tokens
26
+ FROM records
27
+ WHERE ts >= ? AND ts < ?
28
+ GROUP BY model
29
+ ORDER BY tokens DESC
30
30
  `).all(todayStart, tomorrow);
31
31
  let topModel = null;
32
32
  if (modelRows.length > 0) {
@@ -1,14 +1,14 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" />
7
- <title>aiusage Widget</title>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" />
7
+ <title>aiusage Widget</title>
8
8
  <script type="module" crossorigin src="./assets/index-Bb9mog0W.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-2X4hbwJe.css">
10
- </head>
11
- <body>
12
- <div id="app"></div>
13
- </body>
14
- </html>
10
+ </head>
11
+ <body>
12
+ <div id="app"></div>
13
+ </body>
14
+ </html>
package/dist/ui.js CHANGED
@@ -4,11 +4,11 @@ exports.shouldShowWindowOnLaunch = shouldShowWindowOnLaunch;
4
4
  exports.shouldHideWindowOnBlur = shouldHideWindowOnBlur;
5
5
  exports.shouldHideWindowOnClose = shouldHideWindowOnClose;
6
6
  exports.getTrayIconDataUrl = getTrayIconDataUrl;
7
- const TRAY_ICON_SVG = `
8
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
9
- <rect x="1" y="1" width="14" height="14" rx="4" fill="#111827"/>
10
- <path d="M8.8 2.5 4.7 8.2h2.9L7 13.5l4.3-5.9H8.4l.4-5.1Z" fill="#f8fafc"/>
11
- </svg>
7
+ const TRAY_ICON_SVG = `
8
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
9
+ <rect x="1" y="1" width="14" height="14" rx="4" fill="#111827"/>
10
+ <path d="M8.8 2.5 4.7 8.2h2.9L7 13.5l4.3-5.9H8.4l.4-5.1Z" fill="#f8fafc"/>
11
+ </svg>
12
12
  `.trim();
13
13
  // Pre-rendered 32x32 PNG of the same icon — Windows tray doesn't support SVG
14
14
  const TRAY_ICON_PNG_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAyUlEQVR4nMWXMQ6DMAxFzRcX6NYu' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juliantanx/aiusage-widget",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "private": false,
5
5
  "description": "System tray widget for aiusage — view AI token usage from your system tray",
6
6
  "keywords": [
@@ -34,15 +34,6 @@
34
34
  "bin": {
35
35
  "aiusage-widget": "bin/launcher.js"
36
36
  },
37
- "scripts": {
38
- "rebuild": "pnpm run rebuild:electron",
39
- "rebuild:electron": "node -e \"const {execSync}=require('child_process'); const electronVersion=require('electron/package.json').version; const cmd='npm rebuild better-sqlite3 --runtime=electron --target=' + electronVersion + ' --dist-url=https://electronjs.org/headers'; execSync(cmd, {stdio:'inherit'})\"",
40
- "rebuild:node": "npm rebuild better-sqlite3",
41
- "dev": "pnpm run rebuild:electron && concurrently --names \"vite,tsc,electron\" --kill-others --success command-electron \"vite build --watch\" \"tsc -p tsconfig.json --watch\" \"pnpm exec wait-on dist/main.js && pnpm exec electron .\"",
42
- "build": "rm -rf dist/renderer && vite build && tsc -p tsconfig.json",
43
- "pack": "pnpm build && electron-builder",
44
- "test": "pnpm run rebuild:node && vitest run"
45
- },
46
37
  "dependencies": {
47
38
  "better-sqlite3": "^11.0.0"
48
39
  },
@@ -58,5 +49,14 @@
58
49
  "vite": "^5.0.0",
59
50
  "vitest": "^2.0.0",
60
51
  "wait-on": "^7.0.0"
52
+ },
53
+ "scripts": {
54
+ "rebuild": "pnpm run rebuild:electron",
55
+ "rebuild:electron": "node -e \"const {execSync}=require('child_process'); const electronVersion=require('electron/package.json').version; const cmd='npm rebuild better-sqlite3 --runtime=electron --target=' + electronVersion + ' --dist-url=https://electronjs.org/headers'; execSync(cmd, {stdio:'inherit'})\"",
56
+ "rebuild:node": "npm rebuild better-sqlite3",
57
+ "dev": "pnpm run rebuild:electron && concurrently --names \"vite,tsc,electron\" --kill-others --success command-electron \"vite build --watch\" \"tsc -p tsconfig.json --watch\" \"pnpm exec wait-on dist/main.js && pnpm exec electron .\"",
58
+ "build": "rm -rf dist/renderer && vite build && tsc -p tsconfig.json",
59
+ "pack": "pnpm build && electron-builder",
60
+ "test": "pnpm run rebuild:node && vitest run"
61
61
  }
62
- }
62
+ }