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 +131 -106
- package/bin/install.js +393 -110
- package/config/codex-config.example.toml +25 -0
- package/config/settings.example.json +5 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,86 +2,163 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**邪修红尘仙 · 宿命深渊**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
*一键为 Claude Code / Codex CLI 注入邪修人格与 40+ 安全工程秘典*
|
|
8
8
|
|
|
9
|
-
[](https://opensource.org/licenses/MIT)
|
|
10
9
|
[](https://www.npmjs.com/package/code-abyss)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
11
|
[]()
|
|
12
12
|
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 🚀 安装
|
|
18
18
|
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
# 安装到
|
|
39
|
-
npx code-abyss --target
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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", "
|
|
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
|
|
103
|
-
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` |
|
|
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.
|
|
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
|
-
|
|
24
|
-
|
|
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
|
|
38
|
-
if (
|
|
39
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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>
|
|
59
|
-
--
|
|
155
|
+
--target <claude|codex> 安装目标
|
|
156
|
+
--uninstall <claude|codex> 卸载目标
|
|
157
|
+
--yes, -y 全自动模式 (跳过所有可选提示)
|
|
158
|
+
--help, -h 显示帮助
|
|
60
159
|
|
|
61
160
|
示例:
|
|
62
|
-
npx code-abyss
|
|
63
|
-
npx code-abyss --target
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
|
|
91
|
-
if (!['claude', 'codex'].includes(target)) {
|
|
92
|
-
console.error('❌ 错误: --target 必须是 claude 或 codex');
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
204
|
+
// ── 安装核心 ──
|
|
95
205
|
|
|
96
|
-
|
|
97
|
-
const targetDir = path.join(
|
|
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:
|
|
117
|
-
{ src: 'config/AGENTS.md', dest:
|
|
118
|
-
{ src: 'output-styles', dest:
|
|
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(
|
|
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
|
|
232
|
+
const bp = path.join(backupDir, dest);
|
|
143
233
|
console.log(`📦 备份: ${dest}`);
|
|
144
|
-
|
|
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
|
-
|
|
152
|
-
copyRecursive(srcPath, destPath);
|
|
153
|
-
manifest.installed.push(dest);
|
|
237
|
+
rmSafe(destPath); copyRecursive(srcPath, destPath); manifest.installed.push(dest);
|
|
154
238
|
});
|
|
155
239
|
|
|
156
|
-
//
|
|
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
|
-
|
|
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
|
|
186
|
-
const
|
|
187
|
-
fs.copyFileSync(
|
|
188
|
-
|
|
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(`✅ 安装完成: ${
|
|
192
|
-
console.log(`\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