{"record":{"id":"26848d2eba362636","repo":"gitbutlerapp/gitbutler","slug":"human-input-required-run-this-in-a-terminal-or","errorCode":null,"errorMessage":"Human input required - run this in a terminal, or specify --path/--detect to avoid interactive prompts.","messagePattern":"Human input required - run this in a terminal, or specify --path/--detect to avoid interactive prompts\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/skill/mod.rs","lineNumber":880,"sourceCode":"        None => Err(UserCancelled.into()),\n    }\n}\n\n/// Prompt user to select installation scope and format\nfn prompt_for_install_path(\n    ctx: Option<&mut Context>,\n    global: bool,\n    out: &mut OutputChannel,\n    progress: &mut impl std::io::Write,\n) -> Result<PathBuf> {\n    let t = theme::get();\n    if out.for_human().is_none() {\n        anyhow::bail!(\n            \"No supported agent was detected. In non-interactive mode, specify --path or --detect. Use --path <path> to choose an installation directory, or --detect to update an existing installation.\"\n        );\n    }\n    if !out.can_prompt() {\n        anyhow::bail!(\n            \"Human input required - run this in a terminal, or specify --path/--detect to avoid interactive prompts.\"\n        );\n    }\n\n    let local_scope_available = if !global {\n        match ctx.as_ref() {\n            Some(ctx) => {\n                let repo = ctx.repo.get()?;\n                repo.workdir().is_some()\n            }\n            None => false,\n        }\n    } else {\n        false\n    };\n\n    let mut input = out\n        .prepare_for_terminal_input()","sourceCodeStart":862,"sourceCodeEnd":898,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/skill/mod.rs#L862-L898","documentation":"Even when stdout is human-readable, `but skill install` needs interactive stdin to present its scope/directory prompts. prompt_for_install_path checks out.can_prompt() and aborts when stdin is closed or redirected, rather than hanging on a prompt nobody can answer.","triggerScenarios":"`but skill install < /dev/null`, `echo | but skill install`, CI runners that allocate a TTY for stdout only, or harnesses closing stdin while leaving stdout attached.","commonSituations":"Cron jobs, agent-driven sessions with redirected stdin, `docker exec` without -t, piping input into commands by habit.","solutions":["Pass --path or --detect to skip the prompts entirely","Run from a fully interactive terminal (both stdin and stdout attached)","Fix the harness to keep stdin a TTY (e.g. docker run -it)"],"exampleFix":"$ but skill install < /dev/null              # fails: cannot prompt\n$ but skill install --detect                 # no prompt needed","handlingStrategy":"validation","validationCode":"use std::io::IsTerminal;\n// before invoking interactively-dependent commands:\nif !std::io::stdin().is_terminal() {\n    cmd.args([\"--path\", dir]); // or --detect\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check stdin is a TTY, not just stdout","Never pipe stdin into commands that may prompt","Use docker run -it / -t allocation in containerized automation"],"tags":["cli","stdin","interactive","skill","install"],"backgroundTag":"interactive-prompt-unavailable","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}