@joseph0926/plan-loop 1.0.0

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.ko.md ADDED
@@ -0,0 +1,245 @@
1
+ # Plan Loop
2
+
3
+ Plan Loop는 Claude-Code(설계자)와 Codex(검토자) 간의 비동기 계획 검토 루프를 디스크의 세션 상태 공유를 통해 가능하게 하는 MCP 서버입니다.
4
+
5
+ ## 저장소 구조
6
+
7
+ - src/: MCP 서버 소스 코드 (Node.js + TypeScript)
8
+ - .mcp.json.example: MCP 서버 설정 샘플 (`.mcp.json`으로 복사하여 사용)
9
+
10
+ ## 빠른 시작
11
+
12
+ 1) 설치 및 설정 (권장)
13
+
14
+ ```bash
15
+ # npx로 1회 실행 (설치 불필요)
16
+ npx @joseph0926/plan-loop setup
17
+
18
+ # 또는 글로벌 설치
19
+ npm install -g @joseph0926/plan-loop
20
+ plan-loop setup
21
+ ```
22
+
23
+ ### 설정 옵션
24
+
25
+ ```bash
26
+ plan-loop setup # Claude (project) + Codex (user) 모두 설정
27
+ plan-loop setup --claude # Claude Code만 (project scope)
28
+ plan-loop setup --claude --user # Claude Code (user scope, ~/.claude.json)
29
+ plan-loop setup --codex # Codex만 (user scope)
30
+ ```
31
+
32
+ 2) 수동 등록 (선택)
33
+
34
+ **Claude Code** - `.mcp.json` (프로젝트) 또는 `~/.claude.json` (사용자)에 추가:
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "plan-loop": {
40
+ "command": "npx",
41
+ "args": ["-y", "@joseph0926/plan-loop"]
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ **Codex** - `~/.codex/config.toml`에 추가:
48
+
49
+ ```toml
50
+ [mcp_servers.plan-loop]
51
+ command = "npx"
52
+ args = ["-y", "@joseph0926/plan-loop"]
53
+ ```
54
+
55
+ 3) 도구 사용 예시
56
+
57
+ ```text
58
+ pl_start({ goal: "로그인 기능 계획" })
59
+ pl_submit({ session_id: "abc123", plan: "1. ..." })
60
+ pl_get_plan({ session_id: "abc123" })
61
+ pl_feedback({ session_id: "abc123", rating: "🟢", content: "LGTM" })
62
+ ```
63
+
64
+ ## 도구 목록
65
+
66
+ - pl_start: 세션 시작
67
+ - pl_submit: 계획 제출
68
+ - pl_get_plan: 최신 계획 조회
69
+ - pl_feedback: 최신 계획에 대한 피드백 제출
70
+ - pl_get_feedback: 최신 피드백 조회
71
+ - pl_status: 전체 세션 데이터 조회
72
+ - pl_list: 모든 세션 목록 (필터/정렬 지원)
73
+ - pl_delete: 세션 삭제
74
+ - pl_force_approve: exhausted 세션 강제 승인
75
+
76
+ ## 에이전트 협업
77
+
78
+ Claude-Code(설계자)와 Codex(검토자)가 협업하여 계획을 검토합니다.
79
+
80
+ ### 빠른 시작
81
+
82
+ ```text
83
+ # 1. Claude-Code: 세션 시작 및 계획 제출
84
+ pl_start({ goal: "로그인 기능 구현" })
85
+ pl_submit({ session_id: "...", plan: "1. DB 스키마..." })
86
+
87
+ # 2. Codex: 계획 조회 및 피드백
88
+ pl_get_plan({ session_id: "..." })
89
+ pl_feedback({ session_id: "...", rating: "🟡", content: "인증 방식 명시 필요" })
90
+
91
+ # 3. Claude-Code: 피드백 확인 및 수정
92
+ pl_get_feedback({ session_id: "..." })
93
+ pl_submit({ session_id: "...", plan: "수정된 계획..." })
94
+
95
+ # 4. Codex: 승인
96
+ pl_feedback({ session_id: "...", rating: "🟢", content: "LGTM" })
97
+ ```
98
+
99
+ ### 역할별 상세 지침
100
+
101
+ 자세한 워크플로우와 피드백 자동완성 가이드는 [AGENTS.md](AGENTS.md) 참조.
102
+
103
+ ## 상태 저장
104
+
105
+ 세션 파일은 `~/.plan-loop/sessions/`에 저장됩니다.
106
+
107
+ ## 상태 전이
108
+
109
+ ```
110
+ pl_start
111
+
112
+
113
+ [drafting]
114
+
115
+ pl_submit
116
+
117
+
118
+ [pending_review]
119
+
120
+ pl_feedback
121
+
122
+ ┌─────────────────────────┼─────────────────────────┐
123
+ ▼ ▼ ▼
124
+ 🔴 / 🟡 🟢 iteration >= max
125
+ │ │ │
126
+ ▼ ▼ ▼
127
+ [pending_revision] [approved] [exhausted]
128
+ │ │ │
129
+ pl_submit pl_delete pl_force_approve
130
+ │ │ │
131
+ ▼ ▼ ▼
132
+ [pending_review] [deleted] [approved]
133
+ ```
134
+
135
+ ## 응답 형식
136
+
137
+ ### 성공 응답 (데이터 있음)
138
+ ```typescript
139
+ { ready: true, data: { ... } }
140
+ ```
141
+
142
+ ### 대기 응답 (데이터 없음)
143
+ ```typescript
144
+ { ready: false, reason: "no_plan_submitted" | "no_feedback_yet" | "awaiting_feedback" }
145
+ ```
146
+
147
+ #### Pending reason 매핑
148
+ - `pl_get_plan`: plan 없음 → `no_plan_submitted`
149
+ - `pl_get_feedback`:
150
+ - plan 없음 → `no_plan_submitted`
151
+ - 최신 plan에 대한 피드백 대기 → `awaiting_feedback`
152
+ - 기타 피드백 없음 → `no_feedback_yet`
153
+
154
+ ### 에러 응답
155
+ ```typescript
156
+ {
157
+ isError: true,
158
+ content: [{ type: "text", text: "Invalid state: current='approved', expected=['drafting']" }]
159
+ }
160
+ ```
161
+
162
+ ## 세션 관리
163
+
164
+ ### pl_list 필터링 및 정렬
165
+
166
+ ```
167
+ // status 필터
168
+ > pl_list({ status: "approved" })
169
+ > pl_list({ status: ["drafting", "pending_review"] })
170
+
171
+ // 정렬
172
+ > pl_list({ sort: "createdAt", order: "asc" })
173
+ > pl_list({ sort: "updatedAt", order: "desc" }) // 기본값
174
+ ```
175
+
176
+ ### pl_delete 세션 삭제
177
+
178
+ ```
179
+ // approved/exhausted 세션 삭제
180
+ > pl_delete({ session_id: "abc123" })
181
+
182
+ // 활성 세션 삭제 (force 필요)
183
+ > pl_delete({ session_id: "abc123", force: true })
184
+ ```
185
+
186
+ ## 버전 규칙
187
+
188
+ | 필드 | 증가 시점 |
189
+ |------|-----------|
190
+ | `version` | `pl_submit` 호출 시 +1 |
191
+ | `iteration` | `pl_feedback`에서 🔴/🟡 시 +1 |
192
+
193
+ `maxIterations`는 기본값 5이며 **1 이상의 정수**만 허용됩니다.
194
+
195
+ ## 설계 결정
196
+
197
+ ### 최신 plan 자동 매핑
198
+ - `pl_feedback`은 항상 최신 plan에 매핑됨
199
+ - planVersion 파라미터 없음 (단순화)
200
+ - **Trade-off**: 동시 호출 시 race condition 가능 → 운영 규칙으로 관리
201
+
202
+ ### 역할 구분
203
+ - 서버는 호출자를 검증하지 않음
204
+ - Claude-Code는 submit 계열, Codex는 feedback 계열 사용 (약속)
205
+
206
+ ### 상태 영속화
207
+ - `~/.plan-loop/sessions/{id}.json`
208
+ - Atomic write (temp → rename)
209
+
210
+ ### goal 길이 제한
211
+ - `pl_list` 응답에서 goal은 30자(UTF-16 코드 유닛 기준) 초과 시 `...` 추가
212
+ - 최대 33자 (30자 + "...")
213
+
214
+ ## 개발
215
+
216
+ ```bash
217
+ npm run dev
218
+ npm run build
219
+ ```
220
+
221
+ ## 샘플 설정 파일
222
+
223
+ 프로젝트에 MCP 설정을 추가하려면:
224
+
225
+ ```bash
226
+ cp .mcp.json.example .mcp.json
227
+ ```
228
+
229
+ ## 테스트
230
+
231
+ ```bash
232
+ npm test # 테스트 실행
233
+ npm run test:watch # 워치 모드
234
+ npm run test:coverage # 커버리지 리포트
235
+ ```
236
+
237
+ 테스트 격리를 위해 `PLAN_LOOP_STATE_DIR` 환경변수를 지원합니다:
238
+
239
+ ```bash
240
+ PLAN_LOOP_STATE_DIR=/tmp/test-sessions npm test
241
+ ```
242
+
243
+ ## 라이선스
244
+
245
+ MIT
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # Plan Loop
2
+
3
+ Plan Loop is an MCP server that enables an asynchronous plan review loop between Claude-Code (planner) and Codex (reviewer) by sharing session state on disk.
4
+
5
+ ## Repository layout
6
+
7
+ - src/: MCP server source code (Node.js + TypeScript)
8
+ - .mcp.json.example: sample MCP server configuration (copy to `.mcp.json` to use)
9
+
10
+ ## Quick start
11
+
12
+ 1) Install & setup (recommended)
13
+
14
+ ```bash
15
+ # Run once with npx (no install)
16
+ npx @joseph0926/plan-loop setup
17
+
18
+ # Or install globally
19
+ npm install -g @joseph0926/plan-loop
20
+ plan-loop setup
21
+ ```
22
+
23
+ ### Setup options
24
+
25
+ ```bash
26
+ plan-loop setup # Setup both Claude (project) + Codex (user)
27
+ plan-loop setup --claude # Claude Code only (project scope)
28
+ plan-loop setup --claude --user # Claude Code (user scope, ~/.claude.json)
29
+ plan-loop setup --codex # Codex only (user scope)
30
+ ```
31
+
32
+ 2) Manual registration (optional)
33
+
34
+ **Claude Code** - Add to `.mcp.json` (project) or `~/.claude.json` (user):
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "plan-loop": {
40
+ "command": "npx",
41
+ "args": ["-y", "@joseph0926/plan-loop"]
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ **Codex** - Add to `~/.codex/config.toml`:
48
+
49
+ ```toml
50
+ [mcp_servers.plan-loop]
51
+ command = "npx"
52
+ args = ["-y", "@joseph0926/plan-loop"]
53
+ ```
54
+
55
+ 3) Use tools (example)
56
+
57
+ ```text
58
+ pl_start({ goal: "Plan a login feature" })
59
+ pl_submit({ session_id: "abc123", plan: "1. ..." })
60
+ pl_get_plan({ session_id: "abc123" })
61
+ pl_feedback({ session_id: "abc123", rating: "🟢", content: "LGTM" })
62
+ ```
63
+
64
+ ## Tool list
65
+
66
+ - pl_start: start a session
67
+ - pl_submit: submit a plan
68
+ - pl_get_plan: fetch the latest plan
69
+ - pl_feedback: submit feedback for the latest plan
70
+ - pl_get_feedback: fetch the latest feedback
71
+ - pl_status: fetch full session data
72
+ - pl_list: list all sessions (with filter/sort)
73
+ - pl_delete: delete a session
74
+ - pl_force_approve: approve an exhausted session
75
+
76
+ ## Agent Collaboration
77
+
78
+ Claude-Code (planner) and Codex (reviewer) collaborate to review plans.
79
+
80
+ ### Quick Start
81
+
82
+ ```text
83
+ # 1. Claude-Code: Start session and submit plan
84
+ pl_start({ goal: "Implement login feature" })
85
+ pl_submit({ session_id: "...", plan: "1. DB schema..." })
86
+
87
+ # 2. Codex: Fetch plan and provide feedback
88
+ pl_get_plan({ session_id: "..." })
89
+ pl_feedback({ session_id: "...", rating: "🟡", content: "Please specify auth method" })
90
+
91
+ # 3. Claude-Code: Check feedback and revise
92
+ pl_get_feedback({ session_id: "..." })
93
+ pl_submit({ session_id: "...", plan: "Revised plan..." })
94
+
95
+ # 4. Codex: Approve
96
+ pl_feedback({ session_id: "...", rating: "🟢", content: "LGTM" })
97
+ ```
98
+
99
+ ### Detailed Agent Guidelines
100
+
101
+ See [AGENTS.md](AGENTS.md) for detailed workflows and feedback auto-completion guide.
102
+
103
+ ## State storage
104
+
105
+ Session files are stored under `~/.plan-loop/sessions/`.
106
+
107
+ ## Development
108
+
109
+ ```bash
110
+ npm run dev
111
+ npm run build
112
+ ```
113
+
114
+ ## Sample configuration
115
+
116
+ To add MCP configuration to your project:
117
+
118
+ ```bash
119
+ cp .mcp.json.example .mcp.json
120
+ ```
121
+
122
+ ## License
123
+
124
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Plan Loop CLI
4
+ * Setup MCP server for Claude Code and Codex
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;GAGG"}
package/dist/cli.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Plan Loop CLI
4
+ * Setup MCP server for Claude Code and Codex
5
+ */
6
+ import { setupClaude } from './setup/claude.js';
7
+ import { setupCodex } from './setup/codex.js';
8
+ const HELP_TEXT = `
9
+ plan-loop - MCP server for Claude Code and Codex collaboration
10
+
11
+ Usage:
12
+ plan-loop Start MCP server (default)
13
+ plan-loop setup [options] Configure MCP for Claude Code and/or Codex
14
+
15
+ Setup Options:
16
+ --claude Setup Claude Code only (default: project scope)
17
+ --codex Setup Codex only (always user scope)
18
+ --user Use user scope for Claude Code (~/.claude.json)
19
+ --help, -h Show this help message
20
+
21
+ Examples:
22
+ npx @joseph0926/plan-loop setup # Setup both Claude + Codex
23
+ npx @joseph0926/plan-loop setup --claude # Claude Code only (project)
24
+ npx @joseph0926/plan-loop setup --codex # Codex only
25
+ npx @joseph0926/plan-loop setup --user # Claude Code user scope
26
+ `;
27
+ async function main() {
28
+ const args = process.argv.slice(2);
29
+ const command = args[0];
30
+ // Help
31
+ if (args.includes('--help') || args.includes('-h')) {
32
+ console.log(HELP_TEXT);
33
+ process.exit(0);
34
+ }
35
+ // Setup command
36
+ if (command === 'setup') {
37
+ const claudeOnly = args.includes('--claude');
38
+ const codexOnly = args.includes('--codex');
39
+ const userScope = args.includes('--user');
40
+ const both = !claudeOnly && !codexOnly;
41
+ console.log('🔧 Plan Loop Setup\n');
42
+ let success = true;
43
+ if (both || claudeOnly) {
44
+ const scope = userScope ? 'user' : 'project';
45
+ console.log(`📦 Claude Code (${scope} scope)...`);
46
+ const result = await setupClaude({ scope });
47
+ if (result.success) {
48
+ console.log(` ✅ ${result.message}\n`);
49
+ }
50
+ else {
51
+ console.log(` ❌ ${result.message}\n`);
52
+ success = false;
53
+ }
54
+ }
55
+ if (both || codexOnly) {
56
+ console.log('📦 Codex (user scope)...');
57
+ const result = await setupCodex();
58
+ if (result.success) {
59
+ console.log(` ✅ ${result.message}\n`);
60
+ }
61
+ else {
62
+ console.log(` ❌ ${result.message}\n`);
63
+ success = false;
64
+ }
65
+ }
66
+ if (success) {
67
+ console.log('🎉 Setup complete!\n');
68
+ console.log('Verify with:');
69
+ if (both || claudeOnly)
70
+ console.log(' claude mcp list');
71
+ if (both || codexOnly)
72
+ console.log(' codex mcp list');
73
+ console.log('\nOr use /mcp command inside the IDE.');
74
+ }
75
+ else {
76
+ console.log('⚠️ Setup completed with some errors.');
77
+ process.exit(1);
78
+ }
79
+ return;
80
+ }
81
+ // Default: start MCP server
82
+ if (!command || command.startsWith('-')) {
83
+ // Dynamic import to start MCP server
84
+ await import('./index.js');
85
+ return;
86
+ }
87
+ // Unknown command
88
+ console.error(`Unknown command: ${command}`);
89
+ console.log(HELP_TEXT);
90
+ process.exit(1);
91
+ }
92
+ main().catch((err) => {
93
+ console.error('Fatal error:', err);
94
+ process.exit(1);
95
+ });
96
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Plan Loop MCP Server
4
+ * Claude-Code와 Codex 간의 비동기 협업을 위한 MCP 서버
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}