clawt 3.9.10 → 3.9.11
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/dist/index.js +3 -9
- package/docs/post-create-hook.md +1 -5
- package/docs/run.md +1 -2
- package/package.json +1 -1
- package/src/constants/config.ts +0 -4
- package/src/constants/index.ts +1 -1
- package/src/utils/claude.ts +3 -7
- package/src/utils/task-executor.ts +1 -5
- package/tests/unit/utils/claude.test.ts +6 -9
package/dist/index.js
CHANGED
|
@@ -704,7 +704,6 @@ var VALID_TERMINAL_APPS = ["auto", "iterm2", "terminal", "cmux"];
|
|
|
704
704
|
var ITERM2_APP_PATH = "/Applications/iTerm.app";
|
|
705
705
|
|
|
706
706
|
// src/constants/config.ts
|
|
707
|
-
var APPEND_SYSTEM_PROMPT = "Currently, you are in the git worktree directory.";
|
|
708
707
|
var CLAUDE_CODE_ENTRYPOINT_VALUE = "cli";
|
|
709
708
|
var CONFIG_DEFINITIONS = {
|
|
710
709
|
autoDeleteBranch: {
|
|
@@ -2300,9 +2299,7 @@ function launchInteractiveClaude(worktree, options = {}) {
|
|
|
2300
2299
|
const parts = commandStr.split(/\s+/).filter(Boolean);
|
|
2301
2300
|
const cmd = parts[0];
|
|
2302
2301
|
const args = [
|
|
2303
|
-
...parts.slice(1)
|
|
2304
|
-
"--append-system-prompt",
|
|
2305
|
-
APPEND_SYSTEM_PROMPT
|
|
2302
|
+
...parts.slice(1)
|
|
2306
2303
|
];
|
|
2307
2304
|
const hasPreviousSession = options.autoContinue === true && hasClaudeSessionHistory(worktree.path);
|
|
2308
2305
|
if (hasPreviousSession) {
|
|
@@ -2332,11 +2329,9 @@ function escapeShellSingleQuote(str) {
|
|
|
2332
2329
|
}
|
|
2333
2330
|
function buildClaudeCommand(worktree, hasPreviousSession) {
|
|
2334
2331
|
const commandStr = resolveClaudeCodeCommand();
|
|
2335
|
-
const systemPrompt = APPEND_SYSTEM_PROMPT;
|
|
2336
2332
|
const escapedPath = escapeShellSingleQuote(worktree.path);
|
|
2337
|
-
const escapedPrompt = escapeShellSingleQuote(systemPrompt);
|
|
2338
2333
|
const continueFlag = hasPreviousSession ? " --continue" : "";
|
|
2339
|
-
return `cd '${escapedPath}' && ${commandStr}
|
|
2334
|
+
return `cd '${escapedPath}' && ${commandStr}${continueFlag}`;
|
|
2340
2335
|
}
|
|
2341
2336
|
function launchInteractiveClaudeInNewTerminal(worktree, hasPreviousSession) {
|
|
2342
2337
|
const command = buildClaudeCommand(worktree, hasPreviousSession);
|
|
@@ -3112,8 +3107,7 @@ function parseStreamEvent(event) {
|
|
|
3112
3107
|
|
|
3113
3108
|
// src/utils/task-executor.ts
|
|
3114
3109
|
function executeClaudeTask(worktree, task, onActivity, continueSession) {
|
|
3115
|
-
const
|
|
3116
|
-
const args = ["-p", task, "--output-format", "stream-json", "--verbose", "--permission-mode", "bypassPermissions", "--append-system-prompt", systemPrompt];
|
|
3110
|
+
const args = ["-p", task, "--output-format", "stream-json", "--verbose", "--permission-mode", "bypassPermissions"];
|
|
3117
3111
|
if (continueSession) {
|
|
3118
3112
|
args.push("--continue");
|
|
3119
3113
|
}
|
package/docs/post-create-hook.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
postCreate hook 是在 worktree 创建完成后自动执行的钩子命令,可用于执行任意初始化操作(如安装依赖、生成配置文件、编译资源等)。`create` 和 `run` 命令在创建 worktree 之后,会尝试解析并执行 postCreate hook。
|
|
6
6
|
|
|
7
|
-
hook 以 **fire-and-forget** 模式后台异步并行执行,不阻塞主流程(不 await)。执行结果仅写入日志,不影响后续 Claude Code
|
|
7
|
+
hook 以 **fire-and-forget** 模式后台异步并行执行,不阻塞主流程(不 await)。执行结果仅写入日志,不影响后续 Claude Code 的启动。
|
|
8
8
|
|
|
9
9
|
#### 配置方式
|
|
10
10
|
|
|
@@ -100,10 +100,6 @@ clawt run -b feat --no-post-create
|
|
|
100
100
|
- **结果汇总**:后台执行完毕后通过 `.then()` 回调写入日志汇总(成功数 + 失败数)
|
|
101
101
|
- **返回值**:`runPostCreateHooks()` 返回 `void`——以 fire-and-forget 模式后台执行,不等待结果
|
|
102
102
|
|
|
103
|
-
#### 系统提示
|
|
104
|
-
|
|
105
|
-
Claude Code 启动时统一使用 `APPEND_SYSTEM_PROMPT` 常量(定义在 `src/constants/config.ts`)作为 `--append-system-prompt` 参数值,内容为通用的 worktree 目录提示,不因 hook 执行结果而变化。
|
|
106
|
-
|
|
107
103
|
#### 相关类型定义
|
|
108
104
|
|
|
109
105
|
类型定义位于 `src/types/postCreateHook.ts`:
|
package/docs/run.md
CHANGED
|
@@ -86,9 +86,8 @@ clawt run -b <branchName>
|
|
|
86
86
|
5. 通过公共函数 `executeBatchTasks`(`src/utils/task-executor.ts`)启动批量任务执行,该函数负责进度面板渲染、SIGINT 中断处理、并发控制和汇总输出。对每个 worktree 并行启动 Claude Code CLI:
|
|
87
87
|
```bash
|
|
88
88
|
cd ~/.clawt/worktrees/<project>/<branchName>-<i>
|
|
89
|
-
claude -p "<tasks[i]>" --output-format stream-json --verbose --permission-mode bypassPermissions
|
|
89
|
+
claude -p "<tasks[i]>" --output-format stream-json --verbose --permission-mode bypassPermissions
|
|
90
90
|
```
|
|
91
|
-
其中 `--append-system-prompt` 使用统一的 `APPEND_SYSTEM_PROMPT` 常量(定义在 `src/constants/config.ts`)。
|
|
92
91
|
子进程通过 `spawnProcess()`(`src/utils/shell.ts`)启动,会自动注入环境变量 `CLAUDE_CODE_ENTRYPOINT="cli"`(通过 `getEnvWithoutNestedSessionFlag()` 函数),使会话支持通过 `--continue` 恢复。
|
|
93
92
|
使用 `stream-json` 格式可实时获取 Claude Code 的流式事件(工具调用、文本输出、最终结果),用于在进度面板中显示每个任务的实时活动描述和结果预览。流式事件解析由 `src/utils/stream-parser.ts` 负责。
|
|
94
93
|
6. 进入**事件监听通知**阶段(见 [5.3](#53-任务完成通知机制))
|
package/package.json
CHANGED
package/src/constants/config.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ClawtConfig, ConfigDefinitions } from '../types/index.js';
|
|
2
2
|
import { VALID_TERMINAL_APPS } from './terminal.js';
|
|
3
3
|
|
|
4
|
-
/** Claude Code 系统约束提示 */
|
|
5
|
-
export const APPEND_SYSTEM_PROMPT =
|
|
6
|
-
'Currently, you are in the git worktree directory.';
|
|
7
|
-
|
|
8
4
|
/**
|
|
9
5
|
* 通过 clawt 启动的 Claude Code 非交互式会话(claude -p)的 entrypoint 标识
|
|
10
6
|
* 设置为 'cli' 使 claude -p 启动的会话可以通过 --continue 恢复
|
package/src/constants/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { CONFIG_ALIAS_DISABLED_HINT } from './messages/index.js';
|
|
|
5
5
|
export { UPDATE_MESSAGES, UPDATE_COMMANDS } from './messages/update.js';
|
|
6
6
|
export { EXIT_CODES } from './exitCodes.js';
|
|
7
7
|
export { ENABLE_BRACKETED_PASTE, DISABLE_BRACKETED_PASTE, PASTE_THRESHOLD_MS, VALID_TERMINAL_APPS, ITERM2_APP_PATH } from './terminal.js';
|
|
8
|
-
export { DEFAULT_CONFIG, CONFIG_DESCRIPTIONS, CONFIG_DEFINITIONS,
|
|
8
|
+
export { DEFAULT_CONFIG, CONFIG_DESCRIPTIONS, CONFIG_DEFINITIONS, CLAUDE_CODE_ENTRYPOINT_VALUE } from './config.js';
|
|
9
9
|
export { PROJECT_CONFIG_DEFINITIONS, PROJECT_DEFAULT_CONFIG, PROJECT_CONFIG_DESCRIPTIONS } from './project-config.js';
|
|
10
10
|
export { AUTO_SAVE_COMMIT_MESSAGE_PREFIX } from './git.js';
|
|
11
11
|
export { DEBUG_LOG_PREFIX, DEBUG_TIMESTAMP_FORMAT } from './logger.js';
|
package/src/utils/claude.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
2
2
|
import { existsSync, readdirSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { ClawtError } from '../errors/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { CLAUDE_PROJECTS_DIR } from '../constants/index.js';
|
|
6
6
|
import { resolveClaudeCodeCommand } from './project-config.js';
|
|
7
7
|
import { printInfo, printWarning } from './formatter.js';
|
|
8
8
|
import { openCommandInNewTerminalTab } from './terminal.js';
|
|
@@ -56,8 +56,6 @@ export function launchInteractiveClaude(worktree: WorktreeInfo, options: LaunchC
|
|
|
56
56
|
const cmd = parts[0];
|
|
57
57
|
const args = [
|
|
58
58
|
...parts.slice(1),
|
|
59
|
-
'--append-system-prompt',
|
|
60
|
-
APPEND_SYSTEM_PROMPT,
|
|
61
59
|
];
|
|
62
60
|
|
|
63
61
|
// 仅在启用 autoContinue 时检测历史会话并追加 --continue
|
|
@@ -101,20 +99,18 @@ function escapeShellSingleQuote(str: string): string {
|
|
|
101
99
|
|
|
102
100
|
/**
|
|
103
101
|
* 构建在指定 worktree 中启动 Claude Code 的完整 shell 命令
|
|
104
|
-
* 生成格式:cd <path> && <claudeCommand>
|
|
102
|
+
* 生成格式:cd <path> && <claudeCommand> [--continue]
|
|
105
103
|
* @param {WorktreeInfo} worktree - worktree 信息
|
|
106
104
|
* @param {boolean} hasPreviousSession - 是否存在历史会话(由调用方预计算,避免重复 I/O)
|
|
107
105
|
* @returns {string} 完整的 shell 命令字符串
|
|
108
106
|
*/
|
|
109
107
|
export function buildClaudeCommand(worktree: WorktreeInfo, hasPreviousSession: boolean): string {
|
|
110
108
|
const commandStr = resolveClaudeCodeCommand();
|
|
111
|
-
const systemPrompt = APPEND_SYSTEM_PROMPT;
|
|
112
109
|
|
|
113
110
|
const escapedPath = escapeShellSingleQuote(worktree.path);
|
|
114
|
-
const escapedPrompt = escapeShellSingleQuote(systemPrompt);
|
|
115
111
|
const continueFlag = hasPreviousSession ? ' --continue' : '';
|
|
116
112
|
|
|
117
|
-
return `cd '${escapedPath}' && ${commandStr}
|
|
113
|
+
return `cd '${escapedPath}' && ${commandStr}${continueFlag}`;
|
|
118
114
|
}
|
|
119
115
|
|
|
120
116
|
/**
|
|
@@ -5,7 +5,6 @@ import type { ClaudeCodeResult, TaskResult, TaskSummary, WorktreeInfo } from '..
|
|
|
5
5
|
import { spawnProcess, killAllChildProcesses } from './shell.js';
|
|
6
6
|
import { cleanupWorktrees } from './worktree.js';
|
|
7
7
|
import { getConfigValue } from './config.js';
|
|
8
|
-
import { APPEND_SYSTEM_PROMPT } from '../constants/index.js';
|
|
9
8
|
import { printSuccess, printWarning, printInfo, printDoubleSeparator, confirmAction } from './formatter.js';
|
|
10
9
|
import { ProgressRenderer } from './progress.js';
|
|
11
10
|
import { createLineBuffer, parseStreamLine, parseStreamEvent, truncateText } from './stream-parser.js';
|
|
@@ -35,11 +34,8 @@ type ActivityCallback = (activityText: string) => void;
|
|
|
35
34
|
* @returns {ClaudeTaskHandle} 包含子进程引用和结果 Promise
|
|
36
35
|
*/
|
|
37
36
|
function executeClaudeTask(worktree: WorktreeInfo, task: string, onActivity?: ActivityCallback, continueSession?: boolean): ClaudeTaskHandle {
|
|
38
|
-
// 使用统一的系统提示常量
|
|
39
|
-
const systemPrompt = APPEND_SYSTEM_PROMPT;
|
|
40
|
-
|
|
41
37
|
// 旧版使用 --output-format json,现改为 stream-json --verbose 以支持实时活动信息
|
|
42
|
-
const args = ['-p', task, '--output-format', 'stream-json', '--verbose', '--permission-mode', 'bypassPermissions'
|
|
38
|
+
const args = ['-p', task, '--output-format', 'stream-json', '--verbose', '--permission-mode', 'bypassPermissions'];
|
|
43
39
|
|
|
44
40
|
// 追问模式:追加 --continue 继续该目录下最新会话
|
|
45
41
|
if (continueSession) {
|
|
@@ -33,7 +33,6 @@ import { launchInteractiveClaude, hasClaudeSessionHistory, buildClaudeCommand }
|
|
|
33
33
|
import { getConfigValue } from '../../../src/utils/config.js';
|
|
34
34
|
import { printInfo, printWarning } from '../../../src/utils/formatter.js';
|
|
35
35
|
import { ClawtError } from '../../../src/errors/index.js';
|
|
36
|
-
import { APPEND_SYSTEM_PROMPT } from '../../../src/constants/config.js';
|
|
37
36
|
import { createWorktreeInfo } from '../../helpers/fixtures.js';
|
|
38
37
|
|
|
39
38
|
const mockedSpawnSync = vi.mocked(spawnSync);
|
|
@@ -104,7 +103,7 @@ describe('launchInteractiveClaude', () => {
|
|
|
104
103
|
expect(mockedGetConfigValue).toHaveBeenCalledWith('claudeCodeCommand');
|
|
105
104
|
expect(mockedSpawnSync).toHaveBeenCalledWith(
|
|
106
105
|
'claude',
|
|
107
|
-
expect.
|
|
106
|
+
expect.any(Array),
|
|
108
107
|
expect.objectContaining({
|
|
109
108
|
cwd: '/tmp/test-worktree',
|
|
110
109
|
stdio: 'inherit',
|
|
@@ -148,7 +147,7 @@ describe('launchInteractiveClaude', () => {
|
|
|
148
147
|
|
|
149
148
|
expect(mockedSpawnSync).toHaveBeenCalledWith(
|
|
150
149
|
'npx',
|
|
151
|
-
expect.arrayContaining(['claude'
|
|
150
|
+
expect.arrayContaining(['claude']),
|
|
152
151
|
expect.any(Object),
|
|
153
152
|
);
|
|
154
153
|
});
|
|
@@ -285,7 +284,7 @@ describe('launchInteractiveClaude', () => {
|
|
|
285
284
|
expect(callArgs).not.toContain('--continue');
|
|
286
285
|
});
|
|
287
286
|
|
|
288
|
-
it('
|
|
287
|
+
it('不包含 --append-system-prompt 参数', () => {
|
|
289
288
|
mockedGetConfigValue.mockReturnValue('claude');
|
|
290
289
|
mockedExistsSync.mockReturnValue(false);
|
|
291
290
|
mockedSpawnSync.mockReturnValue({
|
|
@@ -301,8 +300,7 @@ describe('launchInteractiveClaude', () => {
|
|
|
301
300
|
launchInteractiveClaude(worktree);
|
|
302
301
|
|
|
303
302
|
const callArgs = mockedSpawnSync.mock.calls[0][1] as string[];
|
|
304
|
-
|
|
305
|
-
expect(callArgs[promptIndex + 1]).toBe(APPEND_SYSTEM_PROMPT);
|
|
303
|
+
expect(callArgs).not.toContain('--append-system-prompt');
|
|
306
304
|
});
|
|
307
305
|
});
|
|
308
306
|
|
|
@@ -319,7 +317,6 @@ describe('buildClaudeCommand', () => {
|
|
|
319
317
|
|
|
320
318
|
expect(cmd).toContain("cd '/tmp/test-worktree'");
|
|
321
319
|
expect(cmd).toContain('claude');
|
|
322
|
-
expect(cmd).toContain('--append-system-prompt');
|
|
323
320
|
});
|
|
324
321
|
|
|
325
322
|
it('hasPreviousSession 为 true 时包含 --continue', () => {
|
|
@@ -338,12 +335,12 @@ describe('buildClaudeCommand', () => {
|
|
|
338
335
|
expect(cmd).not.toContain('--continue');
|
|
339
336
|
});
|
|
340
337
|
|
|
341
|
-
it('
|
|
338
|
+
it('不包含 --append-system-prompt 参数', () => {
|
|
342
339
|
mockedGetConfigValue.mockReturnValue('claude');
|
|
343
340
|
|
|
344
341
|
const cmd = buildClaudeCommand(worktree, false);
|
|
345
342
|
|
|
346
|
-
expect(cmd).toContain(
|
|
343
|
+
expect(cmd).not.toContain('--append-system-prompt');
|
|
347
344
|
});
|
|
348
345
|
|
|
349
346
|
it('路径中的单引号被正确转义', () => {
|