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