Skip to content

Commit d98d1f0

Browse files
StackMemory Bot (CLI)claude
andcommitted
feat(gepa): add AGENT.md support to Prompt Forge watcher
- Watch both CLAUDE.md and AGENT.md for optimization - Spawn separate GEPA processes for each file that exists - Update status message to show all watched files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent cde2190 commit d98d1f0

1 file changed

Lines changed: 31 additions & 27 deletions

File tree

src/cli/claude-sm.ts

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -226,16 +226,18 @@ class ClaudeSM {
226226
return null;
227227
}
228228

229-
private gepaProcess: ReturnType<typeof spawn> | null = null;
229+
private gepaProcesses: ReturnType<typeof spawn>[] = [];
230230

231231
private startGEPAWatcher(): void {
232-
// Find CLAUDE.md in current directory or project root
233-
const claudeMdPath = fs.existsSync(path.join(process.cwd(), 'CLAUDE.md'))
234-
? path.join(process.cwd(), 'CLAUDE.md')
235-
: null;
232+
// Find CLAUDE.md and AGENT.md in current directory or project root
233+
const watchFiles = ['CLAUDE.md', 'AGENT.md']
234+
.map((f) => path.join(process.cwd(), f))
235+
.filter((p) => fs.existsSync(p));
236236

237-
if (!claudeMdPath) {
238-
console.log(chalk.gray(' Prompt Forge: disabled (no CLAUDE.md found)'));
237+
if (watchFiles.length === 0) {
238+
console.log(
239+
chalk.gray(' Prompt Forge: disabled (no CLAUDE.md or AGENT.md found)')
240+
);
239241
return;
240242
}
241243

@@ -272,35 +274,37 @@ class ClaudeSM {
272274
return;
273275
}
274276

275-
// Start GEPA watcher in background
276-
this.gepaProcess = spawn('node', [gepaScript, 'watch', claudeMdPath], {
277-
detached: true,
278-
stdio: ['ignore', 'pipe', 'pipe'],
279-
env: { ...process.env, GEPA_SILENT: '1' },
280-
});
277+
// Start GEPA watcher for each file
278+
for (const filePath of watchFiles) {
279+
const gepaProcess = spawn('node', [gepaScript, 'watch', filePath], {
280+
detached: true,
281+
stdio: ['ignore', 'pipe', 'pipe'],
282+
env: { ...process.env, GEPA_SILENT: '1' },
283+
});
281284

282-
this.gepaProcess.unref();
285+
gepaProcess.unref();
286+
this.gepaProcesses.push(gepaProcess);
283287

284-
// Log output from GEPA (non-blocking)
285-
this.gepaProcess.stdout?.on('data', (data: Buffer) => {
286-
const output = data.toString().trim();
287-
if (output && !output.includes('Watching')) {
288-
console.log(chalk.magenta(`[GEPA] ${output}`));
289-
}
290-
});
288+
// Log output from GEPA (non-blocking)
289+
gepaProcess.stdout?.on('data', (data: Buffer) => {
290+
const output = data.toString().trim();
291+
if (output && !output.includes('Watching')) {
292+
console.log(chalk.magenta(`[GEPA] ${output}`));
293+
}
294+
});
295+
}
291296

297+
const fileNames = watchFiles.map((f) => path.basename(f)).join(', ');
292298
console.log(
293-
chalk.cyan(
294-
` Prompt Forge: watching ${path.basename(claudeMdPath)} for optimization`
295-
)
299+
chalk.cyan(` Prompt Forge: watching ${fileNames} for optimization`)
296300
);
297301
}
298302

299303
private stopGEPAWatcher(): void {
300-
if (this.gepaProcess) {
301-
this.gepaProcess.kill('SIGTERM');
302-
this.gepaProcess = null;
304+
for (const proc of this.gepaProcesses) {
305+
proc.kill('SIGTERM');
303306
}
307+
this.gepaProcesses = [];
304308
}
305309

306310
private ensureGreptileMcp(): void {

0 commit comments

Comments
 (0)