@jojonax/codex-copilot 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jonas Qin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # Codex-Copilot 🤖
2
+
3
+ **PRD-driven automated development orchestrator for CodeX / Cursor**
4
+
5
+ Turn your PRD into working code — automatically. Codex-Copilot reads your product requirement docs, breaks them into tasks, drives CodeX/Cursor to develop each feature, submits PRs, waits for AI code review, fixes issues, and merges — all in a loop.
6
+
7
+ ```
8
+ PRD → Tasks → CodeX Dev → PR → AI Review → Fix → Merge → Next Task
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ # Install globally
15
+ npm install -g codex-copilot
16
+
17
+ # Or run directly without installing
18
+ npx codex-copilot
19
+
20
+ # In your project directory:
21
+ codex-copilot init # Detect PRD, generate task queue
22
+ codex-copilot run # Start the automated dev loop
23
+ ```
24
+
25
+ ## How It Works
26
+
27
+ ### 1. `codex-copilot init`
28
+
29
+ - 🔍 **Auto-detects PRD** files in your project (by filename, size, content keywords)
30
+ - 📋 Generates a task decomposition prompt for CodeX
31
+ - 🗂️ Creates `.codex-copilot/` with config, state, and instructions
32
+
33
+ ### 2. Execute the PRD prompt in CodeX
34
+
35
+ - Paste the generated prompt into CodeX desktop (or use CodeX CLI if available)
36
+ - CodeX breaks down your PRD into ordered, independent tasks → `tasks.json`
37
+
38
+ ### 3. `codex-copilot run`
39
+
40
+ Loops through each task in 4 phases:
41
+
42
+ | Phase | What Happens |
43
+ |-------|-------------|
44
+ | **1. Develop** | Creates feature branch, generates dev prompt, copies to clipboard |
45
+ | **2. PR** | Auto commits, pushes, creates GitHub PR via `gh` CLI |
46
+ | **3. Review** | Polls for AI review (Gemini Code Assist), collects feedback |
47
+ | **4. Merge** | Squash merges after approval, moves to next task |
48
+
49
+ ### Other Commands
50
+
51
+ ```bash
52
+ codex-copilot status # Progress bar + task list
53
+ codex-copilot reset # Reset and start over
54
+ ```
55
+
56
+ ## Prerequisites
57
+
58
+ | Tool | Install |
59
+ |------|---------|
60
+ | Node.js ≥ 18 | `brew install node` |
61
+ | GitHub CLI | `brew install gh && gh auth login` |
62
+ | [Gemini Code Assist](https://github.com/marketplace/gemini-code-assist) | Install on your GitHub repo |
63
+ | CodeX Desktop / Cursor | Official installer |
64
+
65
+ ## Features
66
+
67
+ - **🔍 Smart PRD Detection** — scans project dirs, scores candidates by filename pattern + content analysis
68
+ - **🔄 Breakpoint Resume** — `state.json` persists progress; interrupted runs continue from last task
69
+ - **📋 Clipboard Integration** — auto-copies prompts to clipboard (macOS `pbcopy`)
70
+ - **🤖 Dual Mode** — full-auto with CodeX CLI, or manual clipboard mode for desktop app
71
+ - **🔁 Review Loop** — max 2 rounds of AI review + fix, with human override options
72
+ - **⚙️ Configurable** — edit `.codex-copilot/config.json` for timeouts, branch names, review rounds
73
+
74
+ ## Configuration
75
+
76
+ After `init`, edit `.codex-copilot/config.json`:
77
+
78
+ ```json
79
+ {
80
+ "base_branch": "main",
81
+ "max_review_rounds": 2,
82
+ "review_poll_interval": 60,
83
+ "review_wait_timeout": 600
84
+ }
85
+ ```
86
+
87
+ ## Project Structure
88
+
89
+ ```
90
+ .codex-copilot/ # Created in your project
91
+ ├── config.json # Settings
92
+ ├── state.json # Run state (auto-managed)
93
+ ├── tasks.json # Task queue (CodeX-generated)
94
+ ├── codex-instructions.md # CodeX system prompt
95
+ └── _current_prompt.md # Current prompt (auto-copied to clipboard)
96
+ ```
97
+
98
+ ## How the Review Loop Works
99
+
100
+ ```
101
+ CodeX develops feature
102
+
103
+ Push + Create PR
104
+
105
+ Wait for AI Review (Gemini Code Assist)
106
+
107
+ ┌─ APPROVED → Merge → Next Task
108
+ └─ CHANGES_REQUESTED → Collect feedback
109
+
110
+ Generate fix prompt → CodeX fixes
111
+
112
+ Push → Wait for re-review
113
+
114
+ (max 2 rounds, then human decides)
115
+ ```
116
+
117
+ ## Roadmap
118
+
119
+ - [ ] Support for more AI review tools (CodeRabbit, GitHub Copilot Review)
120
+ - [ ] Built-in task decomposition (no manual CodeX step)
121
+ - [ ] Web dashboard for monitoring multiple projects
122
+ - [ ] GitHub Action for fully server-side automation
123
+ - [ ] Support for monorepo / multi-package projects
124
+
125
+ ## License
126
+
127
+ MIT © Jonas Qin
package/bin/cli.js ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * codex-copilot CLI - PRD → 自动开发 → PR → Review → 修复 → 合并
5
+ *
6
+ * 用法:
7
+ * codex-copilot init # 初始化项目(自动检测 PRD,生成任务)
8
+ * codex-copilot run # 启动自动化开发循环
9
+ * codex-copilot status # 查看当前进度
10
+ * codex-copilot reset # 重置状态(重新开始)
11
+ */
12
+
13
+ import { fileURLToPath } from 'url';
14
+ import { dirname, resolve } from 'path';
15
+ import { existsSync } from 'fs';
16
+
17
+ import { init } from '../src/commands/init.js';
18
+ import { run } from '../src/commands/run.js';
19
+ import { status } from '../src/commands/status.js';
20
+ import { reset } from '../src/commands/reset.js';
21
+ import { log } from '../src/utils/logger.js';
22
+
23
+ const command = process.argv[2];
24
+ const projectDir = process.cwd();
25
+
26
+ // Banner
27
+ console.log('');
28
+ console.log(' ╔══════════════════════════════════════════╗');
29
+ console.log(' ║ 🤖 Codex-Copilot v1.0 ║');
30
+ console.log(' ║ PRD-Driven Auto Development ║');
31
+ console.log(' ╚══════════════════════════════════════════╝');
32
+ console.log('');
33
+
34
+ async function main() {
35
+ try {
36
+ switch (command) {
37
+ case 'init':
38
+ await init(projectDir);
39
+ break;
40
+
41
+ case 'run':
42
+ if (!existsSync(resolve(projectDir, '.codex-copilot/tasks.json'))) {
43
+ log.error('尚未初始化,请先运行: codex-copilot init');
44
+ process.exit(1);
45
+ }
46
+ await run(projectDir);
47
+ break;
48
+
49
+ case 'status':
50
+ if (!existsSync(resolve(projectDir, '.codex-copilot/tasks.json'))) {
51
+ log.error('尚未初始化,请先运行: codex-copilot init');
52
+ process.exit(1);
53
+ }
54
+ await status(projectDir);
55
+ break;
56
+
57
+ case 'reset':
58
+ await reset(projectDir);
59
+ break;
60
+
61
+ default:
62
+ console.log(' 用法: codex-copilot <command>');
63
+ console.log('');
64
+ console.log(' 命令:');
65
+ console.log(' init 初始化项目(自动检测 PRD,生成任务队列)');
66
+ console.log(' run 启动自动化开发循环');
67
+ console.log(' status 查看当前任务进度');
68
+ console.log(' reset 重置状态,重新开始');
69
+ console.log('');
70
+ console.log(' 工作流程:');
71
+ console.log(' 1. cd 到你的项目目录');
72
+ console.log(' 2. codex-copilot init (自动检测 PRD 并拆解任务)');
73
+ console.log(' 3. codex-copilot run (开始自动开发循环)');
74
+ console.log('');
75
+ break;
76
+ }
77
+ } catch (err) {
78
+ log.error(`执行失败: ${err.message}`);
79
+ if (process.env.DEBUG) console.error(err);
80
+ process.exit(1);
81
+ }
82
+ }
83
+
84
+ main();
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@jojonax/codex-copilot",
3
+ "version": "1.0.0",
4
+ "description": "PRD-driven automated development orchestrator for CodeX / Cursor",
5
+ "bin": {
6
+ "codex-copilot": "./bin/cli.js"
7
+ },
8
+ "type": "module",
9
+ "files": [
10
+ "bin/",
11
+ "src/",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "keywords": [
16
+ "codex",
17
+ "cursor",
18
+ "ai",
19
+ "automation",
20
+ "prd",
21
+ "code-review",
22
+ "github",
23
+ "developer-tools",
24
+ "cli"
25
+ ],
26
+ "author": "Jonas Qin",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/jonasqin/codex-copilot.git"
31
+ },
32
+ "homepage": "https://github.com/jonasqin/codex-copilot#readme",
33
+ "bugs": {
34
+ "url": "https://github.com/jonasqin/codex-copilot/issues"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ }
39
+ }
@@ -0,0 +1,257 @@
1
+ /**
2
+ * codex-copilot init - 初始化项目
3
+ *
4
+ * 1. 自动检测 PRD 文档
5
+ * 2. 让用户确认/选择 PRD
6
+ * 3. 生成 CodeX 可执行的任务拆解 Prompt
7
+ * 4. 创建 .codex-copilot/ 目录结构
8
+ */
9
+
10
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, copyFileSync } from 'fs';
11
+ import { resolve, dirname } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { execSync } from 'child_process';
14
+ import { detectPRD, readPRD } from '../utils/detect-prd.js';
15
+ import { log } from '../utils/logger.js';
16
+ import { ask, confirm, select, closePrompt } from '../utils/prompt.js';
17
+ import { git } from '../utils/git.js';
18
+ import { github } from '../utils/github.js';
19
+
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+
22
+ export async function init(projectDir) {
23
+ log.title('📋 初始化 Codex-Copilot');
24
+ log.blank();
25
+
26
+ // ===== 前置检查 =====
27
+ log.step('检查环境...');
28
+
29
+ // 检查是否在 git 仓库中
30
+ try {
31
+ git.currentBranch(projectDir);
32
+ log.info('Git 仓库 ✓');
33
+ } catch {
34
+ log.error('当前目录不是 Git 仓库,请先 git init');
35
+ closePrompt();
36
+ process.exit(1);
37
+ }
38
+
39
+ // 检查 gh CLI
40
+ if (!github.checkGhAuth()) {
41
+ log.error('GitHub CLI 未登录,请先运行: gh auth login');
42
+ closePrompt();
43
+ process.exit(1);
44
+ }
45
+ log.info('GitHub CLI ✓');
46
+
47
+ // 检查 GitHub remote
48
+ try {
49
+ const repo = git.getRepoInfo(projectDir);
50
+ log.info(`GitHub 仓库: ${repo.owner}/${repo.repo} ✓`);
51
+ } catch (err) {
52
+ log.error(err.message);
53
+ closePrompt();
54
+ process.exit(1);
55
+ }
56
+
57
+ log.blank();
58
+
59
+ // ===== 检测 PRD =====
60
+ log.step('扫描 PRD 文档...');
61
+ const candidates = detectPRD(projectDir);
62
+
63
+ let prdPath;
64
+
65
+ if (candidates.length === 0) {
66
+ log.warn('未自动检测到 PRD 文档');
67
+ const manualPath = await ask('请输入 PRD 文件路径(相对或绝对路径):');
68
+ prdPath = resolve(projectDir, manualPath);
69
+ if (!existsSync(prdPath)) {
70
+ log.error(`文件不存在: ${prdPath}`);
71
+ closePrompt();
72
+ process.exit(1);
73
+ }
74
+ } else if (candidates.length === 1) {
75
+ prdPath = candidates[0].path;
76
+ log.info(`找到 PRD: ${candidates[0].relativePath}`);
77
+ const ok = await confirm('使用该文件?');
78
+ if (!ok) {
79
+ const manualPath = await ask('请输入 PRD 文件路径:');
80
+ prdPath = resolve(projectDir, manualPath);
81
+ }
82
+ } else {
83
+ log.info(`找到 ${candidates.length} 个候选 PRD 文件:`);
84
+ const choice = await select('请选择要使用的 PRD:', candidates.map(c => ({
85
+ label: `${c.relativePath} (匹配度: ${c.score})`,
86
+ value: c.path,
87
+ })));
88
+ prdPath = choice.value;
89
+ }
90
+
91
+ log.info(`使用 PRD: ${prdPath}`);
92
+ log.blank();
93
+
94
+ // ===== 读取 PRD =====
95
+ const prdContent = readPRD(prdPath);
96
+ log.info(`PRD 大小: ${(prdContent.length / 1024).toFixed(1)} KB`);
97
+
98
+ // ===== 创建 .codex-copilot 目录 =====
99
+ log.step('创建 .codex-copilot/ 目录...');
100
+ const copilotDir = resolve(projectDir, '.codex-copilot');
101
+ mkdirSync(copilotDir, { recursive: true });
102
+
103
+ // 写入配置文件
104
+ const config = {
105
+ prd_path: prdPath,
106
+ base_branch: git.currentBranch(projectDir) || 'main',
107
+ max_review_rounds: 2,
108
+ review_poll_interval: 60,
109
+ review_wait_timeout: 600,
110
+ created_at: new Date().toISOString(),
111
+ };
112
+ writeFileSync(resolve(copilotDir, 'config.json'), JSON.stringify(config, null, 2));
113
+
114
+ // 写入初始状态
115
+ const state = {
116
+ current_task: 0,
117
+ current_pr: null,
118
+ review_round: 0,
119
+ status: 'initialized',
120
+ };
121
+ writeFileSync(resolve(copilotDir, 'state.json'), JSON.stringify(state, null, 2));
122
+
123
+ // 写入 CodeX 指令模板
124
+ const instructions = `# Codex-Copilot 开发指令
125
+
126
+ ## 角色
127
+ 你是一个高效的自动开发 Agent,负责按照任务描述完成功能开发。
128
+
129
+ ## 规则
130
+ 1. **严格遵循项目技术栈**:使用项目已有的框架、工具和代码风格
131
+ 2. **自测优先**:开发完成前确保代码可以编译/运行
132
+ 3. **Git 规范**:提交信息格式 \`feat(task-N): 简要描述\` 或 \`fix(task-N): 简要描述\`
133
+ 4. **不要修改无关文件**:只修改当前任务需要的文件
134
+ 5. **完成后执行 git commit**:\`git add -A && git commit -m "..."\`
135
+
136
+ ## 修复 Review 时的规则
137
+ 1. 逐条阅读 Review 意见
138
+ 2. 区分必须修复 vs 建议性意见
139
+ 3. 对于不认同的意见,在 commit message 中说明原因
140
+ 4. 修复后确保不引入新问题
141
+ `;
142
+ writeFileSync(resolve(copilotDir, 'codex-instructions.md'), instructions);
143
+
144
+ // 添加 .gitignore 项
145
+ const gitignorePath = resolve(projectDir, '.gitignore');
146
+ const gitignoreEntry = '\n# Codex-Copilot state\n.codex-copilot/state.json\n';
147
+ if (existsSync(gitignorePath)) {
148
+ const content = readFileSync(gitignorePath, 'utf-8');
149
+ if (!content.includes('.codex-copilot/state.json')) {
150
+ writeFileSync(gitignorePath, content + gitignoreEntry);
151
+ }
152
+ }
153
+
154
+ log.info('.codex-copilot/ 目录已创建');
155
+ log.blank();
156
+
157
+ // ===== 生成任务拆解 Prompt =====
158
+ log.step('生成任务拆解 Prompt...');
159
+
160
+ const parsePrompt = buildParsePrompt(prdContent, copilotDir);
161
+ const promptPath = resolve(copilotDir, 'parse-prd-prompt.md');
162
+ writeFileSync(promptPath, parsePrompt);
163
+
164
+ log.info(`任务拆解 Prompt 已保存到: .codex-copilot/parse-prd-prompt.md`);
165
+ log.blank();
166
+
167
+ // ===== 提示用户下一步 =====
168
+ log.title('✅ 初始化完成!');
169
+ log.blank();
170
+ log.info('接下来请执行以下步骤:');
171
+ log.blank();
172
+ console.log(' ┌───────────────────────────────────────────────────┐');
173
+ console.log(' │ 1. 打开 CodeX 桌面版 │');
174
+ console.log(' │ 2. 将以下文件内容粘贴给 CodeX 执行: │');
175
+ console.log(' │ .codex-copilot/parse-prd-prompt.md │');
176
+ console.log(' │ 3. CodeX 会生成 .codex-copilot/tasks.json │');
177
+ console.log(' │ 4. 确认任务列表后运行: │');
178
+ console.log(' │ codex-copilot run │');
179
+ console.log(' └───────────────────────────────────────────────────┘');
180
+ log.blank();
181
+
182
+ // 询问是否尝试自动拆解(如果 codex CLI 可用)
183
+ const hasCodexCLI = checkCodexCLI();
184
+ if (hasCodexCLI) {
185
+ log.info('检测到 CodeX CLI 可用!');
186
+ const autoparse = await confirm('是否自动调用 CodeX 拆解 PRD?');
187
+ if (autoparse) {
188
+ log.step('调用 CodeX CLI 拆解 PRD...');
189
+ try {
190
+ const { execSync } = await import('child_process');
191
+ execSync(`codex -q "${parsePrompt.slice(0, 2000)}"`, {
192
+ cwd: projectDir,
193
+ stdio: 'inherit',
194
+ });
195
+ log.info('CodeX 拆解完成!');
196
+ } catch {
197
+ log.warn('CodeX CLI 调用失败,请手动执行');
198
+ }
199
+ }
200
+ }
201
+
202
+ closePrompt();
203
+ }
204
+
205
+ function checkCodexCLI() {
206
+ try {
207
+ execSync('which codex', { stdio: 'pipe' });
208
+ return true;
209
+ } catch {
210
+ return false;
211
+ }
212
+ }
213
+
214
+ function buildParsePrompt(prdContent, copilotDir) {
215
+ return `请阅读以下 PRD 文档,将其拆解为独立的开发任务。
216
+
217
+ ## 要求
218
+ 1. 每个任务在一个 PR 中可以完成(粒度适中,不要太大也不要太碎)
219
+ 2. 有明确的验收标准
220
+ 3. 按依赖关系排序(被依赖的任务排在前面)
221
+ 4. 第一个任务通常是"项目初始化 / 基础框架搭建"
222
+
223
+ ## 输出格式
224
+ 将结果输出到 \`.codex-copilot/tasks.json\`,格式如下:
225
+
226
+ \`\`\`json
227
+ {
228
+ "project": "项目名称",
229
+ "total": 5,
230
+ "tasks": [
231
+ {
232
+ "id": 1,
233
+ "title": "任务标题(简短)",
234
+ "description": "详细的任务描述,包含需要实现的具体功能和技术细节",
235
+ "acceptance": ["验收条件1", "验收条件2"],
236
+ "branch": "feature/001-task-slug",
237
+ "status": "pending",
238
+ "depends_on": []
239
+ },
240
+ {
241
+ "id": 2,
242
+ "title": "...",
243
+ "description": "...",
244
+ "acceptance": ["..."],
245
+ "branch": "feature/002-task-slug",
246
+ "status": "pending",
247
+ "depends_on": [1]
248
+ }
249
+ ]
250
+ }
251
+ \`\`\`
252
+
253
+ ## PRD 文档内容
254
+
255
+ ${prdContent}
256
+ `;
257
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * codex-copilot reset - 重置状态
3
+ */
4
+
5
+ import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
6
+ import { resolve } from 'path';
7
+ import { log } from '../utils/logger.js';
8
+ import { confirm, closePrompt } from '../utils/prompt.js';
9
+
10
+ export async function reset(projectDir) {
11
+ const statePath = resolve(projectDir, '.codex-copilot/state.json');
12
+ const tasksPath = resolve(projectDir, '.codex-copilot/tasks.json');
13
+
14
+ if (!existsSync(statePath)) {
15
+ log.warn('项目未初始化,无需重置');
16
+ closePrompt();
17
+ return;
18
+ }
19
+
20
+ log.title('🔄 重置 Codex-Copilot 状态');
21
+ log.blank();
22
+
23
+ const resetTasks = await confirm('是否同时重置任务状态 (所有任务标记为 pending)?', false);
24
+
25
+ // 重置 state
26
+ const state = {
27
+ current_task: 0,
28
+ current_pr: null,
29
+ review_round: 0,
30
+ status: 'initialized',
31
+ };
32
+ writeFileSync(statePath, JSON.stringify(state, null, 2));
33
+ log.info('执行状态已重置');
34
+
35
+ // 重置任务状态
36
+ if (resetTasks && existsSync(tasksPath)) {
37
+ const tasks = JSON.parse(readFileSync(tasksPath, 'utf-8'));
38
+ for (const task of tasks.tasks) {
39
+ task.status = 'pending';
40
+ }
41
+ writeFileSync(tasksPath, JSON.stringify(tasks, null, 2));
42
+ log.info('任务状态已重置');
43
+ }
44
+
45
+ // 清理临时文件
46
+ const promptPath = resolve(projectDir, '.codex-copilot/_current_prompt.md');
47
+ if (existsSync(promptPath)) unlinkSync(promptPath);
48
+
49
+ log.blank();
50
+ log.info('✅ 重置完成,可以重新运行 codex-copilot run');
51
+ closePrompt();
52
+ }