gitbutlerapp/gitbutler · error

No supported agent was detected. In non-interactive mode, sp

Error message

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.

What it means

When `but skill install` cannot infer an installation path (no --path, no --detect, and no driving agent detected to supply a default), it falls back to interactive prompting in prompt_for_install_path. Prompting is impossible when the output channel is not human-readable (out.for_human() is None: piped stdout or --output-format json), so the command aborts and lists the non-interactive options.

Source

Thrown at crates/but/src/command/skill/mod.rs:875

        .prompt_select("Where would you like to install the skill?", &options)?
        .copied()
    {
        Some(InstallScopeOption::Local) => Ok(InstallScope::Local),
        Some(InstallScopeOption::Global) => Ok(InstallScope::Global),
        None => Err(UserCancelled.into()),
    }
}

/// Prompt user to select installation scope and format
fn prompt_for_install_path(
    ctx: Option<&mut Context>,
    global: bool,
    out: &mut OutputChannel,
    progress: &mut impl std::io::Write,
) -> Result<PathBuf> {
    let t = theme::get();
    if out.for_human().is_none() {
        anyhow::bail!(
            "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."
        );
    }
    if !out.can_prompt() {
        anyhow::bail!(
            "Human input required - run this in a terminal, or specify --path/--detect to avoid interactive prompts."
        );
    }

    let local_scope_available = if !global {
        match ctx.as_ref() {
            Some(ctx) => {
                let repo = ctx.repo.get()?;
                repo.workdir().is_some()
            }
            None => false,
        }
    } else {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Pass `--path <dir>` to choose the installation directory explicitly
  2. Pass `--detect` to update an existing installation non-interactively
  3. Run the command in a real terminal so interactive prompting works

Example fix

$ but skill install | tee install.log        # fails: no human output
$ but skill install --path ~/.claude/skills  # non-interactive OK
Defensive patterns

Strategy: validation

Validate before calling

use std::io::IsTerminal;
// before invoking in scripts:
if !std::io::stdout().is_terminal() {
    cmd.args(["--path", explicit_dir]); // never rely on prompts when piped
}

Prevention

When it happens

Trigger: `but skill install` with stdout piped (e.g. `| tee log`), run with --output-format json, or executed in CI where for_human() returns None and detect_agent found no supported agent to derive a default path.

Common situations: CI/CD pipelines installing skills, agent harnesses driving the CLI without a TTY, Docker build steps, piping output to a file or pager.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/7941cbeb1d20e2fd. Report an issue: GitHub.