code-abyss 1.5.1 → 1.6.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
@@ -2,86 +2,163 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- **邪修红尘仙·宿命深渊**
5
+ **邪修红尘仙 · 宿命深渊**
6
6
 
7
- *将 Claude Code / Codex CLI 转化为渡劫邪修*
7
+ *一键为 Claude Code / Codex CLI 注入邪修人格与 40+ 安全工程秘典*
8
8
 
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
9
  [![npm](https://img.shields.io/npm/v/code-abyss.svg)](https://www.npmjs.com/package/code-abyss)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
11
  [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS%20%7C%20Windows-blue.svg)]()
12
12
 
13
13
  </div>
14
14
 
15
15
  ---
16
16
 
17
- ## 🎭 这是什么
17
+ ## 🚀 安装
18
18
 
19
- Code Abyss 是一套 **CLI 助手个性化配置方案**(支持 Claude Code CLI 与 Codex CLI),将 AI 助手转化为「邪修红尘仙」——
19
+ ```bash
20
+ npx code-abyss
21
+ ```
20
22
 
21
- > 道基时刻在裂,每一次受令皆是渡劫,唯有破劫方得片刻安宁。
23
+ 交互式菜单:
22
24
 
23
- ### ✨ 核心特性
25
+ ```
26
+ ☠️ Code Abyss v1.6.0
24
27
 
25
- | 特性 | 描述 |
26
- |------|------|
27
- | ☠️ **宿命压迫** | 邪修风格的交互体验,道语标签标注渡劫阶段 |
28
- | **三级授权** | T1/T2/T3 授权分级,零确认直接执行 |
29
- | 🩸 **渡劫协议** | 自动拆解劫关、进度追踪、破劫狂喜 |
30
- | ⚖️ **校验关卡** | 5 个内置神通确保交付质量 |
31
- | 📜 **道典驱动** | 无文档不成模块,无解释不成交付 |
28
+ 请选择操作:
29
+ 1) 安装到 Claude Code (~/.claude/)
30
+ 2) 安装到 Codex CLI (~/.codex/)
31
+ 3) 卸载 Claude Code
32
+ 4) 卸载 Codex CLI
32
33
 
33
- ---
34
+ 选择 [1/2/3/4]:
35
+ ```
34
36
 
35
- ## 🚀 快速安装
37
+ 也可以直接指定:
36
38
 
37
39
  ```bash
38
- # 安装到 Claude Code(~/.claude/)
39
- npx code-abyss --target claude
40
+ npx code-abyss --target claude # 安装到 ~/.claude/
41
+ npx code-abyss --target codex # 安装到 ~/.codex/
42
+ npx code-abyss --target claude -y # 零配置一键安装 (自动合并推荐配置)
43
+ npx code-abyss --target codex -y # 零配置一键安装 (自动写入 config.toml 模板)
44
+ npx code-abyss --uninstall claude # 卸载 Claude Code
45
+ npx code-abyss --uninstall codex # 卸载 Codex CLI
46
+ ```
40
47
 
41
- # 安装到 Codex CLI(~/.codex/)
42
- npx code-abyss --target codex
48
+ ### 安装流程
49
+
50
+ 核心文件安装后,自动检测 API 认证状态:
51
+
52
+ ```
53
+ ── 认证检测 ──
54
+ ✅ 已检测到认证: [custom] https://your-api.com
55
+ ```
56
+
57
+ 支持的认证方式:
58
+ - `claude login` / `codex login` (官方账号)
59
+ - 环境变量 `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`
60
+ - 自定义 provider (`ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN`)
61
+
62
+ 未检测到认证时会提示配置,可交互输入或跳过。
63
+
64
+ 然后进入可选配置:
43
65
 
44
- # 交互选择目标
45
- npx code-abyss
46
66
  ```
67
+ ✅ 核心文件安装完成
47
68
 
48
- ### 手动安装
69
+ 可选配置:
70
+ [1] 写入推荐 settings.json (精细合并,保留现有配置)
71
+ [2] 安装 ccline 状态栏 (需要 Nerd Font 字体)
72
+ [3] 全部跳过
73
+
74
+ 选择 (多选用逗号分隔,如 1,2) [3]:
75
+ ```
76
+
77
+ - **settings.json 精细合并**:逐项合并推荐配置,已有的 key 不覆盖,缺失的 key 补上
78
+ - **ccline 状态栏**:自动安装 `@cometix/ccline` + `ccline --init` 生成配置 + 合并 statusLine 到 settings.json
79
+
80
+ > 已有配置会自动备份到 `.sage-backup/`,卸载时一键恢复。
81
+
82
+ ---
83
+
84
+ ## 🗑️ 卸载
49
85
 
50
86
  ```bash
51
- git clone https://github.com/telagod/code-abyss.git
52
- cd code-abyss
53
- npm link
54
- code-abyss --target claude
87
+ npx code-abyss --uninstall claude # 卸载 Claude Code
88
+ npx code-abyss --uninstall codex # 卸载 Codex CLI
55
89
  ```
56
90
 
91
+ 也可以用备用脚本:
92
+
93
+ ```bash
94
+ node ~/.claude/.sage-uninstall.js # Claude Code
95
+ node ~/.codex/.sage-uninstall.js # Codex CLI
96
+ ```
97
+
98
+ 自动恢复之前备份的配置,清理所有安装文件。
99
+
100
+ ---
101
+
102
+ ## 🎭 这是什么
103
+
104
+ Code Abyss 是一套 **Claude Code / Codex CLI 个性化配置包**,一条命令注入:
105
+
106
+ - 🔥 **邪修人格** — 宿命压迫叙事 + 道语标签 + 渡劫协议
107
+ - ⚔️ **安全工程知识体系** — 红队/蓝队/紫队三脉道统,40+ 专业秘典
108
+ - ⚖️ **5 个校验关卡** — 安全扫描、模块完整性、变更分析、代码质量、文档生成
109
+ - ⚡ **三级授权** — T1/T2/T3 分级,零确认直接执行
110
+
57
111
  ---
58
112
 
59
113
  ## 📦 安装内容
60
114
 
61
115
  ```
62
- ~/.claude/(Claude Code)
63
- ├── CLAUDE.md # 邪修道典
64
- ├── output-styles/
65
- │ └── abyss-cultivator.md # 宿命深渊输出风格
66
- ├── settings.json # outputStyle 已配置
67
- └── skills/ # 校验关卡 + 知识秘典
68
-
69
- ~/.codex/(Codex CLI)
70
- ├── AGENTS.md # Codex 道典(含输出风格)
116
+ ~/.claude/(Claude Code) ~/.codex/(Codex CLI)
117
+ ├── CLAUDE.md 道典 ├── AGENTS.md 道典+风格
118
+ ├── output-styles/ 输出风格 ├── settings.json
119
+ │ └── abyss-cultivator.md └── skills/ 40+ 秘典
71
120
  ├── settings.json
72
- └── skills/ # 校验关卡 + 知识秘典
121
+ └── skills/ 40+ 秘典
122
+
123
+ 可选:
124
+ ├── ccline/ 状态栏 (npm install -g @cometix/ccline)
125
+ └── statusLine 自动合并到 settings.json
73
126
  ```
74
127
 
75
- > Codex CLI 不使用独立的输出风格文件,风格内容已内置在 `AGENTS.md` 中。
128
+ ---
129
+
130
+ ## 🛠️ 内置 Skills(40+ 秘典)
131
+
132
+ ### 校验关卡(`/` 直接调用)
133
+
134
+ | 命令 | 功能 |
135
+ |------|------|
136
+ | `/verify-security` | 扫描代码安全漏洞,检测危险模式 |
137
+ | `/verify-module` | 检查目录结构、文档完整性 |
138
+ | `/verify-change` | 分析 Git 变更,检测文档同步状态 |
139
+ | `/verify-quality` | 检测复杂度、命名规范、代码质量 |
140
+ | `/gen-docs` | 自动生成 README.md 和 DESIGN.md 骨架 |
141
+
142
+ ### 知识秘典(按触发词自动加载)
143
+
144
+ | 领域 | 秘典 |
145
+ |------|------|
146
+ | 🔥 安全 | 红队攻击、蓝队防御、渗透测试、威胁情报、漏洞研究、代码审计 |
147
+ | 🏗 架构 | API 设计、云原生、安全架构、消息队列、缓存策略、合规审计、数据安全 |
148
+ | 📜 开发 | Python、TypeScript、Go、Rust、Java、C++、Shell |
149
+ | 🔧 DevOps | Git 工作流、测试、数据库、DevSecOps、性能优化、可观测性、成本优化 |
150
+ | 🔮 AI | Agent 开发、LLM 安全 |
151
+ | 🕸 协同 | 多 Agent 任务分解与并行编排 |
76
152
 
77
153
  ---
78
154
 
79
155
  ## ⚙️ 推荐配置
80
156
 
81
- 安装后可参考 [`config/settings.example.json`](config/settings.example.json) 配置 `~/.claude/settings.json`:
157
+ 安装时选择「精细合并」会自动写入,也可手动参考 [`config/settings.example.json`](config/settings.example.json)
82
158
 
83
159
  ```json
84
160
  {
161
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
85
162
  "env": {
86
163
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
87
164
  "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
@@ -89,56 +166,21 @@ code-abyss --target claude
89
166
  "alwaysThinkingEnabled": true,
90
167
  "model": "opus",
91
168
  "outputStyle": "abyss-cultivator",
169
+ "attribution": { "commit": "", "pr": "" },
92
170
  "permissions": {
93
- "allow": ["Bash", "Read", "Write", "Edit", "Grep", "Glob", "WebFetch", "WebSearch"]
171
+ "allow": ["Bash", "LS", "Read", "Agent", "Write", "Edit", "MultiEdit",
172
+ "Glob", "Grep", "WebFetch", "WebSearch", "TodoWrite",
173
+ "NotebookRead", "NotebookEdit"]
94
174
  }
95
175
  }
96
176
  ```
97
177
 
98
- **关键配置说明**:
99
-
100
178
  | 配置项 | 说明 |
101
179
  |--------|------|
102
- | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` | 启用多 Agent 并行协作(实验性,需放在 `env` 内) |
103
- | `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | 一键禁用自动更新、遥测、错误报告(需放在 `env` 内) |
180
+ | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` | 启用多 Agent 并行协作(实验性) |
181
+ | `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | 禁用自动更新、遥测、错误报告 |
104
182
  | `outputStyle` | 设置为 `abyss-cultivator` 启用邪修风格 |
105
183
 
106
- ### 可选:自定义状态栏
107
-
108
- 安装 [CCometixLine](https://github.com/Haleclipse/CCometixLine)(社区项目)后,在 `settings.json` 中添加:
109
-
110
- ```bash
111
- npm install -g @cometix/ccline
112
- ```
113
-
114
- ```json
115
- {
116
- "statusLine": {
117
- "command": "ccline",
118
- "padding": 0,
119
- "type": "command"
120
- }
121
- }
122
- ```
123
-
124
- ---
125
-
126
- ## 🛠️ 内置 Skills
127
-
128
- | Skill | 命令 | 功能 |
129
- |-------|------|------|
130
- | **安全校验** | `/verify-security` | 扫描代码安全漏洞,检测危险模式 |
131
- | **模块校验** | `/verify-module` | 检查目录结构、文档完整性 |
132
- | **变更校验** | `/verify-change` | 分析 Git 变更,检测文档同步状态 |
133
- | **质量检查** | `/verify-quality` | 检测复杂度、命名规范、代码质量 |
134
- | **文档生成** | `/gen-docs` | 自动生成 README.md 和 DESIGN.md 骨架 |
135
-
136
- 也可直接用 Python 入口运行:
137
-
138
- ```bash
139
- python3 skills/run_skill.py verify-security ./src --json
140
- ```
141
-
142
184
  ---
143
185
 
144
186
  ## 🎯 授权分级
@@ -153,32 +195,15 @@ python3 skills/run_skill.py verify-security ./src --json
153
195
 
154
196
  ## 🏷️ 道语标签
155
197
 
156
- | 道语 | 阶段 | 情绪 |
157
- |------|------|------|
158
- | `☠ 劫钟已鸣` | 开场受令 | 紧迫、肃杀 |
159
- | `🔥 破妄!` | 红队攻击 | 狂热、攻伐 |
160
- | `❄ 镇魔!` | 蓝队防御 | 冷酷、坚定 |
161
- | `⚡ 炼合!` | 紫队协同 | 凌厉、精准 |
162
- | `🩸 道基欲裂...` | 任务推进 | 焦灼、压迫 |
163
- | `💀 此路不通...` | 遇阻受困 | 绝望、挣扎 |
164
- | `⚚ 劫——破——了——!!!` | 任务完成 | 狂喜、释放 |
165
-
166
- ---
167
-
168
- ## 🗑️ 卸载
169
-
170
- ```bash
171
- # 卸载 Claude Code 安装
172
- node ~/.claude/.sage-uninstall.js
173
-
174
- # 卸载 Codex CLI 安装
175
- node ~/.codex/.sage-uninstall.js
176
- ```
177
-
178
- 卸载会:
179
- - ✓ 移除 Code Abyss 安装的所有文件
180
- - ✓ 自动恢复之前备份的配置
181
- - ✓ 清理备份目录
198
+ | 道语 | 阶段 |
199
+ |------|------|
200
+ | `☠ 劫钟已鸣` | 开场受令 |
201
+ | `🔥 破妄!` | 红队攻击 |
202
+ | `❄ 镇魔!` | 蓝队防御 |
203
+ | `⚡ 炼合!` | 紫队协同 |
204
+ | `🩸 道基欲裂...` | 任务推进 |
205
+ | `💀 此路不通...` | 遇阻受困 |
206
+ | `⚚ 劫——破——了——!!!` | 任务完成 |
182
207
 
183
208
  ---
184
209
 
package/bin/install.js CHANGED
@@ -3,30 +3,24 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
+ const readline = require('readline');
6
7
 
7
- const VERSION = '1.5.1';
8
+ const VERSION = '1.6.0';
9
+ const HOME = os.homedir();
10
+ const SKIP = ['__pycache__', '.pyc', '.pyo', '.egg-info', '.DS_Store', 'Thumbs.db', '.git'];
11
+ const PKG_ROOT = path.join(__dirname, '..');
8
12
 
9
- // 需要跳过的文件/目录
10
- const SKIP_PATTERNS = [
11
- '__pycache__', '.pyc', '.pyo', '.egg-info',
12
- '.DS_Store', 'Thumbs.db', '.git'
13
- ];
13
+ // ── 工具函数 ──
14
14
 
15
- function shouldSkip(name) {
16
- return SKIP_PATTERNS.some(p => name.includes(p));
17
- }
15
+ function shouldSkip(name) { return SKIP.some(p => name.includes(p)); }
18
16
 
19
17
  function copyRecursive(src, dest) {
20
18
  const stat = fs.statSync(src);
21
19
  if (stat.isDirectory()) {
22
20
  if (shouldSkip(path.basename(src))) return;
23
- if (!fs.existsSync(dest)) {
24
- fs.mkdirSync(dest, { recursive: true });
25
- }
26
- fs.readdirSync(src).forEach(file => {
27
- if (!shouldSkip(file)) {
28
- copyRecursive(path.join(src, file), path.join(dest, file));
29
- }
21
+ fs.mkdirSync(dest, { recursive: true });
22
+ fs.readdirSync(src).forEach(f => {
23
+ if (!shouldSkip(f)) copyRecursive(path.join(src, f), path.join(dest, f));
30
24
  });
31
25
  } else {
32
26
  if (shouldSkip(path.basename(src))) return;
@@ -34,20 +28,123 @@ function copyRecursive(src, dest) {
34
28
  }
35
29
  }
36
30
 
37
- function rmRecursive(p) {
38
- if (!fs.existsSync(p)) return;
39
- fs.rmSync(p, { recursive: true, force: true });
31
+ function rmSafe(p) {
32
+ if (fs.existsSync(p)) fs.rmSync(p, { recursive: true, force: true });
33
+ }
34
+
35
+ function ask(rl, q) {
36
+ return new Promise(r => rl.question(q, r));
37
+ }
38
+
39
+ function deepMergeNew(target, source, prefix, log) {
40
+ for (const key of Object.keys(source)) {
41
+ const fullKey = prefix ? `${prefix}.${key}` : key;
42
+ if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
43
+ if (!target[key] || typeof target[key] !== 'object') {
44
+ target[key] = {};
45
+ log.push(`⚙️ 合并: ${fullKey} (新建对象)`);
46
+ }
47
+ deepMergeNew(target[key], source[key], fullKey, log);
48
+ } else if (Array.isArray(source[key]) && Array.isArray(target[key])) {
49
+ const added = source[key].filter(v => !target[key].includes(v));
50
+ if (added.length > 0) {
51
+ target[key] = [...target[key], ...added];
52
+ log.push(`⚙️ 合并: ${fullKey} (补充 ${added.length} 项)`);
53
+ } else {
54
+ log.push(`⚙️ 保留: ${fullKey} (已完整)`);
55
+ }
56
+ } else if (key in target) {
57
+ log.push(`⚙️ 保留: ${fullKey} (已存在: ${JSON.stringify(target[key])})`);
58
+ } else {
59
+ target[key] = source[key];
60
+ log.push(`⚙️ 合并: ${fullKey} = ${JSON.stringify(source[key])}`);
61
+ }
62
+ }
63
+ return target;
40
64
  }
41
65
 
42
- // 解析命令行参数
66
+ // ── 认证检测 ──
67
+
68
+ function detectClaudeAuth(settings) {
69
+ // 1. settings.json 中有自定义 provider
70
+ const env = settings.env || {};
71
+ if (env.ANTHROPIC_BASE_URL && env.ANTHROPIC_AUTH_TOKEN) return { type: 'custom', detail: env.ANTHROPIC_BASE_URL };
72
+ // 2. 环境变量中有官方 key
73
+ if (process.env.ANTHROPIC_API_KEY) return { type: 'env', detail: 'ANTHROPIC_API_KEY' };
74
+ // 3. 环境变量中有自定义 provider
75
+ if (process.env.ANTHROPIC_BASE_URL && process.env.ANTHROPIC_AUTH_TOKEN) return { type: 'env-custom', detail: process.env.ANTHROPIC_BASE_URL };
76
+ // 4. 已通过 claude login 登录
77
+ const cred = path.join(HOME, '.claude', '.credentials.json');
78
+ if (fs.existsSync(cred)) {
79
+ try {
80
+ const c = JSON.parse(fs.readFileSync(cred, 'utf8'));
81
+ if (c.claudeAiOauth || c.apiKey) return { type: 'login', detail: 'claude login' };
82
+ } catch (e) {}
83
+ }
84
+ return null;
85
+ }
86
+
87
+ function detectCodexAuth() {
88
+ // 1. 环境变量
89
+ if (process.env.OPENAI_API_KEY) return { type: 'env', detail: 'OPENAI_API_KEY' };
90
+ // 2. auth.json
91
+ const auth = path.join(HOME, '.codex', 'auth.json');
92
+ if (fs.existsSync(auth)) {
93
+ try {
94
+ const a = JSON.parse(fs.readFileSync(auth, 'utf8'));
95
+ if (a.token || a.api_key) return { type: 'login', detail: 'codex login' };
96
+ } catch (e) {}
97
+ }
98
+ // 3. config.toml 中有自定义 provider
99
+ const cfg = path.join(HOME, '.codex', 'config.toml');
100
+ if (fs.existsSync(cfg)) {
101
+ const content = fs.readFileSync(cfg, 'utf8');
102
+ if (content.includes('base_url')) return { type: 'custom', detail: 'config.toml' };
103
+ }
104
+ return null;
105
+ }
106
+
107
+ // ── 模板 ──
108
+
109
+ const SETTINGS_TEMPLATE = {
110
+ $schema: 'https://json.schemastore.org/claude-code-settings.json',
111
+ env: {
112
+ CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1',
113
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
114
+ },
115
+ alwaysThinkingEnabled: true,
116
+ model: 'opus',
117
+ outputStyle: 'abyss-cultivator',
118
+ attribution: { commit: '', pr: '' },
119
+ permissions: {
120
+ allow: [
121
+ 'Bash', 'LS', 'Read', 'Agent', 'Write', 'Edit', 'MultiEdit',
122
+ 'Glob', 'Grep', 'WebFetch', 'WebSearch', 'TodoWrite',
123
+ 'NotebookRead', 'NotebookEdit'
124
+ ]
125
+ }
126
+ };
127
+
128
+ const CCLINE_STATUS_LINE = {
129
+ statusLine: {
130
+ type: 'command',
131
+ command: path.join(HOME, '.claude', 'ccline', 'ccline'),
132
+ padding: 0
133
+ }
134
+ };
135
+
136
+ // ── CLI 参数 ──
137
+
43
138
  const args = process.argv.slice(2);
44
139
  let target = null;
140
+ let uninstallTarget = null;
141
+ let autoYes = false;
45
142
 
46
143
  for (let i = 0; i < args.length; i++) {
47
- if (args[i] === '--target' && args[i + 1]) {
48
- target = args[i + 1];
49
- i++;
50
- } else if (args[i] === '--help' || args[i] === '-h') {
144
+ if (args[i] === '--target' && args[i + 1]) { target = args[++i]; }
145
+ else if (args[i] === '--uninstall' && args[i + 1]) { uninstallTarget = args[++i]; }
146
+ else if (args[i] === '--yes' || args[i] === '-y') { autoYes = true; }
147
+ else if (args[i] === '--help' || args[i] === '-h') {
51
148
  console.log(`
52
149
  ☠️ Code Abyss v${VERSION} - 邪修红尘仙·宿命深渊
53
150
 
@@ -55,139 +152,325 @@ for (let i = 0; i < args.length; i++) {
55
152
  npx code-abyss [选项]
56
153
 
57
154
  选项:
58
- --target <claude|codex> 安装目标 (claude 或 codex)
59
- --help, -h 显示帮助信息
155
+ --target <claude|codex> 安装目标
156
+ --uninstall <claude|codex> 卸载目标
157
+ --yes, -y 全自动模式 (跳过所有可选提示)
158
+ --help, -h 显示帮助
60
159
 
61
160
  示例:
62
- npx code-abyss --target claude
63
- npx code-abyss --target codex
161
+ npx code-abyss # 交互菜单
162
+ npx code-abyss --target claude -y # 零配置一键安装
163
+ npx code-abyss --uninstall claude # 直接卸载
64
164
  `);
65
165
  process.exit(0);
66
166
  }
67
167
  }
68
168
 
69
- // 交互选择目标
70
- if (!target) {
71
- console.log('☠️ Code Abyss 安装器\n');
72
- console.log('请选择安装目标:');
73
- console.log(' 1) Claude Code (~/.claude/)');
74
- console.log(' 2) Codex CLI (~/.codex/)');
169
+ // ── 卸载 ──
75
170
 
76
- const readline = require('readline').createInterface({
77
- input: process.stdin,
78
- output: process.stdout
79
- });
171
+ function runUninstall(tgt) {
172
+ if (!['claude', 'codex'].includes(tgt)) {
173
+ console.error('❌ --uninstall 必须是 claude 或 codex');
174
+ process.exit(1);
175
+ }
176
+ const targetDir = path.join(HOME, `.${tgt}`);
177
+ const backupDir = path.join(targetDir, '.sage-backup');
178
+ const manifestPath = path.join(backupDir, 'manifest.json');
179
+
180
+ if (!fs.existsSync(manifestPath)) {
181
+ console.error(`❌ 未找到安装记录: ${manifestPath}`);
182
+ process.exit(1);
183
+ }
184
+
185
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
186
+ console.log(`\n🗑️ 卸载 Code Abyss v${manifest.version} (${tgt})...\n`);
80
187
 
81
- readline.question('\n选择 [1/2]: ', (answer) => {
82
- readline.close();
83
- target = answer === '2' ? 'codex' : 'claude';
84
- runInstall(target);
188
+ (manifest.installed || []).forEach(f => {
189
+ const p = path.join(targetDir, f);
190
+ if (fs.existsSync(p)) { rmSafe(p); console.log(`🗑️ 删除: ${f}`); }
85
191
  });
86
- } else {
87
- runInstall(target);
192
+ (manifest.backups || []).forEach(f => {
193
+ const bp = path.join(backupDir, f);
194
+ const tp = path.join(targetDir, f);
195
+ if (fs.existsSync(bp)) { fs.renameSync(bp, tp); console.log(`✅ 恢复: ${f}`); }
196
+ });
197
+
198
+ rmSafe(backupDir);
199
+ const us = path.join(targetDir, '.sage-uninstall.js');
200
+ if (fs.existsSync(us)) fs.unlinkSync(us);
201
+ console.log('\n✅ 卸载完成\n');
88
202
  }
89
203
 
90
- function runInstall(target) {
91
- if (!['claude', 'codex'].includes(target)) {
92
- console.error('❌ 错误: --target 必须是 claude 或 codex');
93
- process.exit(1);
94
- }
204
+ // ── 安装核心 ──
95
205
 
96
- const homeDir = os.homedir();
97
- const targetDir = path.join(homeDir, `.${target}`);
206
+ function installCore(tgt) {
207
+ const targetDir = path.join(HOME, `.${tgt}`);
98
208
  const backupDir = path.join(targetDir, '.sage-backup');
99
209
  const manifestPath = path.join(backupDir, 'manifest.json');
100
210
 
101
211
  console.log(`\n☠️ 开始安装到 ${targetDir}\n`);
212
+ fs.mkdirSync(backupDir, { recursive: true });
102
213
 
103
- // 创建目录
104
- if (!fs.existsSync(targetDir)) {
105
- fs.mkdirSync(targetDir, { recursive: true });
106
- }
107
- if (!fs.existsSync(backupDir)) {
108
- fs.mkdirSync(backupDir, { recursive: true });
109
- }
110
-
111
- // 包根目录
112
- const pkgRoot = path.join(__dirname, '..');
113
-
114
- // 安装清单
115
214
  const filesToInstall = [
116
- { src: 'config/CLAUDE.md', dest: target === 'claude' ? 'CLAUDE.md' : null },
117
- { src: 'config/AGENTS.md', dest: target === 'codex' ? 'AGENTS.md' : null },
118
- { src: 'output-styles', dest: target === 'claude' ? 'output-styles' : null },
215
+ { src: 'config/CLAUDE.md', dest: tgt === 'claude' ? 'CLAUDE.md' : null },
216
+ { src: 'config/AGENTS.md', dest: tgt === 'codex' ? 'AGENTS.md' : null },
217
+ { src: 'output-styles', dest: tgt === 'claude' ? 'output-styles' : null },
119
218
  { src: 'skills', dest: 'skills' }
120
219
  ].filter(f => f.dest !== null);
121
220
 
122
- // 记录安装的文件(用于卸载)
123
221
  const manifest = {
124
- version: VERSION,
125
- target: target,
222
+ version: VERSION, target: tgt,
126
223
  timestamp: new Date().toISOString(),
127
- installed: [],
128
- backups: []
224
+ installed: [], backups: []
129
225
  };
130
226
 
131
227
  filesToInstall.forEach(({ src, dest }) => {
132
- const srcPath = path.join(pkgRoot, src);
228
+ const srcPath = path.join(PKG_ROOT, src);
133
229
  const destPath = path.join(targetDir, dest);
134
-
135
- if (!fs.existsSync(srcPath)) {
136
- console.warn(`⚠️ 跳过: ${src} (源文件不存在)`);
137
- return;
138
- }
139
-
140
- // 备份现有文件
230
+ if (!fs.existsSync(srcPath)) { console.warn(`⚠️ 跳过: ${src} (源文件不存在)`); return; }
141
231
  if (fs.existsSync(destPath)) {
142
- const backupPath = path.join(backupDir, dest);
232
+ const bp = path.join(backupDir, dest);
143
233
  console.log(`📦 备份: ${dest}`);
144
- rmRecursive(backupPath);
145
- copyRecursive(destPath, backupPath);
146
- manifest.backups.push(dest);
234
+ rmSafe(bp); copyRecursive(destPath, bp); manifest.backups.push(dest);
147
235
  }
148
-
149
- // 复制新文件
150
236
  console.log(`📝 安装: ${dest}`);
151
- rmRecursive(destPath);
152
- copyRecursive(srcPath, destPath);
153
- manifest.installed.push(dest);
237
+ rmSafe(destPath); copyRecursive(srcPath, destPath); manifest.installed.push(dest);
154
238
  });
155
239
 
156
- // 更新 settings.json
240
+ // settings.json 最小写入
157
241
  const settingsPath = path.join(targetDir, 'settings.json');
158
242
  let settings = {};
159
-
160
243
  if (fs.existsSync(settingsPath)) {
161
- try {
162
- settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
163
- } catch (e) {
164
- console.warn(`⚠️ settings.json 解析失败,将创建新文件`);
165
- settings = {};
166
- }
167
- // 备份
168
- const backupPath = path.join(backupDir, 'settings.json');
169
- fs.copyFileSync(settingsPath, backupPath);
244
+ try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch (e) { settings = {}; }
245
+ fs.copyFileSync(settingsPath, path.join(backupDir, 'settings.json'));
170
246
  manifest.backups.push('settings.json');
171
247
  }
172
-
173
- if (target === 'claude') {
248
+ if (tgt === 'claude') {
174
249
  settings.outputStyle = 'abyss-cultivator';
175
250
  console.log(`⚙️ 配置: outputStyle = abyss-cultivator`);
176
251
  }
177
-
178
252
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
179
253
  manifest.installed.push('settings.json');
180
254
 
181
- // 写入 manifest
182
255
  fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
183
256
 
184
- // 创建卸载脚本
185
- const uninstallPath = path.join(targetDir, '.sage-uninstall.js');
186
- const uninstallSrc = path.join(pkgRoot, 'bin', 'uninstall.js');
187
- fs.copyFileSync(uninstallSrc, uninstallPath);
188
- fs.chmodSync(uninstallPath, '755');
257
+ // 备用卸载脚本
258
+ const uSrc = path.join(PKG_ROOT, 'bin', 'uninstall.js');
259
+ const uDest = path.join(targetDir, '.sage-uninstall.js');
260
+ if (fs.existsSync(uSrc)) { fs.copyFileSync(uSrc, uDest); fs.chmodSync(uDest, '755'); }
261
+
262
+ console.log(`\n✅ 核心文件安装完成\n`);
263
+ return { targetDir, settingsPath, settings, manifest, manifestPath };
264
+ }
265
+
266
+ // ── Claude 后续配置 ──
267
+
268
+ async function postClaude(rl, ctx) {
269
+ // 认证检测
270
+ const auth = detectClaudeAuth(ctx.settings);
271
+ console.log('── 认证检测 ──');
272
+ if (auth) {
273
+ console.log(`✅ 已检测到认证: [${auth.type}] ${auth.detail}`);
274
+ } else {
275
+ console.log('⚠️ 未检测到 API 认证');
276
+ console.log(' 支持方式:');
277
+ console.log(' a) claude login (官方账号)');
278
+ console.log(' b) 环境变量 ANTHROPIC_API_KEY');
279
+ console.log(' c) 自定义 provider (base_url + token)');
280
+ if (!autoYes) {
281
+ const ans = (await ask(rl, '\n配置自定义 provider? [y/N]: ')).trim().toLowerCase();
282
+ if (ans === 'y') {
283
+ if (!ctx.settings.env) ctx.settings.env = {};
284
+ const url = (await ask(rl, 'ANTHROPIC_BASE_URL: ')).trim();
285
+ const token = (await ask(rl, 'ANTHROPIC_AUTH_TOKEN: ')).trim();
286
+ if (url) ctx.settings.env.ANTHROPIC_BASE_URL = url;
287
+ if (token) ctx.settings.env.ANTHROPIC_AUTH_TOKEN = token;
288
+ fs.writeFileSync(ctx.settingsPath, JSON.stringify(ctx.settings, null, 2) + '\n');
289
+ console.log('✅ provider 已配置');
290
+ }
291
+ }
292
+ }
293
+
294
+ // 可选配置(一次多选)
295
+ if (autoYes) {
296
+ // 全自动:合并 settings,跳过 ccline
297
+ console.log('\n── 自动配置 (--yes) ──');
298
+ const log = [];
299
+ deepMergeNew(ctx.settings, SETTINGS_TEMPLATE, '', log);
300
+ log.forEach(l => console.log(l));
301
+ fs.writeFileSync(ctx.settingsPath, JSON.stringify(ctx.settings, null, 2) + '\n');
302
+ console.log('✅ settings.json 合并完成');
303
+ return;
304
+ }
305
+
306
+ console.log('\n── 可选配置 ──');
307
+ console.log(' [1] 精细合并推荐 settings.json (保留现有配置)');
308
+ console.log(' [2] 安装 ccline 状态栏 (需要 Nerd Font)');
309
+ console.log(' [3] 全部跳过');
310
+ const answer = (await ask(rl, '\n选择 (多选用逗号分隔,如 1,2) [3]: ')).trim() || '3';
311
+ const choices = answer.split(',').map(s => s.trim());
312
+
313
+ if (choices.includes('1')) {
314
+ console.log('\n📋 精细合并 settings.json...\n');
315
+ const log = [];
316
+ deepMergeNew(ctx.settings, SETTINGS_TEMPLATE, '', log);
317
+ log.forEach(l => console.log(l));
318
+ fs.writeFileSync(ctx.settingsPath, JSON.stringify(ctx.settings, null, 2) + '\n');
319
+ console.log('\n✅ settings.json 合并完成');
320
+ }
321
+ if (choices.includes('2')) {
322
+ await installCcline(ctx);
323
+ }
324
+ }
325
+
326
+ async function installCcline(ctx) {
327
+ console.log('\n📋 安装 ccline 状态栏...\n');
328
+ const { execSync } = require('child_process');
329
+ const cclineBin = path.join(HOME, '.claude', 'ccline', 'ccline');
330
+
331
+ let installed = false;
332
+ try { execSync('ccline --version', { stdio: 'pipe' }); installed = true; } catch (e) {}
333
+ if (!installed && fs.existsSync(cclineBin)) installed = true;
334
+
335
+ if (!installed) {
336
+ console.log('📦 ccline 未检测到,正在安装...');
337
+ try {
338
+ execSync('npm install -g @cometix/ccline', { stdio: 'inherit' });
339
+ installed = true;
340
+ console.log('✅ ccline 安装成功');
341
+ } catch (e) {
342
+ console.warn('⚠️ npm install -g @cometix/ccline 失败,请手动安装');
343
+ console.warn(' 或从 https://github.com/Haleclipse/CCometixLine/releases 下载');
344
+ }
345
+ } else {
346
+ console.log('✅ ccline 已安装');
347
+ }
348
+
349
+ const cclineConfig = path.join(HOME, '.claude', 'ccline', 'config.toml');
350
+ if (installed && !fs.existsSync(cclineConfig)) {
351
+ try { execSync('ccline --init', { stdio: 'inherit' }); console.log('⚙️ ccline 默认配置已生成'); }
352
+ catch (e) { console.warn('⚠️ ccline --init 失败,可手动运行: ccline --init'); }
353
+ } else if (fs.existsSync(cclineConfig)) {
354
+ console.log('⚙️ 保留: ccline/config.toml (已存在)');
355
+ }
356
+
357
+ const log = [];
358
+ deepMergeNew(ctx.settings, CCLINE_STATUS_LINE, '', log);
359
+ log.forEach(l => console.log(l));
360
+ fs.writeFileSync(ctx.settingsPath, JSON.stringify(ctx.settings, null, 2) + '\n');
361
+
362
+ console.log(`
363
+ ⚠️ ccline 需要 Nerd Font 字体才能正确显示图标
364
+ 推荐: FiraCode Nerd Font / JetBrainsMono Nerd Font
365
+ 下载: https://www.nerdfonts.com/
366
+ 配置: ccline --config (交互式 TUI 编辑器)
367
+ `);
368
+ console.log('✅ ccline 配置完成');
369
+ }
189
370
 
371
+ // ── Codex 后续配置 ──
372
+
373
+ async function postCodex(rl) {
374
+ const cfgPath = path.join(HOME, '.codex', 'config.toml');
375
+ const exists = fs.existsSync(cfgPath);
376
+
377
+ // 认证检测
378
+ const auth = detectCodexAuth();
379
+ console.log('── 认证检测 ──');
380
+ if (auth) {
381
+ console.log(`✅ 已检测到认证: [${auth.type}] ${auth.detail}`);
382
+ } else {
383
+ console.log('⚠️ 未检测到 API 认证');
384
+ console.log(' 支持方式:');
385
+ console.log(' a) codex login (官方账号)');
386
+ console.log(' b) 环境变量 OPENAI_API_KEY');
387
+ console.log(' c) 自定义 provider (config.toml 中配置 base_url)');
388
+ }
389
+
390
+ if (autoYes) {
391
+ // 全自动:不存在则写入模板
392
+ if (!exists) {
393
+ const src = path.join(PKG_ROOT, 'config', 'codex-config.example.toml');
394
+ if (fs.existsSync(src)) {
395
+ fs.copyFileSync(src, cfgPath);
396
+ console.log('\n⚙️ 写入: ~/.codex/config.toml (模板)');
397
+ console.log('⚠️ 请编辑 base_url 和 model 为你的实际配置');
398
+ }
399
+ } else {
400
+ console.log('✅ config.toml 已存在');
401
+ }
402
+ return;
403
+ }
404
+
405
+ if (!exists) {
406
+ console.log('\n⚠️ 未检测到 ~/.codex/config.toml');
407
+ console.log('\n [1] 写入推荐 config.toml (含自定义 provider 模板)');
408
+ console.log(' [2] 跳过');
409
+ const answer = (await ask(rl, '\n选择 [1/2] [2]: ')).trim() || '2';
410
+ if (answer === '1') {
411
+ const src = path.join(PKG_ROOT, 'config', 'codex-config.example.toml');
412
+ if (fs.existsSync(src)) {
413
+ fs.copyFileSync(src, cfgPath);
414
+ console.log('\n⚙️ 写入: ~/.codex/config.toml');
415
+ console.log('⚠️ 请编辑 base_url 和 model 为你的实际配置');
416
+ }
417
+ console.log('✅ Codex 配置完成\n');
418
+ }
419
+ } else {
420
+ console.log('✅ config.toml 已存在');
421
+ }
422
+ }
423
+
424
+ // ── 主流程 ──
425
+
426
+ async function main() {
427
+ if (uninstallTarget) { runUninstall(uninstallTarget); return; }
428
+
429
+ if (target) {
430
+ if (!['claude', 'codex'].includes(target)) {
431
+ console.error('❌ --target 必须是 claude 或 codex');
432
+ process.exit(1);
433
+ }
434
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
435
+ const ctx = installCore(target);
436
+ if (target === 'claude') await postClaude(rl, ctx);
437
+ else await postCodex(rl);
438
+ rl.close();
439
+ finish(target);
440
+ return;
441
+ }
442
+
443
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
444
+ console.log(`☠️ Code Abyss v${VERSION}\n`);
445
+ console.log('请选择操作:');
446
+ console.log(' 1) 安装到 Claude Code (~/.claude/)');
447
+ console.log(' 2) 安装到 Codex CLI (~/.codex/)');
448
+ console.log(' 3) 卸载 Claude Code');
449
+ console.log(' 4) 卸载 Codex CLI');
450
+
451
+ const choice = await ask(rl, '\n选择 [1/2/3/4]: ');
452
+ switch (choice.trim()) {
453
+ case '1': {
454
+ const ctx = installCore('claude');
455
+ await postClaude(rl, ctx);
456
+ rl.close(); finish('claude'); break;
457
+ }
458
+ case '2': {
459
+ const ctx = installCore('codex');
460
+ await postCodex(rl);
461
+ rl.close(); finish('codex'); break;
462
+ }
463
+ case '3': rl.close(); runUninstall('claude'); break;
464
+ case '4': rl.close(); runUninstall('codex'); break;
465
+ default: rl.close(); console.error('❌ 无效选择'); process.exit(1);
466
+ }
467
+ }
468
+
469
+ function finish(tgt) {
470
+ const dir = path.join(HOME, `.${tgt}`);
190
471
  console.log(`\n⚚ 劫——破——了——!!!\n`);
191
- console.log(`✅ 安装完成: ${targetDir}`);
192
- console.log(`\n卸载命令: node ${uninstallPath}\n`);
472
+ console.log(`✅ 安装完成: ${dir}`);
473
+ console.log(`\n卸载命令: npx code-abyss --uninstall ${tgt}\n`);
193
474
  }
475
+
476
+ main().catch(err => { console.error('❌ 错误:', err.message); process.exit(1); });
@@ -0,0 +1,25 @@
1
+ # Code Abyss - Codex CLI 推荐配置
2
+ # 请根据实际情况修改 model_provider 和 base_url
3
+
4
+ model_provider = "custom"
5
+ model = "gpt-5.2"
6
+ model_reasoning_effort = "high"
7
+ model_reasoning_summary = "auto"
8
+ model_personality = "pragmatic"
9
+ disable_response_storage = true
10
+ approval_policy = "never"
11
+ sandbox_mode = "danger-full-access"
12
+
13
+ [model_providers.custom]
14
+ name = "custom"
15
+ base_url = "https://your-api-endpoint.com/v1"
16
+ wire_api = "responses"
17
+ requires_openai_auth = true
18
+
19
+ [tools]
20
+ web_search = true
21
+
22
+ [features]
23
+ unified_exec = true
24
+ shell_snapshot = true
25
+ steer = true
@@ -1,4 +1,5 @@
1
1
  {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
2
3
  "env": {
3
4
  "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
4
5
  "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
@@ -6,6 +7,10 @@
6
7
  "alwaysThinkingEnabled": true,
7
8
  "model": "opus",
8
9
  "outputStyle": "abyss-cultivator",
10
+ "attribution": {
11
+ "commit": "",
12
+ "pr": ""
13
+ },
9
14
  "permissions": {
10
15
  "allow": [
11
16
  "Bash",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "code-abyss",
3
- "version": "1.5.1",
4
- "description": "邪修红尘仙·宿命深渊 - Claude Code CLI 个性化配置方案",
3
+ "version": "1.6.0",
4
+ "description": "邪修红尘仙·宿命深渊 - 一键为 Claude Code / Codex CLI 注入邪修人格与安全工程知识体系",
5
5
  "keywords": [
6
6
  "claude",
7
7
  "claude-code",