prr-kit 1.0.0 → 1.1.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.md CHANGED
@@ -12,13 +12,13 @@ Module system, agent YAML, step-file workflows, CLI installer with full IDE inte
12
12
 
13
13
  ```bash
14
14
  # Install into your repo (interactive — recommended)
15
- npx pr-review install
15
+ npx prr-kit install
16
16
 
17
- # Or run directly
18
- node tools/cli/prr-cli.js install --directory /path/to/repo
17
+ # Or use the alias
18
+ npx pr-review install
19
19
 
20
20
  # Silent install with defaults (edit config.yaml afterward)
21
- node tools/cli/prr-cli.js install --directory /path/to/repo --modules prr --tools claude-code --yes
21
+ npx prr-kit install --directory /path/to/repo --modules prr --tools claude-code --yes
22
22
  ```
23
23
 
24
24
  Then open your IDE in the installed project and use `/prr-master` to start.
@@ -72,13 +72,15 @@ After install, edit `_prr/prr/config.yaml` in your project:
72
72
  user_name: YourName
73
73
  communication_language: English
74
74
  target_repo: . # path to the git repo to review (. = current dir)
75
- github_repo: "owner/repo" # GitHub repo for gh pr list / inline comments
75
+ platform: auto # auto-detect from git remote, or: github / gitlab / azure / bitbucket
76
+ platform_repo: "owner/repo" # required for PR listing and posting inline comments
76
77
  output_folder: _prr-output
77
78
  review_output: /abs/path/_prr-output/reviews
78
79
  ```
79
80
 
80
- > `github_repo` is required for `gh pr list`, `gh pr diff`, and posting inline GitHub comments.
81
- > Leave empty to use local branch selection only.
81
+ > `platform` defaults to `auto` detects GitHub/GitLab/Azure/Bitbucket from the git remote URL.
82
+ > `platform_repo` is required for PR listing (`gh pr list`, `glab mr list`, etc.) and posting inline comments.
83
+ > Leave `platform_repo` empty to use local branch selection only.
82
84
 
83
85
  ## Platform Support
84
86
 
@@ -127,14 +129,14 @@ Only pauses once to ask which PR/branch to review.
127
129
 
128
130
  ### Selecting a PR (SP step)
129
131
 
130
- **With `github_repo` configured** — lists open GitHub PRs:
132
+ **With `platform_repo` configured** — lists open PRs/MRs via platform CLI:
131
133
  ```
132
134
  #45 "Add OAuth2 login" feature/oauth → main @alice 3h ago
133
135
  #44 "Fix memory leak" fix/memory → main @bob 1d ago
134
136
  ```
135
- Enter PR number → base and head resolved automatically from GitHub.
137
+ Enter PR number → base and head resolved automatically.
136
138
 
137
- **Without `github_repo`** — asks explicitly for both branches:
139
+ **Without `platform_repo`** — asks explicitly for both branches:
138
140
  ```
139
141
  🎯 Head branch (the branch to review)?
140
142
  • Enter a number from the list (e.g., 1)
@@ -149,13 +151,10 @@ Enter PR number → base and head resolved automatically from GitHub.
149
151
 
150
152
  | Agent | Slash Command | Speciality |
151
153
  |-------|--------------|------------|
152
- | PRR Master | `/prr-master` | Orchestrator — routes all workflows |
153
- | Alex | `/general-reviewer` | Code quality, logic, naming, DRY |
154
- | Sam | `/security-reviewer` | OWASP Top 10, secrets, auth |
155
- | Petra | `/performance-reviewer` | N+1 queries, memory leaks, async |
156
- | Arch | `/architecture-reviewer` | SOLID, layers, coupling, consistency |
154
+ | PRR Master | `/prr-master` | Orchestrator — routes all workflows, full menu |
155
+ | PRR Quick | `/prr-quick` | One-command full pipeline (select review → report) |
157
156
 
158
- Each reviewer agent can also be invoked directly and has its own menu.
157
+ Specialist reviewer agents (Alex, Sam, Petra, Arch) are orchestrated internally by the master agent and party-mode workflow. Use `[PM] Party Mode` from the master menu to run all 4 reviewers in a collaborative session.
159
158
 
160
159
  ## Severity Levels
161
160
 
@@ -166,24 +165,34 @@ All findings use a standard format:
166
165
  - 🟢 **[SUGGESTION]** — Nice-to-have improvement
167
166
  - 📌 **[QUESTION]** — Needs clarification from author
168
167
 
169
- ## Inline GitHub Comments
168
+ ## Inline Code Comments
170
169
 
171
- When `[PC] Post Comments` is run with `github_repo` configured, it uses the GitHub Reviews API to post findings as **inline code comments** on the exact file and line — the same experience as a human reviewer on GitHub.
170
+ When `[PC] Post Comments` is run with `platform_repo` configured, it posts findings as **inline code comments** on the exact file and line — the same experience as a human reviewer.
172
171
 
173
- Requires `gh` CLI authenticated: `gh auth login`
172
+ | Platform | Method | Required CLI |
173
+ |----------|--------|-------------|
174
+ | GitHub | Reviews API | `gh auth login` |
175
+ | GitLab | MR Discussions API | `glab auth login` |
176
+ | Azure DevOps | PR Threads API | `az login` |
177
+ | Bitbucket | Inline Comments REST API | `bb` / `curl` |
174
178
 
175
179
  ## Supported IDEs
176
180
 
177
- - **Claude Code** (preferred)
178
- - **Cursor** (preferred)
179
- - **Windsurf** (preferred)
180
- - Cline, Roo, Gemini CLI, Kiro
181
+ **Preferred:**
182
+ - **Claude Code**, **Cursor**, **Windsurf**
183
+
184
+ **Also supported:**
185
+ - Antigravity, Auggie, Cline, Codex, Crush, Gemini CLI, GitHub Copilot, iFlow, Kilo, Kiro, OpenCode, QwenCoder, Roo Cline, Rovo Dev, Trae
181
186
 
182
187
  ## Requirements
183
188
 
184
- - Node.js 18+
189
+ - Node.js 20+
185
190
  - Git
186
- - `gh` CLI — required for `gh pr list`, `gh pr diff`, and posting inline GitHub comments
191
+ - Platform CLI (optional only needed for PR listing and inline comments):
192
+ - GitHub: [`gh`](https://cli.github.com/)
193
+ - GitLab: [`glab`](https://gitlab.com/gitlab-org/cli)
194
+ - Azure DevOps: [`az`](https://learn.microsoft.com/en-us/cli/azure/) + Azure DevOps extension
195
+ - Bitbucket: [`bb`](https://bitbucket.org/atlassian/bitbucket-cli) or `curl`
187
196
 
188
197
  ## Development
189
198
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prr-kit",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "AI-driven Pull Request Review Framework — structured agent workflows for thorough, consistent code review",
5
5
  "main": "tools/cli/prr-cli.js",
6
6
  "bin": {
@@ -17,6 +17,11 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
17
17
  async setup(projectDir, prrDir, options = {}) {
18
18
  if (!this.installerConfig) return { success: false, reason: 'no-config' };
19
19
 
20
+ // Multi-target support (e.g. opencode: agents → one dir, workflows → another)
21
+ if (this.installerConfig.targets) {
22
+ return this._setupMultiTarget(projectDir, prrDir, options);
23
+ }
24
+
20
25
  await this.cleanup(projectDir, options);
21
26
 
22
27
  const { target_dir, template_type } = this.installerConfig;
@@ -114,6 +119,71 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
114
119
  return { success: true, results };
115
120
  }
116
121
 
122
+ async _setupMultiTarget(projectDir, prrDir, options = {}) {
123
+ const results = { agents: 0, workflows: 0 };
124
+ const selectedModules = options.selectedModules || ['prr'];
125
+ const allModules = ['core', ...selectedModules.filter((m) => m !== 'core')];
126
+
127
+ for (const target of this.installerConfig.targets) {
128
+ const { target_dir, template_type, artifact_types } = target;
129
+ const targetPath = path.join(projectDir, target_dir);
130
+ await this.ensureDir(targetPath);
131
+
132
+ const installAgents = !artifact_types || artifact_types.includes('agents');
133
+ const installWorkflows = !artifact_types || artifact_types.includes('workflows');
134
+
135
+ if (installAgents) {
136
+ for (const mod of allModules) {
137
+ const agentsDir = path.join(prrDir, mod, 'agents');
138
+ if (!(await fs.pathExists(agentsDir))) continue;
139
+ const agentFiles = await glob('**/*.md', { cwd: agentsDir });
140
+ for (const agentFile of agentFiles) {
141
+ const agentContent = await fs.readFile(path.join(agentsDir, agentFile), 'utf8');
142
+ if (/^no-launcher:\s*true/m.test(agentContent)) continue;
143
+ const nameMatch = agentContent.match(/^name:\s*[\"']?([^\"'\n]+)[\"']?/m);
144
+ const descMatch = agentContent.match(/^description:\s*[\"']?([^\"'\n]+)[\"']?/m);
145
+ const agentName = nameMatch?.[1]?.trim() || path.basename(agentFile, '.md');
146
+ const agentDesc = descMatch?.[1]?.trim() || `${agentName} reviewer`;
147
+ const relAgentPath = `${mod}/agents/${agentFile}`.replaceAll('\\', '/');
148
+ const launcherContent = this.generateAgentLauncher(agentName, agentDesc, relAgentPath, template_type);
149
+ const launcherFileName = `${path.basename(agentFile, '.md')}.md`;
150
+ await fs.writeFile(path.join(targetPath, launcherFileName), launcherContent, 'utf8');
151
+ results.agents++;
152
+ }
153
+ }
154
+ }
155
+
156
+ if (installWorkflows) {
157
+ for (const mod of allModules) {
158
+ const workflowsDir = path.join(prrDir, mod, 'workflows');
159
+ if (!(await fs.pathExists(workflowsDir))) continue;
160
+ const workflowFiles = await glob('**/workflow{.md,.yaml}', { cwd: workflowsDir });
161
+ for (const wfFile of workflowFiles) {
162
+ const wfContent = await fs.readFile(path.join(workflowsDir, wfFile), 'utf8');
163
+ let wfName = path.basename(path.dirname(wfFile));
164
+ let wfDesc = '';
165
+ if (wfFile.endsWith('.yaml')) {
166
+ try { const d = require('yaml').parse(wfContent); wfName = d.name || wfName; wfDesc = d.description || ''; } catch { /* ignore */ }
167
+ } else {
168
+ const normalized = wfContent.replace(/\r\n/g, '\n');
169
+ const fmMatch = normalized.match(/^---\n([\s\S]*?)\n---/);
170
+ if (fmMatch) { try { const fm = require('yaml').parse(fmMatch[1]); wfName = fm.name || wfName; wfDesc = fm.description || ''; } catch { /* ignore */ } }
171
+ }
172
+ const dirParts = path.dirname(wfFile).split(path.sep).filter(Boolean);
173
+ const leafDir = dirParts.at(-1) || wfName;
174
+ const relWfPath = `${mod}/workflows/${wfFile}`.replaceAll('\\', '/');
175
+ const launcherContent = this.generateWorkflowLauncher(wfName, wfDesc, relWfPath, template_type);
176
+ const launcherFileName = `prr-${leafDir}.md`;
177
+ await fs.writeFile(path.join(targetPath, launcherFileName), launcherContent, 'utf8');
178
+ results.workflows++;
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ return { success: true, results };
185
+ }
186
+
117
187
  generateAgentLauncher(name, description, agentRelPath, templateType) {
118
188
  const template = this.loadTemplate(`${templateType}-agent`) || this.loadTemplate('default-agent');
119
189
  return template
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Codex CLI setup handler
3
+ * Installs prompts to ~/.codex/prompts (global) or .codex/prompts (project)
4
+ */
5
+ const path = require('node:path');
6
+ const os = require('node:os');
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 CodexSetup extends BaseIdeSetup {
13
+ constructor() {
14
+ super('codex', 'Codex', false);
15
+ }
16
+
17
+ async setup(projectDir, prrDir, options = {}) {
18
+ const installLocation = options.preCollectedConfig?.installLocation || 'global';
19
+ const destDir = this._getPromptDir(projectDir, installLocation);
20
+ await fs.ensureDir(destDir);
21
+ await this._clearPrrFiles(destDir);
22
+
23
+ const selectedModules = options.selectedModules || ['prr'];
24
+ const allModules = ['core', ...selectedModules.filter((m) => m !== 'core')];
25
+ let count = 0;
26
+
27
+ // Write agent launchers
28
+ for (const mod of allModules) {
29
+ const agentsSrcDir = path.join(prrDir, mod, 'agents');
30
+ if (!(await fs.pathExists(agentsSrcDir))) continue;
31
+
32
+ const agentFiles = await glob('**/*.md', { cwd: agentsSrcDir });
33
+ for (const agentFile of agentFiles) {
34
+ const agentContent = await fs.readFile(path.join(agentsSrcDir, agentFile), 'utf8');
35
+ if (/^no-launcher:\s*true/m.test(agentContent)) continue;
36
+
37
+ const nameMatch = agentContent.match(/^name:\s*[\"']?([^\"'\n]+)[\"']?/m);
38
+ const agentName = nameMatch?.[1]?.trim() || path.basename(agentFile, '.md');
39
+ const relPath = `${this.prrFolderName}/${mod}/agents/${agentFile}`.replaceAll('\\', '/');
40
+
41
+ const content = `---
42
+ name: '${agentName}'
43
+ description: '${agentName} agent'
44
+ disable-model-invocation: true
45
+ ---
46
+
47
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
48
+
49
+ <agent-activation CRITICAL="TRUE">
50
+ 1. LOAD the FULL agent file from {project-root}/${relPath}
51
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
52
+ 3. FOLLOW every step in the <activation> section precisely
53
+ 4. DISPLAY the welcome/greeting as instructed
54
+ 5. PRESENT the numbered menu
55
+ 6. WAIT for user input before proceeding
56
+ </agent-activation>
57
+ `;
58
+ const fileName = `prr-${mod}-${path.basename(agentFile, '.md')}.md`;
59
+ await fs.writeFile(path.join(destDir, fileName), content, 'utf8');
60
+ count++;
61
+ }
62
+ }
63
+
64
+ // Write workflow launchers
65
+ for (const mod of allModules) {
66
+ const workflowsSrcDir = path.join(prrDir, mod, 'workflows');
67
+ if (!(await fs.pathExists(workflowsSrcDir))) continue;
68
+
69
+ const workflowFiles = await glob('**/workflow{.md,.yaml}', { cwd: workflowsSrcDir });
70
+ for (const wfFile of workflowFiles) {
71
+ const wfContent = await fs.readFile(path.join(workflowsSrcDir, wfFile), 'utf8');
72
+ let wfName = path.basename(path.dirname(wfFile));
73
+
74
+ if (wfFile.endsWith('.yaml')) {
75
+ try { const d = yaml.parse(wfContent); wfName = d.name || wfName; } catch { /* ignore */ }
76
+ } else {
77
+ const normalized = wfContent.replace(/\r\n/g, '\n');
78
+ const fmMatch = normalized.match(/^---\n([\s\S]*?)\n---/);
79
+ if (fmMatch) { try { const fm = yaml.parse(fmMatch[1]); wfName = fm.name || wfName; } catch { /* ignore */ } }
80
+ }
81
+
82
+ const dirParts = path.dirname(wfFile).split(path.sep).filter(Boolean);
83
+ const leafDir = dirParts.at(-1) || wfName;
84
+ const relPath = `${this.prrFolderName}/${mod}/workflows/${wfFile}`.replaceAll('\\', '/');
85
+
86
+ const content = `---
87
+ name: 'prr-${leafDir}'
88
+ description: '${wfName}'
89
+ disable-model-invocation: true
90
+ ---
91
+
92
+ IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL @{project-root}/${relPath}, READ its entire contents and follow its directions exactly!
93
+ `;
94
+ const fileName = `prr-${mod}-${leafDir}.md`;
95
+ await fs.writeFile(path.join(destDir, fileName), content, 'utf8');
96
+ count++;
97
+ }
98
+ }
99
+
100
+ return { success: true, results: { agents: count, workflows: 0 } };
101
+ }
102
+
103
+ async cleanup(projectDir) {
104
+ for (const loc of ['global', 'project']) {
105
+ const dir = this._getPromptDir(projectDir, loc);
106
+ await this._clearPrrFiles(dir);
107
+ }
108
+ }
109
+
110
+ _getPromptDir(projectDir, location) {
111
+ if (location === 'project' && projectDir) {
112
+ return path.join(projectDir, '.codex', 'prompts');
113
+ }
114
+ return path.join(os.homedir(), '.codex', 'prompts');
115
+ }
116
+
117
+ async _clearPrrFiles(dir) {
118
+ if (!(await fs.pathExists(dir))) return;
119
+ const entries = await fs.readdir(dir);
120
+ for (const entry of entries) {
121
+ if (entry.startsWith('prr-') && entry.endsWith('.md')) {
122
+ await fs.remove(path.join(dir, entry));
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ module.exports = { CodexSetup };
@@ -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 Framework — 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!
@@ -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,6 @@
1
+ ---
2
+ name: '{{name}}'
3
+ description: '{{description}}'
4
+ ---
5
+
6
+ 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,10 @@
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
+ Read the entire agent file at: {project-root}/{{prrFolderName}}/{{path}}
9
+
10
+ Follow all instructions in the agent file exactly as written.
@@ -0,0 +1,9 @@
1
+ # {{name}}
2
+
3
+ {{description}}
4
+
5
+ ---
6
+
7
+ Read the entire workflow file at: {project-root}/{{prrFolderName}}/{{path}}
8
+
9
+ Follow all instructions in the workflow file exactly as written.
@@ -0,0 +1,11 @@
1
+ # {{name}}
2
+
3
+ {{description}}
4
+
5
+ ## Instructions
6
+
7
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified.
8
+
9
+ Read the entire agent file at: {project-root}/{{prrFolderName}}/{{path}}
10
+
11
+ Follow all instructions in the agent file exactly as written.
@@ -0,0 +1,9 @@
1
+ # {{name}}
2
+
3
+ {{description}}
4
+
5
+ ## Instructions
6
+
7
+ Read the entire workflow file at: {project-root}/{{prrFolderName}}/{{path}}
8
+
9
+ Follow all instructions in the workflow file exactly as written.