claude_code/client/setup_token/
start.rs1use std::sync::Arc;
2
3use tokio::{
4 process::Command,
5 sync::{oneshot, Mutex},
6};
7
8use super::super::ClaudeClient;
9use super::{
10 capture::spawn_capture_task, process::SetupTokenProcess, session::ClaudeSetupTokenSession,
11 url::UrlCapture,
12};
13use crate::{
14 commands::setup_token::ClaudeSetupTokenRequest,
15 process::{self as cli_process, ConsoleTarget},
16 ClaudeCodeError,
17};
18
19#[cfg(unix)]
20use super::pty::spawn_setup_token_pty;
21
22impl ClaudeClient {
23 pub async fn setup_token_start(&self) -> Result<ClaudeSetupTokenSession, ClaudeCodeError> {
24 self.setup_token_start_with(ClaudeSetupTokenRequest::new())
25 .await
26 }
27
28 pub async fn setup_token_start_with(
29 &self,
30 request: ClaudeSetupTokenRequest,
31 ) -> Result<ClaudeSetupTokenSession, ClaudeCodeError> {
32 self.ensure_home_prepared()?;
33 let requested_timeout = request.timeout;
34 let binary = self.resolve_binary();
35 let argv = request.into_command().argv();
36
37 let stdout_buf = Arc::new(Mutex::new(Vec::<u8>::new()));
38 let stderr_buf = Arc::new(Mutex::new(Vec::<u8>::new()));
39
40 let (url_tx, url_rx) = oneshot::channel::<String>();
41 let url_tx = Arc::new(Mutex::new(Some(url_tx)));
42 let url_state = Arc::new(Mutex::new(UrlCapture::default()));
43
44 #[cfg(unix)]
45 if let Ok((process, stdout_task)) = spawn_setup_token_pty(
46 &binary,
47 &argv,
48 self.working_dir.as_deref(),
49 &self.env,
50 self.mirror_stdout,
51 self.mirror_stderr,
52 stdout_buf.clone(),
53 url_state.clone(),
54 url_tx.clone(),
55 ) {
56 return Ok(ClaudeSetupTokenSession::new(
57 process,
58 stdout_buf,
59 stderr_buf,
60 stdout_task,
61 None,
62 url_rx,
63 requested_timeout,
64 ));
65 }
66
67 let mut cmd = Command::new(&binary);
68 cmd.args(&argv);
69
70 if let Some(dir) = self.working_dir.as_ref() {
71 cmd.current_dir(dir);
72 }
73
74 cli_process::apply_env(&mut cmd, &self.env);
75
76 cmd.stdin(std::process::Stdio::piped());
77 cmd.stdout(std::process::Stdio::piped());
78 cmd.stderr(std::process::Stdio::piped());
79 cmd.kill_on_drop(true);
80
81 let mut child = cli_process::spawn_with_retry(&mut cmd, &binary)?;
82 let stdin = child.stdin.take();
83 let stdout = child.stdout.take().ok_or(ClaudeCodeError::MissingStdout)?;
84 let stderr = child.stderr.take().ok_or(ClaudeCodeError::MissingStderr)?;
85
86 let stdout_task = spawn_capture_task(
87 stdout,
88 ConsoleTarget::Stdout,
89 self.mirror_stdout,
90 stdout_buf.clone(),
91 url_state.clone(),
92 url_tx.clone(),
93 );
94 let stderr_task = spawn_capture_task(
95 stderr,
96 ConsoleTarget::Stderr,
97 self.mirror_stderr,
98 stderr_buf.clone(),
99 url_state.clone(),
100 url_tx.clone(),
101 );
102
103 Ok(ClaudeSetupTokenSession::new(
104 SetupTokenProcess::Pipes { child, stdin },
105 stdout_buf,
106 stderr_buf,
107 stdout_task,
108 Some(stderr_task),
109 url_rx,
110 requested_timeout,
113 ))
114 }
115}