Skip to content

Commit fb06edb

Browse files
oniixxxcursoragent
andcommitted
fix: improvements to install, doctor, and config validation
- install: constants for Codex 32KiB and Windsurf 6k limit; enforce Codex size cap; verbose logs written file paths - doctor: check prompt files (prompts.default, prompts.review) exist when config is valid; only report on failure - load-config: validate tool is one of cursor|claude|codex|windsurf|other Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 9a36632 commit fb06edb

3 files changed

Lines changed: 47 additions & 20 deletions

File tree

cli/src/commands/doctor.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import chalk from 'chalk';
44
import type { Platform } from '../schemas.js';
55
import { findConfigPath, loadPromptConfig } from '../lib/load-config.js';
66
import { mergeGitignore } from '../lib/gitignore.js';
7+
import { readPromptFromYaml } from '../lib/read-prompts.js';
78

89
const GITIGNORE_MARKER = '# prompt-guide (added by prompt-guide-cli)';
910
const PLATFORMS: Platform[] = ['ios', 'android', 'flutter', 'web', 'server'];
@@ -41,6 +42,23 @@ export function runDoctor(
4142
const config = loadPromptConfig(cwd);
4243
const tool = config.tool || 'cursor';
4344
results.push({ ok: true, message: `prompt.config.js exists (tool=${tool})` });
45+
// Check that prompt files referenced in config exist
46+
const defaultPath = config.prompts?.default ?? 'prompts/system.core.yml';
47+
const reviewPath = config.prompts?.review ?? 'prompts/review.yml';
48+
for (const [label, relPath] of [
49+
['prompts.default', defaultPath],
50+
['prompts.review', reviewPath],
51+
] as const) {
52+
try {
53+
readPromptFromYaml(cwd, relPath);
54+
} catch {
55+
results.push({
56+
ok: false,
57+
message: `Prompt file missing: ${relPath}`,
58+
hint: `Create the file or fix ${label} in prompt.config.js`,
59+
});
60+
}
61+
}
4462
} catch {
4563
results.push({ ok: false, message: 'prompt.config.js invalid or failed to load', hint: 'Fix exports or run: prompt-guide init' });
4664
}

cli/src/commands/install.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { loadPromptConfig, type PromptConfig } from '../lib/load-config.js';
55
import { readPromptFromYaml } from '../lib/read-prompts.js';
66

77
const BAR = chalk.dim(' ' + '─'.repeat(44));
8+
const CODEC_AGENTS_MAX_BYTES = 32 * 1024;
9+
const WINDSURF_MAX_CHARS = 6000;
810

911
function writeCursorRules(cwd: string, config: PromptConfig, systemPrompt: string, reviewPrompt: string): void {
1012
const dir = path.join(cwd, '.cursor', 'rules');
@@ -37,32 +39,25 @@ This project uses prompt-guide. Full config: \`prompt.config.js\` and \`prompts/
3739
Below: system core and review criteria (concise). Do not exceed ~32 KiB total.
3840
3941
---
40-
41-
## System core (required rules)
42-
4342
`;
4443
const core = systemPrompt.length > 12000 ? systemPrompt.slice(0, 12000) + '\n\n...(see prompts/system.core.yml for full text)' : systemPrompt;
45-
const reviewSection = `
46-
47-
---
48-
49-
## Review criteria
50-
51-
`;
5244
const review = reviewPrompt.length > 8000 ? reviewPrompt.slice(0, 8000) + '\n\n...(see prompts/review.yml for full)' : reviewPrompt;
53-
const full = intro + core + reviewSection + review;
45+
let full = intro + core + '\n\n---\n\n' + review;
46+
if (Buffer.byteLength(full, 'utf8') > CODEC_AGENTS_MAX_BYTES) {
47+
full = full.slice(0, CODEC_AGENTS_MAX_BYTES - 80) + '\n\n...(truncated to fit Codex ~32 KiB limit)';
48+
}
5449
fs.writeFileSync(filePath, full);
5550
}
5651

5752
function writeWindsurfRules(cwd: string, systemPrompt: string): void {
5853
const filePath = path.join(cwd, '.windsurfrules');
59-
const maxLen = 6000;
60-
const condensed = systemPrompt.replace(/\n{2,}/g, '\n').slice(0, maxLen - 200);
61-
const content = `# Prompt Guide — rules (from prompt.config.js / prompts)
62-
# Edit prompt.config.js and run \`prompt-guide install\` to regenerate.
63-
64-
${condensed}${systemPrompt.length > maxLen - 200 ? '\n\n...(truncated; see prompts/system.core.yml)' : ''}
65-
`;
54+
const note = 'Regenerate: prompt-guide install. Edit prompt.config.js and prompts/.\n\n';
55+
const reserved = note.length + 60;
56+
const condensed = systemPrompt.replace(/\n{2,}/g, '\n').slice(0, WINDSURF_MAX_CHARS - reserved);
57+
const content =
58+
note +
59+
condensed +
60+
(systemPrompt.length > WINDSURF_MAX_CHARS - reserved ? '\n\n...(truncated; see prompts/system.core.yml)' : '');
6661
fs.writeFileSync(filePath, content);
6762
}
6863

@@ -71,10 +66,10 @@ function writeClaudeRules(cwd: string, systemPrompt: string, reviewPrompt: strin
7166
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
7267

7368
const corePath = path.join(dir, 'prompt-guide-core.md');
74-
fs.writeFileSync(corePath, `# System core (prompt-guide)\n\n${systemPrompt}`);
69+
fs.writeFileSync(corePath, systemPrompt);
7570

7671
const reviewPath = path.join(dir, 'prompt-guide-review.md');
77-
fs.writeFileSync(reviewPath, `# Review criteria (prompt-guide)\n\n${reviewPrompt}`);
72+
fs.writeFileSync(reviewPath, reviewPrompt);
7873
}
7974

8075
export type InstallOptions = { dryRun?: boolean; verbose?: boolean };
@@ -111,25 +106,34 @@ export function runInstall(options: InstallOptions = {}): void {
111106
return;
112107
}
113108

109+
const verbose = options.verbose === true;
110+
114111
switch (tool) {
115112
case 'cursor':
116113
writeCursorRules(cwd, config, systemPrompt, reviewPrompt);
117114
console.log(chalk.green(' ✓') + ' .cursor/rules/use-prompt-guide.mdc');
115+
if (verbose) console.log(chalk.dim(' ') + path.join(cwd, '.cursor', 'rules', 'use-prompt-guide.mdc'));
118116
console.log(chalk.dim(' → Edit only prompt.config.js and prompts/. Re-run install only when you change tool.'));
119117
break;
120118
case 'codex':
121119
writeCodexAgentsMd(cwd, systemPrompt, reviewPrompt);
122120
console.log(chalk.green(' ✓') + ' AGENTS.md');
121+
if (verbose) console.log(chalk.dim(' ') + path.join(cwd, 'AGENTS.md'));
123122
console.log(chalk.dim(' → Re-run prompt-guide install after changing config.'));
124123
break;
125124
case 'windsurf':
126125
writeWindsurfRules(cwd, systemPrompt);
127126
console.log(chalk.green(' ✓') + ' .windsurfrules');
127+
if (verbose) console.log(chalk.dim(' ') + path.join(cwd, '.windsurfrules'));
128128
console.log(chalk.dim(' → Re-run prompt-guide install after changing config.'));
129129
break;
130130
case 'claude':
131131
writeClaudeRules(cwd, systemPrompt, reviewPrompt);
132132
console.log(chalk.green(' ✓') + ' .claude/rules/prompt-guide-core.md, prompt-guide-review.md');
133+
if (verbose) {
134+
console.log(chalk.dim(' ') + path.join(cwd, '.claude', 'rules', 'prompt-guide-core.md'));
135+
console.log(chalk.dim(' ') + path.join(cwd, '.claude', 'rules', 'prompt-guide-review.md'));
136+
}
133137
console.log(chalk.dim(' → Re-run prompt-guide install after changing config.'));
134138
break;
135139
default:

cli/src/lib/load-config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,10 @@ export function loadPromptConfig(cwd: string): PromptConfig {
4343
if (!config.tool || typeof config.tool !== 'string') {
4444
throw new Error('prompt.config.js must set "tool" (cursor | claude | codex | windsurf | other).');
4545
}
46+
const tool = config.tool.toLowerCase();
47+
const allowed = ['cursor', 'claude', 'codex', 'windsurf', 'other'];
48+
if (!allowed.includes(tool)) {
49+
throw new Error(`prompt.config.js "tool" must be one of: ${allowed.join(', ')}. Got: ${config.tool}`);
50+
}
4651
return config;
4752
}

0 commit comments

Comments
 (0)