pbakaus/impeccable · error
usage: surface-brief.mjs write <primary-target> <body-file>
Error message
usage: surface-brief.mjs write <primary-target> <body-file>
What it means
Thrown by main() in surface-brief.mjs when the 'write' subcommand is invoked without either the primary target or the body-file argument. The write command persists a brief to disk and needs both: the target names the surface the brief describes, and bodyFile is the file whose contents become the brief text (read via fs.readFileSync). Missing either, there is nothing deterministic to write.
Source
Thrown at skill/scripts/surface-brief.mjs:45
if (!filePath) throw new Error('surface brief path requires a concrete target');
process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
return;
}
if (command === 'list') {
process.stdout.write(`${JSON.stringify(listSurfaceBriefs(projectRoot).map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
return;
}
if (command === 'read') {
const result = resolveSurfaceBrief(projectRoot, target || null);
if (result.brief) {
process.stdout.write(result.brief.text);
return;
}
if (result.candidates.length) process.stderr.write(`${JSON.stringify(result.candidates.map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
process.exit(2);
}
if (command === 'write') {
if (!target || !bodyFile) throw new Error('usage: surface-brief.mjs write <primary-target> <body-file>');
const filePath = writeSurfaceBrief({
projectRoot,
primaryTarget: target,
relatedTargets,
body: fs.readFileSync(bodyFile, 'utf-8'),
});
process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
return;
}
throw new Error('usage: surface-brief.mjs <path|list|read|write> [target] [body-file] [related-target ...]');
}
function isMainModule() {
if (!process.argv[1]) return false;
try {
return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(process.argv[1]);
} catch {
return import.meta.url === pathToFileURL(process.argv[1]).href;View on GitHub (pinned to d14711ae3d)
Solutions
- Supply both: 'surface-brief.mjs write src/components/Header.jsx ./brief.md'.
- Create the body file first (e.g. echo, $EDITOR) so readFileSync succeeds.
- Re-read the usage message: write <primary-target> <body-file> [related-target ...].
Example fix
# before node surface-brief.mjs write src/components/Header.jsx # after node surface-brief.mjs write src/components/Header.jsx ./header-brief.md
Defensive patterns
Strategy: validation
Validate before calling
if (command === 'write' && (!target || !bodyFile)) {
throw new Error('write needs both <primary-target> and <body-file>');
}
if (!fs.existsSync(bodyFile)) throw new Error('body file not found: ' + bodyFile); Prevention
- Check bodyFile existence before invoking so the error message points at the right cause.
- Keep a brief body template handy so 'write' always has a non-empty body file.
- Pin argument order in wrapper scripts: target first, body second.
When it happens
Trigger: The script is run as 'surface-brief.mjs write <target>' with bodyFile omitted, or 'surface-brief.mjs write' with neither. argv destructuring puts argv[2] in target and argv[3] in bodyFile; the guard is !target || !bodyFile.
Common situations: User forgets the body file argument expecting an editor to open; passes only the target; the body path variable was unset in a wrapper; misread the usage line and supplied related-targets before the body file.
Related errors
- surface brief path requires a concrete target
- usage: surface-brief.mjs <path|list|read|write> [target] [bo
- Unknown ignore-rule flag: ${arg}
- Pass a rule id, e.g. ${IMPECCABLE_COMMAND} hooks ignore-rule
- overused-font is value-specific by default. Use ${IMPECCABLE
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/9da980399716324a.
Report an issue: GitHub.