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

Usage: omx auth add <slot> [--device-auth|--with-api-key|--w

Error message

Usage: omx auth add <slot> [--device-auth|--with-api-key|--with-access-token]

What it means

`omx auth add` requires a slot name as its first positional argument (a named credential slot to store the login under). If no slot is provided, the command aborts with a usage message showing the expected form and allowed flags.

Source

Thrown at src/cli/auth.ts:108

  let updated = upsertTopLevelTomlString(existing, "model", DEFAULT_SUBSCRIPTION_MODEL);
  updated = upsertTopLevelTomlString(updated, "model_provider", DEFAULT_SUBSCRIPTION_MODEL_PROVIDER);
  await mkdir(codexHome, { recursive: true });
  await writeFile(configPath, updated);
}


export async function authCommand(args: string[], env: NodeJS.ProcessEnv = process.env): Promise<void> {
  const command = args[0];
  const cwd = process.cwd();
  const home = env.HOME;
  if (!command || command === "--help" || command === "-h" || command === "help") {
    console.log(AUTH_HELP.trim());
    return;
  }

  if (command === "add") {
    const slot = args[1];
    if (!slot) throw new Error("Usage: omx auth add <slot> [--device-auth|--with-api-key|--with-access-token]");
    const loginArgs = args.slice(2);
    const liveAuthPath = resolveLiveAuthPath(cwd, env, home);
    const hadLiveAuth = await fileExists(liveAuthPath);
    const tempCodexHome = await createIsolatedLoginCodexHome(home);
    try {
      runCodexLogin(cwd, { ...env, CODEX_HOME: tempCodexHome }, loginArgs);
      const tempAuthPath = join(tempCodexHome, "auth.json");
      const record = await addSlotFromAuthFile(slot, tempAuthPath, home);
      await ensureSubscriptionCodexDefaults(dirname(liveAuthPath));
      if (!hadLiveAuth) {
        await useSlot(slot, liveAuthPath, home);
      }
      console.log(`Added auth slot ${record.slot}`);
    } finally {
      await rm(tempCodexHome, { recursive: true, force: true }).catch(() => undefined);
    }
    return;
  }

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Provide a slot name: `omx auth add <slot> [--device-auth|--with-api-key|--with-access-token]`
  2. Quote script variables so empty values fail loudly instead of silently: `omx auth add "$SLOT"`
  3. Use a meaningful slot like `work` or `personal` to keep multiple credentials organized

Example fix

# before
omx auth add --device-auth
# after
omx auth add work --device-auth
Defensive patterns

Strategy: validation

Validate before calling

const slot = process.argv[3];
if (!slot || slot.startsWith('--')) {
  console.error('Usage: omx auth add <slot> [--device-auth|--with-api-key|--with-access-token]');
  process.exit(1);
}

Type guard

const isNonEmptySlot = (s?: string): s is string => !!s && !s.startsWith('--');

Try / catch

catch (e) { if (/^Usage: omx auth add/.test(String(e))) { printAuthAddHelp(); } else throw e; }

Prevention

When it happens

Trigger: Running `omx auth add` with no arguments, or `omx auth add --device-auth` where the flag is consumed as the slot slot position incorrectly (missing positional).

Common situations: Users assuming interactive slot prompting that doesn't exist; copy-paste errors dropping the slot name; scripts with unquoted empty variables collapsing to nothing.

Understand the failure class

Background: "no subcommand specified" and "... is required": CLI errors when a required argument is missing — this error's family across 13 libraries.

Related errors


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