{"record":{"id":"4061494d94915371","repo":"screenpipe/screenpipe","slug":"proposal-confirmation-requires-an-interactive-term","errorCode":null,"errorMessage":"proposal confirmation requires an interactive terminal; review the preview and rerun with --yes","messagePattern":"proposal confirmation requires an interactive terminal; review the preview and rerun with --yes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/screenpipe-engine/src/cli/team_skills.rs","lineNumber":409,"sourceCode":"        bundle.files.len(),\n        bundle.total_bytes,\n        bundle.discovery_chars,\n        bundle.activation_chars,\n        bundle.has_scripts\n    );\n    println!(\"digest: {}\", bundle.digest);\n    for (path, content) in &bundle.files {\n        println!(\"  {:<48} {:>8} B\", path, content.len());\n    }\n    println!(\"\\nThis creates a private proposal only. Admin review is required.\");\n}\n\nfn confirm_proposal(yes: bool) -> anyhow::Result<bool> {\n    if yes {\n        return Ok(true);\n    }\n    if !io::stdin().is_terminal() {\n        anyhow::bail!(\n            \"proposal confirmation requires an interactive terminal; review the preview and rerun with --yes\"\n        );\n    }\n    print!(\"Submit this exact bundle for review? [y/N] \");\n    io::stdout().flush()?;\n    let mut answer = String::new();\n    io::stdin().read_line(&mut answer)?;\n    Ok(matches!(\n        answer.trim().to_ascii_lowercase().as_str(),\n        \"y\" | \"yes\"\n    ))\n}\n\nasync fn send_json(builder: reqwest::RequestBuilder, token: &str) -> anyhow::Result<Value> {\n    let response = builder.bearer_auth(token).send().await?;\n    let status = response.status();\n    let body = response.json::<Value>().await.unwrap_or(Value::Null);\n    if !status.is_success() {","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/screenpipe/screenpipe/blob/4ebf712990fee17eeaf904dacf749b6e96ac9bf3/crates/screenpipe-engine/src/cli/team_skills.rs#L391-L427","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run the command once to see the preview, verify the bundle, then rerun with `--yes` to skip the prompt","If running in CI/scripting, add `--yes` to the propose command after confirming the preview manually once","Run the command inside a real interactive TTY if confirmation is desired"],"exampleFix":"// before\necho y | screenpipe team-skills propose ./my-skill\n// after\nscreenpipe team-skills propose ./my-skill --preview   # review output\nscreenpipe team-skills propose ./my-skill --yes       # explicit submit","handlingStrategy":"validation","validationCode":"use std::io::IsTerminal;\nif !std::io::stdin().is_terminal() && !yes {\n    anyhow::bail!(\"add --yes for non-interactive use\");\n}","typeGuard":null,"tryCatchPattern":"match propose_skill(args) {\n    Err(e) if e.to_string().contains(\"interactive terminal\") => {\n        eprintln!(\"non-interactive: rerun with --yes after reviewing preview\");\n    }\n    other => other?,\n}","preventionTips":["Add --yes in scripts/CI after manually reviewing the preview once","Run interactive confirmations in a real TTY","Document the --yes requirement in team automation docs"],"tags":["cli","interactive-terminal","confirmation"],"backgroundTag":"non-interactive-terminal","analyzedSha":"4ebf712990fee17eeaf904dacf749b6e96ac9bf3","analyzedAt":"2026-09-01T23:33:43.065Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}