prr-kit 1.0.0 → 1.1.1

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.
Files changed (29) hide show
  1. package/README.md +235 -226
  2. package/package.json +60 -60
  3. package/src/prr/workflows/2-analyze/describe-pr/templates/pr-description.template.md +51 -51
  4. package/src/prr/workflows/3-review/architecture-review/workflow.yaml +18 -18
  5. package/src/prr/workflows/3-review/general-review/workflow.yaml +18 -18
  6. package/src/prr/workflows/3-review/performance-review/workflow.yaml +18 -18
  7. package/src/prr/workflows/3-review/security-review/workflow.yaml +19 -19
  8. package/src/prr/workflows/4-improve/improve-code/workflow.yaml +18 -18
  9. package/src/prr/workflows/6-report/generate-report/templates/review-report.template.md +78 -78
  10. package/tools/cli/installers/lib/core/installer.js +162 -162
  11. package/tools/cli/installers/lib/ide/_config-driven.js +70 -0
  12. package/tools/cli/installers/lib/ide/codex.js +128 -0
  13. package/tools/cli/installers/lib/ide/github-copilot.js +262 -0
  14. package/tools/cli/installers/lib/ide/kilo.js +132 -0
  15. package/tools/cli/installers/lib/ide/manager.js +37 -1
  16. package/tools/cli/installers/lib/ide/platform-codes.yaml +104 -4
  17. package/tools/cli/installers/lib/ide/templates/combined/antigravity-agent.md +15 -0
  18. package/tools/cli/installers/lib/ide/templates/combined/antigravity-workflow.md +8 -0
  19. package/tools/cli/installers/lib/ide/templates/combined/gemini-agent.md +16 -0
  20. package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.md +7 -0
  21. package/tools/cli/installers/lib/ide/templates/combined/kiro-agent.md +16 -0
  22. package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md +9 -0
  23. package/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +15 -0
  24. package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +6 -0
  25. package/tools/cli/installers/lib/ide/templates/combined/rovodev-agent.md +10 -0
  26. package/tools/cli/installers/lib/ide/templates/combined/rovodev-workflow.md +9 -0
  27. package/tools/cli/installers/lib/ide/templates/combined/trae-agent.md +11 -0
  28. package/tools/cli/installers/lib/ide/templates/combined/trae-workflow.md +9 -0
  29. package/tools/cli/prr-cli.js +36 -36
@@ -0,0 +1,262 @@
1
+ /**
2
+ * GitHub Copilot setup handler
3
+ * Creates agents in .github/agents/, prompts in .github/prompts/,
4
+ * and generates copilot-instructions.md
5
+ */
6
+ const path = require('node:path');
7
+ const { BaseIdeSetup } = require('./_base-ide');
8
+ const fs = require('fs-extra');
9
+ const { glob } = require('glob');
10
+ const yaml = require('yaml');
11
+
12
+ class GitHubCopilotSetup extends BaseIdeSetup {
13
+ constructor() {
14
+ super('github-copilot', 'GitHub Copilot', false);
15
+ this.configDir = null;
16
+ this.githubDir = '.github';
17
+ this.agentsDir = 'agents';
18
+ this.promptsDir = 'prompts';
19
+ this.detectionPaths = ['.github/copilot-instructions.md', '.github/agents'];
20
+ }
21
+
22
+ async setup(projectDir, prrDir, options = {}) {
23
+ const githubDir = path.join(projectDir, this.githubDir);
24
+ const agentsDir = path.join(githubDir, this.agentsDir);
25
+ const promptsDir = path.join(githubDir, this.promptsDir);
26
+ await this.ensureDir(agentsDir);
27
+ await this.ensureDir(promptsDir);
28
+
29
+ await this.cleanup(projectDir);
30
+
31
+ const selectedModules = options.selectedModules || ['prr'];
32
+ const allModules = ['core', ...selectedModules.filter((m) => m !== 'core')];
33
+
34
+ let agentCount = 0;
35
+ let promptCount = 0;
36
+
37
+ // Install agent files to .github/agents/
38
+ for (const mod of allModules) {
39
+ const agentsSrcDir = path.join(prrDir, mod, 'agents');
40
+ if (!(await fs.pathExists(agentsSrcDir))) continue;
41
+
42
+ const agentFiles = await glob('**/*.md', { cwd: agentsSrcDir });
43
+ for (const agentFile of agentFiles) {
44
+ const agentPath = path.join(agentsSrcDir, agentFile);
45
+ const agentContent = await fs.readFile(agentPath, 'utf8');
46
+
47
+ if (/^no-launcher:\s*true/m.test(agentContent)) continue;
48
+
49
+ const nameMatch = agentContent.match(/^name:\s*[\"']?([^\"'\n]+)[\"']?/m);
50
+ const descMatch = agentContent.match(/^description:\s*[\"']?([^\"'\n]+)[\"']?/m);
51
+ const agentName = nameMatch?.[1]?.trim() || path.basename(agentFile, '.md');
52
+ const agentDesc = descMatch?.[1]?.trim() || `${agentName} reviewer`;
53
+ const relAgentPath = `${this.prrFolderName}/${mod}/agents/${agentFile}`.replaceAll('\\', '/');
54
+
55
+ const content = this._agentFileContent(agentName, agentDesc, relAgentPath);
56
+ const fileName = `prr-${path.basename(agentFile, '.md')}.agent.md`;
57
+ await fs.writeFile(path.join(agentsDir, fileName), content, 'utf8');
58
+ agentCount++;
59
+ }
60
+ }
61
+
62
+ // Install workflow prompts to .github/prompts/
63
+ for (const mod of allModules) {
64
+ const workflowsSrcDir = path.join(prrDir, mod, 'workflows');
65
+ if (!(await fs.pathExists(workflowsSrcDir))) continue;
66
+
67
+ const workflowFiles = await glob('**/workflow{.md,.yaml}', { cwd: workflowsSrcDir });
68
+ for (const wfFile of workflowFiles) {
69
+ const wfPath = path.join(workflowsSrcDir, wfFile);
70
+ const wfContent = await fs.readFile(wfPath, 'utf8');
71
+
72
+ let wfName = path.basename(path.dirname(wfFile));
73
+ let wfDesc = '';
74
+
75
+ if (wfFile.endsWith('.yaml')) {
76
+ try { const d = yaml.parse(wfContent); wfName = d.name || wfName; wfDesc = d.description || ''; } catch { /* ignore */ }
77
+ } else {
78
+ const normalized = wfContent.replace(/\r\n/g, '\n');
79
+ const fmMatch = normalized.match(/^---\n([\s\S]*?)\n---/);
80
+ if (fmMatch) {
81
+ try { const fm = yaml.parse(fmMatch[1]); wfName = fm.name || wfName; wfDesc = fm.description || ''; } catch { /* ignore */ }
82
+ }
83
+ }
84
+
85
+ const dirParts = path.dirname(wfFile).split(path.sep).filter(Boolean);
86
+ const leafDir = dirParts.at(-1) || wfName;
87
+ const relWfPath = `${this.prrFolderName}/${mod}/workflows/${wfFile}`.replaceAll('\\', '/');
88
+ const isYaml = wfFile.endsWith('.yaml');
89
+
90
+ const content = this._workflowPromptContent(wfName, wfDesc, relWfPath, isYaml);
91
+ const fileName = `prr-${leafDir}.prompt.md`;
92
+ await fs.writeFile(path.join(promptsDir, fileName), content, 'utf8');
93
+ promptCount++;
94
+ }
95
+ }
96
+
97
+ // Generate copilot-instructions.md
98
+ await this._generateCopilotInstructions(projectDir, prrDir, options);
99
+
100
+ return { success: true, results: { agents: agentCount, workflows: promptCount } };
101
+ }
102
+
103
+ _agentFileContent(name, description, agentPath) {
104
+ return `---
105
+ description: '${description.replaceAll("'", "''")}'
106
+ tools: ['read', 'edit', 'search', 'execute']
107
+ disable-model-invocation: true
108
+ ---
109
+
110
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified.
111
+
112
+ <agent-activation CRITICAL="TRUE">
113
+ 1. LOAD the FULL agent file from {project-root}/${agentPath}
114
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
115
+ 3. FOLLOW every step in the <activation> section precisely
116
+ 4. DISPLAY the welcome/greeting as instructed
117
+ 5. PRESENT the numbered menu
118
+ 6. WAIT for user input before proceeding
119
+ </agent-activation>
120
+ `;
121
+ }
122
+
123
+ _workflowPromptContent(name, description, wfPath, isYaml) {
124
+ const safeDesc = (description || name).replaceAll("'", "''");
125
+ let body;
126
+ if (isYaml) {
127
+ body = `1. Load {project-root}/${this.prrFolderName}/prr/config.yaml and store ALL fields as session variables
128
+ 2. Load the workflow engine at {project-root}/${this.prrFolderName}/core/tasks/workflow.xml
129
+ 3. Load and execute the workflow at {project-root}/${wfPath} using the engine from step 2`;
130
+ } else {
131
+ body = `1. Load {project-root}/${this.prrFolderName}/prr/config.yaml and store ALL fields as session variables
132
+ 2. Load and follow the workflow at {project-root}/${wfPath}`;
133
+ }
134
+
135
+ return `---
136
+ description: '${safeDesc}'
137
+ agent: 'agent'
138
+ tools: ['read', 'edit', 'search', 'execute']
139
+ ---
140
+
141
+ ${body}
142
+ `;
143
+ }
144
+
145
+ async _generateCopilotInstructions(projectDir, prrDir, options = {}) {
146
+ const configPath = path.join(prrDir, 'prr', 'config.yaml');
147
+ let config = {};
148
+ if (await fs.pathExists(configPath)) {
149
+ try { config = yaml.parse(await fs.readFile(configPath, 'utf8')) || {}; } catch { /* ignore */ }
150
+ }
151
+
152
+ const prr = this.prrFolderName;
153
+ const section = `# PR Review Kit — Project Instructions
154
+
155
+ ## Project Configuration
156
+
157
+ - **User**: ${config.user_name || 'Dev'}
158
+ - **Communication Language**: ${config.communication_language || 'English'}
159
+ - **Target Repo**: ${config.target_repo || '.'}
160
+ - **Output Folder**: ${config.output_folder || '_prr-output'}
161
+ - **Review Output**: ${config.review_output || '_prr-output/reviews'}
162
+
163
+ ## PRR Runtime Structure
164
+
165
+ - **Agent definitions**: \`${prr}/core/agents/\` and \`${prr}/prr/agents/\`
166
+ - **Workflow definitions**: \`${prr}/prr/workflows/\` (organized by phase)
167
+ - **Core tasks**: \`${prr}/core/tasks/\`
168
+ - **Module configuration**: \`${prr}/prr/config.yaml\`
169
+
170
+ ## Key Conventions
171
+
172
+ - Always load \`${prr}/prr/config.yaml\` before any agent activation or workflow execution
173
+ - MD-based workflows execute directly — load and follow the \`.md\` file
174
+ - YAML-based workflows require the workflow engine — load \`core/tasks/workflow.xml\` first
175
+ - The \`{project-root}\` variable resolves to the workspace root at runtime
176
+
177
+ ## Available Agents
178
+
179
+ | Agent | Slash Command | Speciality |
180
+ |-------|--------------|------------|
181
+ | PRR Master | \`/prr-master\` | Orchestrator — routes all workflows |
182
+ | PRR Quick | \`/prr-quick\` | One-command full pipeline |
183
+
184
+ ## Slash Commands
185
+
186
+ Use \`#prr-\` in Copilot Chat to access PR Review prompts, or select agents from the agents dropdown.`;
187
+
188
+ const instructionsPath = path.join(projectDir, this.githubDir, 'copilot-instructions.md');
189
+ const markerStart = '<!-- PRR:START -->';
190
+ const markerEnd = '<!-- PRR:END -->';
191
+ const markedContent = `${markerStart}\n${section}\n${markerEnd}`;
192
+
193
+ if (await fs.pathExists(instructionsPath)) {
194
+ const existing = await fs.readFile(instructionsPath, 'utf8');
195
+ const startIdx = existing.indexOf(markerStart);
196
+ const endIdx = existing.indexOf(markerEnd);
197
+
198
+ if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
199
+ const merged = existing.slice(0, startIdx) + markedContent + existing.slice(endIdx + markerEnd.length);
200
+ await fs.writeFile(instructionsPath, merged, 'utf8');
201
+ } else {
202
+ const backupPath = `${instructionsPath}.bak`;
203
+ await fs.copy(instructionsPath, backupPath);
204
+ await fs.writeFile(instructionsPath, `${markedContent}\n`, 'utf8');
205
+ }
206
+ } else {
207
+ await fs.writeFile(instructionsPath, `${markedContent}\n`, 'utf8');
208
+ }
209
+ }
210
+
211
+ async cleanup(projectDir, options = {}) {
212
+ // Clean agents
213
+ const agentsDir = path.join(projectDir, this.githubDir, this.agentsDir);
214
+ if (await fs.pathExists(agentsDir)) {
215
+ const files = await fs.readdir(agentsDir);
216
+ for (const file of files) {
217
+ if (file.startsWith('prr-') && file.endsWith('.agent.md')) {
218
+ await fs.remove(path.join(agentsDir, file));
219
+ }
220
+ }
221
+ }
222
+
223
+ // Clean prompts
224
+ const promptsDir = path.join(projectDir, this.githubDir, this.promptsDir);
225
+ if (await fs.pathExists(promptsDir)) {
226
+ const files = await fs.readdir(promptsDir);
227
+ for (const file of files) {
228
+ if (file.startsWith('prr-') && file.endsWith('.prompt.md')) {
229
+ await fs.remove(path.join(promptsDir, file));
230
+ }
231
+ }
232
+ }
233
+
234
+ // On uninstall, strip PRR markers from copilot-instructions.md
235
+ if (options.isUninstall) {
236
+ await this._cleanupCopilotInstructions(projectDir);
237
+ }
238
+ }
239
+
240
+ async _cleanupCopilotInstructions(projectDir) {
241
+ const instructionsPath = path.join(projectDir, this.githubDir, 'copilot-instructions.md');
242
+ if (!(await fs.pathExists(instructionsPath))) return;
243
+
244
+ const content = await fs.readFile(instructionsPath, 'utf8');
245
+ const markerStart = '<!-- PRR:START -->';
246
+ const markerEnd = '<!-- PRR:END -->';
247
+ const startIdx = content.indexOf(markerStart);
248
+ const endIdx = content.indexOf(markerEnd);
249
+ if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return;
250
+
251
+ const cleaned = content.slice(0, startIdx) + content.slice(endIdx + markerEnd.length);
252
+ if (cleaned.trim().length === 0) {
253
+ await fs.remove(instructionsPath);
254
+ const backupPath = `${instructionsPath}.bak`;
255
+ if (await fs.pathExists(backupPath)) await fs.rename(backupPath, instructionsPath);
256
+ } else {
257
+ await fs.writeFile(instructionsPath, cleaned, 'utf8');
258
+ }
259
+ }
260
+ }
261
+
262
+ module.exports = { GitHubCopilotSetup };
@@ -0,0 +1,132 @@
1
+ /**
2
+ * KiloCoder IDE setup handler
3
+ * Creates custom modes in .kilocodemodes + workflow files in .kilocode/workflows/
4
+ */
5
+ const path = require('node:path');
6
+ const { BaseIdeSetup } = require('./_base-ide');
7
+ const fs = require('fs-extra');
8
+ const { glob } = require('glob');
9
+ const yaml = require('yaml');
10
+
11
+ class KiloSetup extends BaseIdeSetup {
12
+ constructor() {
13
+ super('kilo', 'KiloCoder', false);
14
+ this.configFile = '.kilocodemodes';
15
+ }
16
+
17
+ async setup(projectDir, prrDir, options = {}) {
18
+ await this.cleanup(projectDir);
19
+
20
+ const kiloModesPath = path.join(projectDir, this.configFile);
21
+ let config = {};
22
+ if (await fs.pathExists(kiloModesPath)) {
23
+ try { config = yaml.parse(await fs.readFile(kiloModesPath, 'utf8')) || {}; } catch { config = {}; }
24
+ }
25
+ if (!Array.isArray(config.customModes)) config.customModes = [];
26
+
27
+ const selectedModules = options.selectedModules || ['prr'];
28
+ const allModules = ['core', ...selectedModules.filter((m) => m !== 'core')];
29
+ let modeCount = 0;
30
+
31
+ // Add custom modes from agents
32
+ for (const mod of allModules) {
33
+ const agentsSrcDir = path.join(prrDir, mod, 'agents');
34
+ if (!(await fs.pathExists(agentsSrcDir))) continue;
35
+
36
+ const agentFiles = await glob('**/*.md', { cwd: agentsSrcDir });
37
+ for (const agentFile of agentFiles) {
38
+ const agentContent = await fs.readFile(path.join(agentsSrcDir, agentFile), 'utf8');
39
+ if (/^no-launcher:\s*true/m.test(agentContent)) continue;
40
+
41
+ const nameMatch = agentContent.match(/^name:\s*[\"']?([^\"'\n]+)[\"']?/m);
42
+ const descMatch = agentContent.match(/^description:\s*[\"']?([^\"'\n]+)[\"']?/m);
43
+ const agentName = nameMatch?.[1]?.trim() || path.basename(agentFile, '.md');
44
+ const agentDesc = descMatch?.[1]?.trim() || `${agentName} reviewer`;
45
+ const relPath = `${this.prrFolderName}/${mod}/agents/${agentFile}`.replaceAll('\\', '/');
46
+ const slug = `prr-${mod}-${path.basename(agentFile, '.md')}`;
47
+
48
+ config.customModes.push({
49
+ slug,
50
+ name: agentName,
51
+ roleDefinition: agentDesc,
52
+ whenToUse: `Use for ${agentName} tasks`,
53
+ customInstructions: `Read the full agent file from {project-root}/${relPath} and follow all activation instructions exactly.\n`,
54
+ groups: ['read', 'edit', 'browser', 'command', 'mcp'],
55
+ });
56
+ modeCount++;
57
+ }
58
+ }
59
+
60
+ await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 }), 'utf8');
61
+
62
+ // Write workflow files to .kilocode/workflows/
63
+ const workflowsDir = path.join(projectDir, '.kilocode', 'workflows');
64
+ await this.ensureDir(workflowsDir);
65
+ let wfCount = 0;
66
+
67
+ for (const mod of allModules) {
68
+ const workflowsSrcDir = path.join(prrDir, mod, 'workflows');
69
+ if (!(await fs.pathExists(workflowsSrcDir))) continue;
70
+
71
+ const workflowFiles = await glob('**/workflow{.md,.yaml}', { cwd: workflowsSrcDir });
72
+ for (const wfFile of workflowFiles) {
73
+ const wfContent = await fs.readFile(path.join(workflowsSrcDir, wfFile), 'utf8');
74
+ let wfName = path.basename(path.dirname(wfFile));
75
+ let wfDesc = '';
76
+
77
+ if (wfFile.endsWith('.yaml')) {
78
+ try { const d = yaml.parse(wfContent); wfName = d.name || wfName; wfDesc = d.description || ''; } catch { /* ignore */ }
79
+ } else {
80
+ const normalized = wfContent.replace(/\r\n/g, '\n');
81
+ const fmMatch = normalized.match(/^---\n([\s\S]*?)\n---/);
82
+ if (fmMatch) { try { const fm = yaml.parse(fmMatch[1]); wfName = fm.name || wfName; wfDesc = fm.description || ''; } catch { /* ignore */ } }
83
+ }
84
+
85
+ const dirParts = path.dirname(wfFile).split(path.sep).filter(Boolean);
86
+ const leafDir = dirParts.at(-1) || wfName;
87
+ const relPath = `${this.prrFolderName}/${mod}/workflows/${wfFile}`.replaceAll('\\', '/');
88
+
89
+ const content = `---
90
+ name: 'prr-${leafDir}'
91
+ description: '${wfDesc || wfName}'
92
+ disable-model-invocation: true
93
+ ---
94
+
95
+ IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/${relPath}, READ its entire contents and follow its directions exactly!
96
+ `;
97
+ const fileName = `prr-${leafDir}.md`;
98
+ await fs.writeFile(path.join(workflowsDir, fileName), content, 'utf8');
99
+ wfCount++;
100
+ }
101
+ }
102
+
103
+ return { success: true, results: { agents: modeCount, workflows: wfCount } };
104
+ }
105
+
106
+ async cleanup(projectDir) {
107
+ // Remove prr- modes from .kilocodemodes
108
+ const kiloModesPath = path.join(projectDir, this.configFile);
109
+ if (await fs.pathExists(kiloModesPath)) {
110
+ try {
111
+ const config = yaml.parse(await fs.readFile(kiloModesPath, 'utf8')) || {};
112
+ if (Array.isArray(config.customModes)) {
113
+ config.customModes = config.customModes.filter((m) => !m.slug?.startsWith('prr-'));
114
+ await fs.writeFile(kiloModesPath, yaml.stringify(config, { lineWidth: 0 }), 'utf8');
115
+ }
116
+ } catch { /* ignore */ }
117
+ }
118
+
119
+ // Remove prr- workflow files
120
+ const workflowsDir = path.join(projectDir, '.kilocode', 'workflows');
121
+ if (await fs.pathExists(workflowsDir)) {
122
+ const files = await fs.readdir(workflowsDir);
123
+ for (const file of files) {
124
+ if (file.startsWith('prr-') && file.endsWith('.md')) {
125
+ await fs.remove(path.join(workflowsDir, file));
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ module.exports = { KiloSetup };
@@ -1,5 +1,9 @@
1
1
  /**
2
2
  * IDE Manager — dynamically loads and manages IDE handlers
3
+ *
4
+ * Loading strategy:
5
+ * 1. Custom installer files (github-copilot.js, codex.js, kilo.js) — unique installation logic
6
+ * 2. Config-driven handlers (from platform-codes.yaml) — standard IDE installation patterns
3
7
  */
4
8
  const path = require('node:path');
5
9
  const fs = require('fs-extra');
@@ -30,6 +34,36 @@ class IdeManager {
30
34
  }
31
35
 
32
36
  async loadHandlers() {
37
+ // 1. Load custom installer files first
38
+ await this._loadCustomHandlers();
39
+
40
+ // 2. Load config-driven handlers from platform-codes.yaml (skips platforms with custom handlers)
41
+ await this._loadConfigDrivenHandlers();
42
+ }
43
+
44
+ async _loadCustomHandlers() {
45
+ const customFiles = ['github-copilot.js', 'codex.js', 'kilo.js'];
46
+ const ideDir = __dirname;
47
+
48
+ for (const file of customFiles) {
49
+ const filePath = path.join(ideDir, file);
50
+ if (!fs.existsSync(filePath)) continue;
51
+
52
+ try {
53
+ const HandlerModule = require(filePath);
54
+ const HandlerClass = HandlerModule.default || Object.values(HandlerModule)[0];
55
+ if (!HandlerClass) continue;
56
+
57
+ const instance = new HandlerClass();
58
+ if (typeof instance.setPrrFolderName === 'function') {
59
+ instance.setPrrFolderName(this.prrFolderName);
60
+ }
61
+ this.handlers.set(instance.name, instance);
62
+ } catch { /* ignore load errors */ }
63
+ }
64
+ }
65
+
66
+ async _loadConfigDrivenHandlers() {
33
67
  const platformCodesPath = path.join(__dirname, 'platform-codes.yaml');
34
68
  const content = await fs.readFile(platformCodesPath, 'utf8');
35
69
  const config = yaml.parse(content);
@@ -37,7 +71,9 @@ class IdeManager {
37
71
  const { ConfigDrivenIdeSetup } = require('./_config-driven');
38
72
 
39
73
  for (const [code, info] of Object.entries(config.platforms || {})) {
40
- if (!info.installer) continue;
74
+ if (!info.installer) continue; // No installer = custom handler only
75
+ if (this.handlers.has(code)) continue; // Already loaded as custom handler
76
+
41
77
  const handler = new ConfigDrivenIdeSetup(code, info);
42
78
  handler.setPrrFolderName(this.prrFolderName);
43
79
  this.handlers.set(code, handler);
@@ -2,6 +2,7 @@
2
2
  # IDE/tool registry — defines where to install agent/workflow launchers
3
3
 
4
4
  platforms:
5
+ # Recommended Platforms
5
6
  claude-code:
6
7
  name: "Claude Code"
7
8
  preferred: true
@@ -29,6 +30,25 @@ platforms:
29
30
  target_dir: .windsurf/workflows
30
31
  template_type: windsurf
31
32
 
33
+ # Other IDEs and Tools
34
+ antigravity:
35
+ name: "Google Antigravity"
36
+ preferred: false
37
+ category: ide
38
+ description: "Google's AI development environment"
39
+ installer:
40
+ target_dir: .agent/workflows
41
+ template_type: antigravity
42
+
43
+ auggie:
44
+ name: "Auggie"
45
+ preferred: false
46
+ category: cli
47
+ description: "AI development tool"
48
+ installer:
49
+ target_dir: .augment/commands
50
+ template_type: default
51
+
32
52
  cline:
33
53
  name: "Cline"
34
54
  preferred: false
@@ -38,13 +58,20 @@ platforms:
38
58
  target_dir: .clinerules/workflows
39
59
  template_type: windsurf
40
60
 
41
- roo:
42
- name: "Roo Cline"
61
+ codex:
62
+ name: "Codex"
63
+ preferred: false
64
+ category: cli
65
+ description: "OpenAI Codex CLI"
66
+ # No installer config - uses custom codex.js
67
+
68
+ crush:
69
+ name: "Crush"
43
70
  preferred: false
44
71
  category: ide
45
- description: "Enhanced Cline fork"
72
+ description: "AI development assistant"
46
73
  installer:
47
- target_dir: .roo/commands
74
+ target_dir: .crush/commands
48
75
  template_type: default
49
76
 
50
77
  gemini:
@@ -54,8 +81,31 @@ platforms:
54
81
  description: "Google's CLI for Gemini"
55
82
  installer:
56
83
  target_dir: .gemini/commands
84
+ template_type: gemini
85
+
86
+ github-copilot:
87
+ name: "GitHub Copilot"
88
+ preferred: false
89
+ category: ide
90
+ description: "GitHub's AI pair programmer"
91
+ # No installer config - uses custom github-copilot.js
92
+
93
+ iflow:
94
+ name: "iFlow"
95
+ preferred: false
96
+ category: ide
97
+ description: "AI workflow automation"
98
+ installer:
99
+ target_dir: .iflow/commands
57
100
  template_type: default
58
101
 
102
+ kilo:
103
+ name: "KiloCoder"
104
+ preferred: false
105
+ category: ide
106
+ description: "AI coding platform"
107
+ # No installer config - uses custom kilo.js
108
+
59
109
  kiro:
60
110
  name: "Kiro"
61
111
  preferred: false
@@ -63,8 +113,58 @@ platforms:
63
113
  description: "Amazon's AI-powered IDE"
64
114
  installer:
65
115
  target_dir: .kiro/steering
116
+ template_type: kiro
117
+
118
+ opencode:
119
+ name: "OpenCode"
120
+ preferred: false
121
+ category: ide
122
+ description: "OpenCode terminal coding assistant"
123
+ installer:
124
+ targets:
125
+ - target_dir: .opencode/agent
126
+ template_type: opencode
127
+ artifact_types: [agents]
128
+ - target_dir: .opencode/command
129
+ template_type: opencode
130
+ artifact_types: [workflows]
131
+
132
+ qwen:
133
+ name: "QwenCoder"
134
+ preferred: false
135
+ category: ide
136
+ description: "Qwen AI coding assistant"
137
+ installer:
138
+ target_dir: .qwen/commands
66
139
  template_type: default
67
140
 
141
+ roo:
142
+ name: "Roo Cline"
143
+ preferred: false
144
+ category: ide
145
+ description: "Enhanced Cline fork"
146
+ installer:
147
+ target_dir: .roo/commands
148
+ template_type: default
149
+
150
+ rovo-dev:
151
+ name: "Rovo Dev"
152
+ preferred: false
153
+ category: ide
154
+ description: "Atlassian's Rovo development environment"
155
+ installer:
156
+ target_dir: .rovodev/workflows
157
+ template_type: rovodev
158
+
159
+ trae:
160
+ name: "Trae"
161
+ preferred: false
162
+ category: ide
163
+ description: "AI coding tool"
164
+ installer:
165
+ target_dir: .trae/rules
166
+ template_type: trae
167
+
68
168
  categories:
69
169
  ide:
70
170
  name: "Integrated Development Environment"
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: '{{name}}'
3
+ description: '{{description}}'
4
+ ---
5
+
6
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
7
+
8
+ <agent-activation CRITICAL="TRUE">
9
+ 1. LOAD the FULL agent file from {project-root}/{{prrFolderName}}/{{path}}
10
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
11
+ 3. FOLLOW every step in the <activation> section precisely
12
+ 4. DISPLAY the welcome/greeting as instructed
13
+ 5. PRESENT the numbered menu
14
+ 6. WAIT for user input before proceeding
15
+ </agent-activation>
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: '{{name}}'
3
+ description: '{{description}}'
4
+ ---
5
+
6
+ Read the entire workflow file at: {project-root}/{{prrFolderName}}/{{path}}
7
+
8
+ Follow all instructions in the workflow file exactly as written.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: '{{name}}'
3
+ description: '{{description}}'
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
8
+
9
+ <agent-activation CRITICAL="TRUE">
10
+ 1. LOAD the FULL agent file from {project-root}/{{prrFolderName}}/{{path}}
11
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
12
+ 3. FOLLOW every step in the <activation> section precisely
13
+ 4. DISPLAY the welcome/greeting as instructed
14
+ 5. PRESENT the numbered menu
15
+ 6. WAIT for user input before proceeding
16
+ </agent-activation>
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: '{{name}}'
3
+ description: '{{description}}'
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/{{prrFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!
@@ -0,0 +1,16 @@
1
+ ---
2
+ inclusion: manual
3
+ ---
4
+
5
+ # {{name}}
6
+
7
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
8
+
9
+ <agent-activation CRITICAL="TRUE">
10
+ 1. LOAD the FULL agent file from #[[file:{{prrFolderName}}/{{path}}]]
11
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
12
+ 3. FOLLOW every step in the <activation> section precisely
13
+ 4. DISPLAY the welcome/greeting as instructed
14
+ 5. PRESENT the numbered menu
15
+ 6. WAIT for user input before proceeding
16
+ </agent-activation>
@@ -0,0 +1,9 @@
1
+ ---
2
+ inclusion: manual
3
+ ---
4
+
5
+ # {{name}}
6
+
7
+ {{description}}
8
+
9
+ IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL #[[file:{{prrFolderName}}/{{path}}]], READ its entire contents and follow its directions exactly!