glm-quota-line 1.2.0 → 1.3.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
+ ## 1.3.0
4
+
5
+ - Added `commands` subcommand: list every command with a machine-readable schema via `--json` (name / summary / sideEffect / args / examples), for AI agents and scripting
6
+ - Added per-subcommand `--help` (e.g. `model --help`, `config set --help`) — focused help derived from a single command registry
7
+ - **User-customizable model mapping table** — model context window sizes are now managed by the user at runtime. The bundled `data/models.json` is just a frozen base; your local `modelMap` overlays it, so adapting to a new model (e.g. `glm-5.2` with 1M context) needs only `model set <id> <size>` — no package update or upgrade required
8
+ - Added `model` subcommands: `list`, `get`, `set`, `remove` — manage model context window size mappings via CLI
9
+ - Added `modelMap` persistence in tool config — custom model sizes survive across sessions
10
+ - Added `config reset [--models] [--yes]` — restore user config to defaults. `--models` limits the reset to custom model mappings. Preserves install state; prompts unless `--yes` (required in non-interactive sessions)
11
+ - Model ids reported with a bracket suffix (e.g. `glm-5.2[1M]`) are now normalized to the bare id for lookup and display
12
+ - Updated default table: added `glm-5.2` (1M context), removed `glm-5` and `glm-5.1` (no longer in plan)
13
+ - Added `reset-format` config (`time` / `countdown`) — show reset time as countdown duration instead of time point
14
+ - Weekly quota now displays reset time (time point or countdown) alongside the progress bar
15
+ - Context window resolution now relies solely on the local model map: stdin `context_window_size` is ignored, and stdin-provided window percentages are no longer used as a fallback (they are often inaccurate). If the current model id is not in the map, the context segment is simply not shown rather than guessing
16
+ - ctx cache now keyed by session id + model id: token usage can be 0 or missing on individual status-line frames (session start, between requests), which would make the context segment flash. The cache falls back to the last valid value for the same session and model so the display stays stable — a stale value from a different session or model is never shown
17
+ - Refactored command dispatch into `configCommand.js` / `modelCommand.js`, and extracted a shared `bar.js` and a context-scoped `cache.js`. No behavior change
18
+ - Hardcoded `glm-4.7` fallback remains as a defensive guard against `data/models.json` I/O failure
19
+
3
20
  ## 1.2.0
4
21
 
5
22
  - Added interactive TUI configuration: `glm-quota-line configure` — live preview, per-component toggle and style, global options
package/README.en.md CHANGED
@@ -116,6 +116,21 @@ Pacing analysis calculates theoretical budget based on elapsed work days:
116
116
  - Yellow — usage speed 1.1x–1.3x theoretical
117
117
  - Red — usage speed > 1.3x theoretical
118
118
 
119
+ ### reset-format — Reset time format
120
+
121
+ Controls how the reset time is displayed in the status line.
122
+
123
+ | Value | Description | Example |
124
+ |---|---|---|
125
+ | `time` (default) | Show the reset time point | `reset 14:47` |
126
+ | `countdown` | Show the remaining countdown | `reset 52m` / `reset 2d 5h` |
127
+
128
+ ```bash
129
+ glm-quota-line config set reset-format countdown
130
+ ```
131
+
132
+ The weekly quota also shows the reset info (time point or countdown) alongside its progress bar.
133
+
119
134
  ### --json — JSON output
120
135
 
121
136
  Output structured JSON format (terminal mode only, ignored in status line mode):
@@ -188,6 +203,21 @@ Auth source priority (highest to lowest):
188
203
  2. Environment variables `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_BASE_URL`
189
204
  3. `env` field in `~/.claude/settings.json`
190
205
 
206
+ ### reset — Restore defaults
207
+
208
+ One-shot reset of user config. Install state is preserved (status line / hook are not removed).
209
+
210
+ ```bash
211
+ glm-quota-line config reset # reset all user config (interactive confirm)
212
+ glm-quota-line config reset --models # reset only custom model mappings (modelMap)
213
+ glm-quota-line config reset --yes # skip confirmation (scripts / CI)
214
+ ```
215
+
216
+ - Default scope: all global config keys (theme/display/style/work-days/minimalist/raw-values/reset-format/auth-token/base-url), component layout (lines), and custom model mappings (modelMap).
217
+ - `--models` limits the reset to modelMap only; other config is left untouched.
218
+ - In non-interactive sessions (no TTY) `--yes` is required, otherwise it errors out — to avoid accidental deletion.
219
+ - After reset the status line still works — model mappings fall back to the bundled table (`data/models.json`).
220
+
191
221
  ### configure — Interactive TUI setup
192
222
 
193
223
  Launch a terminal UI with live preview to adjust component toggles, styles, and global options.
@@ -211,6 +241,31 @@ Components:
211
241
  | `reset` | Reset time | — | ✓ |
212
242
  | `ctx` | Context window usage | ✓ (bar/text) | ✓ |
213
243
 
244
+ ### model — Context window management
245
+
246
+ Manage the context window size mapping per model. The context window usage percentage is computed from this mapping.
247
+
248
+ ```bash
249
+ glm-quota-line model list # list all models and their context window size
250
+ glm-quota-line model get <model-id> # show the size of a given model
251
+ glm-quota-line model set <model-id> <size> # set a model size (e.g. 300K or 300000)
252
+ glm-quota-line model remove <model-id> # remove a custom mapping (built-in model reverts to default)
253
+ ```
254
+
255
+ Example `list` output:
256
+
257
+ ```
258
+ glm-4.7 200K
259
+ glm-5.1 200K
260
+ glm-5.2 300K *
261
+ ```
262
+
263
+ The `*` marker indicates a user-configured mapping.
264
+
265
+ The model mapping is a two-layer system: the bundled `data/models.json` is the default base, and the `modelMap` in `~/.claude/glm-quota-line.json` is the user overlay (merged key-by-key at runtime). **When Zhipu releases a new model, you don't need to wait for an npm package update — just run `model set <new-model> <size>` to write the local overlay and it takes effect immediately.**
266
+
267
+ To clear all custom model mappings and return to the bundled default table, run `glm-quota-line config reset --models --yes`.
268
+
214
269
  ## Recommended Combinations
215
270
 
216
271
  | Use case | Config |
@@ -219,9 +274,11 @@ Components:
219
274
  | Light terminal | `style=bar`, `theme=light` |
220
275
  | Minimal setup | `style=compact`, `theme=mono` |
221
276
  | Track usage | `style=bar`, `display=used` |
277
+ | Countdown reset | `reset-format=countdown` |
222
278
  | Scripting | `--json` |
223
279
  | 6-day work week | `work-days=6` |
224
280
  | Minimal values | `minimalist=true` |
281
+ | Custom model | `glm-quota-line model set glm-5.2 300K` |
225
282
  | Interactive setup | `glm-quota-line configure` |
226
283
 
227
284
  ## Command Reference
@@ -234,18 +291,45 @@ glm-quota-line version
234
291
  glm-quota-line check-update
235
292
  glm-quota-line configure
236
293
  glm-quota-line config show
237
- glm-quota-line config set <style|display|theme|auth-token|base-url|work-days|minimalist|raw-values> <value>
294
+ glm-quota-line config set <style|display|theme|auth-token|base-url|work-days|minimalist|raw-values|reset-format> <value>
238
295
  glm-quota-line config unset <key>
296
+ glm-quota-line config reset [--models] [--yes]
297
+ glm-quota-line model list
298
+ glm-quota-line model get <model-id>
299
+ glm-quota-line model set <model-id> <size>
300
+ glm-quota-line model remove <model-id>
239
301
  ```
240
302
 
241
303
  Run `glm-quota-line --help` for full descriptions.
242
304
 
305
+ ## For Agents / Automation
306
+
307
+ If you are an AI agent (Claude Code / Cursor / Codex) or a script author, the following surface is guaranteed stable:
308
+
309
+ ```bash
310
+ # Get the full machine-readable schema of every command in one call
311
+ # (name / summary / sideEffect / args / examples)
312
+ glm-quota-line commands --json
313
+
314
+ # Focused help for a single command or command group
315
+ glm-quota-line model --help
316
+ glm-quota-line config set --help
317
+ ```
318
+
319
+ Conventions:
320
+ - **Exit codes**: `0` on success, `1` on error.
321
+ - **Side-effect tagging**: every command is tagged `read` (safe for automation), `write` (persists config / model map), `mutating` (modifies Claude Code integration), or `interactive` (requires a TTY).
322
+ - **Non-blocking**: no command blocks waiting for input (`config reset` needs `--yes` in non-interactive sessions; `configure` prints a hint instead of launching the TUI when there is no TTY).
323
+ - **Read query**: `glm-quota-line --json` emits structured quota data (5h / week / MCP + reset times).
324
+
325
+ Typical agent workflow: run `commands --json` to discover capabilities → invoke the command you need → parse stdout.
326
+
243
327
  ## Notes
244
328
 
245
329
  - Shows `TOKENS_LIMIT` and `MCP_LIMIT` / `TIME_LIMIT` quotas
246
330
  - Weekly quota progress bar shadow (▒) is a daily pacing baseline: the theoretical budget based on elapsed work days — the more the filled bar (█) extends past the shadow, the faster you're consuming
247
331
  - Context window usage is shown by default; toggle via `glm-quota-line configure`
248
- - Context window usage is calculated from raw tokens when model mapping is available, falls back to API-provided percentages
332
+ - Context window usage is computed from raw tokens using the local model map; if the current model id is not in the map, the context segment is not shown (no guessing)
249
333
  - Each component can be individually toggled and styled via `glm-quota-line configure`
250
334
  - Missing auth returns `GLM | auth expired`; API failures return `GLM | quota unavailable`
251
335
  - `install` does not replace an unmanaged status line unless `--force` is used
package/README.md CHANGED
@@ -46,7 +46,7 @@ glm-quota-line install
46
46
  安装完成。Claude Code 底部状态栏会自动显示配额:
47
47
 
48
48
  ```
49
- GLM Lite █████████░ 91% | W ▒▒▒▒░░░░░ 47% | 14:47 | ctx ███░░░ 45% (glm-4.7/200K)
49
+ GLM Lite █████████░ 91% | W ▒▒▒▒░░░░░ 47% 11:10 | 14:47 | ctx ███░░░ 45% (glm-4.7/200K)
50
50
  ```
51
51
 
52
52
  也可以直接在终端运行 `glm-quota-line` 快速查看用量,无需启动 Claude Code。
@@ -66,9 +66,9 @@ glm-quota-line check-update
66
66
 
67
67
  | 值 | 说明 | 示例 |
68
68
  |---|---|---|
69
- | `bar`(默认) | 进度条可视化 | `GLM Lite █████████░ 91% \| W ▒▒▒▒░░░░░ 47% \| 14:47 \| ctx ███░░░ 45%` |
70
- | `text` | 完整文本 | `GLM Lite \| 5h 91% \| week 47% \| reset 14:47 \| ctx 45%` |
71
- | `compact` | 紧凑模式 | `GLM 5h 91% W 47% \| 14:47` |
69
+ | `bar`(默认) | 进度条可视化 | `GLM Lite █████████░ 91% \| W ▒▒▒▒░░░░░ 47% 11:10 \| 14:47 \| ctx ███░░░ 45%` |
70
+ | `text` | 完整文本 | `GLM Lite \| 5h 91% \| week 47% 11:10 \| reset 14:47 \| ctx 45%` |
71
+ | `compact` | 紧凑模式 | `GLM 5h 91% W 47% 11:10 \| 14:47` |
72
72
 
73
73
  ```bash
74
74
  glm-quota-line config set style compact
@@ -125,8 +125,8 @@ glm-quota-line config set minimalist true
125
125
  ```
126
126
 
127
127
  效果对比:
128
- - 关闭:`GLM Lite █████████░ 91% | W ▒▒▒▒░░░░░ 47% | 14:47`
129
- - 开启:`█████████░ 91% | ▒▒▒▒░░░░░ 47% | 14:47`
128
+ - 关闭:`GLM Lite █████████░ 91% | W ▒▒▒▒░░░░░ 47% 11:10 | 14:47`
129
+ - 开启:`█████████░ 91% | ▒▒▒▒░░░░░ 47% 11:10 | 14:47`
130
130
 
131
131
  ### raw-values — 原始数值
132
132
 
@@ -136,6 +136,21 @@ glm-quota-line config set minimalist true
136
136
  glm-quota-line config set raw-values true
137
137
  ```
138
138
 
139
+ ### reset-format — 重置时间格式
140
+
141
+ 控制状态栏中重置时间的显示格式。
142
+
143
+ | 值 | 说明 | 示例 |
144
+ |---|---|---|
145
+ | `time`(默认) | 显示重置时间点 | `reset 14:47` |
146
+ | `countdown` | 显示剩余倒计时 | `reset 52m` / `reset 2d 5h` |
147
+
148
+ ```bash
149
+ glm-quota-line config set reset-format countdown
150
+ ```
151
+
152
+ 周配额也会同步显示重置信息(时间点或倒计时)。
153
+
139
154
  ### --json — JSON 输出
140
155
 
141
156
  输出结构化 JSON 格式(仅终端模式,状态栏模式忽略):
@@ -169,6 +184,21 @@ glm-quota-line --json
169
184
  }
170
185
  ```
171
186
 
187
+ ### reset — 恢复出厂配置
188
+
189
+ 一键重置用户配置,保留安装状态(不卸载状态栏/hook)。
190
+
191
+ ```bash
192
+ glm-quota-line config reset # 交互确认后重置全部用户配置
193
+ glm-quota-line config reset --models # 只清空自定义模型映射(modelMap)
194
+ glm-quota-line config reset --yes # 跳过确认(脚本/CI 用)
195
+ ```
196
+
197
+ - 默认重置范围:所有全局配置项(theme/display/style/work-days/minimalist/raw-values/reset-format/auth-token/base-url)、组件布局(lines)、自定义模型映射(modelMap)。
198
+ - `--models` 限定只清 modelMap,其它配置不动。
199
+ - 非交互环境(无 TTY)必须加 `--yes`,否则报错退出,避免误删。
200
+ - 重置后状态栏仍正常工作——模型映射会回退到包内默认表(`data/models.json`)。
201
+
172
202
  ### auth-token / base-url — 自定义鉴权
173
203
 
174
204
  当 Claude Code 运行在代理或网关后面时,注入的 `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_BASE_URL` 可能不是实际值,可手动覆盖:
@@ -198,7 +228,7 @@ glm-quota-line configure
198
228
 
199
229
  操作方式:
200
230
  - `↑↓` 选择组件,`Enter` 进入编辑,`Tab` 切换样式,`Space` 开关显示
201
- - `g` 进入全局选项(主题、显示模式、极简模式、原始数值)
231
+ - `g` 进入全局选项(主题、显示模式、极简模式、原始数值、重置时间格式)
202
232
  - `s` 保存,`q` 退出
203
233
 
204
234
  组件列表:
@@ -211,6 +241,31 @@ glm-quota-line configure
211
241
  | `reset` | 重置时间 | — | ✓ |
212
242
  | `ctx` | 上下文窗口用量 | ✓ (bar/text) | ✓ |
213
243
 
244
+ ### model — 模型上下文窗口管理
245
+
246
+ 管理模型的上下文窗口大小映射。上下文窗口用量百分比基于此映射计算。
247
+
248
+ ```bash
249
+ glm-quota-line model list # 查看所有模型及其上下文窗口大小
250
+ glm-quota-line model get <model-id> # 查看指定模型的大小
251
+ glm-quota-line model set <model-id> <size> # 设置模型大小(如 300K 或 300000)
252
+ glm-quota-line model remove <model-id> # 移除自定义映射(内置模型恢复默认值)
253
+ ```
254
+
255
+ `list` 输出示例:
256
+
257
+ ```
258
+ glm-4.7 200K
259
+ glm-5.1 200K
260
+ glm-5.2 300K *
261
+ ```
262
+
263
+ `*` 标记表示用户自定义的映射。
264
+
265
+ 模型映射采用双层结构:包内 `data/models.json` 作为默认底层,`~/.claude/glm-quota-line.json` 里的 `modelMap` 作为用户覆盖层(运行时逐键覆盖)。**智谱发布新模型时,无需等待 npm 包更新——直接 `model set <新模型> <大小>` 写入本地覆盖层即可立刻生效。**
266
+
267
+ 想清空所有自定义模型映射、回到包内默认表:执行 `glm-quota-line config reset --models --yes`。
268
+
214
269
  ## 推荐搭配
215
270
 
216
271
  | 使用场景 | 配置 |
@@ -219,9 +274,11 @@ glm-quota-line configure
219
274
  | 浅色终端 | `style=bar`, `theme=light` |
220
275
  | 极简工作流 | `style=compact`, `theme=mono` |
221
276
  | 关注已用量 | `style=bar`, `display=used` |
277
+ | 倒计时重置 | `reset-format=countdown` |
222
278
  | 脚本调用 | `--json` |
223
279
  | 6 天工作制 | `work-days=6` |
224
280
  | 极简数值 | `minimalist=true` |
281
+ | 自定义模型 | `glm-quota-line model set glm-5.2 300K` |
225
282
  | 交互式配置 | `glm-quota-line configure` |
226
283
 
227
284
  ## 命令参考
@@ -234,12 +291,38 @@ glm-quota-line version
234
291
  glm-quota-line check-update
235
292
  glm-quota-line configure
236
293
  glm-quota-line config show
237
- glm-quota-line config set <style|display|theme|auth-token|base-url|work-days|minimalist|raw-values> <value>
294
+ glm-quota-line config set <style|display|theme|auth-token|base-url|work-days|minimalist|raw-values|reset-format> <value>
238
295
  glm-quota-line config unset <key>
296
+ glm-quota-line config reset [--models] [--yes]
297
+ glm-quota-line model list
298
+ glm-quota-line model get <model-id>
299
+ glm-quota-line model set <model-id> <size>
300
+ glm-quota-line model remove <model-id>
239
301
  ```
240
302
 
241
303
  运行 `glm-quota-line --help` 查看完整说明。
242
304
 
305
+ ## 给 Agent / 自动化
306
+
307
+ 如果你是 AI agent(Claude Code / Cursor / Codex)或脚本作者,以下接口保证稳定:
308
+
309
+ ```bash
310
+ # 一次调用拿到所有命令的 machine-readable schema(name / summary / sideEffect / args / examples)
311
+ glm-quota-line commands --json
312
+
313
+ # 查看单个命令或命令组的聚焦帮助
314
+ glm-quota-line model --help
315
+ glm-quota-line config set --help
316
+ ```
317
+
318
+ 约定:
319
+ - **退出码**:成功 `0`,失败 `1`。
320
+ - **副作用标注**:每个命令标为 `read`(只读,自动化安全)、`write`(改配置/模型映射)、`mutating`(改 Claude Code 集成)、`interactive`(需 TTY)。
321
+ - **非阻塞**:所有命令都不会卡住等待输入(仅 `config reset` 在非交互环境需 `--yes`,`configure` 在非 TTY 时打印提示而非启动 TUI)。
322
+ - **只读查询**:`glm-quota-line --json` 输出结构化配额数据(5h/week/MCP + 重置时间)。
323
+
324
+ 典型 agent 工作流:先 `commands --json` 了解能力 → 调用需要的命令 → 读取 stdout 解析结果。
325
+
243
326
  ## 说明
244
327
 
245
328
  - 展示 `TOKENS_LIMIT` 配额和 `MCP_LIMIT` / `TIME_LIMIT` 配额
@@ -247,6 +330,7 @@ glm-quota-line config unset <key>
247
330
  - 状态栏默认显示上下文窗口用量和模型信息,可通过 `glm-quota-line configure` 交互式关闭
248
331
  - 每个组件可单独控制开关和样式,通过 `glm-quota-line configure` 交互式调整
249
332
  - 上下文窗口使用率优先从原始 token 数计算,当模型映射不可用时回退到 API 提供的百分比
333
+ - 模型上下文窗口大小可通过 `glm-quota-line model` 命令自定义,支持查看、设置、移除和批量导入
250
334
  - 鉴权缺失返回 `GLM | auth expired`;接口异常返回 `GLM | quota unavailable`
251
335
  - 非 GLM 提供商(非智谱 AI 端点)会自动禁用配额查询
252
336
  - `install` 默认不会覆盖非本工具管理的状态栏,除非使用 `--force`
@@ -0,0 +1,10 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "source": "https://open.bigmodel.cn/dev/api#glm",
4
+ "models": {
5
+ "glm-4.5-air": 128000,
6
+ "glm-4.7": 200000,
7
+ "glm-5-turbo": 200000,
8
+ "glm-5.2": 1000000
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glm-quota-line",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Zhipu GLM Coding Plan quota monitor for Claude Code status line.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  },
30
30
  "files": [
31
31
  "src",
32
+ "data",
32
33
  "README.md",
33
34
  "README.en.md",
34
35
  "LICENSE",
@@ -1,5 +1,4 @@
1
1
  import { loadConfig } from "../shared/config.js";
2
- import { clearCtxCache } from "../core/quota/cache.js";
3
2
  import { resolveQuotaStatus } from "../core/quota/service.js";
4
3
  import { readStatusLineInput } from "./input.js";
5
4
  import { readToolConfig } from "./settings.js";
@@ -16,10 +15,6 @@ export async function refreshQuotaOnSessionStart(options = {}) {
16
15
  sessionId: hookInput?.session_id || ""
17
16
  };
18
17
 
19
- if (hookInput?.source === "compact" || hookInput?.source === "clear" || hookInput?.source === "startup") {
20
- await clearCtxCache(config.cacheFilePath).catch(() => {});
21
- }
22
-
23
18
  return resolveQuotaStatusFn(config, {
24
19
  now: options.now,
25
20
  fetchImpl: options.fetchImpl,
@@ -5,6 +5,7 @@ import {
5
5
  TOOL_CONFIG_MANAGED_BY,
6
6
  TOOL_CONFIG_SCHEMA_VERSION,
7
7
  isValidDisplayMode,
8
+ isValidResetFormat,
8
9
  isValidStatusStyle,
9
10
  isValidTheme,
10
11
  isValidWorkDays
@@ -69,6 +70,10 @@ function normalizeToolConfig(config) {
69
70
  normalized.rawValues = base.rawValues;
70
71
  }
71
72
 
73
+ if (isValidResetFormat(base.resetFormat)) {
74
+ normalized.resetFormat = base.resetFormat;
75
+ }
76
+
72
77
  const authToken = normalizeOptionalString(base.authToken);
73
78
  if (authToken) {
74
79
  normalized.authToken = authToken;
@@ -84,6 +89,19 @@ function normalizeToolConfig(config) {
84
89
  normalized.lines = base.lines;
85
90
  }
86
91
 
92
+ // Preserve modelMap (custom model context window sizes)
93
+ if (base.modelMap && typeof base.modelMap === "object") {
94
+ const validMap = {};
95
+ for (const [modelId, size] of Object.entries(base.modelMap)) {
96
+ if (typeof modelId === "string" && modelId && typeof size === "number" && size > 0 && Number.isFinite(size)) {
97
+ validMap[modelId] = size;
98
+ }
99
+ }
100
+ if (Object.keys(validMap).length > 0) {
101
+ normalized.modelMap = validMap;
102
+ }
103
+ }
104
+
87
105
  return normalized;
88
106
  }
89
107
 
@@ -132,3 +150,27 @@ export async function unsetToolConfigValue(key, configPath = getToolConfigPath()
132
150
  await writeToolConfig(current, configPath);
133
151
  return current;
134
152
  }
153
+
154
+ // Reset user config to defaults. Preserves install metadata (does not uninstall
155
+ // the status line), schemaVersion, and managedBy. With modelsOnly, only the
156
+ // user modelMap overlay is cleared (bundled seed still applies at runtime).
157
+ export async function resetToolConfig({ modelsOnly = false } = {}, configPath = getToolConfigPath()) {
158
+ const current = await readToolConfig(configPath);
159
+ const install =
160
+ current.install && typeof current.install === "object" ? current.install : {};
161
+
162
+ let reset;
163
+ if (modelsOnly) {
164
+ reset = { ...current };
165
+ delete reset.modelMap;
166
+ } else {
167
+ reset = {
168
+ schemaVersion: TOOL_CONFIG_SCHEMA_VERSION,
169
+ managedBy: TOOL_CONFIG_MANAGED_BY,
170
+ install
171
+ };
172
+ }
173
+
174
+ await writeToolConfig(reset, configPath);
175
+ return reset;
176
+ }
package/src/cli/args.js CHANGED
@@ -15,6 +15,8 @@ const FLAGS = [
15
15
  { names: ["--theme"], dest: "theme" },
16
16
  { names: ["--force"], dest: "force", boolean: true },
17
17
  { names: ["--json"], dest: "json", boolean: true },
18
+ { names: ["--yes"], dest: "yes", boolean: true },
19
+ { names: ["--models"], dest: "models", boolean: true },
18
20
  { names: ["--help", "-h"], dest: "help", boolean: true },
19
21
  { names: ["--version", "-v"], dest: "version", boolean: true }
20
22
  ];
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  isValidDisplayMode,
3
+ isValidResetFormat,
3
4
  isValidStatusStyle,
4
5
  isValidTheme,
5
6
  isValidWorkDays
@@ -15,6 +16,10 @@ import { installClaudeStatusLine, uninstallClaudeStatusLine } from "../claude/in
15
16
  import { refreshQuotaOnSessionStart } from "../claude/sessionStart.js";
16
17
  import { checkForUpdates } from "./update.js";
17
18
  import { getPackageVersion } from "../shared/packageInfo.js";
19
+ import { handleModelCommand } from "./modelCommand.js";
20
+ import { handleConfigReset } from "./configCommand.js";
21
+ import { renderCommandsTable } from "./help.js";
22
+ import { COMMAND_REGISTRY, GLOBAL_FLAGS, ENVIRONMENT, allCommands } from "./registry.js";
18
23
 
19
24
  function isNonEmptyString(value) {
20
25
  return typeof value === "string" && value.trim().length > 0;
@@ -78,9 +83,17 @@ const CONFIG_KEYS = {
78
83
  validate: (v) => v === "true" || v === "false",
79
84
  invalidMessage: "Invalid raw-values. Use: true or false.",
80
85
  transform: (v) => v === "true"
86
+ },
87
+ "reset-format": {
88
+ property: "resetFormat",
89
+ validate: isValidResetFormat,
90
+ invalidMessage: "Invalid reset-format. Use: time or countdown."
81
91
  }
82
92
  };
83
93
 
94
+ const SUPPORTED_CONFIG_KEYS_MESSAGE =
95
+ "Supported config keys: style, display, theme, auth-token, base-url, work-days, minimalist, raw-values\n";
96
+
84
97
  export async function handleCommand(args, output = process.stdout, dependencies = {}) {
85
98
  const getVersion = dependencies.getVersion || getPackageVersion;
86
99
  const runUpdateCheck = dependencies.runUpdateCheck || checkForUpdates;
@@ -91,6 +104,21 @@ export async function handleCommand(args, output = process.stdout, dependencies
91
104
  return true;
92
105
  }
93
106
 
107
+ if (command === "commands") {
108
+ if (args.json) {
109
+ const payload = {
110
+ version: await getVersion(),
111
+ commands: allCommands(),
112
+ globalFlags: GLOBAL_FLAGS,
113
+ environment: ENVIRONMENT
114
+ };
115
+ output.write(`${JSON.stringify(payload, null, 2)}\n`);
116
+ } else {
117
+ renderCommandsTable(output);
118
+ }
119
+ return true;
120
+ }
121
+
94
122
  if (command === "check-update") {
95
123
  const result = await runUpdateCheck();
96
124
  output.write(`glm-quota-line ${result.currentVersion}\n`);
@@ -163,7 +191,7 @@ export async function handleCommand(args, output = process.stdout, dependencies
163
191
  const configKey = CONFIG_KEYS[key];
164
192
  if (!configKey) {
165
193
  process.exitCode = 1;
166
- output.write("Supported config keys: style, display, theme, auth-token, base-url, work-days, minimalist, raw-values\n");
194
+ output.write(SUPPORTED_CONFIG_KEYS_MESSAGE);
167
195
  return true;
168
196
  }
169
197
 
@@ -187,7 +215,7 @@ export async function handleCommand(args, output = process.stdout, dependencies
187
215
  const configKey = CONFIG_KEYS[key];
188
216
  if (!configKey) {
189
217
  process.exitCode = 1;
190
- output.write("Supported config keys: style, display, theme, auth-token, base-url, work-days, minimalist, raw-values\n");
218
+ output.write(SUPPORTED_CONFIG_KEYS_MESSAGE);
191
219
  return true;
192
220
  }
193
221
 
@@ -196,12 +224,20 @@ export async function handleCommand(args, output = process.stdout, dependencies
196
224
  return true;
197
225
  }
198
226
 
227
+ if (command === "config" && subcommand === "reset") {
228
+ return handleConfigReset(args, output, dependencies.configPath);
229
+ }
230
+
199
231
  if (command === "config") {
200
232
  process.exitCode = 1;
201
- output.write("Supported config subcommands: show, set, unset\n");
233
+ output.write("Supported config subcommands: show, set, unset, reset\n");
202
234
  return true;
203
235
  }
204
236
 
237
+ if (command === "model") {
238
+ return handleModelCommand(subcommand, key, value, output, dependencies.configPath);
239
+ }
240
+
205
241
  if (command === "configure") {
206
242
  return false;
207
243
  }
@@ -0,0 +1,86 @@
1
+ import readline from "node:readline/promises";
2
+
3
+ import {
4
+ getToolConfigPath,
5
+ readToolConfig,
6
+ resetToolConfig
7
+ } from "../claude/settings.js";
8
+
9
+ // Keys considered "user config" for the reset summary (install/schema/managedBy are preserved).
10
+ const RESET_USER_KEYS = [
11
+ "style",
12
+ "displayMode",
13
+ "theme",
14
+ "workDays",
15
+ "minimalist",
16
+ "rawValues",
17
+ "resetFormat",
18
+ "authToken",
19
+ "baseUrl"
20
+ ];
21
+
22
+ export async function handleConfigReset(args, output, configPath) {
23
+ const modelsOnly = Boolean(args.models);
24
+ const skipConfirm = Boolean(args.yes);
25
+ const targetPath = configPath || getToolConfigPath();
26
+ const config = await readToolConfig(targetPath);
27
+
28
+ if (modelsOnly) {
29
+ const count = config.modelMap ? Object.keys(config.modelMap).length : 0;
30
+ if (count === 0) {
31
+ output.write("No custom model mappings to reset.\n");
32
+ return true;
33
+ }
34
+ if (!skipConfirm && !(await confirmReset(`Reset ${count} custom model mapping(s)? [y/N] `, output))) {
35
+ output.write("Aborted.\n");
36
+ return true;
37
+ }
38
+ await resetToolConfig({ modelsOnly: true }, targetPath);
39
+ output.write(`Reset ${count} custom model mapping(s).\nconfig: ${targetPath}\n`);
40
+ return true;
41
+ }
42
+
43
+ const setKeys = RESET_USER_KEYS.filter((k) => config[k] !== undefined);
44
+ const modelCount = config.modelMap ? Object.keys(config.modelMap).length : 0;
45
+ const hasLines = Array.isArray(config.lines) && config.lines.length > 0;
46
+
47
+ if (setKeys.length === 0 && modelCount === 0 && !hasLines) {
48
+ output.write("Nothing to reset — config is already at defaults.\n");
49
+ return true;
50
+ }
51
+
52
+ const parts = [];
53
+ if (setKeys.length > 0) {
54
+ parts.push(`${setKeys.length} config key(s) (${setKeys.join(", ")})`);
55
+ }
56
+ if (modelCount > 0) {
57
+ parts.push(`${modelCount} custom model mapping(s)`);
58
+ }
59
+ if (hasLines) {
60
+ parts.push("component layout (lines)");
61
+ }
62
+
63
+ if (!skipConfirm && !(await confirmReset(`This will remove: ${parts.join(", ")}. Continue? [y/N] `, output))) {
64
+ output.write("Aborted.\n");
65
+ return true;
66
+ }
67
+
68
+ await resetToolConfig({ modelsOnly: false }, targetPath);
69
+ output.write(`Reset ${parts.join(", ")} to defaults.\nconfig: ${targetPath}\n`);
70
+ return true;
71
+ }
72
+
73
+ async function confirmReset(prompt, output) {
74
+ if (!process.stdin.isTTY) {
75
+ process.exitCode = 1;
76
+ output.write("config reset is destructive; pass --yes to skip confirmation in non-interactive sessions.\n");
77
+ return false;
78
+ }
79
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
80
+ try {
81
+ const answer = (await rl.question(prompt)).trim().toLowerCase();
82
+ return answer === "y" || answer === "yes";
83
+ } finally {
84
+ rl.close();
85
+ }
86
+ }