1use anyhow::Result;
2use clap::{Parser, Subcommand};
3
4use crate::duration::parse_idle;
5use crate::paths::Context;
6use crate::{attach, doctor, list, notify, resume, rm, server, service, setup};
7
8#[derive(Debug, Parser)]
10#[command(name = "agent-berth", version, about, propagate_version = true)]
11struct Cli {
12 #[command(subcommand)]
13 command: Command,
14}
15
16#[derive(Debug, Subcommand)]
17enum Command {
18 Server,
20 Setup {
22 #[arg(long)]
24 no_service: bool,
25 },
26 Teardown,
28 Service {
30 #[command(subcommand)]
31 action: ServiceAction,
32 },
33 List {
35 #[arg(long)]
37 json: bool,
38 #[arg(long)]
40 resumable: bool,
41 #[arg(
43 long,
44 value_name = "DURATION",
45 requires = "resumable",
46 num_args = 0..=1,
47 default_missing_value = "20m"
48 )]
49 idle: Option<String>,
50 #[arg(long, requires = "resumable")]
52 here: bool,
53 },
54 Notify {
56 #[arg(long)]
57 provider: String,
58 },
59 Attach {
61 query: Option<String>,
63 #[arg(short, long)]
65 preview: bool,
66 #[arg(short, long)]
68 session: bool,
69 #[arg(long)]
71 dry_run: bool,
72 },
73 Doctor,
75 Resume {
77 pattern: Option<String>,
79 #[arg(
81 long,
82 value_name = "DURATION",
83 num_args = 0..=1,
84 default_missing_value = "20m"
85 )]
86 idle: Option<String>,
87 #[arg(long)]
89 here: bool,
90 #[arg(long)]
92 dry_run: bool,
93 },
94 #[command(alias = "remove")]
96 Rm {
97 patterns: Vec<String>,
99 },
100}
101
102#[derive(Debug, Subcommand)]
103enum ServiceAction {
104 Start,
106 Stop,
108 Restart,
110}
111
112pub fn run() -> Result<()> {
113 let cli = Cli::parse();
114 let ctx = Context::from_env()?;
115 match cli.command {
116 Command::Server => server::run(&ctx),
117 Command::Setup { no_service } => setup::setup(&ctx, no_service),
118 Command::Teardown => setup::teardown(&ctx),
119 Command::Service { action } => match action {
120 ServiceAction::Start => service::start(&ctx),
121 ServiceAction::Stop => service::stop(&ctx),
122 ServiceAction::Restart => service::restart(&ctx),
123 },
124 Command::List {
125 json,
126 resumable,
127 idle,
128 here,
129 } => {
130 let idle = if resumable {
131 parse_idle(idle.as_deref())?
132 } else {
133 None
134 };
135 list::run(&ctx, json, resumable, idle, here)
136 }
137 Command::Notify { provider } => notify::run(&ctx, provider),
138 Command::Attach {
139 query,
140 preview,
141 session,
142 dry_run,
143 } => attach::run(&ctx, query, preview, session, dry_run),
144 Command::Doctor => doctor::run(&ctx),
145 Command::Resume {
146 pattern,
147 idle,
148 here,
149 dry_run,
150 } => resume::run(&ctx, parse_idle(idle.as_deref())?, pattern, here, dry_run),
151 Command::Rm { patterns } => rm::run(&ctx, patterns),
152 }
153}