{"record":{"id":"cc9ab92d70403aaf","repo":"affaan-m/ECC","slug":"non-interactive-guided-install-requires-at-least-o","errorCode":null,"errorMessage":"Non-interactive guided install requires at least one --harness.","messagePattern":"Non-interactive guided install requires at least one --harness\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/install-guided.js","lineNumber":188,"sourceCode":"  return {\n    ...options,\n    harnesses: normalizedHarnesses,\n    claudeScope,\n    claudeHooks,\n    profile,\n  };\n}\n\nfunction selectedHarnessIds(options) {\n  if (options.allHarnesses) return normalizeHarnessSelection(['all']);\n  if (options.harnesses.length === 0) return [];\n  return normalizeHarnessSelection(options.harnesses);\n}\n\nfunction validateExecutionMode(options, interactive) {\n  const harnesses = selectedHarnessIds(options);\n  if (!interactive && harnesses.length === 0) {\n    throw new Error('Non-interactive guided install requires at least one --harness.');\n  }\n  const requiresExplicit = !interactive || options.json;\n  if (requiresExplicit && harnesses.includes('claude') && (!options.claudeScope || !options.claudeHooks)) {\n    throw new Error('Claude requires explicit --claude-scope and --claude-hooks choices in this mode.');\n  }\n  if (requiresExplicit && harnesses.includes('kimi') && !options.profile) {\n    throw new Error('Kimi requires an explicit --profile choice in this mode.');\n  }\n  if ((!interactive || options.json) && !options.yes && !options.dryRun) {\n    throw new Error('Non-interactive and JSON mutations require --yes.');\n  }\n}\n\nfunction printPlan(plan, output) {\n  output.write('\\nECC guided install preview\\n\\n');\n  output.write('Harness       Channel           Destination\\n');\n  for (const entry of plan.harnesses) {\n    const harness = getHarnessCapability(entry.id);","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/install-guided.js#L170-L206","documentation":"When install-guided.js runs without an interactive TTY (piped stdin, CI, or any non-interactive shell), it cannot prompt for harness selection, so at least one --harness (or --all-harnesses) must be supplied on the command line. With zero harnesses in non-interactive mode it throws.","triggerScenarios":"Running the installer in CI with no --harness flag, piping /dev/null to stdin, or invoking from a daemon where no TTY is attached and no harness was preselected.","commonSituations":"CI pipelines, Docker entrypoints, SSH non-interactive sessions, or cron jobs that run the installer without arguments.","solutions":["Add --harness <id> (e.g. claude) or --all-harnesses to the command","Run the installer in an interactive terminal so it can prompt you","Combine with --yes and the required --claude-scope/--claude-hooks/--profile for fully non-interactive runs"],"exampleFix":"// before\nnode scripts/install-guided.js --yes < /dev/null\n// after\nnode scripts/install-guided.js --harness claude --claude-scope user --claude-hooks standard --yes","handlingStrategy":"validation","validationCode":"const interactive = process.stdin.isTTY === true;\nconst hasHarness = argv.some(a => a === '--harness' || a === '--all-harnesses');\nif (!interactive && !hasHarness) {\n  throw new Error('Non-interactive install needs --harness or --all-harnesses');\n}","typeGuard":"function isHarnessSpecified(argv) {\n  return argv.includes('--harness') || argv.includes('--all-harnesses');\n}","tryCatchPattern":"try { validateExecutionMode(options, interactive); }\ncatch (err) {\n  if (/requires at least one --harness/.test(err.message)) {\n    console.error(`${err.message} (or run interactively)`);\n    process.exit(2);\n  }\n  throw err;\n}","preventionTips":["Detect TTY availability before building the command in CI","Always pass --harness explicitly in non-interactive contexts","Fail fast in wrappers when stdin is not a TTY and no harness is set"],"tags":["cli","non-interactive","install-guided","ci"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}