AI 编程 CLI 工具怎么选:Claude Code、Codex CLI 与 OpenCode 对比
如果把这三款工具都装到本地,第一眼看上去它们都像“命令行里的 AI 编程助手”,但真正拉开差距的地方,往往不是聊天体验,而是项目说明文件、权限边界、配置方式和多仓库协作能力。
这篇文章承担的是“总览文”角色,目标不是把每个细节一次讲完,而是帮你快速建立判断框架:哪一款更适合企业团队,哪一款更适合个人开发,哪一款在多模型和灵活性上更有优势。
如果你已经确定自己更关心某一个专题,可以直接跳到下面两篇文章继续看:
写在前面
选这类工具时,最容易掉进的坑,是只看“模型能力”而忽略“机制成本”。真正影响日常体验的,通常是下面几个问题:
- 项目规则文件会不会自动继承,能不能覆盖多仓库场景。
- 权限模型是白名单式、审批式,还是命令规则式。
- 配置写法是否足够简单,团队成员能不能长期维护。
- 当项目规模变大时,规则和权限会不会越来越难收拾。
如果先把这些问题想清楚,后面的表格和细节就不会只剩“参数对参数”的堆砌。
工具概览
| 维度 | Claude Code | Codex CLI | OpenCode |
|---|
| 开发方 | Anthropic | OpenAI | SST(开源) |
| 语言实现 | Node.js | Node.js | Go |
| 开源 | ❌ 闭源 | ✅ 开源 | ✅ 开源 |
| 发布时间 | 2025 年初 | 2025 年 4 月 | 2025 年中 |
| 界面形式 | 终端交互 | 终端交互 | TUI + 终端 + 桌面应用 |
| 多模型支持 | ❌ 仅 Claude | ❌ 仅 OpenAI | ✅ 支持多家提供商 |
| 定位 | 企业级编程助手 | 轻量代码助手 | 开源全能编程 Agent |
指令文件机制
指令文件用于向 AI 提供项目上下文、编码规范、工作流约定等自然语言说明,相当于 AI 的"项目说明书"。
文件名与位置
Claude Code — CLAUDE.md
| 层级 | 路径 | 说明 |
|---|
| 系统托管 | /etc/claude-code/CLAUDE.md(Linux)
/Library/Application Support/ClaudeCode/CLAUDE.md(macOS) | IT 管理员下发,最高优先级 |
| 用户全局 | ~/.claude/CLAUDE.md | 对当前用户所有项目生效 |
| 项目根目录 | ./CLAUDE.md 或 ./.claude/CLAUDE.md | 提交到 git,团队共享 |
| 子目录 | ./src/CLAUDE.md、./pkg/foo/CLAUDE.md 等 | 懒加载,按需触发 |
Codex CLI — AGENTS.md
| 层级 | 路径 | 说明 |
|---|
| 用户全局 | ~/.codex/AGENTS.md | 对所有项目生效 |
| 仓库根目录 | <git repo root>/AGENTS.md | 提交到 git,团队共享 |
| 当前工作目录 | <cwd>/AGENTS.md | 与仓库根不同时单独加载 |
注意:Codex CLI 不做目录向上遍历,只从以上三个固定路径加载,按顺序合并。可用 --no-project-doc 或 CODEX_DISABLE_PROJECT_DOC=1 禁用项目文件加载。
OpenCode — AGENTS.md(优先)/ CLAUDE.md(兼容回退)
| 层级 | 路径 | 说明 |
|---|
| 用户全局 | ~/.config/opencode/AGENTS.md | 对所有项目生效,不提交 git |
| 项目根目录 | ./AGENTS.md | 提交到 git,团队共享 |
| Claude 兼容(回退) | ./CLAUDE.md(无 AGENTS.md 时) | 迁移兼容,两者同时存在时忽略 CLAUDE.md |
| 扩展引用 | 通过 opencode.json 的 instructions 字段 glob 引入任意文件 | 跨文件聚合 |
OpenCode 兼容说明:若同时存在 AGENTS.md 和 CLAUDE.md,只读取 AGENTS.md,CLAUDE.md 被忽略。
目录继承行为
三个工具都支持向上遍历目录查找指令文件,但行为有所不同:
1
2
3
4
5
6
7
8
9
10
11
| 多仓库场景示例(每个服务是独立的 git repo):
~/projects/
├── CLAUDE.md / AGENTS.md ← 多仓库共享层(projects 目录)
├── order-service/ ← git repo ①
│ ├── CLAUDE.md / AGENTS.md ← 项目级
│ └── src/
│ └── order/
│ └── CLAUDE.md ← 子模块级(当前工作目录)
└── notify-service/ ← git repo ②
└── CLAUDE.md / AGENTS.md ← 项目级
|
Claude Code 遍历行为
1
2
3
4
5
6
7
8
9
10
11
12
| 当前工作目录:~/projects/order-service/src/order/
加载顺序(启动时全量加载):
1. ~/.claude/CLAUDE.md ← 用户全局(独立加载,非遍历结果)
2. ~/projects/CLAUDE.md ← 多仓库共享层(实测验证:越过 git root 继续向上)
3. ~/projects/order-service/CLAUDE.md ← 项目根目录
4. ~/projects/order-service/src/CLAUDE.md ← 遍历沿途(如存在)
5. ~/projects/order-service/src/order/CLAUDE.md ← 当前工作目录
子目录懒加载(按需):
当 Claude 读取 src/payment/ 中的文件时,
才加载 src/payment/CLAUDE.md(如果存在)
|
遍历终止条件:官方文档未明确说明,但经实测验证:Claude Code 不会停在 git root,会继续向上遍历父目录。例如工作目录为 /data/work/ai-mvn(git repo),/data/work/CLAUDE.md(repo 外的上级目录)同样会被加载。~/.claude/CLAUDE.md 是独立的用户全局配置,并非遍历结果。可通过 /context 命令查看当前会话实际加载的文件列表。
多仓库场景下的文件职责划分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| ~/.claude/CLAUDE.md → 个人偏好,所有项目通用(语言、风格)
~/projects/CLAUDE.md → 多仓库共享约定
- 技术栈统一规范
- 服务目录(所有服务地址、职责)
- 跨服务 HTTP 调用约定
- 接口变更协作流程
~/projects/order-service/CLAUDE.md → 本服务内容
- 本服务职责与模块结构
- 本服务对外暴露的接口
- 本服务依赖的上游接口契约(重点!)
~/projects/order-service/src/*/CLAUDE.md → 子模块特殊说明(可选)
|
示例:~/projects/CLAUDE.md(多仓库共享层)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 多服务共享规范
## 技术栈
- Java 8 + Spring Boot 2.x
- 服务间通信:HTTP REST,统一使用 Feign Client
- 统一响应结构:{ code: int, message: String, data: T }
## 服务目录
| 服务 | 职责 | 内网地址 |
|------|------|----------|
| user-service | 用户账户、余额管理 | http://user-service:8001 |
| order-service | 订单生命周期管理 | http://order-service:8002 |
| notify-service | 短信/Push 通知 | http://notify-service:8003 |
## 跨服务开发约定
- 修改任何对外接口前,先确认所有下游调用方
- Feign Client 定义在各服务的 api 模块,不在 core 模块直接 HTTP 调用
- 接口字段变更(新增除外)需同步更新所有调用方
|
示例:~/projects/order-service/CLAUDE.md(项目层)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| # order-service
## 本服务职责
管理订单全生命周期:创建 → 支付确认 → 发货 → 完成 / 取消
## 模块结构
- order-api 对外 Feign Client 接口定义(供其他服务引用)
- order-core 业务逻辑层
- order-server 启动入口 + Controller
## 本服务对外接口
- POST /api/orders 创建订单
- PUT /api/orders/{id}/pay 支付回调
- GET /api/orders/{id} 查询订单详情
## 依赖的上游接口(修改时需同步)
### user-service
- GET /api/users/{id}/balance
响应:{ code: 0, data: { balance: BigDecimal } }
- POST /api/users/{id}/balance/freeze
请求:{ amount: BigDecimal, orderId: String }
响应:{ code: 0, data: { freezeId: String } }
### notify-service
- POST /api/notify/send
请求:{ userId: String, type: "ORDER_CREATED"|"ORDER_PAID", bizId: String }
响应:{ code: 0, data: { msgId: String } }
|
Codex CLI 加载行为(固定路径,无目录遍历)
1
2
3
4
5
6
7
8
| 当前工作目录:~/projects/order-service/src/order/
加载顺序(仅三个固定路径,按顺序合并):
1. ~/.codex/AGENTS.md ← 用户全局
2. ~/projects/order-service/AGENTS.md ← git 仓库根目录
3. ~/projects/order-service/src/order/AGENTS.md ← 当前工作目录(与仓库根不同时)
不会加载 ~/projects/AGENTS.md(不在固定路径内,直接忽略)。
|
多仓库限制:Codex CLI 无法加载 ~/projects/ 层级的共享文件。跨项目共享内容只能放入 ~/.codex/AGENTS.md 用户全局文件,token 有限时需精简。
多仓库场景下的文件职责划分:
1
2
3
4
5
6
7
8
9
| ~/.codex/AGENTS.md → 必须承担所有跨项目内容
- 技术栈规范
- 服务目录
- 跨服务约定
(内容较多时注意 token 消耗)
~/projects/order-service/AGENTS.md → 本服务内容
- 本服务职责与接口
- 依赖的上游接口契约
|
OpenCode 遍历行为
1
2
3
4
5
6
7
8
9
10
11
| 当前工作目录:~/projects/order-service/src/order/
加载顺序:
1. ~/.config/opencode/AGENTS.md ← 用户全局
2. 从当前目录向上遍历至 git root,每层取一个文件
- ~/projects/order-service/src/order/AGENTS.md ← 当前目录
- ~/projects/order-service/src/AGENTS.md ← 若存在
- ~/projects/order-service/AGENTS.md ← git root,停止
3. opencode.json 中 instructions 字段引用的额外文件
不会加载 ~/projects/AGENTS.md(遍历止于 git root)。
|
多仓库限制:与 Codex CLI 类似,OpenCode 停在 git root,无法自动读取 ~/projects/ 层级的共享文件。但可通过 opencode.json 的 instructions 字段显式引入。
多仓库场景下推荐用 instructions 引入共享文件:
1
2
3
4
5
6
7
8
9
| ~/projects/
├── _shared/ ← 共享契约目录(非 git repo)
│ ├── conventions.md ← 技术栈、服务目录、跨服务约定
│ └── api-contracts/
│ ├── user-service.md
│ └── notify-service.md
└── order-service/
├── AGENTS.md ← 本服务职责与对外接口
└── opencode.json ← 通过 instructions 引入共享内容
|
1
2
3
4
5
6
7
8
9
| // ~/projects/order-service/opencode.json
{
"instructions": [
"./AGENTS.md",
"~/_shared/conventions.md",
"~/_shared/api-contracts/user-service.md",
"~/_shared/api-contracts/notify-service.md"
]
}
|
多文件合并策略
| 工具 | 合并方式 | 优先级规则 |
|---|
| Claude Code | ✅ 全部合并,所有层级的文件都加入上下文 | 越具体的层级(越靠近当前目录)优先级越高;冲突指令 Claude 可能随机选择一个 |
| Codex CLI | ✅ 全部合并,沿途所有文件拼接 | 越靠近当前目录的文件内容排列在后,隐式优先 |
| OpenCode | ⚠️ 每层级取一个文件,不跨文件合并;但可通过 instructions 字段显式引入多文件 | 越靠近当前目录优先级越高 |
OpenCode instructions 字段示例(显式多文件合并)
1
2
3
4
5
6
7
8
9
| // opencode.json
{
"instructions": [
"./AGENTS.md",
"./docs/coding-standards.md",
"packages/*/AGENTS.md",
"https://example.com/shared-rules.md"
]
}
|
权限与设置文件机制
配置文件层级
Claude Code — settings.json(4 层级,固定路径,不遍历目录)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 优先级从高到低:
① 系统托管(不可被覆盖)
macOS: /Library/Application Support/ClaudeCode/managed-settings.json
Linux: /etc/claude-code/managed-settings.json
Windows: C:\Program Files\ClaudeCode\managed-settings.json
HKLM\SOFTWARE\Policies\ClaudeCode(注册表)
② 命令行参数(临时会话级覆盖)
③ 本地项目(个人私有,git 忽略)
.claude/settings.local.json
④ 共享项目(团队共享,git 追踪)
.claude/settings.json
⑤ 用户全局(最低优先级)
~/.claude/settings.json
|
注意:settings.json 不走目录遍历,只从上述固定路径加载。这与 CLAUDE.md 的行为完全不同——即使 ~/projects/.claude/settings.json 这样的路径存在,也不会被加载。
与 CLAUDE.md 加载行为的核心差异:
1
2
| CLAUDE.md → 目录向上遍历,沿途所有文件全部加载(越过 git root 继续)
settings.json → 固定 4 个路径,不做任何目录遍历
|
多仓库场景下的配置策略:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| ~/projects/
├── CLAUDE.md ✅ 会被加载(目录遍历)
├── .claude/settings.json ❌ 不会被加载(不在固定路径)
│
├── order-service/ git repo ①
│ ├── CLAUDE.md ✅ 会被加载
│ └── .claude/
│ ├── settings.json ✅ 项目级权限(团队共享)
│ └── settings.local.json ✅ 本地个人权限(git 忽略)
│
└── notify-service/ git repo ②
├── CLAUDE.md ✅ 会被加载
└── .claude/
└── settings.json ✅ 项目级权限(团队共享)
|
跨多个项目共享权限配置,只能放入用户全局文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // ~/.claude/settings.json(对所有项目生效)
{
"permissions": {
"allow": [
"Bash(git *)",
"Bash(mvn *)",
"Bash(npm run *)"
],
"deny": [
"Bash(rm -rf *)",
"Read(./.env*)"
],
"ask": [
"Bash(git push *)",
"Bash(kubectl *)"
]
}
}
|
1
2
3
4
5
6
7
8
9
| // ~/projects/order-service/.claude/settings.json(仅 order-service 生效)
{
"permissions": {
"allow": [
"Bash(java *)",
"Bash(mvn spring-boot:run)"
]
}
}
|
1
2
3
4
5
6
7
8
9
| // ~/projects/order-service/.claude/settings.local.json(个人本地,不提交 git)
{
"permissions": {
"allow": [
"Bash(ssh *)",
"Read(~/.ssh/config)"
]
}
}
|
合并结果:三个文件的 permissions 数组会跨层级合并去重,最终生效的规则是三者的并集。deny 规则任意层级设置后,低层级无法解除。
Codex CLI — 无配置文件
1
2
3
4
5
6
7
8
9
| Codex CLI 没有权限配置文件,权限控制完全依赖启动参数:
--approval-mode suggest 所有操作需用户确认(默认)
--approval-mode auto-edit 文件编辑自动批准,shell 命令需确认
--approval-mode full-auto 全自动执行(依赖 OS 沙箱隔离)
沙箱机制:
macOS:Seatbelt(系统调用级别隔离)
Linux:Docker 容器隔离
|
OpenCode — opencode.json(2 层级 + 远程配置,支持目录遍历)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 加载顺序(优先级从低到高):
① 远程组织配置(最低)
.well-known/opencode(通过 HTTP 拉取,组织级默认值)
② 用户全局配置
~/.config/opencode/opencode.json
③ 环境变量指定路径
$OPENCODE_CONFIG 指向的文件
④ 项目配置(从当前目录向上遍历查找)
./opencode.json
⑤ .opencode 目录(agents/, commands/, plugins/ 等子目录)
⑥ 内联配置(最高)
$OPENCODE_CONFIG_CONTENT 环境变量内容
|
OpenCode 特点:opencode.json 支持目录向上遍历查找(不同于 Claude Code 的固定路径),且多层级配置深度合并而非替换。
权限规则语法
Claude Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // .claude/settings.json
{
"permissions": {
"allow": [
"Bash(npm run *)", // Bash 命令,支持通配符
"Bash(git commit *)",
"Read(./src/**)", // 文件读取,gitignore 风格
"Read(~/.zshrc)", // 波浪号路径
"Edit(/src/**/*.java)", // 文件编辑
"WebFetch(domain:github.com)", // 域名匹配
"Glob(**/*.ts)", // 文件搜索
"Grep(./src/**)", // 内容搜索
"mcp__server__toolname" // MCP 工具
],
"deny": [
"Bash(rm -rf *)",
"Bash(curl *)",
"Read(./.env*)", // 拒绝读取环境变量文件
"Read(./secrets/**)"
],
"ask": [
"Bash(git push *)", // 敏感操作需二次确认
"Bash(docker *)"
]
}
}
|
匹配规则:deny → ask → allow,首个匹配生效,后续规则忽略。
支持的工具名:
| 工具 | 说明 | 模式示例 |
|---|
Bash(pattern) | Shell 命令执行 | Bash(npm run *) |
Read(pattern) | 文件读取 | Read(./src/**) |
Edit(pattern) | 文件编辑 | Edit(**/*.java) |
Write(pattern) | 文件写入 | Write(./tmp/**) |
Glob(pattern) | 文件名搜索 | Glob(**/*.ts) |
Grep(pattern) | 内容搜索 | Grep(./src/**) |
WebFetch(domain:x) | HTTP 请求 | WebFetch(domain:api.github.com) |
Agent(name) | 子 Agent 调用 | Agent(general-purpose) |
mcp__srv__tool | MCP 工具 | mcp__filesystem__read |
OpenCode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| // opencode.json
{
"permission": {
// 工具级别全局设置
"read": "allow",
"edit": "ask",
"glob": "allow",
"grep": "allow",
"list": "allow",
"webfetch": "ask",
"task": "allow",
"lsp": "allow",
// bash 细粒度规则(最后匹配生效)
"bash": {
"*": "ask", // 默认:所有命令需确认
"git status": "allow", // 精确匹配
"git *": "allow", // 通配符
"npm run *": "allow",
"rm *": "deny", // 拒绝危险命令
"rm -rf *": "deny"
},
// 全局快捷设置(覆盖所有工具)
// "permission": "allow" // 全部放行
// "permission": "ask" // 全部询问
// "permission": "deny" // 全部拒绝
}
}
|
匹配规则:最后匹配生效(Last Match Wins),与 Claude Code 相反。
支持的工具名:
| 工具 | 说明 | 默认值 |
|---|
read | 文件读取 | allow |
edit | 文件编辑 | allow |
glob | 文件搜索 | allow |
grep | 内容搜索 | allow |
list | 目录列表 | allow |
bash | Shell 命令 | ask |
webfetch | HTTP 请求 | allow |
task | 任务执行 | allow |
lsp | 语言服务器 | allow |
skill | 技能调用 | allow |
external_directory | 外部目录访问 | ask |
doom_loop | 循环执行 | ask |
特殊默认行为:即使 read 为 allow,.env 文件默认仍为 deny,需显式解除。
Codex CLI
1
2
3
4
5
6
7
| # 无配置文件,仅启动参数
codex --approval-mode suggest # 全部询问(默认)
codex --approval-mode auto-edit # 文件编辑自动放行
codex --approval-mode full-auto # 沙箱内全自动
# 沙箱说明:
# full-auto 模式下网络访问被完全禁止,文件系统访问受 OS 限制
|
合并策略
Claude Code settings.json 合并规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 数组类字段(跨层级合并,去重):
permissions.allow
permissions.deny
permissions.ask
sandbox.filesystem.allowWrite / denyWrite / denyRead
hooks(各事件的 hook 列表)
环境变量数组
示例:
managed-settings.json: allow: ["Bash(//opt/company-tools/*)"]
~/.claude/settings.json: allow: ["Bash(npm run *)"]
.claude/settings.json: allow: ["Bash(git *)"]
最终生效: allow: ["Bash(//opt/company-tools/*)", "Bash(npm run *)", "Bash(git *)"]
标量字段(高优先级完全覆盖低优先级):
model、theme 等配置项
deny 的特殊地位:
任何层级的 deny 规则均生效,低层级无法解除 managed 的 deny
|
OpenCode opencode.json 合并规则
OpenCode 使用深度合并(Deep Merge),同时注意最后匹配生效(Last Match Wins)的规则逻辑,这两点组合起来决定了最终权限行为。
规则一:多层级配置文件深度合并
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| ~/.config/opencode/opencode.json(用户全局):
{
"permission": {
"read": "allow",
"edit": "allow",
"bash": {
"*": "ask", // 默认所有 bash 命令需确认
"git *": "allow" // git 命令放行
}
}
}
./opencode.json(项目级):
{
"permission": {
"webfetch": "deny", // 项目级禁止 HTTP 请求
"bash": {
"npm run *": "allow" // 项目级追加:npm 命令放行
}
}
}
合并结果:
{
"permission": {
"read": "allow", // 来自全局
"edit": "allow", // 来自全局
"webfetch": "deny", // 来自项目(新增字段)
"bash": {
"*": "ask", // 来自全局
"git *": "allow", // 来自全局
"npm run *": "allow" // 来自项目(追加)
}
}
}
|
规则二:bash 规则内部按"最后匹配"生效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 合并后的 bash 规则:
"*": "ask" ← 通配兜底
"git *": "allow" ← 覆盖通配,git 命令放行
"npm run *": "allow" ← 覆盖通配,npm 命令放行
执行 "git commit -m fix" 时:
匹配 "*" → ask
匹配 "git *" → allow ← 最后匹配,最终生效 ✅
执行 "curl http://..." 时:
匹配 "*" → ask ← 只有这一条匹配,最终生效 ✅
执行 "rm -rf /tmp" 时:
匹配 "*" → ask ← 最终生效 ✅(没有更具体的规则覆盖)
|
规则三:Agent 级别的 permission 覆盖全局(不合并)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| opencode.json:
{
"permission": {
"bash": { "*": "ask", "git *": "allow" } // 全局权限
},
"agent": {
"reviewer": {
"permission": {
"read": "allow",
"bash": "deny", // ← 直接覆盖,不与全局 bash 规则合并
"edit": "deny"
}
}
}
}
reviewer agent 最终权限:
read: "allow" ← 来自 agent 定义
bash: "deny" ← 来自 agent 定义(全局的 git * allow 被完全忽略)
edit: "deny" ← 来自 agent 定义
默认 agent 最终权限:
bash: { "*": "ask", "git *": "allow" } ← 使用全局规则
|
与 Claude Code 的关键区别:Claude Code 的 deny 一旦设置任意层级均不可逆;OpenCode 的 agent 级别可以完全覆盖全局规则,包括把全局的 deny 改回 allow。
详细配置参考
Claude Code
完整 settings.json 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| // .claude/settings.json(项目级,团队共享)
{
"model": "claude-opus-4-6",
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(mvn *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Read(./**)",
"Edit(./src/**)",
"Glob(**/*.java)",
"Grep(./src/**)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push *)",
"Bash(curl *)",
"Read(./.env*)",
"Read(./secrets/**)",
"Read(./credentials/**)"
],
"ask": [
"Bash(git push *)",
"Bash(docker *)",
"Bash(kubectl *)",
"WebFetch(*)"
]
},
"env": {
"JAVA_HOME": "/usr/lib/jvm/java-8-openjdk",
"MAVEN_OPTS": "-Xmx2g"
}
}
|
1
2
3
4
5
6
7
8
9
| // .claude/settings.local.json(本地私有,git 忽略)
{
"permissions": {
"allow": [
"Bash(ssh *)",
"Read(~/.ssh/config)"
]
}
}
|
CLAUDE.md 加载顺序完整示意
1
2
3
4
5
6
7
8
9
10
| 启动时加载(全量,按优先级从低到高):
/etc/claude-code/CLAUDE.md → 系统策略
~/.claude/CLAUDE.md → 用户全局
~/projects/CLAUDE.md → 中间路径(如存在)
~/projects/my-app/CLAUDE.md → 项目根目录
~/projects/my-app/src/api/CLAUDE.md → 当前工作目录
按需加载(访问时触发):
~/projects/my-app/src/auth/CLAUDE.md → 当 Claude 读取 auth/ 中文件时加载
~/projects/my-app/test/CLAUDE.md → 当 Claude 读取 test/ 中文件时加载
|
CLAUDE.md Import 语法
1
2
3
4
5
| <!-- CLAUDE.md 中引用其他文件 -->
@./docs/coding-standards.md
@./docs/api-guidelines.md
@~/.claude/personal-preferences.md
@/absolute/path/to/shared-rules.md
|
Codex CLI
启动参数参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 基础使用
codex "帮我重构这个函数"
codex --model gpt-4o "解释这段代码"
# 权限模式
codex --approval-mode suggest # 默认:所有操作需确认
codex --approval-mode auto-edit # 文件编辑自动批准
codex --approval-mode full-auto # 全自动(需沙箱支持)
# 沙箱控制
codex --no-sandbox # 禁用沙箱(不推荐)
# 上下文控制
codex --context ./README.md # 指定额外上下文文件
codex --cwd ./src # 指定工作目录
|
AGENTS.md 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Project Rules
## Tech Stack
- Node.js 18+, TypeScript 5.x
- Express.js for REST APIs
- Prisma ORM with PostgreSQL
## Coding Standards
- Use async/await, avoid callbacks
- All functions must have TypeScript types
- Test files: *.test.ts
## Git Conventions
- Commit format: feat/fix/docs/refactor: description
- Never commit directly to main
|
OpenCode
完整 opencode.json 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| // opencode.json(项目级)
{
// 默认模型
"model": "anthropic/claude-sonnet-4-6",
"small_model": "anthropic/claude-haiku-4-5",
// 权限配置
"permission": {
"read": "allow",
"edit": "allow",
"glob": "allow",
"grep": "allow",
"list": "allow",
"webfetch": "ask",
"bash": {
"*": "ask",
"git *": "allow",
"npm run *": "allow",
"yarn *": "allow",
"cat *": "allow",
"ls *": "allow",
"find *": "allow",
"rm -rf *": "deny",
"curl *": "deny",
"wget *": "deny"
}
},
// 额外指令文件(支持 glob 和 URL)
"instructions": [
"./AGENTS.md",
"./docs/coding-standards.md",
"packages/*/AGENTS.md"
],
// 自定义 Agent
"agent": {
"reviewer": {
"model": "anthropic/claude-opus-4-6",
"prompt": "You are a strict code reviewer focused on security and performance.",
"permission": {
"read": "allow",
"edit": "deny",
"bash": "deny"
}
}
},
// MCP 服务器
"mcp": {
"filesystem": {
"type": "local",
"command": ["mcp-server-filesystem", "./"]
}
},
// 自动更新
"autoupdate": true,
// 文件快照(用于变更追踪)
"snapshot": true
}
|
Agent 权限继承示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| {
// 全局权限:bash 默认询问
"permission": {
"bash": { "*": "ask" }
},
"agent": {
// build agent:继承全局 + 扩展允许
"build": {
"permission": {
"bash": {
"*": "ask", // 继承全局
"npm *": "allow", // agent 扩展
"make *": "allow"
}
}
},
// plan agent:只读,覆盖全局
"plan": {
"permission": {
"read": "allow",
"edit": "deny",
"bash": "deny"
}
}
}
}
|
横向对比总表
指令文件对比
| 特性 | Claude Code | Codex CLI | OpenCode |
|---|
| 文件名 | CLAUDE.md | AGENTS.md | AGENTS.md(优先)
CLAUDE.md(兼容回退) |
| 用户全局路径 | ~/.claude/CLAUDE.md | ~/.codex/AGENTS.md | ~/.config/opencode/AGENTS.md |
| 项目路径 | 遍历中找到的所有层级 | git 仓库根目录 AGENTS.md | ./AGENTS.md |
| 向上目录遍历 | ✅ 全部加载(越过 git root 继续向上,实测验证) | ❌ 三个固定路径 | ✅ 每层取一个(停在 git root) |
| 子目录懒加载 | ✅ 按需触发 | ❌ | ❌ |
| 多文件全量合并 | ✅ | ✅(三个固定文件合并) | ⚠️ 需借助 instructions 字段 |
| Import 语法 | ✅ @path | ❌ | ❌(用 instructions 代替) |
| 系统级策略文件 | ✅ | ❌ | ⚠️ 远程 .well-known/opencode |
| 兼容对方格式 | ❌ | ❌ | ✅ 兼容 CLAUDE.md |
权限设置对比
| 特性 | Claude Code | Codex CLI | OpenCode |
|---|
| 权限配置文件 | settings.json | 无 | opencode.json |
| 层级数量 | 4层(managed/user/project/local) | 无 | 2层 + 远程(remote/global/project) |
| 目录向上遍历 | ❌ 固定路径 | ❌ | ✅ 向上遍历查找 |
| 企业管控层 | ✅ managed 不可覆盖 | ❌ | ⚠️ 远程配置(需 HTTPS) |
| 细粒度 allow/deny/ask | ✅ | ❌ | ✅ |
| 匹配规则逻辑 | 首个匹配生效(deny→ask→allow) | 无 | 最后匹配生效 |
| 数组跨层合并 | ✅ permissions 数组跨层合并 | ❌ | ✅ 深度合并 |
| Agent 级别权限 | ❌ | ❌ | ✅ 可覆盖全局 |
| 沙箱机制 | 规则白名单 | macOS Seatbelt / Docker | 规则白名单 |
| .env 文件保护 | ⚠️ 需手动 deny | ❌ | ✅ 默认 deny |
规则匹配逻辑对比
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| Claude Code(首个匹配):
规则顺序:deny → ask → allow
第一个匹配的规则立即生效,后续规则被忽略
适合:明确的白名单/黑名单,规则顺序无歧义
示例:
deny: ["Bash(rm *)"]
allow: ["Bash(rm -rf /tmp/*)"] ← 永远不会生效(已被 deny 首先匹配)
OpenCode(最后匹配):
同一工具下,越靠后的规则优先级越高
适合:从宽泛默认逐步精细化覆盖
示例:
"bash": {
"*": "ask", // 默认询问
"rm *": "deny", // 拒绝 rm
"rm /tmp/*": "allow" // 最后匹配:/tmp 下 rm 允许 ✅
}
|
选型建议
按场景推荐
| 场景 | 推荐工具 | 理由 |
|---|
| 企业团队,需严格权限管控 | Claude Code | managed 层不可覆盖,4层细粒度管控 |
| 个人开发,快速上手 | Codex CLI | 无配置负担,沙箱保底安全 |
| 开源项目,多模型切换 | OpenCode | 多 Provider 支持,配置灵活,TUI 体验好 |
| 已有 CLAUDE.md 迁移 | OpenCode | 内置 CLAUDE.md 兼容回退 |
| 需要 Agent 分角色权限 | OpenCode | 原生支持多 Agent 差异化权限 |
成熟度评估
1
2
3
4
5
6
7
8
9
| 权限体系成熟度:
Claude Code ████████████ 最完整,企业级
OpenCode ████████░░░░ 快速迭代,功能完善
Codex CLI ████░░░░░░░░ 简单,靠 OS 沙箱兜底
指令文件机制:
Claude Code ████████████ 最完整,懒加载 + Import
Codex CLI ████████░░░░ 简单直接,全量合并
OpenCode ███████░░░░░ 灵活,兼容性好,合并需显式配置
|
总结
如果你所在的是团队协作环境,并且很在意规则继承、权限边界和企业级治理,Claude Code 的整体体系更成熟。
如果你想以最低学习成本进入 AI 编程 CLI,Codex CLI 更像“先跑起来再说”的选择,简单但边界也更粗。
如果你既在意多模型能力,又愿意自己维护规则和权限,OpenCode 的灵活性会更有吸引力。
总览文适合用来完成第一轮选型,真正准备落地时,建议再回到指令文件和权限两篇专题文,把细节啃透。
参考资料: