screenpipe/screenpipe · error

proposal confirmation requires an interactive terminal; revi

Error message

proposal confirmation requires an interactive terminal; review the preview and rerun with --yes

What it means

confirm_proposal is the safety gate before submitting a team skill bundle for review. When the operator did not pass --yes, it requires an interactive terminal to show a y/N prompt; if stdin is not a TTY (piped input, CI, scripts) it refuses to guess and bails, telling the user to review the preview and rerun with --yes.

Source

Thrown at crates/screenpipe-engine/src/cli/team_skills.rs:409

        bundle.files.len(),
        bundle.total_bytes,
        bundle.discovery_chars,
        bundle.activation_chars,
        bundle.has_scripts
    );
    println!("digest: {}", bundle.digest);
    for (path, content) in &bundle.files {
        println!("  {:<48} {:>8} B", path, content.len());
    }
    println!("\nThis creates a private proposal only. Admin review is required.");
}

fn confirm_proposal(yes: bool) -> anyhow::Result<bool> {
    if yes {
        return Ok(true);
    }
    if !io::stdin().is_terminal() {
        anyhow::bail!(
            "proposal confirmation requires an interactive terminal; review the preview and rerun with --yes"
        );
    }
    print!("Submit this exact bundle for review? [y/N] ");
    io::stdout().flush()?;
    let mut answer = String::new();
    io::stdin().read_line(&mut answer)?;
    Ok(matches!(
        answer.trim().to_ascii_lowercase().as_str(),
        "y" | "yes"
    ))
}

async fn send_json(builder: reqwest::RequestBuilder, token: &str) -> anyhow::Result<Value> {
    let response = builder.bearer_auth(token).send().await?;
    let status = response.status();
    let body = response.json::<Value>().await.unwrap_or(Value::Null);
    if !status.is_success() {

View on GitHub (pinned to 4ebf712990)

Solutions

  1. Run the command once to see the preview, verify the bundle, then rerun with `--yes` to skip the prompt
  2. If running in CI/scripting, add `--yes` to the propose command after confirming the preview manually once
  3. Run the command inside a real interactive TTY if confirmation is desired

Example fix

// before
echo y | screenpipe team-skills propose ./my-skill
// after
screenpipe team-skills propose ./my-skill --preview   # review output
screenpipe team-skills propose ./my-skill --yes       # explicit submit
Defensive patterns

Strategy: validation

Validate before calling

use std::io::IsTerminal;
if !std::io::stdin().is_terminal() && !yes {
    anyhow::bail!("add --yes for non-interactive use");
}

Try / catch

match propose_skill(args) {
    Err(e) if e.to_string().contains("interactive terminal") => {
        eprintln!("non-interactive: rerun with --yes after reviewing preview");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `screenpipe team-skills propose` without `--yes` in any context where stdin is not a terminal: CI pipelines, `echo y | screenpipe ...`, ssh without a TTY, or piping output through another command.

Common situations: Automation scripts that call the CLI non-interactively; running the command from an IDE terminal wrapper without a TTY; forgetting --yes in a documented CI job; cron/systemd invocations.

Related errors


AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01). Data as JSON: /api/errors/4061494d94915371. Report an issue: GitHub.