1use clap::Parser;
2use remote_server::Commands;
3use std::io::Write as _;
4use std::path::PathBuf;
5
6#[derive(Parser)]
7#[command(disable_version_flag = true)]
8struct Cli {
9 #[command(subcommand)]
10 command: Option<Commands>,
11 /// Used for SSH/Git password authentication, to remove the need for netcat as a dependency,
12 /// by having Zed act like netcat communicating over a Unix socket.
13 #[arg(long, hide = true)]
14 askpass: Option<String>,
15 /// Used for recording minidumps on crashes by having the server run a separate
16 /// process communicating over a socket.
17 #[arg(long, hide = true)]
18 crash_handler: Option<PathBuf>,
19 /// Used for loading the environment from the project.
20 #[arg(long, hide = true)]
21 printenv: bool,
22}
23
24fn main() -> anyhow::Result<()> {
25 let cli = Cli::parse();
26
27 if let Some(socket_path) = &cli.askpass {
28 askpass::main(socket_path);
29 return Ok(());
30 }
31
32 if let Some(socket) = &cli.crash_handler {
33 crashes::crash_server(socket.as_path());
34 return Ok(());
35 }
36
37 if cli.printenv {
38 util::shell_env::print_env();
39 return Ok(());
40 }
41
42 #[cfg(not(windows))]
43 if let Some(command) = cli.command {
44 use remote_server::unix::ExecuteProxyError;
45
46 let res = remote_server::run(command);
47 if let Err(e) = &res
48 && let Some(e) = e.downcast_ref::<ExecuteProxyError>()
49 {
50 std::io::stderr().write_fmt(format_args!("{e:#}\n")).ok();
51 // It is important for us to report the proxy spawn exit code here
52 // instead of the generic 1 that result returns
53 // The client reads the exit code to determine if the server process has died when trying to reconnect
54 // signaling that it needs to try spawning a new server
55 std::process::exit(e.to_exit_code());
56 }
57 res
58 } else {
59 std::io::stderr()
60 .write_all(b"usage: remote <run|proxy|version>\n")
61 .ok();
62 std::process::exit(1);
63 }
64
65 #[cfg(windows)]
66 if let Some(_) = cli.command {
67 std::io::stderr()
68 .write_all(b"run is not supported on Windows\n")
69 .ok();
70 std::process::exit(2);
71 } else {
72 std::io::stderr()
73 .write_all(b"usage: remote <run|proxy|version>\n")
74 .ok();
75 std::process::exit(1);
76 }
77}