ccsetup 1.2.0 → 1.2.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.
- package/README.md +93 -24
- package/bin/create-project.js +373 -773
- package/lib/templates/README.md +2 -2
- package/lib/templates/metadata/agents.json +1 -1
- package/package.json +3 -2
- package/template/.claude/settings.json +18 -1
- package/template/.claude/skills/codex-review/SKILL.md +139 -0
- package/template/.claude/skills/secops/SKILL.md +259 -0
- package/template/.codex/skills/codex-review/SKILL.md +139 -0
- package/template/.codex/skills/prd/SKILL.md +343 -0
- package/template/.codex/skills/ralph/SKILL.md +339 -0
- package/template/AGENTS.md +43 -0
- package/template/CLAUDE.md +106 -4
- package/template/docs/codex-setup.md +32 -0
- package/template/hooks/codex-review/index.js +105 -0
- package/template/scripts/codex-review/codex-review.sh +266 -0
- package/template/scripts/ralph/CODEX.md +76 -0
- package/template/scripts/ralph/ralph.sh +32 -9
- package/bin/lib/contextGenerator.js +0 -287
- package/bin/lib/scanner/index.js +0 -28
- package/bin/scan.js +0 -367
- package/lib/aiMergeHelper.js +0 -112
- package/lib/contextGenerator.js +0 -574
- package/lib/contextMerger.js +0 -812
- package/lib/progressReporter.js +0 -88
- package/lib/scanConfig.js +0 -200
- package/lib/scanner/fileAnalyzer.js +0 -605
- package/lib/scanner/index.js +0 -164
- package/lib/scanner/patterns.js +0 -277
- package/lib/scanner/projectDetector.js +0 -147
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Ralph Wiggum - Long-running AI agent loop
|
|
3
|
-
# Usage: ./ralph.sh [--tool
|
|
3
|
+
# Usage: ./ralph.sh [--tool claude|codex] [--model <model>] [max_iterations]
|
|
4
4
|
|
|
5
5
|
set -e
|
|
6
6
|
|
|
7
7
|
# Parse arguments
|
|
8
|
-
TOOL="
|
|
9
|
-
MODEL=""
|
|
8
|
+
TOOL="claude"
|
|
9
|
+
MODEL=""
|
|
10
10
|
MAX_ITERATIONS=10
|
|
11
11
|
|
|
12
12
|
while [[ $# -gt 0 ]]; do
|
|
@@ -38,8 +38,8 @@ while [[ $# -gt 0 ]]; do
|
|
|
38
38
|
done
|
|
39
39
|
|
|
40
40
|
# Validate tool choice
|
|
41
|
-
if [[ "$TOOL" != "
|
|
42
|
-
echo "Error: Invalid tool '$TOOL'. Must be '
|
|
41
|
+
if [[ "$TOOL" != "claude" && "$TOOL" != "codex" ]]; then
|
|
42
|
+
echo "Error: Invalid tool '$TOOL'. Must be 'claude' or 'codex'."
|
|
43
43
|
exit 1
|
|
44
44
|
fi
|
|
45
45
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -47,6 +47,25 @@ PRD_FILE="$SCRIPT_DIR/prd.json"
|
|
|
47
47
|
PROGRESS_FILE="$SCRIPT_DIR/progress.txt"
|
|
48
48
|
ARCHIVE_DIR="$SCRIPT_DIR/archive"
|
|
49
49
|
LAST_BRANCH_FILE="$SCRIPT_DIR/.last-branch"
|
|
50
|
+
CLAUDE_PROMPT_FILE="$SCRIPT_DIR/CLAUDE.md"
|
|
51
|
+
CODEX_PROMPT_FILE="$SCRIPT_DIR/CODEX.md"
|
|
52
|
+
|
|
53
|
+
if ! command -v jq &>/dev/null; then
|
|
54
|
+
echo "Error: jq is required for Ralph. Install jq and try again."
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
if [[ "$TOOL" == "claude" ]]; then
|
|
59
|
+
if ! command -v claude &>/dev/null; then
|
|
60
|
+
echo "Error: claude CLI is not installed. Install Claude Code and try again."
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
else
|
|
64
|
+
if ! command -v codex &>/dev/null; then
|
|
65
|
+
echo "Error: codex CLI is not installed. Install it with: npm install -g @openai/codex"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
fi
|
|
50
69
|
|
|
51
70
|
# Archive previous run if branch changed
|
|
52
71
|
if [ -f "$PRD_FILE" ] && [ -f "$LAST_BRANCH_FILE" ]; then
|
|
@@ -98,15 +117,19 @@ for i in $(seq 1 $MAX_ITERATIONS); do
|
|
|
98
117
|
echo "==============================================================="
|
|
99
118
|
|
|
100
119
|
# Run the selected tool with the ralph prompt
|
|
101
|
-
if [[ "$TOOL" == "
|
|
102
|
-
OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr) || true
|
|
103
|
-
else
|
|
120
|
+
if [[ "$TOOL" == "claude" ]]; then
|
|
104
121
|
# Claude Code: use --dangerously-skip-permissions for autonomous operation, --print for output
|
|
105
122
|
MODEL_FLAG=""
|
|
106
123
|
if [[ -n "$MODEL" ]]; then
|
|
107
124
|
MODEL_FLAG="--model $MODEL"
|
|
108
125
|
fi
|
|
109
|
-
OUTPUT=$(claude $MODEL_FLAG --dangerously-skip-permissions --chrome --print < "$
|
|
126
|
+
OUTPUT=$(claude $MODEL_FLAG --dangerously-skip-permissions --chrome --print < "$CLAUDE_PROMPT_FILE" 2>&1 | tee /dev/stderr) || true
|
|
127
|
+
else
|
|
128
|
+
CMD_ARGS=()
|
|
129
|
+
if [[ -n "$MODEL" ]]; then
|
|
130
|
+
CMD_ARGS+=(--model "$MODEL")
|
|
131
|
+
fi
|
|
132
|
+
OUTPUT=$(codex exec ${CMD_ARGS[@]+"${CMD_ARGS[@]}"} "$(<"$CODEX_PROMPT_FILE")" 2>&1 | tee /dev/stderr) || true
|
|
110
133
|
fi
|
|
111
134
|
|
|
112
135
|
# Check for completion signal
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
class ContextGenerator {
|
|
2
|
-
constructor(scanResults) {
|
|
3
|
-
this.scanResults = scanResults;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
generate() {
|
|
7
|
-
return {
|
|
8
|
-
overview: this.generateOverview(),
|
|
9
|
-
techStack: this.generateTechStack(),
|
|
10
|
-
commands: this.generateCommands(),
|
|
11
|
-
structure: this.generateStructure(),
|
|
12
|
-
patterns: this.generatePatterns(),
|
|
13
|
-
context: this.generateImportantContext()
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
generateOverview() {
|
|
18
|
-
const { projectType, purpose, frameworks } = this.scanResults;
|
|
19
|
-
|
|
20
|
-
if (purpose) {
|
|
21
|
-
return purpose;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let overview = `This is a ${projectType || 'Unknown'} project`;
|
|
25
|
-
|
|
26
|
-
if (frameworks && frameworks.length > 0) {
|
|
27
|
-
overview += ` using ${frameworks.join(', ')}`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
overview += '.';
|
|
31
|
-
|
|
32
|
-
return overview;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
generateTechStack() {
|
|
36
|
-
const techStack = {
|
|
37
|
-
languages: [],
|
|
38
|
-
frameworks: [],
|
|
39
|
-
databases: [],
|
|
40
|
-
devTools: [],
|
|
41
|
-
testing: [],
|
|
42
|
-
deployment: []
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// All results now come from Claude Code
|
|
46
|
-
if (this.scanResults.projectType) {
|
|
47
|
-
techStack.languages.push(this.scanResults.projectType);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (this.scanResults.frameworks && Array.isArray(this.scanResults.frameworks)) {
|
|
51
|
-
techStack.frameworks.push(...this.scanResults.frameworks);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (this.scanResults.dependencies) {
|
|
55
|
-
if (this.scanResults.dependencies.runtime) {
|
|
56
|
-
const dbPackages = ['mysql', 'postgresql', 'mongodb', 'redis', 'sqlite'];
|
|
57
|
-
|
|
58
|
-
for (const dep of this.scanResults.dependencies.runtime) {
|
|
59
|
-
if (dbPackages.some(db => dep.toLowerCase().includes(db))) {
|
|
60
|
-
techStack.databases.push(dep);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (this.scanResults.dependencies.dev) {
|
|
66
|
-
const devToolPackages = ['eslint', 'prettier', 'webpack', 'rollup', 'vite'];
|
|
67
|
-
|
|
68
|
-
for (const dep of this.scanResults.dependencies.dev) {
|
|
69
|
-
if (devToolPackages.some(tool => dep.toLowerCase().includes(tool))) {
|
|
70
|
-
techStack.devTools.push(dep);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (this.scanResults.patterns) {
|
|
77
|
-
if (this.scanResults.patterns.testing) {
|
|
78
|
-
techStack.testing.push(...this.scanResults.patterns.testing);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (this.scanResults.patterns.deployment) {
|
|
82
|
-
techStack.deployment.push(...this.scanResults.patterns.deployment);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
techStack.languages = [...new Set(techStack.languages)];
|
|
87
|
-
techStack.frameworks = [...new Set(techStack.frameworks)];
|
|
88
|
-
techStack.databases = [...new Set(techStack.databases)];
|
|
89
|
-
techStack.devTools = [...new Set(techStack.devTools)];
|
|
90
|
-
techStack.testing = [...new Set(techStack.testing)];
|
|
91
|
-
techStack.deployment = [...new Set(techStack.deployment)];
|
|
92
|
-
|
|
93
|
-
return techStack;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
generateCommands() {
|
|
97
|
-
const commands = {};
|
|
98
|
-
|
|
99
|
-
// All results now come from Claude Code
|
|
100
|
-
if (this.scanResults.commands && Array.isArray(this.scanResults.commands)) {
|
|
101
|
-
commands.available = this.scanResults.commands.map(cmd => ({
|
|
102
|
-
name: cmd.command,
|
|
103
|
-
description: cmd.description,
|
|
104
|
-
command: cmd.command
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return commands;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
generateStructure() {
|
|
112
|
-
const structure = {
|
|
113
|
-
overview: '',
|
|
114
|
-
keyDirectories: []
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
if (this.scanResults.structure && Array.isArray(this.scanResults.structure)) {
|
|
118
|
-
structure.keyDirectories = this.scanResults.structure.map(dir => ({
|
|
119
|
-
name: dir.path,
|
|
120
|
-
purpose: dir.purpose
|
|
121
|
-
}));
|
|
122
|
-
|
|
123
|
-
if (structure.keyDirectories.length > 0) {
|
|
124
|
-
structure.overview = `Project organized into ${structure.keyDirectories.length} key directories`;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return structure;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
generatePatterns() {
|
|
132
|
-
const patterns = {
|
|
133
|
-
architecture: [],
|
|
134
|
-
testing: [],
|
|
135
|
-
deployment: []
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
if (this.scanResults.patterns) {
|
|
139
|
-
if (this.scanResults.patterns.architecture) {
|
|
140
|
-
patterns.architecture = this.scanResults.patterns.architecture.map(name => ({
|
|
141
|
-
name,
|
|
142
|
-
description: `${name} pattern detected`
|
|
143
|
-
}));
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (this.scanResults.patterns.testing) {
|
|
147
|
-
patterns.testing = this.scanResults.patterns.testing.map(name => ({
|
|
148
|
-
name,
|
|
149
|
-
description: `${name} testing framework`
|
|
150
|
-
}));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (this.scanResults.patterns.deployment) {
|
|
154
|
-
patterns.deployment = this.scanResults.patterns.deployment.map(name => ({
|
|
155
|
-
name,
|
|
156
|
-
description: `${name} deployment method`
|
|
157
|
-
}));
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return patterns;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
generateImportantContext() {
|
|
165
|
-
const context = [];
|
|
166
|
-
|
|
167
|
-
if (this.scanResults.frameworks && this.scanResults.frameworks.length > 0) {
|
|
168
|
-
context.push(`Primary frameworks: ${this.scanResults.frameworks.join(', ')}`);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (this.scanResults.patterns && this.scanResults.patterns.architecture && this.scanResults.patterns.architecture.length > 0) {
|
|
172
|
-
context.push(`Architecture: ${this.scanResults.patterns.architecture.join(', ')}`);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const hasDatabases = this.scanResults.dependencies &&
|
|
176
|
-
this.scanResults.dependencies.runtime &&
|
|
177
|
-
this.scanResults.dependencies.runtime.some(dep =>
|
|
178
|
-
['mysql', 'postgresql', 'mongodb', 'redis', 'sqlite'].some(db =>
|
|
179
|
-
dep.toLowerCase().includes(db)
|
|
180
|
-
)
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
if (hasDatabases) {
|
|
184
|
-
context.push('Uses database connectivity');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (this.scanResults.patterns && this.scanResults.patterns.deployment && this.scanResults.patterns.deployment.includes('Docker')) {
|
|
188
|
-
context.push('Containerized with Docker');
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return context;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
formatForClaude() {
|
|
195
|
-
const generated = this.generate();
|
|
196
|
-
const sections = [];
|
|
197
|
-
|
|
198
|
-
sections.push('\n## Additional Notes\n');
|
|
199
|
-
|
|
200
|
-
if (generated.overview) {
|
|
201
|
-
sections.push('### Project Overview');
|
|
202
|
-
sections.push(generated.overview);
|
|
203
|
-
sections.push('');
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const techStack = generated.techStack;
|
|
207
|
-
if (Object.values(techStack).some(arr => arr.length > 0)) {
|
|
208
|
-
sections.push('### Tech Stack');
|
|
209
|
-
|
|
210
|
-
if (techStack.languages.length > 0) {
|
|
211
|
-
sections.push(`- **Languages**: ${techStack.languages.join(', ')}`);
|
|
212
|
-
}
|
|
213
|
-
if (techStack.frameworks.length > 0) {
|
|
214
|
-
sections.push(`- **Frameworks**: ${techStack.frameworks.join(', ')}`);
|
|
215
|
-
}
|
|
216
|
-
if (techStack.databases.length > 0) {
|
|
217
|
-
sections.push(`- **Databases**: ${techStack.databases.join(', ')}`);
|
|
218
|
-
}
|
|
219
|
-
if (techStack.devTools.length > 0 && techStack.devTools.length <= 8) {
|
|
220
|
-
sections.push(`- **Dev Tools**: ${techStack.devTools.join(', ')}`);
|
|
221
|
-
}
|
|
222
|
-
if (techStack.testing.length > 0) {
|
|
223
|
-
sections.push(`- **Testing**: ${techStack.testing.join(', ')}`);
|
|
224
|
-
}
|
|
225
|
-
if (techStack.deployment.length > 0) {
|
|
226
|
-
sections.push(`- **Deployment**: ${techStack.deployment.join(', ')}`);
|
|
227
|
-
}
|
|
228
|
-
sections.push('');
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const commands = generated.commands;
|
|
232
|
-
if (commands.available && commands.available.length > 0) {
|
|
233
|
-
sections.push('### Key Commands');
|
|
234
|
-
|
|
235
|
-
for (const cmd of commands.available.slice(0, 10)) {
|
|
236
|
-
sections.push(`- \`${cmd.command}\` - ${cmd.description}`);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
sections.push('');
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const structure = generated.structure;
|
|
243
|
-
if (structure.keyDirectories.length > 0) {
|
|
244
|
-
sections.push('### Project Structure');
|
|
245
|
-
|
|
246
|
-
for (const dir of structure.keyDirectories.slice(0, 8)) {
|
|
247
|
-
sections.push(`- \`${dir.name}\` - ${dir.purpose}`);
|
|
248
|
-
}
|
|
249
|
-
sections.push('');
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const patterns = generated.patterns;
|
|
253
|
-
const allPatterns = [
|
|
254
|
-
...patterns.architecture,
|
|
255
|
-
...patterns.testing,
|
|
256
|
-
...patterns.deployment
|
|
257
|
-
];
|
|
258
|
-
|
|
259
|
-
if (allPatterns.length > 0) {
|
|
260
|
-
sections.push('### Architecture & Patterns');
|
|
261
|
-
for (const pattern of allPatterns.slice(0, 8)) {
|
|
262
|
-
sections.push(`- **${pattern.name}**: ${pattern.description}`);
|
|
263
|
-
}
|
|
264
|
-
sections.push('');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (generated.context.length > 0) {
|
|
268
|
-
sections.push('### Important Context');
|
|
269
|
-
for (const item of generated.context) {
|
|
270
|
-
sections.push(`- ${item}`);
|
|
271
|
-
}
|
|
272
|
-
sections.push('');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const scanInfo = this.scanResults;
|
|
276
|
-
if (scanInfo.scanDate) {
|
|
277
|
-
sections.push('### Scan Information');
|
|
278
|
-
sections.push(`- Analyzed using Claude Code AI`);
|
|
279
|
-
sections.push(`- Last scanned: ${new Date(scanInfo.scanDate).toLocaleString()}`);
|
|
280
|
-
sections.push('');
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return sections.join('\n');
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
module.exports = ContextGenerator;
|
package/bin/lib/scanner/index.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const ClaudeInterface = require('../claudeInterface');
|
|
2
|
-
|
|
3
|
-
class RepositoryScanner {
|
|
4
|
-
constructor(projectPath, options = {}) {
|
|
5
|
-
this.projectPath = projectPath;
|
|
6
|
-
this.options = options;
|
|
7
|
-
this.claudeInterface = new ClaudeInterface(this.projectPath);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Scan repository using ONLY Claude Code CLI
|
|
12
|
-
*/
|
|
13
|
-
async scan() {
|
|
14
|
-
// Check if Claude Code is available
|
|
15
|
-
const isAvailable = await this.claudeInterface.isAvailable();
|
|
16
|
-
|
|
17
|
-
if (!isAvailable) {
|
|
18
|
-
throw new Error('Claude Code CLI is required but not found. Please install it first: npm install -g @anthropic-ai/claude-code');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
console.log('✓ Claude Code detected, starting AI-powered analysis...');
|
|
22
|
-
|
|
23
|
-
// Use Claude Code to scan the repository
|
|
24
|
-
return await this.claudeInterface.scanRepository();
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
module.exports = RepositoryScanner;
|