cc-reviewer 2.0.0 → 3.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.md +15 -35
- package/commands/{codex-xhigh.md → codex-xhigh-review.md} +3 -3
- package/commands/{multi.md → multi-review.md} +1 -1
- package/dist/adapters/base.d.ts +3 -41
- package/dist/adapters/codex.d.ts +4 -6
- package/dist/adapters/codex.js +68 -322
- package/dist/adapters/gemini.d.ts +4 -6
- package/dist/adapters/gemini.js +46 -276
- package/dist/commands.d.ts +2 -3
- package/dist/commands.js +33 -11
- package/dist/decoders/codex.d.ts +11 -0
- package/dist/decoders/codex.js +29 -0
- package/dist/handoff.d.ts +2 -17
- package/dist/handoff.js +3 -87
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -22
- package/dist/schema.d.ts +6 -195
- package/dist/schema.js +1 -190
- package/dist/tools/feedback.d.ts +5 -6
- package/dist/tools/feedback.js +63 -338
- package/dist/types.d.ts +0 -1
- package/package.json +2 -3
- package/commands/ask-codex.md +0 -36
- package/commands/ask-gemini.md +0 -35
- package/commands/ask-multi.md +0 -39
- package/dist/setup.d.ts +0 -7
- package/dist/setup.js +0 -27
- package/dist/tools/peer.d.ts +0 -194
- package/dist/tools/peer.js +0 -347
- /package/commands/{codex.md → codex-review.md} +0 -0
- /package/commands/{gemini.md → gemini-review.md} +0 -0
package/dist/tools/feedback.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MCP Tool Implementations
|
|
2
|
+
* MCP Tool Implementations — Review Tools
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. Multi-model parallel review (multi_review)
|
|
4
|
+
* Returns raw reviewer text to CC. No JSON parsing, no reformatting.
|
|
5
|
+
* CC handles interpretation and synthesis.
|
|
7
6
|
*/
|
|
8
7
|
import { z } from 'zod';
|
|
9
8
|
import { getAdapter, getAvailableAdapters, } from '../adapters/index.js';
|
|
@@ -24,7 +23,7 @@ export const ReviewInputSchema = z.object({
|
|
|
24
23
|
serviceTier: z.enum(['default', 'fast', 'flex']).optional().describe('Codex service tier (default: default, fast = priority processing, flex = cheaper/slower)')
|
|
25
24
|
});
|
|
26
25
|
// =============================================================================
|
|
27
|
-
//
|
|
26
|
+
// HELPERS
|
|
28
27
|
// =============================================================================
|
|
29
28
|
function toReviewRequest(input) {
|
|
30
29
|
return {
|
|
@@ -38,260 +37,70 @@ function toReviewRequest(input) {
|
|
|
38
37
|
serviceTier: input.serviceTier,
|
|
39
38
|
};
|
|
40
39
|
}
|
|
41
|
-
function
|
|
40
|
+
function formatResult(result, modelName) {
|
|
42
41
|
if (!result.success) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
critical: '🔴',
|
|
52
|
-
high: '🟠',
|
|
53
|
-
medium: '🟡',
|
|
54
|
-
low: '🟢',
|
|
55
|
-
minimal: '✅',
|
|
56
|
-
};
|
|
57
|
-
lines.push(`### Risk Assessment ${riskEmoji[output.risk_assessment.overall_level]}`);
|
|
58
|
-
lines.push(`**${output.risk_assessment.overall_level.toUpperCase()}** (Score: ${output.risk_assessment.score}/100)`);
|
|
59
|
-
lines.push(`${output.risk_assessment.summary}\n`);
|
|
60
|
-
// Findings
|
|
61
|
-
if (output.findings.length > 0) {
|
|
62
|
-
lines.push(`### New Findings (${output.findings.length})\n`);
|
|
63
|
-
for (const finding of output.findings) {
|
|
64
|
-
const severityEmoji = {
|
|
65
|
-
critical: '🔴', high: '🟠', medium: '🟡', low: '🟢', info: 'ℹ️'
|
|
66
|
-
};
|
|
67
|
-
const confidence = Math.round(finding.confidence * 100);
|
|
68
|
-
lines.push(`${severityEmoji[finding.severity]} **${finding.title}** [${confidence}% confidence]`);
|
|
69
|
-
if (finding.location) {
|
|
70
|
-
const loc = finding.location.line_start
|
|
71
|
-
? `${finding.location.file}:${finding.location.line_start}`
|
|
72
|
-
: finding.location.file;
|
|
73
|
-
lines.push(` 📍 ${loc}`);
|
|
74
|
-
}
|
|
75
|
-
lines.push(` ${finding.description}`);
|
|
76
|
-
if (finding.suggestion) {
|
|
77
|
-
lines.push(` 💡 ${finding.suggestion}`);
|
|
78
|
-
}
|
|
79
|
-
lines.push('');
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Uncertainty Responses
|
|
83
|
-
if (output.uncertainty_responses && output.uncertainty_responses.length > 0) {
|
|
84
|
-
lines.push(`### Uncertainty Responses (${output.uncertainty_responses.length})\n`);
|
|
85
|
-
for (const ur of output.uncertainty_responses) {
|
|
86
|
-
const icon = ur.verified ? '✓' : '✗';
|
|
87
|
-
lines.push(`${icon} **Uncertainty #${ur.uncertainty_index}**: ${ur.finding}`);
|
|
88
|
-
if (ur.recommendation) {
|
|
89
|
-
lines.push(` → ${ur.recommendation}`);
|
|
90
|
-
}
|
|
91
|
-
lines.push('');
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// Question Answers
|
|
95
|
-
if (output.question_answers && output.question_answers.length > 0) {
|
|
96
|
-
lines.push(`### Question Answers (${output.question_answers.length})\n`);
|
|
97
|
-
for (const qa of output.question_answers) {
|
|
98
|
-
const confidence = qa.confidence != null ? ` [${Math.round(qa.confidence * 100)}%]` : '';
|
|
99
|
-
lines.push(`**Q${qa.question_index}**${confidence}: ${qa.answer}`);
|
|
100
|
-
lines.push('');
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// Agreements
|
|
104
|
-
if (output.agreements.length > 0) {
|
|
105
|
-
lines.push(`### Agreements (${output.agreements.length})\n`);
|
|
106
|
-
for (const agreement of output.agreements) {
|
|
107
|
-
const confidence = Math.round(agreement.confidence * 100);
|
|
108
|
-
lines.push(`✓ **${agreement.original_claim}** [${confidence}%]`);
|
|
109
|
-
if (agreement.supporting_evidence) {
|
|
110
|
-
lines.push(` ${agreement.supporting_evidence}`);
|
|
111
|
-
}
|
|
112
|
-
lines.push('');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// Disagreements
|
|
116
|
-
if (output.disagreements.length > 0) {
|
|
117
|
-
lines.push(`### Disagreements (${output.disagreements.length})\n`);
|
|
118
|
-
for (const disagreement of output.disagreements) {
|
|
119
|
-
const confidence = Math.round(disagreement.confidence * 100);
|
|
120
|
-
lines.push(`✗ **${disagreement.original_claim}** [${disagreement.issue}] [${confidence}%]`);
|
|
121
|
-
lines.push(` ${disagreement.reason}`);
|
|
122
|
-
if (disagreement.correction) {
|
|
123
|
-
lines.push(` → Correction: ${disagreement.correction}`);
|
|
124
|
-
}
|
|
125
|
-
lines.push('');
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// Alternatives
|
|
129
|
-
if (output.alternatives.length > 0) {
|
|
130
|
-
lines.push(`### Alternatives (${output.alternatives.length})\n`);
|
|
131
|
-
for (const alt of output.alternatives) {
|
|
132
|
-
lines.push(`**${alt.topic}**`);
|
|
133
|
-
lines.push(` Current: ${alt.current_approach}`);
|
|
134
|
-
lines.push(` Alternative: ${alt.alternative}`);
|
|
135
|
-
lines.push(` Recommendation: ${alt.recommendation}`);
|
|
136
|
-
lines.push('');
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return lines.join('\n');
|
|
140
|
-
}
|
|
141
|
-
function formatErrorResponse(error, suggestion) {
|
|
142
|
-
const emoji = {
|
|
143
|
-
cli_not_found: '❌',
|
|
144
|
-
timeout: '⏱️',
|
|
145
|
-
rate_limit: '🚫',
|
|
146
|
-
auth_error: '🔐',
|
|
147
|
-
parse_error: '⚠️',
|
|
148
|
-
cli_error: '❌',
|
|
149
|
-
};
|
|
150
|
-
let response = `${emoji[error.type] || '❌'} **${error.type}**: ${error.message}`;
|
|
151
|
-
if (suggestion) {
|
|
152
|
-
response += `\n\n💡 ${suggestion}`;
|
|
42
|
+
const emoji = {
|
|
43
|
+
cli_not_found: '❌', timeout: '⏱️', rate_limit: '🚫',
|
|
44
|
+
auth_error: '🔐', cli_error: '❌',
|
|
45
|
+
};
|
|
46
|
+
let msg = `${emoji[result.error.type] || '❌'} **${result.error.type}**: ${result.error.message}`;
|
|
47
|
+
if (result.suggestion)
|
|
48
|
+
msg += `\n\n💡 ${result.suggestion}`;
|
|
49
|
+
return msg;
|
|
153
50
|
}
|
|
154
|
-
return
|
|
51
|
+
return `## ${modelName} Review\n\n**Execution Time:** ${(result.executionTimeMs / 1000).toFixed(1)}s\n\n${result.output}`;
|
|
155
52
|
}
|
|
156
53
|
// =============================================================================
|
|
157
54
|
// SINGLE MODEL HANDLERS
|
|
158
55
|
// =============================================================================
|
|
159
56
|
export async function handleCodexReview(input) {
|
|
160
57
|
const adapter = getAdapter('codex');
|
|
161
|
-
if (!adapter)
|
|
162
|
-
return {
|
|
163
|
-
content: [{
|
|
164
|
-
type: 'text',
|
|
165
|
-
text: '❌ Codex adapter not registered'
|
|
166
|
-
}]
|
|
167
|
-
};
|
|
168
|
-
}
|
|
58
|
+
if (!adapter)
|
|
59
|
+
return { content: [{ type: 'text', text: '❌ Codex adapter not registered' }] };
|
|
169
60
|
const available = await adapter.isAvailable();
|
|
170
|
-
if (!available)
|
|
171
|
-
return {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
text: '❌ Codex CLI not found.\n\nInstall with: npm install -g @openai/codex\n\nAlternative: Use gemini_review instead'
|
|
175
|
-
}]
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
const request = toReviewRequest(input);
|
|
179
|
-
const result = await adapter.runReview(request);
|
|
180
|
-
return {
|
|
181
|
-
content: [{
|
|
182
|
-
type: 'text',
|
|
183
|
-
text: formatSingleReviewResponse(result, 'Codex')
|
|
184
|
-
}]
|
|
185
|
-
};
|
|
61
|
+
if (!available)
|
|
62
|
+
return { content: [{ type: 'text', text: '❌ Codex CLI not found.\n\nInstall with: npm install -g @openai/codex-cli\n\nAlternative: Use gemini_review instead' }] };
|
|
63
|
+
const result = await adapter.runReview(toReviewRequest(input));
|
|
64
|
+
return { content: [{ type: 'text', text: formatResult(result, 'Codex') }] };
|
|
186
65
|
}
|
|
187
66
|
export async function handleGeminiReview(input) {
|
|
188
67
|
const adapter = getAdapter('gemini');
|
|
189
|
-
if (!adapter)
|
|
190
|
-
return {
|
|
191
|
-
content: [{
|
|
192
|
-
type: 'text',
|
|
193
|
-
text: '❌ Gemini adapter not registered'
|
|
194
|
-
}]
|
|
195
|
-
};
|
|
196
|
-
}
|
|
68
|
+
if (!adapter)
|
|
69
|
+
return { content: [{ type: 'text', text: '❌ Gemini adapter not registered' }] };
|
|
197
70
|
const available = await adapter.isAvailable();
|
|
198
|
-
if (!available)
|
|
199
|
-
return {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
text: '❌ Gemini CLI not found.\n\nInstall with: npm install -g @google/gemini-cli\n\nAlternative: Use codex_review instead'
|
|
203
|
-
}]
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
const request = toReviewRequest(input);
|
|
207
|
-
const result = await adapter.runReview(request);
|
|
208
|
-
return {
|
|
209
|
-
content: [{
|
|
210
|
-
type: 'text',
|
|
211
|
-
text: formatSingleReviewResponse(result, 'Gemini')
|
|
212
|
-
}]
|
|
213
|
-
};
|
|
71
|
+
if (!available)
|
|
72
|
+
return { content: [{ type: 'text', text: '❌ Gemini CLI not found.\n\nInstall with: npm install -g @google/gemini-cli\n\nAlternative: Use codex_review instead' }] };
|
|
73
|
+
const result = await adapter.runReview(toReviewRequest(input));
|
|
74
|
+
return { content: [{ type: 'text', text: formatResult(result, 'Gemini') }] };
|
|
214
75
|
}
|
|
215
76
|
// =============================================================================
|
|
216
77
|
// MULTI-MODEL HANDLER
|
|
217
78
|
// =============================================================================
|
|
218
79
|
export async function handleMultiReview(input) {
|
|
219
80
|
const request = toReviewRequest(input);
|
|
220
|
-
// Get all available adapters
|
|
221
81
|
const availableAdapters = await getAvailableAdapters();
|
|
222
82
|
if (availableAdapters.length === 0) {
|
|
223
|
-
return {
|
|
224
|
-
content: [{
|
|
225
|
-
type: 'text',
|
|
226
|
-
text: `❌ No AI CLIs found.
|
|
227
|
-
|
|
228
|
-
Install at least one:
|
|
229
|
-
- Codex: npm install -g @openai/codex
|
|
230
|
-
- Gemini: npm install -g @google/gemini-cli`
|
|
231
|
-
}]
|
|
232
|
-
};
|
|
83
|
+
return { content: [{ type: 'text', text: '❌ No AI CLIs found.\n\nInstall at least one:\n - Codex: npm install -g @openai/codex-cli\n - Gemini: npm install -g @google/gemini-cli' }] };
|
|
233
84
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const adapterRequest = { ...request };
|
|
237
|
-
const result = await adapter.runReview(adapterRequest);
|
|
85
|
+
const results = await Promise.all(availableAdapters.map(async (adapter) => {
|
|
86
|
+
const result = await adapter.runReview({ ...request });
|
|
238
87
|
return { adapter, result };
|
|
239
|
-
});
|
|
240
|
-
const results = await Promise.all(promises);
|
|
241
|
-
// Collect successful and failed results
|
|
242
|
-
const successful = [];
|
|
243
|
-
const failed = [];
|
|
244
|
-
for (const { adapter, result } of results) {
|
|
245
|
-
if (result.success) {
|
|
246
|
-
successful.push({ model: adapter.id, output: result.output });
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
failed.push({ model: adapter.id, error: result.error.message });
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
// Build response
|
|
88
|
+
}));
|
|
253
89
|
const lines = [];
|
|
254
|
-
|
|
255
|
-
|
|
90
|
+
const allFailed = results.every(r => !r.result.success);
|
|
91
|
+
const someFailed = results.some(r => !r.result.success);
|
|
92
|
+
if (allFailed)
|
|
256
93
|
lines.push('## Multi-Model Review ❌ All Failed\n');
|
|
257
|
-
|
|
258
|
-
else if (failed.length > 0) {
|
|
94
|
+
else if (someFailed)
|
|
259
95
|
lines.push('## Multi-Model Review ⚠️ Partial Success\n');
|
|
260
|
-
|
|
261
|
-
else {
|
|
96
|
+
else
|
|
262
97
|
lines.push('## Multi-Model Review ✓\n');
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
// Successful reviews
|
|
267
|
-
for (const { model, output } of successful) {
|
|
268
|
-
lines.push(`### ${model.charAt(0).toUpperCase() + model.slice(1)} Review\n`);
|
|
269
|
-
lines.push(formatSingleReviewResponse({ success: true, output, executionTimeMs: 0 }, model));
|
|
270
|
-
lines.push('');
|
|
271
|
-
}
|
|
272
|
-
// Failed reviews
|
|
273
|
-
if (failed.length > 0) {
|
|
274
|
-
lines.push('### Failures\n');
|
|
275
|
-
for (const { model, error } of failed) {
|
|
276
|
-
lines.push(`**${model}:** ${error}`);
|
|
277
|
-
}
|
|
98
|
+
lines.push(`**Models:** ${availableAdapters.map(a => a.id).join(', ')}\n`);
|
|
99
|
+
for (const { adapter, result } of results) {
|
|
100
|
+
lines.push(formatResult(result, adapter.getCapabilities().name));
|
|
278
101
|
lines.push('');
|
|
279
102
|
}
|
|
280
|
-
|
|
281
|
-
if (successful.length > 1) {
|
|
282
|
-
lines.push(`---
|
|
283
|
-
|
|
284
|
-
**Synthesis Instructions:**
|
|
285
|
-
- ✓✓ Mark agreements where both models concur
|
|
286
|
-
- Resolve conflicts with your own judgment
|
|
287
|
-
- Note unique insights from each model`);
|
|
288
|
-
}
|
|
289
|
-
return {
|
|
290
|
-
content: [{
|
|
291
|
-
type: 'text',
|
|
292
|
-
text: lines.join('\n')
|
|
293
|
-
}]
|
|
294
|
-
};
|
|
103
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
295
104
|
}
|
|
296
105
|
// =============================================================================
|
|
297
106
|
// TOOL DEFINITIONS
|
|
@@ -299,135 +108,51 @@ Install at least one:
|
|
|
299
108
|
export const TOOL_DEFINITIONS = {
|
|
300
109
|
codex_review: {
|
|
301
110
|
name: 'codex_review',
|
|
302
|
-
description: "ONLY use when user explicitly requests '/codex' or 'review with codex'. Get external second-opinion from OpenAI Codex CLI. Codex focuses on correctness, edge cases, and performance. DO NOT use for general 'review' requests.",
|
|
111
|
+
description: "ONLY use when user explicitly requests '/codex-review' or 'review with codex'. Get external second-opinion from OpenAI Codex CLI. Codex focuses on correctness, edge cases, and performance. DO NOT use for general 'review' requests.",
|
|
303
112
|
inputSchema: {
|
|
304
113
|
type: 'object',
|
|
305
114
|
properties: {
|
|
306
|
-
workingDir: {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
outputType: {
|
|
315
|
-
type: 'string',
|
|
316
|
-
enum: ['plan', 'findings', 'analysis', 'proposal'],
|
|
317
|
-
description: 'Type of output being reviewed'
|
|
318
|
-
},
|
|
319
|
-
analyzedFiles: {
|
|
320
|
-
type: 'array',
|
|
321
|
-
items: { type: 'string' },
|
|
322
|
-
description: 'File paths that CC analyzed'
|
|
323
|
-
},
|
|
324
|
-
focusAreas: {
|
|
325
|
-
type: 'array',
|
|
326
|
-
items: {
|
|
327
|
-
type: 'string',
|
|
328
|
-
enum: ['security', 'performance', 'architecture', 'correctness', 'maintainability', 'scalability', 'testing', 'documentation']
|
|
329
|
-
},
|
|
330
|
-
description: 'Areas to focus the review on'
|
|
331
|
-
},
|
|
332
|
-
customPrompt: {
|
|
333
|
-
type: 'string',
|
|
334
|
-
description: 'Custom instructions for the reviewer'
|
|
335
|
-
},
|
|
336
|
-
reasoningEffort: {
|
|
337
|
-
type: 'string',
|
|
338
|
-
enum: ['high', 'xhigh'],
|
|
339
|
-
description: 'Codex reasoning effort (default: high, use xhigh for deeper analysis)'
|
|
340
|
-
},
|
|
341
|
-
serviceTier: {
|
|
342
|
-
type: 'string',
|
|
343
|
-
enum: ['default', 'fast', 'flex'],
|
|
344
|
-
description: 'Codex service tier (fast = priority processing, flex = cheaper/slower)'
|
|
345
|
-
}
|
|
115
|
+
workingDir: { type: 'string', description: 'Working directory for the CLI to operate in' },
|
|
116
|
+
ccOutput: { type: 'string', description: "Claude Code's output to review (findings, plan, analysis)" },
|
|
117
|
+
outputType: { type: 'string', enum: ['plan', 'findings', 'analysis', 'proposal'], description: 'Type of output being reviewed' },
|
|
118
|
+
analyzedFiles: { type: 'array', items: { type: 'string' }, description: 'File paths that CC analyzed' },
|
|
119
|
+
focusAreas: { type: 'array', items: { type: 'string', enum: ['security', 'performance', 'architecture', 'correctness', 'maintainability', 'scalability', 'testing', 'documentation'] }, description: 'Areas to focus the review on' },
|
|
120
|
+
customPrompt: { type: 'string', description: 'Custom instructions for the reviewer' },
|
|
121
|
+
reasoningEffort: { type: 'string', enum: ['high', 'xhigh'], description: 'Codex reasoning effort (default: high, use xhigh for deeper analysis)' },
|
|
122
|
+
serviceTier: { type: 'string', enum: ['default', 'fast', 'flex'], description: 'Codex service tier (fast = priority processing, flex = cheaper/slower)' }
|
|
346
123
|
},
|
|
347
124
|
required: ['workingDir', 'ccOutput', 'outputType']
|
|
348
125
|
}
|
|
349
126
|
},
|
|
350
127
|
gemini_review: {
|
|
351
128
|
name: 'gemini_review',
|
|
352
|
-
description: "ONLY use when user explicitly requests '/gemini' or 'review with gemini'. Get external second-opinion from Google Gemini CLI. Gemini focuses on design patterns, scalability, and tech debt. DO NOT use for general 'review' requests.",
|
|
129
|
+
description: "ONLY use when user explicitly requests '/gemini-review' or 'review with gemini'. Get external second-opinion from Google Gemini CLI. Gemini focuses on design patterns, scalability, and tech debt. DO NOT use for general 'review' requests.",
|
|
353
130
|
inputSchema: {
|
|
354
131
|
type: 'object',
|
|
355
132
|
properties: {
|
|
356
|
-
workingDir: {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
},
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
description: "Claude Code's output to review (findings, plan, analysis)"
|
|
363
|
-
},
|
|
364
|
-
outputType: {
|
|
365
|
-
type: 'string',
|
|
366
|
-
enum: ['plan', 'findings', 'analysis', 'proposal'],
|
|
367
|
-
description: 'Type of output being reviewed'
|
|
368
|
-
},
|
|
369
|
-
analyzedFiles: {
|
|
370
|
-
type: 'array',
|
|
371
|
-
items: { type: 'string' },
|
|
372
|
-
description: 'File paths that CC analyzed'
|
|
373
|
-
},
|
|
374
|
-
focusAreas: {
|
|
375
|
-
type: 'array',
|
|
376
|
-
items: {
|
|
377
|
-
type: 'string',
|
|
378
|
-
enum: ['security', 'performance', 'architecture', 'correctness', 'maintainability', 'scalability', 'testing', 'documentation']
|
|
379
|
-
},
|
|
380
|
-
description: 'Areas to focus the review on'
|
|
381
|
-
},
|
|
382
|
-
customPrompt: {
|
|
383
|
-
type: 'string',
|
|
384
|
-
description: 'Custom instructions for the reviewer'
|
|
385
|
-
}
|
|
133
|
+
workingDir: { type: 'string', description: 'Working directory for the CLI to operate in' },
|
|
134
|
+
ccOutput: { type: 'string', description: "Claude Code's output to review (findings, plan, analysis)" },
|
|
135
|
+
outputType: { type: 'string', enum: ['plan', 'findings', 'analysis', 'proposal'], description: 'Type of output being reviewed' },
|
|
136
|
+
analyzedFiles: { type: 'array', items: { type: 'string' }, description: 'File paths that CC analyzed' },
|
|
137
|
+
focusAreas: { type: 'array', items: { type: 'string', enum: ['security', 'performance', 'architecture', 'correctness', 'maintainability', 'scalability', 'testing', 'documentation'] }, description: 'Areas to focus the review on' },
|
|
138
|
+
customPrompt: { type: 'string', description: 'Custom instructions for the reviewer' },
|
|
386
139
|
},
|
|
387
140
|
required: ['workingDir', 'ccOutput', 'outputType']
|
|
388
141
|
}
|
|
389
142
|
},
|
|
390
143
|
multi_review: {
|
|
391
144
|
name: 'multi_review',
|
|
392
|
-
description: "ONLY use when user explicitly requests '/multi' or 'review with both codex and gemini'. Get parallel second-opinions from both external CLIs (Codex and Gemini). Returns combined reviews for synthesis. DO NOT use for general 'review' requests.",
|
|
145
|
+
description: "ONLY use when user explicitly requests '/multi-review' or 'review with both codex and gemini'. Get parallel second-opinions from both external CLIs (Codex and Gemini). Returns combined reviews for synthesis. DO NOT use for general 'review' requests.",
|
|
393
146
|
inputSchema: {
|
|
394
147
|
type: 'object',
|
|
395
148
|
properties: {
|
|
396
|
-
workingDir: {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
},
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
},
|
|
404
|
-
outputType: {
|
|
405
|
-
type: 'string',
|
|
406
|
-
enum: ['plan', 'findings', 'analysis', 'proposal'],
|
|
407
|
-
description: 'Type of output being reviewed'
|
|
408
|
-
},
|
|
409
|
-
analyzedFiles: {
|
|
410
|
-
type: 'array',
|
|
411
|
-
items: { type: 'string' },
|
|
412
|
-
description: 'File paths that CC analyzed'
|
|
413
|
-
},
|
|
414
|
-
focusAreas: {
|
|
415
|
-
type: 'array',
|
|
416
|
-
items: {
|
|
417
|
-
type: 'string',
|
|
418
|
-
enum: ['security', 'performance', 'architecture', 'correctness', 'maintainability', 'scalability', 'testing', 'documentation']
|
|
419
|
-
},
|
|
420
|
-
description: 'Areas to focus the review on'
|
|
421
|
-
},
|
|
422
|
-
customPrompt: {
|
|
423
|
-
type: 'string',
|
|
424
|
-
description: 'Custom instructions for the reviewer'
|
|
425
|
-
},
|
|
426
|
-
serviceTier: {
|
|
427
|
-
type: 'string',
|
|
428
|
-
enum: ['default', 'fast', 'flex'],
|
|
429
|
-
description: 'Codex service tier (fast = priority processing, flex = cheaper/slower). Only applies to Codex.'
|
|
430
|
-
}
|
|
149
|
+
workingDir: { type: 'string', description: 'Working directory for the CLI to operate in' },
|
|
150
|
+
ccOutput: { type: 'string', description: "Claude Code's output to review (findings, plan, analysis)" },
|
|
151
|
+
outputType: { type: 'string', enum: ['plan', 'findings', 'analysis', 'proposal'], description: 'Type of output being reviewed' },
|
|
152
|
+
analyzedFiles: { type: 'array', items: { type: 'string' }, description: 'File paths that CC analyzed' },
|
|
153
|
+
focusAreas: { type: 'array', items: { type: 'string', enum: ['security', 'performance', 'architecture', 'correctness', 'maintainability', 'scalability', 'testing', 'documentation'] }, description: 'Areas to focus the review on' },
|
|
154
|
+
customPrompt: { type: 'string', description: 'Custom instructions for the reviewer' },
|
|
155
|
+
serviceTier: { type: 'string', enum: ['default', 'fast', 'flex'], description: 'Codex service tier (fast = priority processing, flex = cheaper/slower). Only applies to Codex.' }
|
|
431
156
|
},
|
|
432
157
|
required: ['workingDir', 'ccOutput', 'outputType']
|
|
433
158
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export type FocusArea = 'security' | 'performance' | 'architecture' | 'correctne
|
|
|
6
6
|
export type CliType = 'codex' | 'gemini';
|
|
7
7
|
export type ReasoningEffort = 'high' | 'xhigh';
|
|
8
8
|
export type ServiceTier = 'default' | 'fast' | 'flex';
|
|
9
|
-
export type TaskType = 'plan' | 'debug' | 'explain' | 'question' | 'fix' | 'explore' | 'general';
|
|
10
9
|
export interface FeedbackRequest {
|
|
11
10
|
workingDir: string;
|
|
12
11
|
ccOutput: string;
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-reviewer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "MCP server for Claude Code - Get second-opinion feedback from Codex/Gemini CLIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"cc-reviewer": "dist/index.js"
|
|
9
|
-
"cc-reviewer-setup": "dist/setup.js"
|
|
8
|
+
"cc-reviewer": "dist/index.js"
|
|
10
9
|
},
|
|
11
10
|
"files": [
|
|
12
11
|
"dist/**/*",
|
package/commands/ask-codex.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# Ask Codex
|
|
2
|
-
|
|
3
|
-
Ask OpenAI Codex CLI for help as a peer engineer.
|
|
4
|
-
|
|
5
|
-
## Arguments
|
|
6
|
-
- `$ARGUMENTS` - Your question or request
|
|
7
|
-
|
|
8
|
-
## Codex Strengths
|
|
9
|
-
- **Correctness**: Logic errors, edge cases, bugs
|
|
10
|
-
- **Performance**: Efficiency, complexity analysis
|
|
11
|
-
- **Security**: Vulnerability detection
|
|
12
|
-
|
|
13
|
-
## Tool Invocation
|
|
14
|
-
|
|
15
|
-
Call `ask_codex` with:
|
|
16
|
-
|
|
17
|
-
```json
|
|
18
|
-
{
|
|
19
|
-
"workingDir": "<current directory>",
|
|
20
|
-
"prompt": "<your question or request from $ARGUMENTS>",
|
|
21
|
-
"taskType": "<infer from request: plan|debug|explain|question|fix|explore|general>",
|
|
22
|
-
"relevantFiles": ["<files related to the question>"],
|
|
23
|
-
"context": "<any error messages or prior analysis>",
|
|
24
|
-
"serviceTier": "<if user says 'fast mode'/'fast'/'priority' → 'fast'; if 'flex'/'cheap'/'budget' → 'flex'; otherwise omit>"
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## After Receiving Response
|
|
29
|
-
|
|
30
|
-
1. **Read the answer** and key points
|
|
31
|
-
2. **Check file references** — verify they exist
|
|
32
|
-
3. **Evaluate suggested actions** — do they make sense?
|
|
33
|
-
4. **Apply your judgment** — you may disagree
|
|
34
|
-
5. **Act on the suggestions** or ask follow-up questions
|
|
35
|
-
|
|
36
|
-
$ARGUMENTS
|
package/commands/ask-gemini.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Ask Gemini
|
|
2
|
-
|
|
3
|
-
Ask Google Gemini CLI for help as a peer engineer.
|
|
4
|
-
|
|
5
|
-
## Arguments
|
|
6
|
-
- `$ARGUMENTS` - Your question or request
|
|
7
|
-
|
|
8
|
-
## Gemini Strengths
|
|
9
|
-
- **Architecture**: Design patterns, structure
|
|
10
|
-
- **Scalability**: Load handling, bottlenecks
|
|
11
|
-
- **Maintainability**: Code clarity, tech debt
|
|
12
|
-
|
|
13
|
-
## Tool Invocation
|
|
14
|
-
|
|
15
|
-
Call `ask_gemini` with:
|
|
16
|
-
|
|
17
|
-
```json
|
|
18
|
-
{
|
|
19
|
-
"workingDir": "<current directory>",
|
|
20
|
-
"prompt": "<your question or request from $ARGUMENTS>",
|
|
21
|
-
"taskType": "<infer from request: plan|debug|explain|question|fix|explore|general>",
|
|
22
|
-
"relevantFiles": ["<files related to the question>"],
|
|
23
|
-
"context": "<any error messages or prior analysis>"
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## After Receiving Response
|
|
28
|
-
|
|
29
|
-
1. **Read the answer** and key points
|
|
30
|
-
2. **Check file references** — verify they exist
|
|
31
|
-
3. **Evaluate suggested actions** — do they make sense?
|
|
32
|
-
4. **Apply your judgment** — you may disagree
|
|
33
|
-
5. **Act on the suggestions** or ask follow-up questions
|
|
34
|
-
|
|
35
|
-
$ARGUMENTS
|
package/commands/ask-multi.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Ask Multi
|
|
2
|
-
|
|
3
|
-
Ask both Codex and Gemini for help in parallel — get multiple perspectives.
|
|
4
|
-
|
|
5
|
-
## Arguments
|
|
6
|
-
- `$ARGUMENTS` - Your question or request
|
|
7
|
-
|
|
8
|
-
## When to Use
|
|
9
|
-
|
|
10
|
-
Use `/ask-multi` when you want perspectives from both models on the same question.
|
|
11
|
-
|
|
12
|
-
## Tool Invocation
|
|
13
|
-
|
|
14
|
-
Call `ask_multi` with:
|
|
15
|
-
|
|
16
|
-
```json
|
|
17
|
-
{
|
|
18
|
-
"workingDir": "<current directory>",
|
|
19
|
-
"prompt": "<your question or request from $ARGUMENTS>",
|
|
20
|
-
"taskType": "<infer from request: plan|debug|explain|question|fix|explore|general>",
|
|
21
|
-
"relevantFiles": ["<files related to the question>"],
|
|
22
|
-
"context": "<any error messages or prior analysis>",
|
|
23
|
-
"serviceTier": "<if user says 'fast mode'/'fast'/'priority' → 'fast'; if 'flex'/'cheap'/'budget' → 'flex'; otherwise omit. Applies to Codex only.>"
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## After Receiving Responses
|
|
28
|
-
|
|
29
|
-
You will receive separate responses from each model.
|
|
30
|
-
|
|
31
|
-
### Synthesize
|
|
32
|
-
|
|
33
|
-
1. **Find agreements** — both models say the same thing (higher confidence)
|
|
34
|
-
2. **Identify conflicts** — they disagree (YOU decide who's right)
|
|
35
|
-
3. **Note unique insights** — findings only one model provided
|
|
36
|
-
4. **Verify file references** — check they exist
|
|
37
|
-
5. **Make YOUR recommendation** — don't just relay, apply judgment
|
|
38
|
-
|
|
39
|
-
$ARGUMENTS
|
package/dist/setup.d.ts
DELETED
package/dist/setup.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Setup script for cc-reviewer slash commands
|
|
4
|
-
*
|
|
5
|
-
* Copies the slash command files to ~/.claude/commands/
|
|
6
|
-
*/
|
|
7
|
-
import { installCommands, getCommandPaths } from './commands.js';
|
|
8
|
-
function setup() {
|
|
9
|
-
const { target } = getCommandPaths();
|
|
10
|
-
console.log('CC Reviewer - Setup Slash Commands\n');
|
|
11
|
-
const result = installCommands();
|
|
12
|
-
if (!result.success) {
|
|
13
|
-
console.error(`Error: ${result.error}`);
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
console.log('Installed slash commands:\n');
|
|
17
|
-
for (const cmd of result.installed) {
|
|
18
|
-
console.log(` /${cmd} -> ${target}/${cmd}.md`);
|
|
19
|
-
}
|
|
20
|
-
console.log('\n✓ Done! Restart Claude Code to use the commands.\n');
|
|
21
|
-
console.log('Available commands:');
|
|
22
|
-
for (const cmd of result.installed) {
|
|
23
|
-
console.log(` /${cmd}`);
|
|
24
|
-
}
|
|
25
|
-
console.log('');
|
|
26
|
-
}
|
|
27
|
-
setup();
|