Yeachan-Heo/oh-my-codex · error · UltragoalError

Missing brief text. Pass --brief, --brief-file, --from-stdin

Error message

Missing brief text. Pass --brief, --brief-file, --from-stdin, or positional text.

What it means

The create/create-goals subcommand requires brief text and looks for it in order: --brief, --brief-file (file contents), --from-stdin (piped input), then positional text. If none yields non-whitespace text, it throws this error listing all four sources.

Source

Thrown at src/cli/ultragoal.ts:385

  const json = hasFlag(rest, '--json');
  const cwd = process.cwd();
  const buildGoalInstruction = deps.buildCodexGoalInstruction ?? buildCodexGoalInstruction;

  try {
    if (command === 'help' || command === '--help' || command === '-h') {
      console.log(ULTRAGOAL_HELP);
      return;
    }

    assertUltragoalMutationAllowedFromCurrentProcess(command);

    if (command === 'create' || command === 'create-goals') {
      const briefFile = readValue(rest, '--brief-file');
      const brief = readValue(rest, '--brief')
        ?? (briefFile ? await readFile(briefFile, 'utf-8') : undefined)
        ?? (hasFlag(rest, '--from-stdin') ? await readStdin() : undefined)
        ?? positionalText(rest);
      if (!brief.trim()) throw new UltragoalError('Missing brief text. Pass --brief, --brief-file, --from-stdin, or positional text.');
      const goals = readRepeated(rest, '--goal').map(parseGoalArg);
      const plan = await createUltragoalPlan(cwd, {
        brief,
        goals,
        codexGoalMode: normalizeCodexGoalMode(readValue(rest, '--codex-goal-mode')),
        force: hasFlag(rest, '--force'),
      });
      if (json) printJson({ ok: true, plan, summary: summarizeUltragoalPlan(plan) });
      else {
        console.log(`ultragoal plan created: ${plan.goals.length} goal(s)`);
        console.log(`brief: ${plan.briefPath}`);
        console.log(`goals: ${plan.goalsPath}`);
        console.log(`ledger: ${plan.ledgerPath}`);
      }
      return;
    }

    if (command === 'status') {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Pass `--brief "..."` directly, or `--brief-file brief.md` with a non-empty file, or pipe stdin with --from-stdin
  2. Verify the file is non-empty: `wc -c brief.md` should be > 0
  3. In CI, ensure stdin is provided (`echo b | omx ultragoal create --from-stdin`) or use a flag

Example fix

# before
omx ultragoal create
# Error: Missing brief text. Pass --brief, --brief-file, --from-stdin, or positional text.

# after
omx ultragoal create --brief "Ship v2 API with auth and tests"
Defensive patterns

Strategy: validation

Validate before calling

const brief = flag('--brief') ?? (briefFile ? readFileSync(briefFile, 'utf-8') : '') ;
if (!brief.trim()) { console.error('provide non-empty --brief/--brief-file or pipe stdin'); process.exit(2); }

Type guard

function hasBriefText(v: string | undefined): v is string {
  return !!v && v.trim().length > 0;
}

Prevention

When it happens

Trigger: Running `omx ultragoal create` with no brief flags; --brief-file pointing at an empty file (empty string fails the trim check); --from-stdin with empty stdin (no pipe attached); positional text being only whitespace.

Common situations: Forgetting the flag assuming a prompt appears; CI job with stdin closed so --from-stdin reads ''; wrong path making briefFile undefined; trailing-newline-only file.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/6d8707a14547980e. Report an issue: GitHub.