affaan-m/ECC · error
Non-interactive guided install requires at least one --harne
Error message
Non-interactive guided install requires at least one --harness.
What it means
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.
Source
Thrown at scripts/install-guided.js:188
return {
...options,
harnesses: normalizedHarnesses,
claudeScope,
claudeHooks,
profile,
};
}
function selectedHarnessIds(options) {
if (options.allHarnesses) return normalizeHarnessSelection(['all']);
if (options.harnesses.length === 0) return [];
return normalizeHarnessSelection(options.harnesses);
}
function validateExecutionMode(options, interactive) {
const harnesses = selectedHarnessIds(options);
if (!interactive && harnesses.length === 0) {
throw new Error('Non-interactive guided install requires at least one --harness.');
}
const requiresExplicit = !interactive || options.json;
if (requiresExplicit && harnesses.includes('claude') && (!options.claudeScope || !options.claudeHooks)) {
throw new Error('Claude requires explicit --claude-scope and --claude-hooks choices in this mode.');
}
if (requiresExplicit && harnesses.includes('kimi') && !options.profile) {
throw new Error('Kimi requires an explicit --profile choice in this mode.');
}
if ((!interactive || options.json) && !options.yes && !options.dryRun) {
throw new Error('Non-interactive and JSON mutations require --yes.');
}
}
function printPlan(plan, output) {
output.write('\nECC guided install preview\n\n');
output.write('Harness Channel Destination\n');
for (const entry of plan.harnesses) {
const harness = getHarnessCapability(entry.id);View on GitHub (pinned to 01e15490f0)
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
Example fix
// before node scripts/install-guided.js --yes < /dev/null // after node scripts/install-guided.js --harness claude --claude-scope user --claude-hooks standard --yes
Defensive patterns
Strategy: validation
Validate before calling
const interactive = process.stdin.isTTY === true;
const hasHarness = argv.some(a => a === '--harness' || a === '--all-harnesses');
if (!interactive && !hasHarness) {
throw new Error('Non-interactive install needs --harness or --all-harnesses');
} Type guard
function isHarnessSpecified(argv) {
return argv.includes('--harness') || argv.includes('--all-harnesses');
} Try / catch
try { validateExecutionMode(options, interactive); }
catch (err) {
if (/requires at least one --harness/.test(err.message)) {
console.error(`${err.message} (or run interactively)`);
process.exit(2);
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: CI pipelines, Docker entrypoints, SSH non-interactive sessions, or cron jobs that run the installer without arguments.
Related errors
- Claude requires explicit --claude-scope and --claude-hooks c
- Kimi requires an explicit --profile choice in this mode.
- Non-interactive and JSON mutations require --yes.
- Unknown argument: ${arg}
- Unknown argument: ${arg}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/cc9ab92d70403aaf.
Report an issue: GitHub.