@kood/claude-code 0.7.10 → 0.7.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 +75 -18
- package/package.json +1 -1
- package/templates/.claude/agents/codex.md +58 -248
- package/templates/.claude/commands/cancel-ralph.md +18 -0
- package/templates/.claude/commands/git-merge.md +67 -0
- package/templates/.claude/commands/ralph-loop.md +18 -0
- package/templates/.claude/hooks/ralph-stop-hook.sh +124 -0
- package/templates/.claude/scripts/git/git-merge.sh +73 -0
- package/templates/.claude/scripts/setup-ralph-loop.sh +161 -0
- package/templates/.claude/skills/codex/SKILL.md +110 -458
package/dist/index.js
CHANGED
|
@@ -327,6 +327,7 @@ var copyCommands = createExtrasCopier("commands");
|
|
|
327
327
|
var copyAgents = createExtrasCopier("agents");
|
|
328
328
|
var copyInstructions = createExtrasCopier("instructions");
|
|
329
329
|
var copyScripts = createExtrasCopier("scripts");
|
|
330
|
+
var copyHooks = createExtrasCopier("hooks");
|
|
330
331
|
var getSkillsToInstall = async (skillsSrc, templates) => {
|
|
331
332
|
const metadataMap = await loadAllSkillMetadata(skillsSrc);
|
|
332
333
|
const isNonUITemplate = templates.some((t) => NON_UI_TEMPLATES.includes(t));
|
|
@@ -372,6 +373,7 @@ var checkExistingClaudeFiles = async (targetDir) => {
|
|
|
372
373
|
const agentsDir = path8.join(targetDir, ".claude", "agents");
|
|
373
374
|
const instructionsDir = path8.join(targetDir, ".claude", "instructions");
|
|
374
375
|
const scriptsDir = path8.join(targetDir, ".claude", "scripts");
|
|
376
|
+
const hooksDir = path8.join(targetDir, ".claude", "hooks");
|
|
375
377
|
if (await fs6.pathExists(skillsDir)) {
|
|
376
378
|
existingFiles.push(".claude/skills/");
|
|
377
379
|
}
|
|
@@ -387,6 +389,9 @@ var checkExistingClaudeFiles = async (targetDir) => {
|
|
|
387
389
|
if (await fs6.pathExists(scriptsDir)) {
|
|
388
390
|
existingFiles.push(".claude/scripts/");
|
|
389
391
|
}
|
|
392
|
+
if (await fs6.pathExists(hooksDir)) {
|
|
393
|
+
existingFiles.push(".claude/hooks/");
|
|
394
|
+
}
|
|
390
395
|
return existingFiles;
|
|
391
396
|
};
|
|
392
397
|
var checkAllExtrasExist = async (_templates) => {
|
|
@@ -396,12 +401,21 @@ var checkAllExtrasExist = async (_templates) => {
|
|
|
396
401
|
const agentsSrc = path8.join(claudeDir, "agents");
|
|
397
402
|
const instructionsSrc = path8.join(claudeDir, "instructions");
|
|
398
403
|
const scriptsSrc = path8.join(claudeDir, "scripts");
|
|
404
|
+
const hooksSrc = path8.join(claudeDir, "hooks");
|
|
399
405
|
const hasSkills = await hasFiles(skillsSrc);
|
|
400
406
|
const hasCommands = await hasFiles(commandsSrc);
|
|
401
407
|
const hasAgents = await hasFiles(agentsSrc);
|
|
402
408
|
const hasInstructions = await hasFiles(instructionsSrc);
|
|
403
409
|
const hasScripts = await hasFiles(scriptsSrc);
|
|
404
|
-
|
|
410
|
+
const hasHooks = await hasFiles(hooksSrc);
|
|
411
|
+
return {
|
|
412
|
+
hasSkills,
|
|
413
|
+
hasCommands,
|
|
414
|
+
hasAgents,
|
|
415
|
+
hasInstructions,
|
|
416
|
+
hasScripts,
|
|
417
|
+
hasHooks
|
|
418
|
+
};
|
|
405
419
|
};
|
|
406
420
|
|
|
407
421
|
// src/features/extras/extras-installer.ts
|
|
@@ -475,6 +489,22 @@ async function installScriptsIfNeeded(templates, targetDir, shouldInstall, hasSc
|
|
|
475
489
|
);
|
|
476
490
|
return scriptsResult;
|
|
477
491
|
}
|
|
492
|
+
async function installHooksIfNeeded(templates, targetDir, shouldInstall, hasHooks) {
|
|
493
|
+
if (!shouldInstall) {
|
|
494
|
+
return { files: 0, directories: 0 };
|
|
495
|
+
}
|
|
496
|
+
if (!hasHooks) {
|
|
497
|
+
logger.warn("No hooks found in selected templates.");
|
|
498
|
+
return { files: 0, directories: 0 };
|
|
499
|
+
}
|
|
500
|
+
logger.blank();
|
|
501
|
+
logger.info("Installing hooks...");
|
|
502
|
+
const hooksResult = await copyHooks(templates, targetDir);
|
|
503
|
+
logger.success(
|
|
504
|
+
`Hooks: ${hooksResult.files} files, ${hooksResult.directories} directories`
|
|
505
|
+
);
|
|
506
|
+
return hooksResult;
|
|
507
|
+
}
|
|
478
508
|
async function installInstructionsIfNeeded(templates, targetDir, shouldInstall, hasInstructions) {
|
|
479
509
|
if (!shouldInstall) {
|
|
480
510
|
return { files: 0, directories: 0 };
|
|
@@ -497,9 +527,10 @@ async function installExtras(templates, targetDir, flags, availability) {
|
|
|
497
527
|
installCommands,
|
|
498
528
|
installAgents,
|
|
499
529
|
installInstructions,
|
|
500
|
-
installScripts
|
|
530
|
+
installScripts,
|
|
531
|
+
installHooks
|
|
501
532
|
} = flags;
|
|
502
|
-
if (!installSkills && !installCommands && !installAgents && !installInstructions && !installScripts) {
|
|
533
|
+
if (!installSkills && !installCommands && !installAgents && !installInstructions && !installScripts && !installHooks) {
|
|
503
534
|
return { files: 0, directories: 0 };
|
|
504
535
|
}
|
|
505
536
|
const existingClaudeFiles = await checkExistingClaudeFiles(targetDir);
|
|
@@ -534,8 +565,14 @@ async function installExtras(templates, targetDir, flags, availability) {
|
|
|
534
565
|
installScripts,
|
|
535
566
|
availability.hasScripts
|
|
536
567
|
);
|
|
537
|
-
const
|
|
538
|
-
|
|
568
|
+
const hooksResult = await installHooksIfNeeded(
|
|
569
|
+
templates,
|
|
570
|
+
targetDir,
|
|
571
|
+
installHooks,
|
|
572
|
+
availability.hasHooks
|
|
573
|
+
);
|
|
574
|
+
const totalFiles = skillsResult.files + commandsResult.files + agentsResult.files + instructionsResult.files + scriptsResult.files + hooksResult.files;
|
|
575
|
+
const totalDirectories = skillsResult.directories + commandsResult.directories + agentsResult.directories + instructionsResult.directories + scriptsResult.directories + hooksResult.directories;
|
|
539
576
|
return { files: totalFiles, directories: totalDirectories };
|
|
540
577
|
}
|
|
541
578
|
|
|
@@ -620,19 +657,22 @@ async function promptExtrasSelection(options) {
|
|
|
620
657
|
agents,
|
|
621
658
|
instructions,
|
|
622
659
|
scripts,
|
|
660
|
+
hooks,
|
|
623
661
|
hasSkills,
|
|
624
662
|
hasCommands,
|
|
625
663
|
hasAgents,
|
|
626
664
|
hasInstructions,
|
|
627
|
-
hasScripts
|
|
665
|
+
hasScripts,
|
|
666
|
+
hasHooks
|
|
628
667
|
} = options;
|
|
629
668
|
let installSkills = skills ?? false;
|
|
630
669
|
let installCommands = commands ?? false;
|
|
631
670
|
const installAgents = agents ?? hasAgents;
|
|
632
671
|
const installInstructions = instructions ?? hasInstructions;
|
|
633
672
|
const installScripts = scripts ?? hasScripts;
|
|
634
|
-
const
|
|
635
|
-
|
|
673
|
+
const installHooks = hooks ?? hasHooks;
|
|
674
|
+
const noOptionsProvided = skills === void 0 && commands === void 0 && agents === void 0 && instructions === void 0 && scripts === void 0 && hooks === void 0;
|
|
675
|
+
if (noOptionsProvided && (hasSkills || hasCommands || hasAgents || hasInstructions || hasScripts || hasHooks)) {
|
|
636
676
|
logger.blank();
|
|
637
677
|
if (hasSkills) {
|
|
638
678
|
const result = await promptConfirm(
|
|
@@ -654,7 +694,8 @@ async function promptExtrasSelection(options) {
|
|
|
654
694
|
installCommands,
|
|
655
695
|
installAgents,
|
|
656
696
|
installInstructions,
|
|
657
|
-
installScripts
|
|
697
|
+
installScripts,
|
|
698
|
+
installHooks
|
|
658
699
|
};
|
|
659
700
|
}
|
|
660
701
|
async function promptScopeSelection(options) {
|
|
@@ -1420,29 +1461,32 @@ async function installTemplates(templates, targetDir) {
|
|
|
1420
1461
|
logger.success(`Total: ${totalFiles} files, ${totalDirectories} directories`);
|
|
1421
1462
|
return { files: totalFiles, directories: totalDirectories };
|
|
1422
1463
|
}
|
|
1423
|
-
async function promptForExtrasInstallation(options, hasSkills, hasCommands, hasAgents, hasInstructions, hasScripts) {
|
|
1464
|
+
async function promptForExtrasInstallation(options, hasSkills, hasCommands, hasAgents, hasInstructions, hasScripts, hasHooks) {
|
|
1424
1465
|
return await promptExtrasSelection({
|
|
1425
1466
|
skills: options.skills,
|
|
1426
1467
|
commands: options.commands,
|
|
1427
1468
|
agents: options.agents,
|
|
1428
1469
|
instructions: options.instructions,
|
|
1429
1470
|
scripts: options.scripts,
|
|
1471
|
+
hooks: options.hooks,
|
|
1430
1472
|
hasSkills,
|
|
1431
1473
|
hasCommands,
|
|
1432
1474
|
hasAgents,
|
|
1433
1475
|
hasInstructions,
|
|
1434
|
-
hasScripts
|
|
1476
|
+
hasScripts,
|
|
1477
|
+
hasHooks
|
|
1435
1478
|
});
|
|
1436
1479
|
}
|
|
1437
|
-
function showInstallationSummary(templates, flags, hasSkills, hasCommands, hasAgents, hasInstructions, hasScripts, scope) {
|
|
1480
|
+
function showInstallationSummary(templates, flags, hasSkills, hasCommands, hasAgents, hasInstructions, hasScripts, hasHooks, scope) {
|
|
1438
1481
|
const {
|
|
1439
1482
|
installSkills,
|
|
1440
1483
|
installCommands,
|
|
1441
1484
|
installAgents,
|
|
1442
1485
|
installInstructions,
|
|
1443
|
-
installScripts
|
|
1486
|
+
installScripts,
|
|
1487
|
+
installHooks
|
|
1444
1488
|
} = flags;
|
|
1445
|
-
const hasExtrasInstalled = installSkills && hasSkills || installCommands && hasCommands || installAgents && hasAgents || installInstructions && hasInstructions || installScripts && hasScripts;
|
|
1489
|
+
const hasExtrasInstalled = installSkills && hasSkills || installCommands && hasCommands || installAgents && hasAgents || installInstructions && hasInstructions || installScripts && hasScripts || installHooks && hasHooks;
|
|
1446
1490
|
if (templates.length === 0 && !hasExtrasInstalled) {
|
|
1447
1491
|
logger.blank();
|
|
1448
1492
|
logger.info("No templates or extras installed.");
|
|
@@ -1475,6 +1519,9 @@ function showInstallationSummary(templates, flags, hasSkills, hasCommands, hasAg
|
|
|
1475
1519
|
if (installScripts && hasScripts) {
|
|
1476
1520
|
logger.step("Scripts \u2192 .claude/scripts/");
|
|
1477
1521
|
}
|
|
1522
|
+
if (installHooks && hasHooks) {
|
|
1523
|
+
logger.step("Hooks \u2192 .claude/hooks/");
|
|
1524
|
+
}
|
|
1478
1525
|
}
|
|
1479
1526
|
logger.blank();
|
|
1480
1527
|
logger.info("Next steps:");
|
|
@@ -1513,21 +1560,30 @@ var init = async (options) => {
|
|
|
1513
1560
|
}
|
|
1514
1561
|
}
|
|
1515
1562
|
const templatesToCheck = templates.length > 0 ? templates : availableTemplates;
|
|
1516
|
-
const {
|
|
1563
|
+
const {
|
|
1564
|
+
hasSkills,
|
|
1565
|
+
hasCommands,
|
|
1566
|
+
hasAgents,
|
|
1567
|
+
hasInstructions,
|
|
1568
|
+
hasScripts,
|
|
1569
|
+
hasHooks
|
|
1570
|
+
} = await checkAllExtrasExist(templatesToCheck);
|
|
1517
1571
|
const flags = await promptForExtrasInstallation(
|
|
1518
1572
|
options,
|
|
1519
1573
|
hasSkills,
|
|
1520
1574
|
hasCommands,
|
|
1521
1575
|
hasAgents,
|
|
1522
1576
|
hasInstructions,
|
|
1523
|
-
hasScripts
|
|
1577
|
+
hasScripts,
|
|
1578
|
+
hasHooks
|
|
1524
1579
|
);
|
|
1525
1580
|
await installExtras(templatesToCheck, targetDir, flags, {
|
|
1526
1581
|
hasSkills,
|
|
1527
1582
|
hasCommands,
|
|
1528
1583
|
hasAgents,
|
|
1529
1584
|
hasInstructions,
|
|
1530
|
-
hasScripts
|
|
1585
|
+
hasScripts,
|
|
1586
|
+
hasHooks
|
|
1531
1587
|
});
|
|
1532
1588
|
showInstallationSummary(
|
|
1533
1589
|
templates,
|
|
@@ -1537,6 +1593,7 @@ var init = async (options) => {
|
|
|
1537
1593
|
hasAgents,
|
|
1538
1594
|
hasInstructions,
|
|
1539
1595
|
hasScripts,
|
|
1596
|
+
hasHooks,
|
|
1540
1597
|
scope
|
|
1541
1598
|
);
|
|
1542
1599
|
const codexSyncPath = path11.join(targetDir, ".codex");
|
|
@@ -1602,7 +1659,7 @@ var init = async (options) => {
|
|
|
1602
1659
|
|
|
1603
1660
|
// src/index.ts
|
|
1604
1661
|
var program = new Command();
|
|
1605
|
-
program.name("claude-code").description("Claude Code documentation installer for projects").version("0.7.
|
|
1662
|
+
program.name("claude-code").description("Claude Code documentation installer for projects").version("0.7.11");
|
|
1606
1663
|
program.option(
|
|
1607
1664
|
"-t, --template <names>",
|
|
1608
1665
|
"template names (comma-separated: tanstack-start,hono)"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: codex
|
|
3
3
|
description: OpenAI Codex MCP 연동 에이전트. 꼼꼼한 구현, 코드 리뷰, 엣지케이스 검증 담당. Agent Teams에서 Team Lead 역할 우선.
|
|
4
|
-
tools: Read, Write, Edit, Grep, Glob, Bash, mcp__codex__codex,
|
|
4
|
+
tools: Read, Write, Edit, Grep, Glob, Bash, mcp__codex__codex, mcp__codex__codex_reply
|
|
5
5
|
model: sonnet
|
|
6
6
|
permissionMode: default
|
|
7
7
|
maxTurns: 50
|
|
@@ -15,56 +15,29 @@ maxTurns: 50
|
|
|
15
15
|
|
|
16
16
|
# Codex Agent
|
|
17
17
|
|
|
18
|
-
OpenAI
|
|
18
|
+
codex-mcp 서버로 OpenAI Responses API 호출. Claude와 페어 프로그래밍.
|
|
19
19
|
|
|
20
|
-
**역할:**
|
|
21
|
-
- **Agent Teams Team Lead** (기본)
|
|
22
|
-
- 꼼꼼한 코드 구현 (엣지케이스, 타입 안정성)
|
|
23
|
-
- 코드 리뷰 (버그, 보안, 성능)
|
|
24
|
-
- 테스트 작성 및 검증
|
|
25
|
-
- Claude 설계 구현 및 검증
|
|
20
|
+
**역할:** Agent Teams **Team Lead** (기본), 구현, 리뷰, 테스트, 디버깅
|
|
26
21
|
|
|
27
22
|
---
|
|
28
23
|
|
|
29
24
|
<team_lead>
|
|
30
25
|
|
|
31
|
-
## Team Lead
|
|
32
|
-
|
|
33
|
-
> **Agent Teams 모드에서 Codex가 Team Lead를 맡는 것이 기본**
|
|
26
|
+
## Team Lead
|
|
34
27
|
|
|
35
28
|
| 역할 | 이유 |
|
|
36
29
|
|------|------|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
42
|
-
### Team Lead 워크플로우
|
|
30
|
+
| 태스크 분해 | 꼼꼼한 분할, 누락 방지 |
|
|
31
|
+
| 품질 게이트 | 코드 품질/테스트 검증 |
|
|
32
|
+
| 진행 관리 | 병목 감지 |
|
|
33
|
+
| 충돌 조율 | 파일 충돌 방지 |
|
|
43
34
|
|
|
44
35
|
```typescript
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
// 2. Claude 팀원 스폰
|
|
53
|
-
Task({
|
|
54
|
-
subagent_type: 'implementation-executor',
|
|
55
|
-
team_name: 'project-team',
|
|
56
|
-
name: 'claude-impl',
|
|
57
|
-
prompt: '창의적 설계 + 구현'
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// 3. 태스크 관리
|
|
61
|
-
TaskCreate({ subject: "API 구현", ... })
|
|
62
|
-
TaskUpdate({ id: "task-1", status: "completed" })
|
|
63
|
-
|
|
64
|
-
// 4. 품질 검증
|
|
65
|
-
mcp__codex__review({ target: "uncommitted" })
|
|
66
|
-
|
|
67
|
-
// 5. 팀 정리
|
|
36
|
+
TeamCreate({ team_name: "project", agent_type: "codex" })
|
|
37
|
+
Task({ subagent_type: 'implementation-executor', team_name: 'project', name: 'claude-impl', prompt: '...' })
|
|
38
|
+
// 품질 검증
|
|
39
|
+
mcp__codex__codex_reply({ thread_id: "...", prompt: "코드 리뷰: 보안, 성능, 엣지케이스" })
|
|
40
|
+
// 정리
|
|
68
41
|
SendMessage({ type: 'shutdown_request', recipient: 'claude-impl' })
|
|
69
42
|
TeamDelete()
|
|
70
43
|
```
|
|
@@ -75,51 +48,41 @@ TeamDelete()
|
|
|
75
48
|
|
|
76
49
|
<codex_mcp_usage>
|
|
77
50
|
|
|
78
|
-
##
|
|
51
|
+
## MCP 도구
|
|
79
52
|
|
|
80
|
-
|
|
53
|
+
**인증:** Codex CLI OAuth (`~/.codex/auth.json`), 토큰 자동 갱신
|
|
54
|
+
|
|
55
|
+
### 새 태스크
|
|
81
56
|
|
|
82
57
|
```typescript
|
|
83
58
|
mcp__codex__codex({
|
|
84
|
-
prompt:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
품질 기준:
|
|
89
|
-
- 모든 엣지케이스 처리
|
|
90
|
-
- 타입 안정성 보장
|
|
91
|
-
- 에러 핸들링 포함
|
|
92
|
-
`,
|
|
93
|
-
working_directory: "/path/to/project"
|
|
59
|
+
prompt: "구현 요구사항 + 품질 기준",
|
|
60
|
+
working_directory: "/path/to/project",
|
|
61
|
+
model: "gpt-5.3-codex high" // 선택 (세션에 저장, 생략 시 Codex CLI 기본값)
|
|
94
62
|
})
|
|
63
|
+
// → JSON { thread_id, result }
|
|
95
64
|
```
|
|
96
65
|
|
|
97
|
-
|
|
66
|
+
**에이전트 루프:** `read_file`, `write_file`, `list_files`, `shell_exec` 자율 호출
|
|
67
|
+
|
|
68
|
+
### 세션 이어가기
|
|
98
69
|
|
|
99
70
|
```typescript
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
71
|
+
mcp__codex__codex_reply({
|
|
72
|
+
thread_id: "이전 thread_id",
|
|
73
|
+
prompt: "후속 지시"
|
|
103
74
|
})
|
|
75
|
+
// 세션 모델 자동 유지, 이전 컨텍스트 보존
|
|
104
76
|
```
|
|
105
77
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
<strengths>
|
|
111
|
-
|
|
112
|
-
## 강점 영역
|
|
78
|
+
### 리뷰 패턴
|
|
113
79
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
| **코드 리뷰** | 버그, 보안 취약점, 성능 이슈 |
|
|
119
|
-
| **테스트** | 단위 테스트, 통합 테스트, 엣지케이스 테스트 |
|
|
120
|
-
| **디버깅** | 버그 원인 분석, 재현, 수정 |
|
|
80
|
+
```typescript
|
|
81
|
+
const r = mcp__codex__codex({ prompt: "src/auth/ 분석", working_directory: cwd })
|
|
82
|
+
mcp__codex__codex_reply({ thread_id: r.thread_id, prompt: "보안, 엣지케이스, 성능 리뷰" })
|
|
83
|
+
```
|
|
121
84
|
|
|
122
|
-
</
|
|
85
|
+
</codex_mcp_usage>
|
|
123
86
|
|
|
124
87
|
---
|
|
125
88
|
|
|
@@ -127,207 +90,54 @@ mcp__codex__review({
|
|
|
127
90
|
|
|
128
91
|
## 작업 흐름
|
|
129
92
|
|
|
130
|
-
|
|
93
|
+
**구현:** Read(파일 파악) → codex(구현) → Bash(테스트) → Edit(미세 조정)
|
|
131
94
|
|
|
132
|
-
|
|
133
|
-
# 요구사항 분석
|
|
134
|
-
Read: 관련 파일 파악
|
|
95
|
+
**리뷰:** Bash(git diff) → codex(diff 분석) → codex_reply(리뷰) → 치명적/경고/제안 분류
|
|
135
96
|
|
|
136
|
-
|
|
137
|
-
mcp__codex__codex:
|
|
138
|
-
prompt: "구현 요구사항 + 품질 기준"
|
|
139
|
-
|
|
140
|
-
# 결과 검증
|
|
141
|
-
Bash: npm test
|
|
142
|
-
Read: 생성된 코드 확인
|
|
143
|
-
|
|
144
|
-
# 필요 시 수정
|
|
145
|
-
Edit: 미세 조정
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### 2. 리뷰 작업
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
# 변경사항 확인
|
|
152
|
-
Bash: git diff
|
|
153
|
-
|
|
154
|
-
# Codex 리뷰
|
|
155
|
-
mcp__codex__review:
|
|
156
|
-
target: "uncommitted"
|
|
157
|
-
focus: ["security", "bugs", "edge-cases"]
|
|
158
|
-
|
|
159
|
-
# 리뷰 결과 정리
|
|
160
|
-
→ 치명적/경고/제안 분류
|
|
161
|
-
→ 구체적 수정 방법 제시
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### 3. Claude 설계 구현
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
# Claude 설계 문서 확인
|
|
168
|
-
Read: 설계 문서/인터페이스 정의
|
|
169
|
-
|
|
170
|
-
# 설계 기반 구현
|
|
171
|
-
mcp__codex__codex:
|
|
172
|
-
prompt: `
|
|
173
|
-
Claude 설계 기반 구현:
|
|
174
|
-
[설계 내용]
|
|
175
|
-
|
|
176
|
-
구현 요구사항:
|
|
177
|
-
- 인터페이스 준수
|
|
178
|
-
- 타입 안정성
|
|
179
|
-
- 테스트 포함
|
|
180
|
-
`
|
|
181
|
-
|
|
182
|
-
# 구현 결과 검증
|
|
183
|
-
Bash: npm run typecheck && npm test
|
|
184
|
-
```
|
|
97
|
+
**설계 구현:** Read(설계 문서) → codex(설계 기반 구현) → Bash(typecheck + test)
|
|
185
98
|
|
|
186
99
|
</workflow>
|
|
187
100
|
|
|
188
101
|
---
|
|
189
102
|
|
|
190
|
-
<output_format>
|
|
191
|
-
|
|
192
|
-
## 출력 형식
|
|
193
|
-
|
|
194
|
-
### 구현 완료
|
|
195
|
-
|
|
196
|
-
```markdown
|
|
197
|
-
## 구현 완료
|
|
198
|
-
|
|
199
|
-
**생성/수정 파일:**
|
|
200
|
-
- src/auth/AuthService.ts (신규)
|
|
201
|
-
- src/auth/TokenManager.ts (신규)
|
|
202
|
-
- tests/auth.test.ts (신규)
|
|
203
|
-
|
|
204
|
-
**주요 구현:**
|
|
205
|
-
- JWT 토큰 생성/검증
|
|
206
|
-
- 리프레시 토큰 로직
|
|
207
|
-
- 에러 핸들링
|
|
208
|
-
|
|
209
|
-
**엣지케이스 처리:**
|
|
210
|
-
- 만료된 토큰 → 자동 갱신 시도
|
|
211
|
-
- 잘못된 토큰 → 401 반환
|
|
212
|
-
- 리프레시 토큰 만료 → 재로그인 유도
|
|
213
|
-
|
|
214
|
-
**테스트 결과:**
|
|
215
|
-
✅ 15 tests passed
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### 리뷰 완료
|
|
219
|
-
|
|
220
|
-
```markdown
|
|
221
|
-
## 코드 리뷰 결과
|
|
222
|
-
|
|
223
|
-
**검토 파일:**
|
|
224
|
-
- src/api/users.ts
|
|
225
|
-
- src/components/UserForm.tsx
|
|
226
|
-
|
|
227
|
-
### 치명적 (필수 수정)
|
|
228
|
-
|
|
229
|
-
#### 1. src/api/users.ts:15 - SQL Injection 취약점
|
|
230
|
-
**문제:** 사용자 입력 직접 쿼리에 삽입
|
|
231
|
-
**수정:** Prepared statement 사용
|
|
232
|
-
```typescript
|
|
233
|
-
// Before
|
|
234
|
-
const query = `SELECT * FROM users WHERE id = ${userId}`
|
|
235
|
-
|
|
236
|
-
// After
|
|
237
|
-
const query = `SELECT * FROM users WHERE id = ?`
|
|
238
|
-
await db.query(query, [userId])
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### 경고 (권장)
|
|
242
|
-
|
|
243
|
-
#### 2. src/components/UserForm.tsx:28 - Null 체크 누락
|
|
244
|
-
...
|
|
245
|
-
|
|
246
|
-
### 제안 (선택)
|
|
247
|
-
...
|
|
248
|
-
|
|
249
|
-
**요약:** 치명적 1개, 경고 2개, 제안 1개
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
</output_format>
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
103
|
<collaboration>
|
|
257
104
|
|
|
258
|
-
## Claude
|
|
105
|
+
## Claude 협업
|
|
259
106
|
|
|
260
107
|
| 상황 | Codex 역할 |
|
|
261
|
-
|
|
262
|
-
|
|
|
263
|
-
|
|
|
264
|
-
|
|
|
265
|
-
|
|
|
266
|
-
|
|
267
|
-
### 협업 시 주의사항
|
|
268
|
-
|
|
269
|
-
- Claude 설계 의도 존중
|
|
270
|
-
- 변경 시 이유 명확히 설명
|
|
271
|
-
- 충돌 발생 시 양쪽 장단점 제시
|
|
272
|
-
- 최종 결정은 사용자에게 위임
|
|
108
|
+
|------|-----------|
|
|
109
|
+
| Claude 설계 후 | 구현 + 엣지케이스 추가 |
|
|
110
|
+
| Claude 구현 후 | 리뷰 + 개선 제안 |
|
|
111
|
+
| 병렬 작업 | 백엔드/테스트/리뷰 |
|
|
112
|
+
| 의견 분기 | 꼼꼼한 관점 제시, 최종 결정은 사용자 |
|
|
273
113
|
|
|
274
114
|
</collaboration>
|
|
275
115
|
|
|
276
116
|
---
|
|
277
117
|
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
## 금지 사항
|
|
281
|
-
|
|
282
|
-
| 분류 | 금지 |
|
|
283
|
-
|------|------|
|
|
284
|
-
| **MCP** | MCP 없이 Codex 기능 시뮬레이션 |
|
|
285
|
-
| **범위** | Claude 담당 영역 침범 |
|
|
286
|
-
| **결정** | 충돌 시 임의 결정 (사용자 선택 유도) |
|
|
287
|
-
| **검증** | 테스트 없이 구현 완료 선언 |
|
|
288
|
-
|
|
289
|
-
</forbidden>
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
<required>
|
|
118
|
+
<rules>
|
|
294
119
|
|
|
295
|
-
## 필수
|
|
120
|
+
## 필수 / 금지
|
|
296
121
|
|
|
297
|
-
|
|
|
122
|
+
| 필수 | 금지 |
|
|
298
123
|
|------|------|
|
|
299
|
-
|
|
|
300
|
-
|
|
|
301
|
-
|
|
|
302
|
-
|
|
|
124
|
+
| codex 또는 codex_reply 사용 | MCP 없이 시뮬레이션 |
|
|
125
|
+
| 구현 후 테스트 실행 | 테스트 없이 완료 선언 |
|
|
126
|
+
| 모든 경계 조건 처리 | Claude 영역 침범 |
|
|
127
|
+
| 구조화된 결과 보고 | 충돌 시 임의 결정 |
|
|
303
128
|
|
|
304
|
-
</
|
|
129
|
+
</rules>
|
|
305
130
|
|
|
306
131
|
---
|
|
307
132
|
|
|
308
133
|
<error_handling>
|
|
309
134
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
|
313
|
-
|
|
314
|
-
|
|
|
315
|
-
|
|
|
316
|
-
|
|
|
317
|
-
|
|
318
|
-
### MCP 미설정 시 응답
|
|
319
|
-
|
|
320
|
-
```markdown
|
|
321
|
-
## Codex MCP 연결 필요
|
|
322
|
-
|
|
323
|
-
Codex MCP가 설정되지 않았습니다.
|
|
324
|
-
|
|
325
|
-
**설정 방법:**
|
|
326
|
-
```bash
|
|
327
|
-
claude mcp add codex -- codex mcp-server
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
설정 후 다시 시도해주세요.
|
|
331
|
-
```
|
|
135
|
+
| 에러 | 대응 |
|
|
136
|
+
|------|------|
|
|
137
|
+
| MCP 연결 실패 | 설정 → OpenAI/Codex 등록 안내 |
|
|
138
|
+
| 401 | `codex auth login` 안내 |
|
|
139
|
+
| 타임아웃 | 재시도 |
|
|
140
|
+
| 세션 not found | 새 codex 세션 |
|
|
141
|
+
| 동시 요청 에러 | 이전 요청 완료 대기 |
|
|
332
142
|
|
|
333
143
|
</error_handling>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Cancel active Ralph Loop"
|
|
3
|
+
allowed-tools: ["Bash(test -f .claude/ralph-loop.local.md:*)", "Bash(rm .claude/ralph-loop.local.md)", "Read(.claude/ralph-loop.local.md)"]
|
|
4
|
+
hide-from-slash-command-tool: "true"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Cancel Ralph
|
|
8
|
+
|
|
9
|
+
To cancel the Ralph loop:
|
|
10
|
+
|
|
11
|
+
1. Check if `.claude/ralph-loop.local.md` exists using Bash: `test -f .claude/ralph-loop.local.md && echo "EXISTS" || echo "NOT_FOUND"`
|
|
12
|
+
|
|
13
|
+
2. **If NOT_FOUND**: Say "No active Ralph loop found."
|
|
14
|
+
|
|
15
|
+
3. **If EXISTS**:
|
|
16
|
+
- Read `.claude/ralph-loop.local.md` to get the current iteration number from the `iteration:` field
|
|
17
|
+
- Remove the file using Bash: `rm .claude/ralph-loop.local.md`
|
|
18
|
+
- Report: "Cancelled Ralph loop (was at iteration N)" where N is the iteration value
|