{"record":{"id":"a4392d247b3b5a69","repo":"gitbutlerapp/gitbutler","slug":"interactive-setup-requires-a-terminal-use-but-ag","errorCode":null,"errorMessage":"Interactive setup requires a terminal. Use `but agent setup --print` to print the default instructions without modifying files.","messagePattern":"Interactive setup requires a terminal\\. Use `but agent setup --print` to print the default instructions without modifying files\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but/src/command/agent/mod.rs","lineNumber":66,"sourceCode":") -> Result<()> {\n    match cmd {\n        // Bare `but agent` runs the setup wizard, same as `but agent setup`.\n        None => setup(current_dir, out, false),\n        Some(agent::Subcommands::Setup { print }) => setup(current_dir, out, print),\n    }\n}\n\nfn setup(current_dir: &Path, out: &mut OutputChannel, print_only: bool) -> Result<()> {\n    if print_only {\n        let default_policy = render_managed_policy_block(&WizardAnswers::default());\n        print_policy(out, &default_policy)?;\n        return Ok(());\n    }\n\n    let repo = discover_repo(current_dir);\n\n    if !out.can_prompt() {\n        anyhow::bail!(\n            \"Interactive setup requires a terminal. Use `but agent setup --print` to print the default instructions without modifying files.\"\n        );\n    }\n\n    let mut input = out\n        .prepare_for_terminal_input()\n        .context(\"Interactive setup requires a terminal.\")?;\n\n    let plan = collect_plan(&mut input, repo)?;\n    drop(input);\n\n    match plan {\n        Some(plan) => apply_plan(out, current_dir, &plan),\n        None => print_cancelled(out),\n    }\n}\n\n/// Run the interactive wizard. Returns the confirmed plan, or `None` if the user","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/agent/mod.rs#L48-L84","documentation":"`but agent setup` runs an interactive wizard that needs a real terminal for prompts (via `out.prepare_for_terminal_input()`). When `out.can_prompt()` is false the command bails with this message and points at the non-interactive alternative `but agent setup --print`, which prints the default instructions without touching any files.","triggerScenarios":"Running `but agent setup` (without --print) when stdout/stdin is not a TTY: piped output (`but agent setup | cat`), CI jobs, cron, ssh with no tty, non-interactive scripts, or a harness that captures output","commonSituations":"Setting up agent instructions in a Dockerfile or CI pipeline; Ansible/Puppet provisioning that runs `but` non-interactively; piping but output to tee or a log file; running through an IDE task runner that allocates no pty","solutions":["Use `but agent setup --print` to get the default policy text, and write it to the target file yourself: `but agent setup --print > AGENTS.md`","Or run `but agent setup` in an interactive terminal (ssh -t, docker run -it, un-piped)","For automation, skip the wizard and commit the printed block directly","If you need TTY prompts over ssh, force tty allocation with `ssh -t`"],"exampleFix":"# before (in CI, fails):\nbut agent setup\n\n# after (non-interactive):\nbut agent setup --print > AGENTS.md\ngit add AGENTS.md","handlingStrategy":"validation","validationCode":"if [ -t 0 ] && [ -t 1 ]; then but agent setup; else but agent setup --print > AGENTS.md; fi","typeGuard":null,"tryCatchPattern":"# shell: fall back to the non-interactive form when the tty check fails\nif ! but agent setup 2>&1 | tee /dev/stderr | grep -q 'requires a terminal'; then :; else but agent setup --print > AGENTS.md; fi","preventionTips":["Probe interactivity ([ -t 0 ]) before invoking interactive wizards","Bake `but agent setup --print` into Dockerfiles/CI instead of the wizard","When orchestrating over ssh, use `ssh -t` if prompts are actually wanted"],"tags":["cli","tty","interactive","agent-setup","non-interactive"],"backgroundTag":"requires-tty-non-interactive","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}