Skip to content

Commit 5122ca6

Browse files
committed
fix: no-instrument flag didn't work and crashed
1 parent b3c46e7 commit 5122ca6

2 files changed

Lines changed: 113 additions & 42 deletions

File tree

src/auth.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,11 @@ fn maybe_warn_api_key_override(base: &BaseArgs) {
405405

406406
if let Some(profile_name) = ignored_profile {
407407
eprintln!(
408-
"Warning: using --api-key/BRAINTRUST_API_KEY credentials; selected profile '{profile_name}' is ignored for this command. Use --prefer-profile or unset BRAINTRUST_API_KEY.",
408+
"Info: using --api-key/BRAINTRUST_API_KEY credentials; selected profile '{profile_name}' is ignored for this command. Use --prefer-profile or unset BRAINTRUST_API_KEY to use a profile with OAuth login.",
409409
);
410410
} else {
411411
eprintln!(
412-
"Warning: using --api-key/BRAINTRUST_API_KEY credentials for this command. Use --prefer-profile or unset BRAINTRUST_API_KEY."
412+
"Info: using --api-key/BRAINTRUST_API_KEY credentials for this command. Use --prefer-profile or unset BRAINTRUST_API_KEY to use a registered profile."
413413
);
414414
}
415415
}

src/setup/mod.rs

Lines changed: 111 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,22 @@ pub struct SetupArgs {
7373
#[arg(long)]
7474
instrument: bool,
7575

76-
/// Do not run instrumentation agent
77-
#[arg(long, conflicts_with = "instrument")]
76+
/// Do not run instrumentation agent (skills and MCP are still configured)
77+
#[arg(
78+
long,
79+
conflicts_with = "instrument",
80+
conflicts_with = "tui",
81+
conflicts_with = "background",
82+
conflicts_with = "yolo"
83+
)]
7884
no_instrument: bool,
7985

8086
/// Run the agent in interactive TUI mode [default]
81-
#[arg(long, conflicts_with = "background")]
87+
#[arg(long, conflicts_with = "background", conflicts_with = "no_instrument")]
8288
tui: bool,
8389

8490
/// Run the agent in background (non-interactive) mode
85-
#[arg(long, conflicts_with = "tui")]
91+
#[arg(long, conflicts_with = "tui", conflicts_with = "no_instrument")]
8692
background: bool,
8793

8894
/// Language(s) to instrument (repeatable; case-insensitive).
@@ -150,7 +156,7 @@ struct AgentsSetupArgs {
150156
workers: usize,
151157

152158
/// Grant the agent full permissions (bypass permission prompts)
153-
#[arg(long)]
159+
#[arg(long, conflicts_with = "no_instrument")]
154160
yolo: bool,
155161
}
156162

@@ -215,6 +221,10 @@ struct InstrumentSetupArgs {
215221
/// Grant the agent full permissions (bypass permission prompts)
216222
#[arg(long)]
217223
yolo: bool,
224+
225+
/// Set up skills and write the task file but do not launch the agent.
226+
#[arg(skip)]
227+
skip_launch: bool,
218228
}
219229

220230
#[derive(Debug, Clone, Args)]
@@ -651,9 +661,6 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
651661
any_installed = true;
652662
}
653663
}
654-
if outcome.installed_count == 0 && !agents.is_empty() {
655-
had_failures = true;
656-
}
657664
if !verbose {
658665
let label = if any_installed {
659666
"configured"
@@ -681,8 +688,10 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
681688
print_wizard_step(4, "Instrument");
682689
}
683690
if git_root.is_some() {
684-
// --no-instrument opts out; --instrument opts in; otherwise prompt or default on.
685-
let do_instrument = if flag_no_instrument {
691+
// Whether to launch the agent at the end of this step.
692+
// --no-instrument / interactive "no": set up skills/docs but skip the launch.
693+
// --instrument / non-interactive: always launch.
694+
let launch_agent = if flag_no_instrument {
686695
false
687696
} else if flag_instrument || !interactive {
688697
true
@@ -692,7 +701,10 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
692701
.default(true)
693702
.interact()?
694703
};
695-
if do_instrument {
704+
705+
// Skills, docs, and the task file are always set up when a git root exists.
706+
// Only the agent launch is conditional.
707+
{
696708
// Determine agent: explicit flag > single detected > ask user
697709
let instrument_agent =
698710
determine_wizard_instrument_agent(flag_agent, git_root.as_deref(), &home);
@@ -749,32 +761,35 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
749761
vec![WorkflowArg::Instrument, WorkflowArg::Observe]
750762
};
751763

752-
// Run mode: --tui / --background flag > interactive prompt > default TUI.
753-
let run_tui = if flag_tui {
754-
true
755-
} else if flag_background {
756-
false
757-
} else if interactive {
758-
let idx = Select::with_theme(&ColorfulTheme::default())
759-
.with_prompt("How do you want to run the agent?")
760-
.items(&["Interactive (TUI)", "Background"])
761-
.default(0)
762-
.interact()?;
763-
idx == 0
764-
} else {
765-
true
766-
};
767-
768-
// Yolo: explicit flag > interactive prompt > default false.
769-
let effective_yolo = if flag_yolo {
770-
true
771-
} else if interactive {
772-
Confirm::new()
773-
.with_prompt("Grant agent full permissions? (bypass permission prompts)")
774-
.default(false)
775-
.interact()?
764+
// Run mode and yolo are only meaningful when actually launching.
765+
let (run_tui, effective_yolo) = if launch_agent {
766+
let tui = if flag_tui {
767+
true
768+
} else if flag_background {
769+
false
770+
} else if interactive {
771+
let idx = Select::with_theme(&ColorfulTheme::default())
772+
.with_prompt("How do you want to run the agent?")
773+
.items(&["Interactive (TUI)", "Background"])
774+
.default(0)
775+
.interact()?;
776+
idx == 0
777+
} else {
778+
true
779+
};
780+
let yolo = if flag_yolo {
781+
true
782+
} else if interactive {
783+
Confirm::new()
784+
.with_prompt("Grant agent full permissions? (bypass permission prompts)")
785+
.default(false)
786+
.interact()?
787+
} else {
788+
false
789+
};
790+
(tui, yolo)
776791
} else {
777-
false
792+
(false, false)
778793
};
779794

780795
run_instrument_setup(
@@ -791,12 +806,11 @@ async fn run_setup_wizard(mut base: BaseArgs, flags: WizardFlags) -> Result<()>
791806
tui: run_tui,
792807
background: !run_tui,
793808
yolo: effective_yolo,
809+
skip_launch: !launch_agent,
794810
},
795811
false,
796812
)
797813
.await?;
798-
} else if verbose {
799-
eprintln!(" {}", style("Skipped").dim());
800814
}
801815
} else if verbose {
802816
eprintln!(" {}", style("Skipped").dim());
@@ -1274,8 +1288,11 @@ async fn run_instrument_setup(
12741288
// Determine run mode: interactive TUI vs background (autonomous).
12751289
// --tui: interactive TUI (inherits terminal)
12761290
// --background / --yes / non-interactive terminal: background (autonomous)
1291+
// skip_launch: not launching at all — default to non-interactive for task rendering
12771292
// Otherwise: ask the user.
1278-
let run_interactive = if args.tui {
1293+
let run_interactive = if args.skip_launch {
1294+
false
1295+
} else if args.tui {
12791296
true
12801297
} else if args.background || args.yes || !ui::is_interactive() {
12811298
false
@@ -1325,6 +1342,37 @@ async fn run_instrument_setup(
13251342
task_path.display()
13261343
));
13271344

1345+
// --no-instrument (skip_launch): skills configured, task file written — done.
1346+
if args.skip_launch {
1347+
if base.json {
1348+
let report = SetupJsonReport {
1349+
scope: InstallScope::Local.as_str().to_string(),
1350+
selected_agents: vec![selected],
1351+
detected_agents: detected,
1352+
results: results.clone(),
1353+
warnings,
1354+
notes,
1355+
};
1356+
println!(
1357+
"{}",
1358+
serde_json::to_string_pretty(&report)
1359+
.context("failed to serialize setup report")?
1360+
);
1361+
} else {
1362+
eprintln!();
1363+
for result in &results {
1364+
print_wizard_agent_result(result);
1365+
}
1366+
eprintln!(
1367+
" {} Task file: {}",
1368+
style("✓").green(),
1369+
task_path.display()
1370+
);
1371+
print_wizard_done(false);
1372+
}
1373+
return Ok(());
1374+
}
1375+
13281376
let invocation = resolve_instrument_invocation(
13291377
selected,
13301378
args.agent_cmd.as_deref(),
@@ -3027,6 +3075,8 @@ fn install_mcp_for_agent(
30273075
/// Install the Braintrust MCP server into Claude Code's user-wide config (~/.claude.json).
30283076
/// Falls back to ~/.mcp.json if the `claude` CLI is not available.
30293077
fn install_mcp_for_claude_user(home: &Path, api_key: Option<&str>) -> Result<AgentInstallResult> {
3078+
let claude_json_path = home.join(".claude.json");
3079+
30303080
let Some(key) = api_key else {
30313081
// No API key available — fall back to ~/.mcp.json with env-var placeholder and
30323082
// tell the user they need BRAINTRUST_API_KEY set for Claude Code to authenticate.
@@ -3041,6 +3091,25 @@ fn install_mcp_for_claude_user(home: &Path, api_key: Option<&str>) -> Result<Age
30413091
});
30423092
};
30433093

3094+
// If braintrust is already registered in ~/.claude.json (written by a prior `claude mcp add
3095+
// -s user`), skip the subprocess call — `claude mcp add` exits non-zero when the name
3096+
// already exists.
3097+
if let Ok(root) = load_json_object_or_default(&claude_json_path) {
3098+
if root
3099+
.get("mcpServers")
3100+
.and_then(|v| v.as_object())
3101+
.map(|m| m.contains_key("braintrust"))
3102+
.unwrap_or(false)
3103+
{
3104+
return Ok(AgentInstallResult {
3105+
agent: Agent::Claude,
3106+
status: InstallStatus::Skipped,
3107+
message: "already configured".to_string(),
3108+
paths: vec![claude_json_path.display().to_string()],
3109+
});
3110+
}
3111+
}
3112+
30443113
let header = format!("Authorization: Bearer {key}");
30453114
let output = std::process::Command::new("claude")
30463115
.args([
@@ -3062,7 +3131,7 @@ fn install_mcp_for_claude_user(home: &Path, api_key: Option<&str>) -> Result<Age
30623131
agent: Agent::Claude,
30633132
status: InstallStatus::Installed,
30643133
message: "installed MCP config".to_string(),
3065-
paths: vec![home.join(".claude.json").display().to_string()],
3134+
paths: vec![claude_json_path.display().to_string()],
30663135
}),
30673136
Ok(out) => {
30683137
let stderr = String::from_utf8_lossy(&out.stderr);
@@ -3618,6 +3687,7 @@ mod tests {
36183687
tui: false,
36193688
background: false,
36203689
yolo: false,
3690+
skip_launch: false,
36213691
};
36223692

36233693
let selected = resolve_instrument_workflow_selection(&args, &mut false)
@@ -3641,6 +3711,7 @@ mod tests {
36413711
tui: false,
36423712
background: false,
36433713
yolo: false,
3714+
skip_launch: false,
36443715
};
36453716

36463717
let selected = resolve_instrument_workflow_selection(&args, &mut false)

0 commit comments

Comments
 (0)