claude-coder 1.0.6 → 1.0.8
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/docs/ARCHITECTURE.md +6 -4
- package/docs/README.en.md +1 -1
- package/package.json +1 -1
- package/src/config.js +6 -1
- package/src/indicator.js +18 -7
- package/src/prompts.js +22 -0
- package/src/runner.js +1 -0
- package/src/session.js +5 -1
- package/templates/CLAUDE.md +3 -2
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -183,11 +183,11 @@ flowchart TB
|
|
|
183
183
|
|
|
184
184
|
| Session 类型 | systemPrompt | user prompt | 触发条件 |
|
|
185
185
|
|---|---|---|---|
|
|
186
|
-
| **编码** | CLAUDE.md | `buildCodingPrompt()` +
|
|
186
|
+
| **编码** | CLAUDE.md | `buildCodingPrompt()` + 10 个条件 hint | 主循环每次迭代 |
|
|
187
187
|
| **扫描** | CLAUDE.md + SCAN_PROTOCOL.md | `buildScanPrompt()` + 任务分解指导 + profile 质量要求 | 首次运行 |
|
|
188
188
|
| **追加** | CLAUDE.md | `buildAddPrompt()` + 任务分解指导 | `claude-coder add` |
|
|
189
189
|
|
|
190
|
-
### 编码 Session 的
|
|
190
|
+
### 编码 Session 的 10 个条件 Hint
|
|
191
191
|
|
|
192
192
|
| # | Hint | 触发条件 | 影响 |
|
|
193
193
|
|---|---|---|---|
|
|
@@ -197,8 +197,10 @@ flowchart TB
|
|
|
197
197
|
| 4 | `docsHint` | profile.existing_docs 非空或 profile 有缺陷 | Step 4:读文档后再编码;profile 缺陷时提示 Agent 在 Step 6 补全 services/docs |
|
|
198
198
|
| 5 | `envHint` | 连续成功且 session>1 | Step 2:跳过 init |
|
|
199
199
|
| 6 | `retryContext` | 上次校验失败 | 全局:避免同样错误 |
|
|
200
|
-
| 7 | `taskHint` | tasks.json 存在且有待办任务 | Step 1:跳过读取 tasks.json,harness 已注入当前任务上下文 |
|
|
200
|
+
| 7 | `taskHint` | tasks.json 存在且有待办任务 | Step 1:跳过读取 tasks.json,harness 已注入当前任务上下文 + .claude-coder/ 路径提示 |
|
|
201
201
|
| 8 | `memoryHint` | session_result.json 存在且有历史记录 | Step 1:跳过读取 session_result.json,harness 已注入上次会话摘要 |
|
|
202
|
+
| 9 | `serviceHint` | 始终注入 | Step 6:单次模式停止服务,连续模式保持服务运行 |
|
|
203
|
+
| 10 | `toolGuidance` | 始终注入 | 全局:工具使用规范(Grep/Glob/Read/LS/MultiEdit/Task 替代 bash 命令),非 Claude 模型必需 |
|
|
202
204
|
|
|
203
205
|
---
|
|
204
206
|
|
|
@@ -266,7 +268,7 @@ sequenceDiagram
|
|
|
266
268
|
| 维度 | 评分 | 说明 |
|
|
267
269
|
|------|------|------|
|
|
268
270
|
| **CLAUDE.md 系统提示** | 8/10 | U 型注意力设计;铁律清晰;状态机和 6 步流程是核心竞争力 |
|
|
269
|
-
| **动态 prompt** |
|
|
271
|
+
| **动态 prompt** | 9/10 | 10 个条件 hint 精准注入,含 task/memory 上下文注入 + 服务管理 + 工具使用指导,减少 Agent 冗余操作 |
|
|
270
272
|
| **SCAN_PROTOCOL.md** | 8.5/10 | 新旧项目分支完整,profile 格式全面 |
|
|
271
273
|
| **tests.json 设计** | 7.5/10 | 精简字段,核心目的(防反复测试)明确 |
|
|
272
274
|
| **注入时机** | 9/10 | 静态规则 vs 动态上下文分离干净 |
|
package/docs/README.en.md
CHANGED
|
@@ -50,9 +50,9 @@ Each session, the agent autonomously follows 6 steps: restore context → env ch
|
|
|
50
50
|
|---------|-------------|
|
|
51
51
|
| `claude-coder setup` | Interactive model configuration |
|
|
52
52
|
| `claude-coder run [requirement]` | Auto-coding loop |
|
|
53
|
+
| `claude-coder run --max 1` | Single session (replaces old view mode) |
|
|
53
54
|
| `claude-coder run --dry-run` | Preview mode |
|
|
54
55
|
| `claude-coder init` | Initialize project environment |
|
|
55
|
-
| `claude-coder view [requirement]` | Observation mode (single session) |
|
|
56
56
|
| `claude-coder add "instruction"` | Append tasks |
|
|
57
57
|
| `claude-coder validate` | Manually validate last session |
|
|
58
58
|
| `claude-coder status` | View progress and costs |
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -148,7 +148,12 @@ function buildEnvVars(config) {
|
|
|
148
148
|
// --------------- Allowed tools ---------------
|
|
149
149
|
|
|
150
150
|
function getAllowedTools(config) {
|
|
151
|
-
const tools = [
|
|
151
|
+
const tools = [
|
|
152
|
+
'Read', 'Edit', 'MultiEdit', 'Write',
|
|
153
|
+
'Bash', 'Glob', 'Grep', 'LS',
|
|
154
|
+
'Task',
|
|
155
|
+
'WebSearch', 'WebFetch',
|
|
156
|
+
];
|
|
152
157
|
if (config.mcpPlaywright) tools.push('mcp__playwright__*');
|
|
153
158
|
return tools;
|
|
154
159
|
}
|
package/src/indicator.js
CHANGED
|
@@ -58,24 +58,29 @@ class Indicator {
|
|
|
58
58
|
try { fs.writeFileSync(paths().stepFile, this.step, 'utf8'); } catch { /* ignore */ }
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
getStatusLine() {
|
|
62
62
|
const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
|
|
63
63
|
const mm = String(Math.floor(elapsed / 60)).padStart(2, '0');
|
|
64
64
|
const ss = String(elapsed % 60).padStart(2, '0');
|
|
65
65
|
const spinner = SPINNERS[this.spinnerIndex % SPINNERS.length];
|
|
66
|
-
this.spinnerIndex++;
|
|
67
66
|
|
|
68
67
|
const phaseLabel = this.phase === 'thinking'
|
|
69
68
|
? `${COLOR.yellow}思考中${COLOR.reset}`
|
|
70
69
|
: `${COLOR.green}编码中${COLOR.reset}`;
|
|
71
70
|
|
|
72
|
-
let line =
|
|
71
|
+
let line = `${spinner} [Session ${this.sessionNum}] ${phaseLabel} ${mm}:${ss}`;
|
|
73
72
|
if (this.step) line += ` | ${this.step}`;
|
|
73
|
+
return line;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
_render() {
|
|
77
|
+
this.spinnerIndex++;
|
|
78
|
+
const line = this.getStatusLine();
|
|
74
79
|
|
|
75
80
|
const maxWidth = process.stderr.columns || 80;
|
|
76
|
-
|
|
81
|
+
const truncated = line.length > maxWidth + 20 ? line.slice(0, maxWidth + 20) : line;
|
|
77
82
|
|
|
78
|
-
process.stderr.write(`\r\x1b[K${
|
|
83
|
+
process.stderr.write(`\r\x1b[K${truncated}`);
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
|
|
@@ -83,7 +88,7 @@ class Indicator {
|
|
|
83
88
|
function inferPhaseStep(indicator, toolName, toolInput) {
|
|
84
89
|
const name = (toolName || '').toLowerCase();
|
|
85
90
|
|
|
86
|
-
if (name === 'write' || name === 'edit' || name === 'str_replace_editor' || name === 'strreplace') {
|
|
91
|
+
if (name === 'write' || name === 'edit' || name === 'multiedit' || name === 'str_replace_editor' || name === 'strreplace') {
|
|
87
92
|
indicator.updatePhase('coding');
|
|
88
93
|
} else if (name === 'bash' || name === 'shell') {
|
|
89
94
|
const cmd = typeof toolInput === 'object' ? (toolInput.command || '') : String(toolInput || '');
|
|
@@ -97,9 +102,15 @@ function inferPhaseStep(indicator, toolName, toolInput) {
|
|
|
97
102
|
} else {
|
|
98
103
|
indicator.updatePhase('coding');
|
|
99
104
|
}
|
|
100
|
-
} else if (name === 'read' || name === 'glob' || name === 'grep') {
|
|
105
|
+
} else if (name === 'read' || name === 'glob' || name === 'grep' || name === 'ls') {
|
|
101
106
|
indicator.updatePhase('thinking');
|
|
102
107
|
indicator.updateStep('读取文件');
|
|
108
|
+
} else if (name === 'task') {
|
|
109
|
+
indicator.updatePhase('thinking');
|
|
110
|
+
indicator.updateStep('子 Agent 搜索');
|
|
111
|
+
} else if (name === 'websearch' || name === 'webfetch') {
|
|
112
|
+
indicator.updatePhase('thinking');
|
|
113
|
+
indicator.updateStep('查阅文档');
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
const summary = typeof toolInput === 'object'
|
package/src/prompts.js
CHANGED
|
@@ -108,6 +108,7 @@ function buildCodingPrompt(sessionNum, opts = {}) {
|
|
|
108
108
|
taskHint = `任务上下文: ${next.id} "${next.description}" (${next.status}), ` +
|
|
109
109
|
`category=${next.category}, steps=${next.steps.length}步。` +
|
|
110
110
|
`进度: ${stats.done}/${stats.total} done, ${stats.failed} failed。` +
|
|
111
|
+
`运行时目录: .claude-coder/(隐藏目录,ls -a 可见,所有 tasks.json/profile 等文件均在此目录下)。` +
|
|
111
112
|
`第一步无需读取 tasks.json(已注入),直接确认任务后进入 Step 2。`;
|
|
112
113
|
}
|
|
113
114
|
}
|
|
@@ -126,6 +127,25 @@ function buildCodingPrompt(sessionNum, opts = {}) {
|
|
|
126
127
|
} catch { /* ignore */ }
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
// Hint 9: Service management (continuous vs single-shot mode)
|
|
131
|
+
const maxSessions = opts.maxSessions || 50;
|
|
132
|
+
const serviceHint = maxSessions === 1
|
|
133
|
+
? '单次模式:收尾时停止所有后台服务。'
|
|
134
|
+
: '连续模式:收尾时不要停止后台服务,保持服务运行以便下个 session 继续使用。';
|
|
135
|
+
|
|
136
|
+
// Hint 10: Tool usage guidance (critical for non-Claude models)
|
|
137
|
+
const toolGuidance = [
|
|
138
|
+
'可用工具与使用规范(严格遵守):',
|
|
139
|
+
'- 搜索文件名: Glob(如 **/*.ts),禁止 bash find',
|
|
140
|
+
'- 搜索文件内容: Grep(正则,基于 ripgrep),禁止 bash grep',
|
|
141
|
+
'- 读文件: Read(支持批量多文件同时读取),禁止 bash cat/head/tail',
|
|
142
|
+
'- 列目录: LS,禁止 bash ls',
|
|
143
|
+
'- 编辑文件: 同一文件多处修改用 MultiEdit(一次原子调用),单处用 Edit',
|
|
144
|
+
'- 复杂搜索: Task(启动子 Agent 并行搜索,不消耗主 context),适合开放式探索',
|
|
145
|
+
'- 查文档/API: WebSearch + WebFetch',
|
|
146
|
+
'- 效率: 多个 Read/Glob/Grep 尽量合并为一次批量调用,减少工具轮次',
|
|
147
|
+
].join('\n');
|
|
148
|
+
|
|
129
149
|
return [
|
|
130
150
|
`Session ${sessionNum}。执行 6 步流程。`,
|
|
131
151
|
'效率要求:先规划后编码,完成全部编码后再统一测试,禁止编码-测试反复跳转。后端任务用 curl 验证,不启动浏览器。',
|
|
@@ -136,6 +156,8 @@ function buildCodingPrompt(sessionNum, opts = {}) {
|
|
|
136
156
|
envHint,
|
|
137
157
|
taskHint,
|
|
138
158
|
memoryHint,
|
|
159
|
+
serviceHint,
|
|
160
|
+
toolGuidance,
|
|
139
161
|
`完成后写入 session_result.json。${retryContext}`,
|
|
140
162
|
].filter(Boolean).join('\n');
|
|
141
163
|
}
|
package/src/runner.js
CHANGED
package/src/session.js
CHANGED
|
@@ -66,7 +66,11 @@ function logMessage(message, logStream, indicator) {
|
|
|
66
66
|
if (message.type === 'assistant' && message.message?.content) {
|
|
67
67
|
for (const block of message.message.content) {
|
|
68
68
|
if (block.type === 'text' && block.text) {
|
|
69
|
-
if (indicator)
|
|
69
|
+
if (indicator) {
|
|
70
|
+
const statusLine = indicator.getStatusLine();
|
|
71
|
+
process.stderr.write('\r\x1b[K');
|
|
72
|
+
if (statusLine) process.stderr.write(statusLine + '\n');
|
|
73
|
+
}
|
|
70
74
|
process.stdout.write(block.text);
|
|
71
75
|
if (logStream) logStream.write(block.text);
|
|
72
76
|
}
|
package/templates/CLAUDE.md
CHANGED
|
@@ -210,7 +210,8 @@ pending ──→ in_progress ──→ testing ──→ done
|
|
|
210
210
|
- 确认方案完整后,**一次性**完成所有编码
|
|
211
211
|
- **禁止边写边试**:完成全部编码后再进入第五步统一测试
|
|
212
212
|
4. **高效执行**:禁止碎片化操作(读一个文件、思考、再读一个),批量读取、批量修改、减少工具调用轮次
|
|
213
|
-
5.
|
|
213
|
+
5. **工具优先**:用 Grep/Glob 替代 bash grep/find,用 Read/LS 替代 bash cat/ls,同一文件多处修改用 MultiEdit
|
|
214
|
+
6. **跳过已完成的步骤**:文件已存在且内容正确的步骤直接跳过
|
|
214
215
|
|
|
215
216
|
### 第五步:测试验证
|
|
216
217
|
|
|
@@ -241,7 +242,7 @@ pending ──→ in_progress ──→ testing ──→ done
|
|
|
241
242
|
|
|
242
243
|
### 第六步:收尾(每次会话必须执行)
|
|
243
244
|
|
|
244
|
-
1.
|
|
245
|
+
1. **后台服务管理**:根据 prompt 提示决定——单次模式(`--max 1`)时停止所有后台服务(`lsof -ti :端口 | xargs kill`);连续模式时保持服务运行,下个 session 继续使用
|
|
245
246
|
2. **按需更新文档和 profile**:
|
|
246
247
|
- **README / 用户文档**:仅当对外行为变化(新增功能、API 变更、使用方式变化)时更新
|
|
247
248
|
- **架构 / API 文档**:如果本次新增了模块、改变了模块职责或新增了 API 端点,更新 `existing_docs` 中对应的架构或 API 文档。同时更新 `project_profile.json` 的 `existing_docs` 列表(若新增了文档文件)
|