@@ -610,11 +610,12 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
610610 }
611611 let choices = [ "Skills" , "MCP" ] ;
612612 let defaults = [ true , false ] ;
613+ let term = ui:: tty_term ( ) . ok_or_else ( || anyhow ! ( "interactive mode requires TTY" ) ) ?;
613614 let selected = MultiSelect :: with_theme ( & ColorfulTheme :: default ( ) )
614615 . with_prompt ( "What would you like to set up?" )
615616 . items ( & choices)
616617 . defaults ( & defaults)
617- . interact ( ) ?;
618+ . interact_on ( & term ) ?;
618619 ( selected. contains ( & 0 ) , selected. contains ( & 1 ) )
619620 } ;
620621
@@ -668,7 +669,7 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
668669 local : matches ! ( * scope, InstallScope :: Local ) ,
669670 global : matches ! ( * scope, InstallScope :: Global ) ,
670671 workflows : Vec :: new ( ) ,
671- no_workflow : false ,
672+ no_workflow : flag_no_workflow ,
672673 yes : true ,
673674 no_fetch_docs : true ,
674675 refresh_docs : false ,
@@ -735,10 +736,11 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
735736 }
736737 true
737738 } else {
739+ let term = ui:: tty_term ( ) . ok_or_else ( || anyhow ! ( "interactive mode requires TTY" ) ) ?;
738740 Confirm :: with_theme ( & ColorfulTheme :: default ( ) )
739741 . with_prompt ( "Run instrumentation agent to set up tracing in this repo?" )
740742 . default ( true )
741- . interact ( ) ?
743+ . interact_on ( & term ) ?
742744 } ;
743745 if instrument {
744746 let instrument_agent = setup_context
@@ -972,10 +974,11 @@ async fn select_project_for_setup(
972974
973975 if selection == labels. len ( ) - 1 {
974976 let default_name = default_setup_project_name ( ) ;
977+ let term = ui:: tty_term ( ) . ok_or_else ( || anyhow ! ( "interactive mode requires TTY" ) ) ?;
975978 let name: String = dialoguer:: Input :: with_theme ( & ColorfulTheme :: default ( ) )
976979 . with_prompt ( "Project name" )
977980 . default ( default_name)
978- . interact_text ( ) ?;
981+ . interact_text_on ( & term ) ?;
979982 let trimmed = name. trim ( ) ;
980983 if trimmed. is_empty ( ) {
981984 bail ! ( "project name cannot be empty" ) ;
@@ -1052,7 +1055,9 @@ fn maybe_init(org: &str, project: &crate::projects::api::Project) -> Result<bool
10521055 let update = Confirm :: new ( )
10531056 . with_prompt ( format ! ( "Update .bt/config.json to {org}/{}?" , project. name) )
10541057 . default ( true )
1055- . interact ( ) ?;
1058+ . interact_on (
1059+ & ui:: tty_term ( ) . ok_or_else ( || anyhow ! ( "interactive mode requires TTY" ) ) ?,
1060+ ) ?;
10561061 if !update {
10571062 return Ok ( false ) ;
10581063 }
@@ -2174,7 +2179,7 @@ fn resolve_setup_selection(args: &AgentsSetupArgs, home: &Path) -> Result<SetupS
21742179 if scope. is_none ( ) {
21752180 steps. push ( SetupWizardStep :: Scope ) ;
21762181 }
2177- if !args. no_fetch_docs && args. workflows . is_empty ( ) {
2182+ if !args. no_fetch_docs && !args . no_workflow && args. workflows . is_empty ( ) {
21782183 steps. push ( SetupWizardStep :: Workflows ) ;
21792184 }
21802185
@@ -2500,11 +2505,12 @@ fn resolve_local_root_for_scope(scope: InstallScope) -> Result<Option<PathBuf>>
25002505
25012506fn prompt_scope_selection ( prompt : & str ) -> Result < Option < InstallScope > > {
25022507 let choices = [ "local (current git repo)" , "global (user-wide)" ] ;
2508+ let term = ui:: tty_term ( ) . ok_or_else ( || anyhow ! ( "interactive mode requires TTY" ) ) ?;
25032509 let idx = Select :: with_theme ( & ColorfulTheme :: default ( ) )
25042510 . with_prompt ( prompt)
25052511 . items ( & choices)
25062512 . default ( 1 )
2507- . interact_opt ( ) ?;
2513+ . interact_on_opt ( & term ) ?;
25082514 Ok ( idx. map ( |i| {
25092515 if i == 0 {
25102516 InstallScope :: Local
@@ -2538,13 +2544,14 @@ fn prompt_workflows_selection(defaults: &[WorkflowArg]) -> Result<Option<Vec<Wor
25382544 . map ( |workflow| default_set. contains ( workflow) )
25392545 . collect :: < Vec < _ > > ( ) ;
25402546
2547+ let term = ui:: tty_term ( ) . ok_or_else ( || anyhow ! ( "interactive mode requires TTY" ) ) ?;
25412548 let selected = MultiSelect :: with_theme ( & ColorfulTheme :: default ( ) )
25422549 . with_prompt (
25432550 "Select the workflows you are interested in (will prefetch docs for them) (Esc: back)" ,
25442551 )
25452552 . items ( & labels)
25462553 . defaults ( & default_flags)
2547- . interact_opt ( ) ?;
2554+ . interact_on_opt ( & term ) ?;
25482555
25492556 Ok ( selected. map ( |indexes| {
25502557 indexes
@@ -2596,6 +2603,9 @@ fn resolve_default_agent_selection(
25962603
25972604 let path_agents = detected_agents_on_path ( detected) ;
25982605 if allow_prompt {
2606+ if path_agents. len ( ) == 1 {
2607+ return Ok ( path_agents[ 0 ] ) ;
2608+ }
25992609 let default = pick_agent_mode_target ( & path_agents) . unwrap_or ( Agent :: Codex ) ;
26002610 return prompt_agent_selection ( prompt, default) ?
26012611 . ok_or_else ( || anyhow ! ( "setup cancelled by user" ) ) ;
@@ -3514,6 +3524,25 @@ mod tests {
35143524 assert ! ( selection. selected_workflows. is_empty( ) ) ;
35153525 }
35163526
3527+ #[ test]
3528+ fn resolve_setup_selection_honors_no_workflow ( ) {
3529+ let args = AgentsSetupArgs {
3530+ agent : Some ( AgentArg :: Codex ) ,
3531+ local : false ,
3532+ global : true ,
3533+ workflows : vec ! [ WorkflowArg :: Evaluate ] ,
3534+ no_workflow : true ,
3535+ yes : true ,
3536+ no_fetch_docs : false ,
3537+ refresh_docs : false ,
3538+ workers : crate :: sync:: default_workers ( ) ,
3539+ yolo : false ,
3540+ } ;
3541+ let home = std:: env:: temp_dir ( ) ;
3542+ let selection = resolve_setup_selection ( & args, & home) . expect ( "resolve setup selection" ) ;
3543+ assert ! ( selection. selected_workflows. is_empty( ) ) ;
3544+ }
3545+
35173546 #[ test]
35183547 fn resolve_workflow_selection_resolves_explicit_values ( ) {
35193548 let selected =
@@ -4083,4 +4112,17 @@ mod tests {
40834112 let resolved = resolve_unambiguous_instrument_agent ( & [ ] , & detected) ;
40844113 assert_eq ! ( resolved, Some ( Agent :: Codex ) ) ;
40854114 }
4115+
4116+ #[ test]
4117+ fn resolve_default_agent_selection_auto_selects_single_path_agent_even_when_prompt_allowed ( ) {
4118+ let detected = vec ! [ DetectionSignal {
4119+ agent: Agent :: Codex ,
4120+ on_path: true ,
4121+ reason: "binary" . to_string( ) ,
4122+ } ] ;
4123+
4124+ let resolved = resolve_default_agent_selection ( None , & detected, "ignored" , true )
4125+ . expect ( "resolve default agent selection" ) ;
4126+ assert_eq ! ( resolved, Agent :: Codex ) ;
4127+ }
40864128}
0 commit comments