glm-quota-line 0.6.0 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0
4
+
5
+ - Added progressive refresh backoff: new sessions start at 3-minute intervals, advance to 5 minutes after 5 refreshes, and cap at 10 minutes after 5 more — giving new users fast feedback while reducing API pressure in long sessions
6
+ - Added low-quota override: when remaining quota drops below 30%, the refresh interval is forced back to 3 minutes regardless of current tier, so users see accurate data when it matters most
7
+ - Low-quota refreshes do not advance the tier counter, preserving the previous tier when quota recovers
8
+ - SessionStart (startup / resume / clear) resets the tier to level 0, ensuring fresh sessions always start responsive
9
+ - Rate-limited and failed responses no longer advance the tier counter
10
+ - Old cache files without tier fields automatically migrate to tier 0
11
+ - Simplified README quick start to two commands with style config clearly marked as optional
12
+
13
+ ## 0.7.0
14
+
15
+ - Added `--version` and `version` so the installed CLI version is visible directly from the command line
16
+ - Added `check-update` to compare the installed version with npm and print a suggested upgrade command without auto-updating
17
+ - Improved CLI help and README docs with upgrade and version-check examples
18
+ - Corrected published package metadata to include `README.en.md` in the npm file list
19
+
3
20
  ## 0.6.0
4
21
 
5
22
  - Added official international GLM quota endpoint support for `api.z.ai` while preserving domestic `open.bigmodel.cn` detection
package/README.en.md ADDED
@@ -0,0 +1,122 @@
1
+ <h1 align="center">glm-quota-line</h1>
2
+
3
+ <p align="center">
4
+ One-command install, zero dependencies. Shows accurate Zhipu GLM Coding Plan quota balance and reset time in the Claude Code status line — data from the official API, not estimated.
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/glm-quota-line"><img alt="npm version" src="https://img.shields.io/npm/v/glm-quota-line?logo=npm&color=cb3837"></a>
9
+ <a href="https://www.npmjs.com/package/glm-quota-line"><img alt="node version" src="https://img.shields.io/node/v/glm-quota-line?logo=node.js&color=339933"></a>
10
+ <a href="./LICENSE"><img alt="license" src="https://img.shields.io/npm/l/glm-quota-line"></a>
11
+ <img alt="dependencies" src="https://img.shields.io/badge/dependencies-0-2ea44f">
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="./README.md">简体中文</a>
16
+ </p>
17
+
18
+ `glm-quota-line` reads the Zhipu GLM Coding Plan quota API, caches results, and prints a short status line for Claude Code's `statusLine.command`. A `SessionStart` hook pre-refreshes the cache so new sessions never show stale data.
19
+
20
+ ## Features
21
+
22
+ - **One-command install** — `glm-quota-line install` wires status line and `SessionStart` hooks into Claude Code automatically
23
+ - **Accurate quota display** — reads directly from the official GLM quota API, not estimated; shows both 5-hour and weekly token quotas
24
+ - **Domestic + international endpoints** — auto-detects `open.bigmodel.cn` and `api.z.ai`
25
+ - **Zero dependencies** — no runtime deps, single-purpose CLI
26
+ - **Smart caching** — refreshes by session, TTL, and token usage; supports manual auth overrides for proxy/gateway setups
27
+
28
+ ## Quick Start
29
+
30
+ ```bash
31
+ npm install -g glm-quota-line
32
+ glm-quota-line install
33
+ ```
34
+
35
+ That's it — works out of the box. Default output (`style=text`, `theme=ansi`, `palette=dark`):
36
+
37
+ ```text
38
+ GLM Lite | 5h 91% | week 47% | reset 14:47
39
+ ```
40
+
41
+ Both the 5-hour quota (primary) and weekly quota (secondary) are shown with automatic reset time.
42
+
43
+ Upgrade:
44
+
45
+ ```bash
46
+ npm install -g glm-quota-line
47
+ glm-quota-line check-update
48
+ ```
49
+
50
+ ## Custom Styles
51
+
52
+ All style options are optional — adjust only if needed:
53
+
54
+ ```bash
55
+ glm-quota-line config set style bar # layout: text / compact / bar
56
+ glm-quota-line config set theme ansi # color: plain / ansi
57
+ glm-quota-line config set palette dark # palette: dark / mono (only when theme=ansi)
58
+ ```
59
+
60
+ Different `style` outputs:
61
+
62
+ ```text
63
+ # style=text (default)
64
+ GLM Lite | 5h 91% | week 47% | reset 14:47
65
+
66
+ # style=compact
67
+ GLM 5h 91% W 47% | 14:47
68
+
69
+ # style=bar
70
+ GLM Lite █░░░░░░░░░ 91% | W 47% | 14:47
71
+ ```
72
+
73
+ Recommended combinations:
74
+
75
+ | Use case | Config |
76
+ | -------------- | --------------------------------------------- |
77
+ | Dark terminal | `style=bar`, `theme=ansi`, `palette=dark` |
78
+ | Light terminal | `style=compact`, `theme=ansi`, `palette=mono` |
79
+ | Plain fallback | any `style`, `theme=plain` |
80
+
81
+ ## Custom Auth
82
+
83
+ If Claude Code runs behind a gateway or proxy and the injected `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_BASE_URL` are not the real values:
84
+
85
+ ```bash
86
+ glm-quota-line config set auth-token <your-real-token>
87
+ glm-quota-line config set base-url https://open.bigmodel.cn/api/anthropic
88
+ # or
89
+ glm-quota-line config set base-url https://api.z.ai/api/anthropic
90
+ ```
91
+
92
+ Clear with `glm-quota-line config unset auth-token` / `base-url`. Stored overrides take precedence over Claude-injected environment variables.
93
+
94
+ ## Commands
95
+
96
+ ```bash
97
+ glm-quota-line [--style text|compact|bar] [--display left|used|both]
98
+ [--theme plain|ansi] [--palette dark|mono]
99
+
100
+ glm-quota-line install [--force]
101
+ glm-quota-line uninstall
102
+ glm-quota-line version
103
+ glm-quota-line check-update
104
+ glm-quota-line config show
105
+ glm-quota-line config set <style|display|theme|palette|auth-token|base-url> <value>
106
+ glm-quota-line config unset <key>
107
+ ```
108
+
109
+ Run `glm-quota-line --help` for full descriptions.
110
+
111
+ Use `glm-quota-line --version` to print the installed version. `check-update` only checks and prints the suggested upgrade command; it does not modify your environment.
112
+
113
+ ## Notes
114
+
115
+ - Only `TOKENS_LIMIT` quotas are shown; `TIME_LIMIT` / MCP usage is ignored
116
+ - Missing auth returns `GLM | auth expired`; API failures return `GLM | quota unavailable`
117
+ - `install` does not replace an unmanaged status line unless `--force` is used
118
+ - `install --force` backs up the previous entry; `uninstall` restores it when possible
119
+
120
+ ## License
121
+
122
+ [MIT](./LICENSE)
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <h1 align="center">glm-quota-line</h1>
2
2
 
3
3
  <p align="center">
4
- Zero-dependency CLI for showing GLM Coding Plan quota in the Claude Code status line.
4
+ 一行命令安装、零依赖,在 Claude Code 状态栏实时显示智谱(Zhipu)GLM Coding Plan 配额余额与重置时间。数据来自官方接口,精准非估算。
5
5
  </p>
6
6
 
7
7
  <p align="center">
@@ -12,127 +12,86 @@
12
12
  </p>
13
13
 
14
14
  <p align="center">
15
- <a href="./README.zh-CN.md">简体中文</a>
15
+ <a href="./README.en.md">English</a>
16
16
  </p>
17
17
 
18
- ## Overview
18
+ `glm-quota-line` 读取智谱(Zhipu)GLM Coding Plan 配额接口、缓存结果,并输出一行适合 Claude Code `statusLine.command` 的状态文本。通过 `SessionStart` hook 预刷新缓存,新会话不会显示旧配额。
19
19
 
20
- `glm-quota-line` reads the GLM quota endpoint, caches successful responses, and prints a single short line for `statusLine.command`.
20
+ ## 功能
21
21
 
22
- It also installs a Claude Code `SessionStart` hook to pre-refresh the quota cache before a new session renders the status line.
22
+ - **一行命令安装** — `glm-quota-line install` 自动接入 Claude Code 状态栏和 `SessionStart` hook
23
+ - **精准配额显示** — 数据来自官方配额接口,非估算;同时展示 5 小时和周 token 配额
24
+ - **国内 + 国际端点** — 自动识别 `open.bigmodel.cn` 和 `api.z.ai`
25
+ - **零依赖** — 无运行时依赖,单一用途
26
+ - **智能缓存** — 按会话、TTL 和 token 用量刷新;支持代理/网关手动覆盖鉴权
23
27
 
24
- It is intentionally scoped to one host only: Claude Code.
25
-
26
- ## Why
27
-
28
- - Built for a single purpose: show GLM quota clearly in Claude Code
29
- - Small and predictable: no runtime dependencies, no unnecessary abstraction
30
- - Practical for real usage: cache-aware, session-aware, and easy to install
31
-
32
- ## Features
33
-
34
- - Built for Claude Code `statusLine.command`
35
- - No runtime dependencies
36
- - Optional `text`, `compact`, and `bar` layouts
37
- - Optional ANSI color themes for dark and light terminals
38
- - Manual `auth-token` and `base-url` overrides for proxy or gateway setups
39
- - Automatic install and uninstall for Claude Code status line integration
40
- - SessionStart pre-refresh so a new Claude session does not briefly show stale quota
41
-
42
- ## Installation
43
-
44
- Recommended:
28
+ ## 快速开始
45
29
 
46
30
  ```bash
47
31
  npm install -g glm-quota-line
32
+ glm-quota-line install
48
33
  ```
49
34
 
50
- From a local clone:
35
+ 两步完成,开箱即用。默认输出(`style=text`,`theme=ansi`,`palette=dark`):
51
36
 
52
- ```bash
53
- npm install -g .
37
+ ```text
38
+ GLM Lite | 5h 91% | week 47% | reset 14:47
54
39
  ```
55
40
 
56
- `npx` is fine for one-off previews, but global install is the better default for Claude Code integration because `install` writes stable executable paths into both `statusLine.command` and the managed `SessionStart` hooks.
41
+ 同时显示 5 小时配额(主要)和周配额(次要),并自动展示重置时间。
57
42
 
58
- ## Quick Start
43
+ 升级版本:
59
44
 
60
45
  ```bash
61
- glm-quota-line install
62
- glm-quota-line config set style bar
63
- glm-quota-line config set theme ansi
64
- glm-quota-line config set palette dark
46
+ npm install -g glm-quota-line
47
+ glm-quota-line check-update
65
48
  ```
66
49
 
67
- For a one-off preview:
50
+ ## 自定义样式
51
+
52
+ 所有样式配置均为可选,按需调整:
68
53
 
69
54
  ```bash
70
- glm-quota-line --style compact
55
+ glm-quota-line config set style bar # 布局: text / compact / bar
56
+ glm-quota-line config set theme ansi # 配色: plain / ansi
57
+ glm-quota-line config set palette dark # 色板: dark / mono(仅 theme=ansi 时生效)
71
58
  ```
72
59
 
73
- ## Output
60
+ 不同 style 效果:
74
61
 
75
62
  ```text
76
- GLM Lite | 5h left 91% | week 47% | reset 14:47
63
+ # style=text(默认)
64
+ GLM Lite | 5h 91% | week 47% | reset 14:47
77
65
 
66
+ # style=compact
78
67
  GLM 5h 91% W 47% | 14:47
79
68
 
69
+ # style=bar
80
70
  GLM Lite █░░░░░░░░░ 91% | W 47% | 14:47
81
71
  ```
82
72
 
83
- ## Recommended Setups
84
-
85
- | Use case | Config |
86
- | -------------- | --------------------------------------------- |
87
- | Dark terminal | `style=bar`, `theme=ansi`, `palette=dark` |
88
- | Light terminal | `style=compact`, `theme=ansi`, `palette=mono` |
89
- | Plain fallback | any `style`, `theme=plain` |
90
-
91
- ## Color Presets
73
+ 推荐搭配:
92
74
 
93
- `style` controls layout. `theme` enables or disables ANSI color. `palette` only applies when `theme=ansi`.
75
+ | 使用场景 | 配置 |
76
+ | ---------- | --------------------------------------------- |
77
+ | 深色终端 | `style=bar`, `theme=ansi`, `palette=dark` |
78
+ | 浅色终端 | `style=compact`, `theme=ansi`, `palette=mono` |
79
+ | 纯文本回退 | 任意 `style`,`theme=plain` |
94
80
 
95
- - Dark terminal: `theme=ansi` + `palette=dark`
96
- - Light terminal: `theme=ansi` + `palette=mono`
97
- - Maximum compatibility: `theme=plain`
81
+ ## 自定义鉴权
98
82
 
99
- Examples:
100
-
101
- ```bash
102
- glm-quota-line config set style text
103
- glm-quota-line config set theme ansi
104
- glm-quota-line config set palette dark
105
-
106
- glm-quota-line config set style compact
107
- glm-quota-line config set theme ansi
108
- glm-quota-line config set palette mono
109
-
110
- glm-quota-line config set theme plain
111
- ```
112
-
113
- Set `NO_COLOR=1` to force plain output.
114
-
115
- ## Manual Credential Overrides
116
-
117
- If Claude Code is running behind a gateway or proxy and the injected `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_BASE_URL` are not the real values, store explicit overrides:
83
+ 如果 Claude Code 运行在代理或网关后面,注入的 `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_BASE_URL` 不是实际值:
118
84
 
119
85
  ```bash
120
86
  glm-quota-line config set auth-token <your-real-token>
121
87
  glm-quota-line config set base-url https://open.bigmodel.cn/api/anthropic
122
- # or
88
+ # 或
123
89
  glm-quota-line config set base-url https://api.z.ai/api/anthropic
124
90
  ```
125
91
 
126
- Clear them later with:
127
-
128
- ```bash
129
- glm-quota-line config unset auth-token
130
- glm-quota-line config unset base-url
131
- ```
132
-
133
- Stored overrides take precedence over Claude-injected environment variables. `config show` redacts the token, but the local config file still stores the real value in plain text.
92
+ 清除:`glm-quota-line config unset auth-token` / `base-url`。手动保存的值优先于 Claude 注入的环境变量。
134
93
 
135
- ## Commands
94
+ ## 命令
136
95
 
137
96
  ```bash
138
97
  glm-quota-line [--style text|compact|bar] [--display left|used|both]
@@ -140,28 +99,24 @@ glm-quota-line [--style text|compact|bar] [--display left|used|both]
140
99
 
141
100
  glm-quota-line install [--force]
142
101
  glm-quota-line uninstall
102
+ glm-quota-line version
103
+ glm-quota-line check-update
143
104
  glm-quota-line config show
144
- glm-quota-line config set style <text|compact|bar>
145
- glm-quota-line config set display <left|used|both>
146
- glm-quota-line config set theme <plain|ansi>
147
- glm-quota-line config set palette <dark|mono>
148
- glm-quota-line config set auth-token <token>
149
- glm-quota-line config set base-url <url>
150
- glm-quota-line config unset <style|display|theme|palette|auth-token|base-url>
105
+ glm-quota-line config set <style|display|theme|palette|auth-token|base-url> <value>
106
+ glm-quota-line config unset <key>
151
107
  ```
152
108
 
153
- Run `glm-quota-line --help` for the full command descriptions and examples.
109
+ 完整说明运行 `glm-quota-line --help`。
110
+
111
+ `glm-quota-line --version` 可直接查看当前安装版本;`check-update` 只检查并提示升级命令,不会自动修改环境。
154
112
 
155
- ## Notes
113
+ ## 说明
156
114
 
157
- - Default output is plain text
158
- - Missing or expired auth returns `GLM | auth expired`
159
- - API or parsing failures return `GLM | quota unavailable`
160
- - Only `TOKENS_LIMIT` quotas are shown; `TIME_LIMIT` / MCP usage is ignored
161
- - `install` wires both the status line command and managed `SessionStart` hooks
162
- - `install` does not replace an unmanaged Claude status line unless `--force` is used
163
- - `install --force` backs up the previous entry and `uninstall` restores it when possible
115
+ - 只展示 `TOKENS_LIMIT` 配额,忽略 `TIME_LIMIT` / MCP 使用量
116
+ - 鉴权缺失返回 `GLM | auth expired`;接口异常返回 `GLM | quota unavailable`
117
+ - `install` 默认不会覆盖非本工具管理的状态栏,除非使用 `--force`
118
+ - `install --force` 会备份旧配置,`uninstall` 会在可能时恢复
164
119
 
165
- ## License
120
+ ## 许可证
166
121
 
167
122
  [MIT](./LICENSE)
package/package.json CHANGED
@@ -1,17 +1,19 @@
1
1
  {
2
2
  "name": "glm-quota-line",
3
- "version": "0.6.0",
4
- "description": "Claude Code status line helper for GLM Coding Plan quota.",
3
+ "version": "0.8.0",
4
+ "description": "Zhipu GLM Coding Plan quota monitor for Claude Code status line.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "caojian",
8
8
  "preferGlobal": true,
9
9
  "keywords": [
10
10
  "claude-code",
11
- "statusline",
12
11
  "glm",
12
+ "zhipu",
13
+ "z.ai",
14
+ "coding-plan",
13
15
  "quota",
14
- "cli"
16
+ "statusline"
15
17
  ],
16
18
  "repository": {
17
19
  "type": "git",
@@ -27,7 +29,7 @@
27
29
  "files": [
28
30
  "src",
29
31
  "README.md",
30
- "README.zh-CN.md",
32
+ "README.en.md",
31
33
  "LICENSE",
32
34
  "CHANGELOG.md"
33
35
  ],
@@ -32,7 +32,7 @@ function isToolManagedStatusLine(statusLine) {
32
32
  return isToolManagedCommand(statusLine?.command);
33
33
  }
34
34
 
35
- export function getStatusLineEntryPath() {
35
+ function getStatusLineEntryPath() {
36
36
  return path.resolve(__dirname, "..", "cli", "index.js");
37
37
  }
38
38
 
@@ -53,38 +53,41 @@ function isToolManagedHook(hook) {
53
53
  return hook?.type === "command" && isToolManagedCommand(hook.command);
54
54
  }
55
55
 
56
- function removeManagedSessionStartHooks(settings) {
57
- if (!settings.hooks || typeof settings.hooks !== "object") {
58
- return false;
59
- }
60
-
61
- const existingGroups = Array.isArray(settings.hooks.SessionStart) ? settings.hooks.SessionStart : null;
62
- if (!existingGroups) {
63
- return false;
64
- }
56
+ function filterManagedHooksFromGroups(groups) {
57
+ let hadManaged = false;
58
+ const filtered = [];
65
59
 
66
- let removed = false;
67
- const nextGroups = [];
68
-
69
- for (const group of existingGroups) {
60
+ for (const group of groups) {
70
61
  if (!group || typeof group !== "object" || !Array.isArray(group.hooks)) {
71
- nextGroups.push(group);
62
+ filtered.push(group);
72
63
  continue;
73
64
  }
74
65
 
75
66
  const nextHooks = group.hooks.filter((hook) => !isToolManagedHook(hook));
76
67
  if (nextHooks.length !== group.hooks.length) {
77
- removed = true;
68
+ hadManaged = true;
78
69
  }
79
70
 
80
71
  if (nextHooks.length > 0) {
81
- nextGroups.push({
82
- ...group,
83
- hooks: nextHooks
84
- });
72
+ filtered.push({ ...group, hooks: nextHooks });
85
73
  }
86
74
  }
87
75
 
76
+ return { groups: filtered, hadManaged };
77
+ }
78
+
79
+ function removeManagedSessionStartHooks(settings) {
80
+ if (!settings.hooks || typeof settings.hooks !== "object") {
81
+ return false;
82
+ }
83
+
84
+ const existingGroups = Array.isArray(settings.hooks.SessionStart) ? settings.hooks.SessionStart : null;
85
+ if (!existingGroups) {
86
+ return false;
87
+ }
88
+
89
+ const { groups: nextGroups, hadManaged: removed } = filterManagedHooksFromGroups(existingGroups);
90
+
88
91
  if (nextGroups.length > 0) {
89
92
  settings.hooks.SessionStart = nextGroups;
90
93
  } else {
@@ -101,21 +104,10 @@ function removeManagedSessionStartHooks(settings) {
101
104
  function installManagedSessionStartHooks(settings, command) {
102
105
  const existingGroups =
103
106
  settings.hooks && typeof settings.hooks === "object" && Array.isArray(settings.hooks.SessionStart)
104
- ? settings.hooks.SessionStart.map((group) =>
105
- group && typeof group === "object" ? { ...group, hooks: Array.isArray(group.hooks) ? [...group.hooks] : group.hooks } : group
106
- )
107
+ ? settings.hooks.SessionStart
107
108
  : [];
108
109
 
109
- const nextGroups = existingGroups.map((group) => {
110
- if (!group || typeof group !== "object" || !Array.isArray(group.hooks)) {
111
- return group;
112
- }
113
-
114
- return {
115
- ...group,
116
- hooks: group.hooks.filter((hook) => !isToolManagedHook(hook))
117
- };
118
- });
110
+ const { groups: nextGroups } = filterManagedHooksFromGroups(existingGroups);
119
111
 
120
112
  for (const matcher of SESSION_START_MATCHERS) {
121
113
  const targetGroup = nextGroups.find(
@@ -123,21 +115,13 @@ function installManagedSessionStartHooks(settings, command) {
123
115
  );
124
116
 
125
117
  if (targetGroup) {
126
- targetGroup.hooks.push({
127
- type: "command",
128
- command
129
- });
118
+ targetGroup.hooks.push({ type: "command", command });
130
119
  continue;
131
120
  }
132
121
 
133
122
  nextGroups.push({
134
123
  matcher,
135
- hooks: [
136
- {
137
- type: "command",
138
- command
139
- }
140
- ]
124
+ hooks: [{ type: "command", command }]
141
125
  });
142
126
  }
143
127
 
@@ -3,7 +3,7 @@ import { resolveQuotaStatus } from "../core/quota/service.js";
3
3
  import { readStatusLineInput } from "./input.js";
4
4
  import { readToolConfig } from "./settings.js";
5
5
 
6
- export const SESSION_START_MATCHERS = ["startup", "resume", "clear", "compact"];
6
+ export const SESSION_START_MATCHERS = ["startup", "resume", "clear"];
7
7
 
8
8
  export async function refreshQuotaOnSessionStart(options = {}) {
9
9
  const hookInput = await readStatusLineInput(options.stdin ?? process.stdin);
@@ -12,10 +12,7 @@ export async function refreshQuotaOnSessionStart(options = {}) {
12
12
  const resolveQuotaStatusFn = options.resolveQuotaStatusFn ?? resolveQuotaStatus;
13
13
  const config = {
14
14
  ...loadConfigFn(options.env ?? process.env, userConfig),
15
- sessionId: hookInput?.session_id || "",
16
- // SessionStart runs before statusLine has token totals, so treat a new session
17
- // as starting from zero to preserve later token-threshold refreshes.
18
- observedTokens: 0
15
+ sessionId: hookInput?.session_id || ""
19
16
  };
20
17
 
21
18
  return resolveQuotaStatusFn(config, {
@@ -10,8 +10,9 @@ import {
10
10
  isValidTheme
11
11
  } from "../shared/constants.js";
12
12
  import { readJsonFile, writeJsonFile } from "../shared/jsonFile.js";
13
+ import { normalizeOptionalString } from "../shared/config.js";
13
14
 
14
- export function getClaudeDir() {
15
+ function getClaudeDir() {
15
16
  return path.join(os.homedir(), ".claude");
16
17
  }
17
18
 
@@ -23,15 +24,6 @@ export function getToolConfigPath() {
23
24
  return path.join(getClaudeDir(), "glm-quota-line.json");
24
25
  }
25
26
 
26
- function normalizeOptionalString(value) {
27
- if (typeof value !== "string") {
28
- return undefined;
29
- }
30
-
31
- const trimmed = value.trim();
32
- return trimmed || undefined;
33
- }
34
-
35
27
  function redactSecret(value) {
36
28
  if (!value) {
37
29
  return value;
package/src/cli/args.js CHANGED
@@ -26,6 +26,11 @@ export function parseArgs(argv = process.argv.slice(2)) {
26
26
  continue;
27
27
  }
28
28
 
29
+ if (arg === "--version" || arg === "-v") {
30
+ options.version = true;
31
+ continue;
32
+ }
33
+
29
34
  if (arg === "--force") {
30
35
  options.force = true;
31
36
  continue;
@@ -67,4 +72,3 @@ export function parseArgs(argv = process.argv.slice(2)) {
67
72
  options.positionals = positionals;
68
73
  return options;
69
74
  }
70
-
@@ -13,6 +13,8 @@ import {
13
13
  } from "../claude/settings.js";
14
14
  import { installClaudeStatusLine, uninstallClaudeStatusLine } from "../claude/install.js";
15
15
  import { refreshQuotaOnSessionStart } from "../claude/sessionStart.js";
16
+ import { checkForUpdates } from "./update.js";
17
+ import { getPackageVersion } from "../shared/packageInfo.js";
16
18
 
17
19
  function isNonEmptyString(value) {
18
20
  return typeof value === "string" && value.trim().length > 0;
@@ -66,9 +68,36 @@ const CONFIG_KEYS = {
66
68
  }
67
69
  };
68
70
 
69
- export async function handleCommand(args, output = process.stdout) {
71
+ export async function handleCommand(args, output = process.stdout, dependencies = {}) {
72
+ const getVersion = dependencies.getVersion || getPackageVersion;
73
+ const runUpdateCheck = dependencies.runUpdateCheck || checkForUpdates;
70
74
  const [command, subcommand, key, value] = args.positionals;
71
75
 
76
+ if (command === "version") {
77
+ output.write(`glm-quota-line ${await getVersion()}\n`);
78
+ return true;
79
+ }
80
+
81
+ if (command === "check-update") {
82
+ const result = await runUpdateCheck();
83
+ output.write(`glm-quota-line ${result.currentVersion}\n`);
84
+
85
+ if (result.status === "up-to-date") {
86
+ output.write(`latest: ${result.latestVersion}\nstatus: up to date\n`);
87
+ return true;
88
+ }
89
+
90
+ if (result.status === "update-available") {
91
+ output.write(
92
+ `latest: ${result.latestVersion}\nstatus: update available\nupgrade: ${result.upgradeCommand}\n`
93
+ );
94
+ return true;
95
+ }
96
+
97
+ output.write(`status: unable to check updates\nreason: ${result.errorMessage}\n`);
98
+ return true;
99
+ }
100
+
72
101
  if (command === "install") {
73
102
  const result = await installClaudeStatusLine(undefined, undefined, undefined, {
74
103
  force: Boolean(args.force)