ReactiveX/rxjs · error · Error

Usage: rxjs-migrate-skill <check|install|update|remove> --ha

Error message

Usage: rxjs-migrate-skill <check|install|update|remove> --harness <codex|claude|cursor> [--project-root <dir>] [--force]

What it means

Thrown by parseSkillArguments when the first CLI argument is not one of check, install, update, or remove. The skill CLI is strict about its action verb and prints usage in the error message.

Source

Thrown at packages/migrate/src/skill-cli.ts:73

export async function resolveCanonicalSkillRoot(modulePath = process.argv[1]): Promise<string> {
  if (!modulePath) throw new Error('Cannot locate the @rxjs/migrate package entry point.');
  const moduleDirectory = dirname(resolve(modulePath));
  for (const localPath of ['../skill', '../../skill']) {
    const candidate = resolve(moduleDirectory, localPath);
    try {
      if ((await stat(join(candidate, 'SKILL.md'))).isFile()) return candidate;
    } catch {
      // Try the source-tree or built-package alternative.
    }
  }
  throw new Error('Cannot locate the canonical Skill shipped by @rxjs/migrate.');
}

function parseSkillArguments(argv: readonly string[]): ParsedSkillCliOptions {
  const action = argv[0];
  if (action !== 'check' && action !== 'install' && action !== 'update' && action !== 'remove') {
    throw new Error(
      'Usage: rxjs-migrate-skill <check|install|update|remove> --harness <codex|claude|cursor> [--project-root <dir>] [--force]'
    );
  }
  let harness: SkillHarness | undefined;
  let projectRoot = process.cwd();
  let force = false;
  for (let index = 1; index < argv.length; index++) {
    const argument = argv[index];
    if (argument === '--harness') {
      const value = argv[++index];
      if (!value || !skillHarnesses.includes(value as SkillHarness)) throw new Error('--harness requires codex, claude, or cursor');
      harness = value as SkillHarness;
    } else if (argument === '--project-root') {
      const value = argv[++index];
      if (!value) throw new Error('--project-root requires a directory');
      projectRoot = value;
    } else if (argument === '--force') {
      force = true;

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Use exactly one of: rxjs-migrate-skill check|install|update|remove
  2. Put the action first, before --harness and other flags
  3. Check the CLI help/usage string for the accepted verbs

Example fix

# before
rxjs-migrate-skill install-skill --harness claude
# after
rxjs-migrate-skill install --harness claude
Defensive patterns

Strategy: validation

Validate before calling

const actions = ['check','install','update','remove'] as const;
if (!actions.includes(argv[0] as any)) { console.error('Usage: ...'); process.exit(2); }

Type guard

const isSkillAction = (a: string): a is 'check'|'install'|'update'|'remove' => ['check','install','update','remove'].includes(a);

Prevention

When it happens

Trigger: Running rxjs-migrate-skill with no arguments, a misspelled action ('instal', 'list'), or an action in the wrong position (after flags).

Common situations: Typos, forgetting the action, or assuming a 'list'/'init' subcommand exists.

Related errors


AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28). Data as JSON: /api/errors/eab6d3ebd88e410f. Report an issue: GitHub.