ccjk 15.6.0 → 15.7.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # ccjk
2
2
 
3
- > Clavue / Claude Code 配置 CLI。一条命令搞定 init、API、MCP、doctor、git 模板。
3
+ > Clavue / Claude Code / Codex 的本地配置 CLI。一条命令搞定 API、Profile、权限、MCP、状态栏、版本管理。
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/ccjk.svg)](https://www.npmjs.com/package/ccjk)
6
6
  [![license](https://img.shields.io/npm/l/ccjk.svg)](./LICENSE)
@@ -12,47 +12,90 @@
12
12
  npm install -g ccjk
13
13
  ```
14
14
 
15
- ## 快速上手
15
+ 升级:`npm install -g ccjk@latest`
16
16
 
17
- ```bash
18
- ccjk # 交互菜单
19
- ccjk init # 配置 API(同时存为 profile)
20
- ccjk use # 一键切换已配过的 API
21
- ccjk perms standard # 一键设权限档位(同时作用于 3 个工具)
22
- ccjk doctor --fix # 体检并自动修复配置问题
23
- ccjk mcp # MCP 服务(预设勾选)
24
- ccjk mcp-ls # 列已装的 MCP
25
- ccjk rollback # 从备份还原 settings.json
26
- ```
17
+ ## ccjk 能干什么
18
+
19
+ | 场景 | 命令 |
20
+ |---|---|
21
+ | 第一次配 API key | `ccjk init` |
22
+ | 多个 API key 之间切换(GLM/Kimi/Anthropic/...) | `ccjk use` |
23
+ | 不想每次都点确认权限 | `ccjk perms standard` |
24
+ | 看不到当前模型/用量 | `ccjk statusline-install` |
25
+ | settings.json 出问题 | `ccjk doctor --fix` |
26
+ | 装 MCP 服务(context7、serena、playwright...) | `ccjk mcp` |
27
+ | 看哪个工具该升级了 | `ccjk tools --check-updates` |
28
+ | 写入出错想还原 | `ccjk rollback` |
29
+ | 跨机器迁移配置 | `ccjk profile export` / `import` |
30
+ | 不想记命令 | `ccjk`(交互菜单) |
27
31
 
28
32
  ## 命令一览
29
33
 
34
+ ### 配置 API(init / use / profile)
35
+
30
36
  | 命令 | 用途 |
31
37
  |---|---|
32
- | `ccjk` | 交互菜单(默认) |
33
- | `ccjk init` | 配置 API:写 `~/.claude/settings.json` 的 env,并保存为 profile |
34
- | `ccjk use [name]` | **快速切换 profile**(不带参=交互选择) |
35
- | `ccjk profile ls/show/rm` | profile 列表 / 详情 / 删除 |
36
- | `ccjk profile export` | **导出 profile JSON 包**(迁移到其它机器) |
37
- | `ccjk profile import <file>` | **从 JSON 包导入 profile** |
38
- | `ccjk perms [tier]` | **一键设权限档位**(safe/standard/yolo),同时作用于 clavue/claude-code/codex |
38
+ | `ccjk init` | API:写 `~/.claude/settings.json` 的 env,并自动保存为 profile |
39
+ | `ccjk use [name]` | 一键切换 profile(不带参=交互选) |
40
+ | `ccjk profile ls` / `show` / `rm` | profile 列表 / 详情 / 删除 |
41
+ | `ccjk profile export` | 导出 profile JSON 包(迁移 / 团队共享) |
42
+ | `ccjk profile import <file>` | JSON 包导入 profile |
43
+
44
+ ### 权限档位(perms
45
+
46
+ | 命令 | 用途 |
47
+ |---|---|
48
+ | `ccjk perms [tier]` | 一键设权限档位(`safe` / `standard` / `yolo`),同步 3 个工具 |
39
49
  | `ccjk perms-show` | 查看三个工具当前的权限状态 |
40
- | `ccjk statusline-install` | **安装状态栏**:模型 / 目录 / context 用量 / 今日调用 / 速率 |
41
- | `ccjk statusline-uninstall` | 卸载状态栏 |
50
+
51
+ ### MCP 服务
52
+
53
+ | 命令 | 用途 |
54
+ |---|---|
42
55
  | `ccjk mcp` | 选装预设 MCP 服务(交互勾选) |
43
56
  | `ccjk mcp-ls` | 列出已安装的 MCP |
44
- | `ccjk mcp-add [name]` | 添加自定义 MCP 服务 |
57
+ | `ccjk mcp-add <name>` | 添加自定义 MCP 服务 |
45
58
  | `ccjk mcp-rm [name]` | 卸载 MCP 服务 |
46
- | `ccjk doctor` | 检查 settings.json 中的常见配置问题 |
47
- | `ccjk doctor --fix` | **自动修复**能修的问题(修改前备份) |
48
- | `ccjk rollback` | **从备份还原** settings.json / config.toml |
49
- | `ccjk tools` | **查看 Clavue/Claude Code/Codex 版本**(加 `--check-updates` 查最新) |
50
- | `ccjk install [tool]` | **安装代码工具**(不带参=交互选;`--all` 装全部缺失的) |
51
- | `ccjk update [tool]` | **更新代码工具到最新版**(不带参=交互选 outdated;`--all` 全部) |
59
+
60
+ ### 状态栏(statusline)
61
+
62
+ | 命令 | 用途 |
63
+ |---|---|
64
+ | `ccjk statusline-install` | 安装状态栏,显示模型 / 目录 / context 用量 / 今日调用 / 速率 |
65
+ | `ccjk statusline-uninstall` | 卸载状态栏 |
66
+
67
+ ### 体检 / 还原
68
+
69
+ | 命令 | 用途 |
70
+ |---|---|
71
+ | `ccjk doctor` | 检查 settings.json 的常见配置问题 |
72
+ | `ccjk doctor --fix` | 自动修可修的问题(修改前备份) |
73
+ | `ccjk rollback` | 从备份还原 settings.json / config.toml |
74
+
75
+ ### 工具版本管理
76
+
77
+ | 命令 | 用途 |
78
+ |---|---|
79
+ | `ccjk tools` | 查看 Clavue / Claude Code / Codex 本地版本 |
80
+ | `ccjk tools --check-updates` | 加查 npm latest,标记 outdated |
81
+ | `ccjk install [tool]` | 安装代码工具(`--all` 装全部缺失的) |
82
+ | `ccjk update [tool]` | 升级代码工具到最新版(`--all` 全部 outdated) |
83
+
84
+ ### 其他
85
+
86
+ | 命令 | 用途 |
87
+ |---|---|
88
+ | `ccjk` | 交互菜单(默认) |
52
89
  | `ccjk detect` | 列出已安装的代码工具 |
53
90
  | `ccjk git-install` | 安装 `/ccjk:git-commit` 等 slash 命令模板 |
54
91
 
55
- ### Profile:多 API 一键切换
92
+ ---
93
+
94
+ ## 详解
95
+
96
+ ### Profile:多 API 切换
97
+
98
+ `ccjk init` 配完 API 默认会问"保存为 profile?"。之后 `ccjk use` 可以在多个 profile 之间一键切换:
56
99
 
57
100
  ```bash
58
101
  ccjk init -t clavue -p glm --api-key sk-xxx --profile work -y
@@ -70,12 +113,12 @@ Profile 存储在 `~/.ccjk/profiles/<name>.json`,当前激活的记录在 `~/.
70
113
  #### 导出 / 导入:跨机器迁移
71
114
 
72
115
  ```bash
73
- ccjk profile export # 交互勾选要导出的 profile
74
- ccjk profile export -n work free -o team.json -y # 直接导出 work + free
75
- ccjk profile export --redact -o template.json -y # 抹去 API key(导出"模板")
116
+ ccjk profile export # 交互勾选
117
+ ccjk profile export -n work free -o team.json -y # 直接导出 work + free
118
+ ccjk profile export --redact -o template.json -y # 抹去 API key"模板")
76
119
 
77
120
  # 在另一台机器
78
- ccjk profile import team.json # 同名时交互问跳过/覆盖/重命名
121
+ ccjk profile import team.json # 同名时交互问跳过/覆盖/重命名
79
122
  ccjk profile import team.json --conflict skip -y # 全部 skip 已有的
80
123
  ```
81
124
 
@@ -85,37 +128,50 @@ ccjk profile import team.json --conflict skip -y # 全部 skip 已有的
85
128
 
86
129
  一条命令把 Clavue / Claude Code / Codex 的权限同步到同一档位,减少每次操作都要点确认的烦躁。
87
130
 
88
- | 档位 | 适合 | Claude/Clavue | Codex |
131
+ | 档位 | 适合 | Claude / Clavue | Codex |
89
132
  |---|---|---|---|
90
133
  | `safe` | 浏览代码、新手 | 仅放行只读(Read/Grep/...) | `approval_policy=untrusted`, `sandbox_mode=read-only` |
91
134
  | `standard`(推荐) | 日常开发 | + git/npm/pnpm/python/ls/cat 等高频命令 | `approval_policy=on-failure`, `sandbox_mode=workspace-write` |
92
135
  | `yolo` | 可信项目放飞 | `Bash(*)` + `allowUnsandboxedCommands=true` | `approval_policy=never`, `sandbox_mode=workspace-write` |
93
136
 
94
- 不论哪一档,都强制写入 `deny`:`rm -rf /`、`git push --force`、`npm publish`、`sudo` 等不可逆 / 高危命令,避免手抖。
137
+ 不论哪一档,都强制写入 `deny`:`rm -rf /`、`git push --force`、`npm publish`、`sudo` 等不可逆 / 高危命令。
95
138
 
96
139
  ```bash
97
- ccjk perms # 交互选档位(推荐)
98
- ccjk perms standard # 直接应用 standard 到全部 3 个工具
99
- ccjk perms safe --tools clavue,claude-code # 只作用于这两个
100
- ccjk perms yolo --reset # --reset 会清空原 allow 后再写(默认是 append + dedupe)
101
- ccjk perms-show # 看三个工具当前各是哪档
140
+ ccjk perms # 交互选档位(推荐)
141
+ ccjk perms standard # 直接应用 standard 到全部 3 个工具
142
+ ccjk perms safe --tools clavue,claude-code # 只作用于这两个
143
+ ccjk perms yolo --reset # --reset 会清空原 allow 后再写
144
+ ccjk perms-show # 看三个工具当前各是哪档
102
145
  ```
103
146
 
104
147
  合并策略:
105
148
  - `allow`:默认 append + dedupe,保护用户自定义白名单。`--reset` 强制覆盖。
106
149
  - `deny`:始终覆盖,确保危险命令一定被拦。
107
150
 
108
- ### 非交互模式
151
+ ### Statusline:底部状态栏
152
+
153
+ 显示模型、当前目录、context 用量、今日 API 调用次数、tokens 速率。
109
154
 
110
155
  ```bash
111
- ccjk init -t clavue -p glm --api-key sk-xxx --profile work -y
112
- ccjk perms standard -y
113
- ccjk mcp -s context7 serena -y
114
- ccjk mcp-add my-server --command npx --args "-y @scope/pkg" -y
115
- ccjk doctor --fix -y
116
- ccjk git-install --scope user -y
156
+ ccjk statusline-install # 写入 settings.statusLine(重启 Claude Code 生效)
157
+ ccjk statusline-uninstall # 卸载
158
+ ```
159
+
160
+ 效果(一行):
161
+
162
+ ```
163
+ Sonnet 4.5 1M │ 📁 ccjk │ ⚡ 4.5% 45.0k │ 12 calls · 1.5k tok/m
117
164
  ```
118
165
 
166
+ 字段含义:
167
+ - `Sonnet 4.5 1M` — 模型名 + context window 大小(1M / 200k)
168
+ - `📁 ccjk` — 当前工作目录的 basename(home 显示为 `~`)
169
+ - `⚡ 4.5% 45.0k` — context 已用百分比 + 当前 token 数
170
+ - `12 calls` — 今日总 API 调用数(聚合所有 transcripts)
171
+ - `1.5k tok/m` 或 `80 tok/s` — 今日产出速率(output tokens / 活跃秒数)
172
+
173
+ 实现:扫 `~/.claude/projects/*/*.jsonl` 当天 mtime 文件,读 `message.usage` 聚合。错误一律 swallow,不会让 Claude Code UI 报红。
174
+
119
175
  ### Doctor:体检 + 自动修复
120
176
 
121
177
  ```bash
@@ -124,12 +180,17 @@ ccjk doctor --fix # 自动修可修的(修改前备份)
124
180
  ccjk doctor --fix -y # 跳过确认
125
181
  ```
126
182
 
127
- 可自动修复:`model-overrides-env`(删顶层 model)、`duplicate-auth`(保留 AUTH_TOKEN,删 API_KEY)。
128
- 不可自动修:`missing-credentials`、`invalid-base-url`(需要正确的 URL/Key,跑 `ccjk init`)。
183
+ | 规则 | 严重度 | 自动修 | 说明 |
184
+ |---|---|---|---|
185
+ | `model-overrides-env` | error | ✓ | 顶层 `settings.model` 会覆盖 `env.ANTHROPIC_MODEL` |
186
+ | `duplicate-auth` | warn | ✓ | 同时存在 `API_KEY` 和 `AUTH_TOKEN`(保留 AUTH_TOKEN,删 API_KEY) |
187
+ | `missing-credentials` | error | ✗ | 设了 `BASE_URL` 但缺凭证 → 跑 `ccjk init` |
188
+ | `invalid-base-url` | error | ✗ | URL 格式不合法 → 跑 `ccjk init` |
189
+ | `hook-bloat` | warn | ✗ | 单个 hook 注册超过 5 个处理器(人工审查) |
129
190
 
130
191
  ### Rollback:从备份还原
131
192
 
132
- 每次 `init` / `mcp` / `perms` / `doctor --fix` 写入前都会自动备份到 `xxx.bak-<ISO时间戳>`。
193
+ 每次 `init` / `mcp` / `perms` / `doctor --fix` / `mcp-add/rm` / `statusline-install` 写入前都会自动备份到 `<file>.bak-<ISO时间戳>`。
133
194
 
134
195
  ```bash
135
196
  ccjk rollback # 列所有备份,按时间倒序
@@ -138,101 +199,88 @@ ccjk rollback -t clavue # 只看一个工具的备份
138
199
 
139
200
  还原前会再备份一份当前状态,所以**还原本身也可还原**。
140
201
 
141
- ### Statusline:底部状态栏
202
+ ### Tools / Install / Update:版本管理
142
203
 
143
- 显示模型、当前目录、context 用量、今日 API 调用次数、tokens 速率。
204
+ 三个开发工具的本地版本、npm 最新版、安装、升级——都在 ccjk 里。
144
205
 
145
206
  ```bash
146
- ccjk statusline-install # 写入 settings.statusLine(重启 Claude Code 生效)
147
- ccjk statusline-uninstall # 卸载
148
- ```
149
-
150
- 效果(一行):
151
-
152
- ```
153
- Sonnet 4.5 1M │ 📁 ccjk │ ⚡ 4.5% 45.0k │ 12 calls · 1.5k tok/m
154
- ```
207
+ ccjk tools # 看本地版本
208
+ ccjk tools --check-updates # 加查 npm latest
155
209
 
156
- 字段含义:
157
- - `Sonnet 4.5 1M` — 模型名 + context window 大小(1M / 200k)
158
- - `📁 ccjk` — 当前工作目录的 basename(home 显示为 `~`)
159
- - `⚡ 4.5% 45.0k` — context 已用百分比 + 当前 token 数
160
- - `12 calls` — 今日总 API 调用数(聚合所有 transcripts)
161
- - `1.5k tok/m` 或 `80 tok/s` — 今日产出速率(output tokens / 跨度秒数)
162
-
163
- 实现细节:扫 `~/.claude/projects/*/*.jsonl` 当天 mtime 文件,读 `message.usage` 字段聚合。错误一律 swallow,不会让 Claude Code UI 报红。
164
-
165
- ### Tools:工具版本管理
166
-
167
- 三个开发工具(Clavue / Claude Code / Codex)的本地版本、npm 最新版、安装、升级——一条命令搞定。
168
-
169
- ```bash
170
- ccjk tools # 看本地三个工具的版本
171
- ccjk tools --check-updates # 额外查 npm latest,标记 outdated
172
-
173
- ccjk install # 交互选择要安装的工具
174
- ccjk install codex # 安装 Codex
210
+ ccjk install # 交互选要装的工具
211
+ ccjk install codex # 直接装 Codex
175
212
  ccjk install --all # 装全部缺失的
176
213
 
177
- ccjk update # 交互选择 outdated 的工具更新
178
- ccjk update claude-code # 更新 Claude Code
179
- ccjk update --all # 更新所有 outdated
214
+ ccjk update # 交互选 outdated 的工具
215
+ ccjk update claude-code # 直接升级 Claude Code
216
+ ccjk update --all # 升级所有 outdated
217
+ ccjk update --dry-run # 只显示命令不执行
180
218
  ```
181
219
 
182
220
  输出示例:
183
221
 
184
222
  ```
185
- Clavue 8.9.2 (latest)
223
+ Clavue 8.9.2 (latest)
186
224
  Claude Code 2.1.138 (latest)
187
225
  Codex 0.128.0 → 0.130.0 可升级
188
226
  ```
189
227
 
190
- 实现就是 `npm install -g <pkg>` / `npm install -g <pkg>@<latest>`,所有命令执行前都会展示给用户确认。如果 npm 因权限失败,会把建议的 `sudo <cmd>` 打印出来让用户自己跑。加 `--dry-run` 只看命令不执行。
228
+ 实现是 `npm install -g <pkg>` / `npm install -g <pkg>@<latest>`,命令完整列出后等用户确认。npm 因权限失败时会输出建议的 `sudo` 命令让用户自己跑,不假装成功。
191
229
 
192
- ## 支持
230
+ ### 非交互模式
193
231
 
194
- | 工具 | 配置目标 | 状态 |
195
- |---|---|---|
196
- | Clavue | `~/.claude/settings.json` | 主推 |
197
- | Claude Code | `~/.claude/settings.json` | 完整支持 |
198
- | Codex | `~/.codex/config.toml` | 仅检测 |
232
+ 适合脚本 / CI / 装机:
199
233
 
200
- ### 内置 Provider
234
+ ```bash
235
+ ccjk init -t clavue -p glm --api-key sk-xxx --profile work -y
236
+ ccjk perms standard -y
237
+ ccjk mcp -s context7 serena -y
238
+ ccjk mcp-add my-server --command npx --args "-y @scope/pkg" -y
239
+ ccjk doctor --fix -y
240
+ ccjk statusline-install -y
241
+ ccjk update --all -y
242
+ ccjk git-install --scope user -y
243
+ ```
201
244
 
202
- `glm` / `kimi` / `minimax` / `anthropic` / `custom`
245
+ ---
203
246
 
204
- ## doctor 规则
247
+ ## 支持的工具
205
248
 
206
- | 规则 | 严重度 | 说明 |
249
+ | 工具 | 配置目标 | 范围 |
207
250
  |---|---|---|
208
- | `model-overrides-env` | error | 顶层 `settings.model` 会覆盖 `env.ANTHROPIC_MODEL` |
209
- | `duplicate-auth` | warn | API_KEY AUTH_TOKEN 同时存在 |
210
- | `missing-credentials` | error | 设了 BASE_URL 但缺凭证 |
211
- | `invalid-base-url` | error | URL 格式不合法 |
212
- | `hook-bloat` | warn | 单个 hook 注册超过 5 个处理器 |
251
+ | Clavue | `~/.claude/settings.json` | API / Profile / Perms / MCP / Statusline / Doctor / Rollback |
252
+ | Claude Code | `~/.claude/settings.json` | API / Profile / Perms / MCP / Statusline / Doctor / Rollback |
253
+ | Codex | `~/.codex/config.toml` | Perms / Detect / Install / Update(API 配置请直接编辑 config.toml) |
254
+
255
+ ### 内置 API Provider
256
+
257
+ `glm` / `kimi` / `minimax` / `anthropic` / `custom`
213
258
 
214
259
  ## 设计原则
215
260
 
216
- - 配置工具就是配置工具。不做 brain、orchestrator、sandbox、dashboard 这类东西。
217
- - 不写 `~/.claude/CLAUDE.md`,不装 hooks,不开后台进程。
218
- - 用户不调用,ccjk 就什么都不做。
261
+ - **配置工具就是配置工具**。不做 brain、orchestrator、sandbox、dashboard 这类东西。
262
+ - **不主动写代码**。不写 `~/.claude/CLAUDE.md`,不装 hooks,不开后台进程。
263
+ - **可还原**。所有写入前都备份;`ccjk rollback` 能找回任何旧版本。
264
+ - **可重复**。所有交互式命令都有非交互参数(`-y`、`--profile`、`--tools`、`--services`...),适合脚本。
265
+ - **不偷跑命令**。`install` / `update` 会显示完整命令并等用户确认。
219
266
 
220
267
  ## 从 v14 升级
221
268
 
222
- v15 是从零重写的版本,命令集和行为都和 v14.x 不兼容:
269
+ v15 是从零重写的精简版本,命令集和行为都和 v14.x 不兼容:
223
270
 
224
- - v14 的子命令(brain/sandbox/teleport/cloud-sync 等)在 v15 中**不存在**。
225
- - v14 在 `~/.claude/CLAUDE.md` 中注入的 "Smart Assistant Mode" 在 v15 中**不会再写入**。如需手动清理旧版残留,删除该文件中相关段落即可。
226
- - 如果你只用 v14 的 init/mcp/doctor/git 几个核心功能,直接 `npm install -g ccjk@latest` 升级即可。
271
+ - v14 的子命令(brain/sandbox/teleport/cloud-sync 等)在 v15 **不存在**。
272
+ - v14 在 `~/.claude/CLAUDE.md` 注入的 "Smart Assistant Mode" 在 v15 **不会再写入**。如需手动清理旧版残留,删除该文件中相关段落即可。
273
+ - 如果你只用 v14 的 init/mcp/doctor/git 等核心功能,直接 `npm install -g ccjk@latest` 升级即可。
227
274
  - 需要 v14 的扩展能力,请固定旧版本:`npm install -g ccjk@14`。
228
275
 
229
276
  ## 开发
230
277
 
231
278
  ```bash
232
279
  pnpm install
233
- pnpm typecheck
234
- pnpm test
235
- pnpm build
280
+ pnpm typecheck # TypeScript 检查
281
+ pnpm test # 跑全部测试(>100 测试)
282
+ pnpm lint # ESLint
283
+ pnpm build # tsc 出 dist/
236
284
  ```
237
285
 
238
286
  ## 许可
@@ -1,3 +1,6 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
1
4
  import inquirer from 'inquirer';
2
5
  import ansis from 'ansis';
3
6
  import { detectCommand } from './detect.js';
@@ -10,43 +13,99 @@ import { permsCommand } from './perms.js';
10
13
  import { rollbackCommand } from './rollback.js';
11
14
  import { statusLineInstallCommand } from './statusline.js';
12
15
  import { installCommand, updateCommand, versionCommand } from './version.js';
13
- import { listProfiles, readState } from '../core/profiles.js';
14
- const ITEMS = [
15
- { key: '1', label: '配置 API(init)', run: () => initCommand() },
16
- { key: '2', label: '切换 Profile(快速切换 API', run: () => profileUseCommand(undefined) },
17
- { key: '3', label: '一键设权限档位(safe/standard/yolo)', run: () => permsCommand(undefined) },
18
- { key: '4', label: '安装状态栏(显示模型/用量/速率)', run: () => statusLineInstallCommand() },
19
- { key: '5', label: '配置 MCP 服务', run: () => mcpCommand() },
20
- { key: '6', label: '体检(doctor)', run: () => doctorCommand() },
21
- { key: '7', label: '从备份还原(rollback)', run: () => rollbackCommand() },
22
- { key: '8', label: '查看工具版本 / 检查更新', run: () => versionCommand({ checkUpdates: true }) },
23
- { key: '9', label: '安装代码工具(Clavue/Claude Code/Codex)', run: () => installCommand(undefined) },
24
- { key: '0', label: '更新代码工具到最新版', run: () => updateCommand(undefined) },
25
- { key: 'g', label: '安装 Git 命令模板', run: () => gitInstallCommand() },
26
- { key: 'd', label: '检测已安装的工具', run: async () => detectCommand() },
16
+ import { collectStatus, renderBanner, renderStatusBar } from '../core/banner.js';
17
+ const GROUPS = [
18
+ {
19
+ title: '配置 API',
20
+ items: [
21
+ { label: '配置 API(init)', hint: '写 settings.json,存为 profile', run: () => initCommand() },
22
+ { label: '切换 Profile', hint: '在已配过的 API 之间切换', run: () => profileUseCommand(undefined) },
23
+ { label: '权限档位', hint: 'safe / standard / yolo(同步 3 工具)', run: () => permsCommand(undefined) },
24
+ ],
25
+ },
26
+ {
27
+ title: '增强体验',
28
+ items: [
29
+ { label: '安装状态栏', hint: '显示模型 / 用量 / 速率', run: () => statusLineInstallCommand() },
30
+ { label: '配置 MCP 服务', hint: 'context7 / serena / playwright ...', run: () => mcpCommand() },
31
+ { label: '安装 Git 命令模板', hint: '/ccjk:git-commit 等 slash 命令', run: () => gitInstallCommand() },
32
+ ],
33
+ },
34
+ {
35
+ title: '维护与诊断',
36
+ items: [
37
+ { label: '体检(doctor)', hint: '检查 settings.json 配置问题', run: () => doctorCommand() },
38
+ { label: '从备份还原', hint: '回滚 settings.json / config.toml', run: () => rollbackCommand() },
39
+ { label: '查看版本 / 检查更新', hint: '本地 + npm latest', run: () => versionCommand({ checkUpdates: true }) },
40
+ { label: '安装代码工具', hint: 'Clavue / Claude Code / Codex', run: () => installCommand(undefined) },
41
+ { label: '更新代码工具', hint: '升级到最新版', run: () => updateCommand(undefined) },
42
+ { label: '检测已安装的工具', hint: '看哪些已装哪些没装', run: async () => detectCommand() },
43
+ ],
44
+ },
27
45
  ];
28
- export async function menuCommand() {
29
- console.log(ansis.bold('\nccjk - Clavue/Claude Code 配置助手\n'));
30
- const profiles = await listProfiles();
31
- const state = await readState();
32
- if (profiles.length > 0) {
33
- const cur = state.current ?? ansis.gray('(未设置)');
34
- console.log(ansis.dim(` 当前 profile: ${cur} · 共 ${profiles.length} 个\n`));
46
+ /**
47
+ * 中文字符在 monospace 终端通常占 2 列。padEnd 按字符数算不对齐,
48
+ * 这里手动补空格让 hint 对齐到第 22 列。
49
+ */
50
+ function padToVisibleWidth(s, width) {
51
+ let w = 0;
52
+ for (const ch of s) {
53
+ const code = ch.codePointAt(0) ?? 0;
54
+ if (code >= 0x4e00 && code <= 0x9fff)
55
+ w += 2;
56
+ else if (code >= 0x3000 && code <= 0x303f)
57
+ w += 2;
58
+ else if (code >= 0xff00 && code <= 0xffef)
59
+ w += 2;
60
+ else
61
+ w += 1;
62
+ }
63
+ return s + ' '.repeat(Math.max(0, width - w));
64
+ }
65
+ function getVersion() {
66
+ try {
67
+ const pkgPath = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json');
68
+ const raw = readFileSync(pkgPath, 'utf-8');
69
+ return JSON.parse(raw).version;
35
70
  }
36
- for (const { key, label } of ITEMS) {
37
- console.log(` ${ansis.green(key)}. ${label}`);
71
+ catch {
72
+ return '?.?.?';
73
+ }
74
+ }
75
+ export async function menuCommand() {
76
+ console.log();
77
+ console.log(renderBanner(getVersion()));
78
+ console.log();
79
+ const status = await collectStatus();
80
+ const statusLines = renderStatusBar(status);
81
+ for (const l of statusLines)
82
+ console.log(l);
83
+ console.log();
84
+ const choices = [];
85
+ let idx = 0;
86
+ const flat = [];
87
+ for (const g of GROUPS) {
88
+ choices.push(new inquirer.Separator(ansis.dim(`── ${g.title} ───────────────────────────`)));
89
+ for (const item of g.items) {
90
+ const hint = item.hint ? ` ${ansis.dim(item.hint)}` : '';
91
+ const padded = padToVisibleWidth(item.label, 20);
92
+ choices.push({ name: `${padded}${hint}`, value: idx, short: item.label });
93
+ flat.push(item);
94
+ idx++;
95
+ }
38
96
  }
39
- console.log(` ${ansis.gray('q')}. 退出`);
97
+ choices.push(new inquirer.Separator(ansis.dim('──────────────────────────────────────────')));
98
+ choices.push({ name: ansis.gray('退出'), value: -1, short: '退出' });
40
99
  const { choice } = await inquirer.prompt([{
41
- type: 'input',
100
+ type: 'list',
42
101
  name: 'choice',
43
- message: '\n选择',
44
- validate: (v) => /^([0-9]|[gdq])$/.test(v.trim()) || '输入有效的选项',
102
+ message: ansis.bold('选择操作'),
103
+ choices,
104
+ pageSize: 20,
105
+ loop: false,
45
106
  }]);
46
- if (choice.trim() === 'q')
107
+ if (choice < 0)
47
108
  return;
48
- const item = ITEMS.find(i => i.key === choice.trim());
49
- if (item)
50
- await item.run();
109
+ await flat[choice].run();
51
110
  }
52
111
  //# sourceMappingURL=menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/commands/menu.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,KAAK,GAAG;IACZ,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE;IAC7D,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE;IACpF,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,6BAA6B,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE;IACtF,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,wBAAwB,EAAE,EAAE;IAC/E,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,EAAE;IACzD,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,EAAE;IAC7D,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,eAAe,EAAE,EAAE;IACpE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE;IACvF,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,kCAAkC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE;IAC7F,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE;IACtE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,EAAE;IAClE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,aAAa,EAAE,EAAE;CAClE,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;IAE9D,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,GAAG,UAAU,QAAQ,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAExC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAqB,CAAC;YAC5D,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,SAAS;SACvE,CAAC,CAAC,CAAC;IAEJ,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG;QAAE,OAAO;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACtD,IAAI,IAAI;QAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/commands/menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAajF,MAAM,MAAM,GAAgB;IAC1B;QACE,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE;YACL,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,4BAA4B,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE;YACvF,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE;YACxF,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,iCAAiC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE;SAC/F;KACF;IACD;QACE,KAAK,EAAE,MAAM;QACb,KAAK,EAAE;YACL,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,wBAAwB,EAAE,EAAE;YACjF,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,oCAAoC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,EAAE;YAC3F,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,6BAA6B,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,EAAE;SAC9F;KACF;IACD;QACE,KAAK,EAAE,OAAO;QACd,KAAK,EAAE;YACL,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,uBAAuB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,EAAE;YAClF,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gCAAgC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,eAAe,EAAE,EAAE;YACxF,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE;YACpG,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,8BAA8B,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE;YAC/F,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE;YACxE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,aAAa,EAAE,EAAE;SAC3E;KACF;CACF,CAAC;AAEF;;;GAGG;AACH,SAAS,iBAAiB,CAAC,CAAS,EAAE,KAAa;IACjD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM;YAAE,CAAC,IAAI,CAAC,CAAC;aACxC,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM;YAAE,CAAC,IAAI,CAAC,CAAC;aAC7C,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM;YAAE,CAAC,IAAI,CAAC,CAAC;;YAC7C,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC1F,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC,OAAO,CAAC;IAC1D,CAAC;IACD,MAAM,CAAC;QACL,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,EAAE,CAAC;IAId,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,8BAA8B,CAAC,CAAC,CAAC,CAAC;QAC7F,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YAC1E,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,GAAG,EAAE,CAAC;QACR,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC,CAAC,CAAC;IAC9F,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAqB,CAAC;YAC5D,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3B,OAAO;YACP,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC,CAAC;IAEJ,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO;IACvB,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,122 @@
1
+ import ansis from 'ansis';
2
+ import { homedir } from 'node:os';
3
+ import { existsSync } from 'node:fs';
4
+ import { TOOLS } from './tools.js';
5
+ import { getInstalledVersion } from './versions.js';
6
+ import { listProfiles, readState } from './profiles.js';
7
+ import { readSettings } from './settings.js';
8
+ import { detectClaudeTier } from './perms.js';
9
+ import { expandHome } from './paths.js';
10
+ /**
11
+ * 渲染启动横幅。简洁优先:
12
+ * - 不闪烁、不动画
13
+ * - ASCII art 用单字节字符,避免双宽字体导致对齐歪
14
+ * - 终端不支持颜色时降级(ansis 自动处理)
15
+ */
16
+ export function renderBanner(version) {
17
+ const lines = [];
18
+ const dim = ansis.dim;
19
+ const bold = ansis.bold;
20
+ // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
21
+ // ▄▄ ▄▄ ▄ ▄ ▄ ▄
22
+ // 走字母 art:每行严格 6 字符 × n,全部 ASCII:
23
+ //
24
+ // ██████╗ ██████╗ ██╗██╗ ██╗
25
+ // ██╔════╝ ██╔════╝ ██║██║ ██╔╝
26
+ // ██║ ██║ ██║█████╔╝
27
+ // ██║ ██║ ██ ██║██╔═██╗
28
+ // ╚██████╗ ╚██████╗ ╚█████╔╝██║ ██╗
29
+ // ╚═════╝ ╚═════╝ ╚════╝ ╚═╝ ╚═╝
30
+ //
31
+ // 这些字符(█ ╗ ╔ ║ ═ ╚)大多数 monospace 字体里都是单宽,对齐稳。
32
+ const art = [
33
+ ' ██████╗ ██████╗ ██╗██╗ ██╗',
34
+ ' ██╔════╝ ██╔════╝ ██║██║ ██╔╝',
35
+ ' ██║ ██║ ██║█████╔╝ ',
36
+ ' ██║ ██║ ██ ██║██╔═██╗ ',
37
+ ' ╚██████╗ ╚██████╗ ╚█████╔╝██║ ██╗',
38
+ ' ╚═════╝ ╚═════╝ ╚════╝ ╚═╝ ╚═╝',
39
+ ];
40
+ for (const a of art)
41
+ lines.push(bold.cyan(a));
42
+ lines.push('');
43
+ lines.push(` ${bold('Clavue 官方配置工具')} ${dim('· Claude Code / Codex 通用')}`);
44
+ lines.push(` ${dim(`v${version} · npm i -g ccjk · github.com/miounet11/ccjk`)}`);
45
+ return lines.join('\n');
46
+ }
47
+ export async function collectStatus() {
48
+ const profiles = await listProfiles().catch(() => []);
49
+ const state = await readState().catch(() => ({}));
50
+ // 读 Claude/Clavue settings 决定 perms 档位 + statusline 是否装了
51
+ let permsTier;
52
+ let statuslineInstalled = false;
53
+ try {
54
+ const path = expandHome(TOOLS.clavue.settingsFile);
55
+ if (existsSync(path)) {
56
+ const s = await readSettings(TOOLS.clavue.settingsFile);
57
+ const detected = detectClaudeTier(s);
58
+ if (detected)
59
+ permsTier = detected;
60
+ const sl = s.statusLine;
61
+ if (sl?.command)
62
+ statuslineInstalled = true;
63
+ }
64
+ }
65
+ catch { /* swallow */ }
66
+ const toolsInstalled = Object.keys(TOOLS).map((t) => {
67
+ const v = getInstalledVersion(t);
68
+ return {
69
+ tool: t,
70
+ ...(v.version ? { version: v.version } : {}),
71
+ installed: v.installed,
72
+ };
73
+ });
74
+ return {
75
+ ...(state.current ? { profileName: state.current } : {}),
76
+ profileCount: profiles.length,
77
+ ...(permsTier ? { permsTier } : {}),
78
+ statuslineInstalled,
79
+ toolsInstalled,
80
+ };
81
+ }
82
+ /** 渲染状态行(横幅下方一行) */
83
+ export function renderStatusBar(s) {
84
+ const out = [];
85
+ // 左边:profile + 档位 + 状态栏
86
+ const pieces = [];
87
+ if (s.profileName) {
88
+ pieces.push(`${ansis.dim('profile')} ${ansis.cyan(s.profileName)}`);
89
+ }
90
+ else {
91
+ pieces.push(ansis.dim('profile (未设置)'));
92
+ }
93
+ if (s.permsTier) {
94
+ const c = s.permsTier === 'safe' ? ansis.green : s.permsTier === 'standard' ? ansis.cyan : ansis.yellow;
95
+ pieces.push(`${ansis.dim('perms')} ${c(s.permsTier)}`);
96
+ }
97
+ pieces.push(`${ansis.dim('statusline')} ${s.statuslineInstalled ? ansis.green('●') : ansis.gray('○')}`);
98
+ out.push(` ${pieces.join(' · ')}`);
99
+ // 右边:工具版本一行
100
+ const toolPieces = s.toolsInstalled.map((t) => {
101
+ const meta = TOOLS[t.tool];
102
+ if (!t.installed)
103
+ return ansis.gray(`${meta.displayName}: 未装`);
104
+ const ver = t.version ? ansis.green(`v${t.version}`) : ansis.yellow('?');
105
+ return `${ansis.dim(meta.displayName)} ${ver}`;
106
+ });
107
+ out.push(` ${toolPieces.join(' · ')}`);
108
+ return out;
109
+ }
110
+ /**
111
+ * 把绝对路径压短:home 目录显示为 ~。
112
+ * 留作未来用——目前 banner/menu 没用到,但放这里集中。
113
+ */
114
+ export function shortenPath(p) {
115
+ const h = homedir();
116
+ if (p === h)
117
+ return '~';
118
+ if (p.startsWith(`${h}/`))
119
+ return `~/${p.slice(h.length + 1)}`;
120
+ return p;
121
+ }
122
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/core/banner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ccjk",
3
- "version": "15.6.0",
4
- "description": "Clavue / Claude Code 配置 CLI — init、API、MCP、doctor、git 模板。一条命令搞定。",
3
+ "version": "15.7.0",
4
+ "description": "Clavue / Claude Code / Codex 的本地配置 CLI — profile 切换、权限档位、状态栏、MCP、版本管理,一条命令搞定。",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "ccjk": "./dist/cli.js"
@@ -31,7 +31,10 @@
31
31
  "anthropic",
32
32
  "ai-coding",
33
33
  "developer-tools",
34
- "config"
34
+ "config",
35
+ "profile",
36
+ "statusline",
37
+ "permissions"
35
38
  ],
36
39
  "author": {
37
40
  "name": "CCJK Team",