pbakaus/impeccable · error

Pass only one scope flag: --shared or --local

Error message

Pass only one scope flag: --shared or --local

What it means

Thrown by parseIgnoreFileArgs when both --shared and --local are passed to `hooks ignore-file`. The two flags select which config file receives the glob (shared project config vs local personal config); they are mutually exclusive and the parser cannot write to both, so it refuses rather than picking one silently.

Solutions

  1. Keep exactly one scope flag: --shared for the committed project config, --local for your personal gitignored config.
  2. Omit both to use the default shared scope.
  3. If you need the glob in both scopes, run the command twice.

Example fix

# before
impeccable hooks ignore-file "src/legacy/**" --shared --local

# after
impeccable hooks ignore-file "src/legacy/**" --shared
impeccable hooks ignore-file "src/legacy/**" --local   # separate run if truly needed
Defensive patterns

Strategy: validation

Validate before calling

function scopeFlags({ shared, local }) {
  if (shared && local) throw new Error('choose exactly one scope');
  if (local) return ['--local'];
  if (shared) return ['--shared'];
  return []; // default shared
}

Prevention

When it happens

Trigger: `hooks ignore-file "src/**" --shared --local`; scripts assembling flags from multiple toggles that both end up true; users hedging because they are unsure which scope they want.

Common situations: Wrapper scripts that OR together boolean options into one command line; copy-paste accumulation of flags across attempts.

Related errors


AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18). Data as JSON: /api/errors/333c04d9f573a6e1. Report an issue: GitHub.

Appendix: source

Thrown at skill/scripts/hook-admin.mjs:609

  let shared = false;
  let local = false;

  for (const raw of args) {
    const arg = String(raw || '');
    if (arg === '--shared') {
      shared = true;
    } else if (arg === '--local') {
      local = true;
    } else if (arg === '--reason' || arg.startsWith('--reason=')) {
      throw new Error('--reason is not supported for ignore-file because detector.ignoreFiles stores globs only; use ignore-value when a documented rule-specific exception fits');
    } else if (arg.startsWith('--')) {
      throw new Error(`Unknown ignore-file flag: ${arg}`);
    } else {
      positionals.push(arg);
    }
  }

  if (shared && local) throw new Error('Pass only one scope flag: --shared or --local');
  if (positionals.length > 1) throw new Error('Pass exactly one glob to ignore-file');

  return {
    glob: positionals[0],
    local,
  };
}

function addIgnoreFile(cwd, args) {
  const parsed = parseIgnoreFileArgs(args);
  const glob = parsed.glob;
  if (!glob) throw new Error(`Pass a glob, e.g. ${IMPECCABLE_COMMAND} hooks ignore-file "src/legacy/**"`);
  const config = mergeDetectorConfig(readRawDetectorConfig(cwd, { local: parsed.local }));
  if (!config.ignoreFiles.includes(glob)) config.ignoreFiles.push(glob);
  const target = writeDetectorConfig(cwd, config, { local: parsed.local });
  const scope = parsed.local ? 'local detector.ignoreFiles' : 'shared detector.ignoreFiles';
  return `Added "${glob}" to ${scope} (${path.relative(cwd, target) || target}). Current: ${config.ignoreFiles.join(', ')}`;
}

View on GitHub (pinned to f88b2837a7)