1use clap::{Args, Parser, Subcommand};
2use clap_complete::Shell;
3
4use crate::output::OutputFormat;
5
6#[derive(Debug, Parser)]
7#[command(
8 name = "teams",
9 version,
10 long_version = env!("TEAMS_LONG_VERSION"),
11 about = "Microsoft Teams from your terminal, for humans and agents",
12 after_help = "Get started:\n teams init Guided setup\n teams init --backend desktop --desktop-client browser-core
13 Lightweight browser, personal account
14 teams tui --demo Explore without an account\n teams doctor Diagnose configuration and access\n teams schema --command 'messages send'\n Inspect the automation contract"
15)]
16pub struct Cli {
17 #[arg(long, global = true, env = "TEAMS_PROFILE")]
19 pub profile: Option<String>,
20 #[arg(short = 'o', long, global = true, value_enum, default_value = "auto")]
22 pub output: OutputFormat,
23 #[arg(long, global = true)]
25 pub quiet: bool,
26 #[arg(long, short = 'y', global = true)]
28 pub yes: bool,
29 #[arg(long, global = true, hide = true)]
31 pub json: bool,
32 #[command(subcommand)]
33 pub command: Option<Command>,
34}
35
36#[derive(Debug, Subcommand)]
37pub enum Command {
38 Init(InitArgs),
40 Auth {
42 #[command(subcommand)]
43 command: AuthCommand,
44 },
45 Profile {
47 #[command(subcommand)]
48 command: ProfileCommand,
49 },
50 Config {
52 #[command(subcommand)]
53 command: ConfigCommand,
54 },
55 Whoami,
57 List(OffsetPageArgs),
59 Channels {
61 #[command(subcommand)]
62 command: ChannelsCommand,
63 },
64 Chats {
66 #[command(subcommand)]
67 command: ChatsCommand,
68 },
69 People {
71 #[command(subcommand)]
72 command: PeopleCommand,
73 },
74 Messages {
76 #[command(subcommand)]
77 command: MessagesCommand,
78 },
79 Tui(TuiArgs),
81 Doctor {
83 #[arg(long)]
85 offline: bool,
86 },
87 Desktop {
89 #[command(subcommand)]
90 command: DesktopCommand,
91 },
92 Capabilities,
94 Schema {
96 #[arg(long)]
97 command: Option<String>,
98 },
99 Completions { shell: Shell },
101 #[command(hide = true, name = "desktop-helper")]
103 DesktopHelper,
104}
105
106#[derive(Debug, Args)]
107pub struct InitArgs {
108 #[arg(long, value_enum, default_value = "graph")]
110 pub backend: crate::config::BackendKind,
111 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
113 pub desktop_port: Option<u16>,
114 #[arg(long, value_enum)]
116 pub desktop_account: Option<crate::config::DesktopAccount>,
117 #[arg(long, value_enum)]
119 pub desktop_client: Option<crate::config::DesktopClientKind>,
120 #[arg(long)]
122 pub client_id: Option<String>,
123 #[arg(long)]
125 pub tenant: Option<String>,
126 #[arg(long)]
128 pub no_login: bool,
129 #[arg(long)]
131 pub device_code: bool,
132 #[arg(long)]
134 pub channel_history: bool,
135 #[arg(long, env = "TEAMS_READ_ONLY")]
137 pub read_only: bool,
138 #[arg(long)]
140 pub allow_send: bool,
141}
142
143#[derive(Debug, Subcommand)]
144pub enum ConfigCommand {
145 Show,
147 Path,
149}
150
151#[derive(Debug, Subcommand)]
152pub enum AuthCommand {
153 Login {
155 #[arg(long)]
157 device_code: bool,
158 #[arg(long)]
160 channel_history: bool,
161 },
162 Logout,
164 Status {
166 #[arg(long)]
168 offline: bool,
169 },
170}
171
172#[derive(Debug, Subcommand)]
173pub enum ProfileCommand {
174 List,
176 Use { name: String },
178 Remove { name: String },
180}
181
182#[derive(Debug, Subcommand)]
183pub enum ChannelsCommand {
184 List {
186 team: String,
187 #[command(flatten)]
188 page: OffsetPageArgs,
189 },
190}
191
192#[derive(Debug, Subcommand)]
193pub enum ChatsCommand {
194 List(PageArgs),
195 Create {
197 #[arg(long)]
199 recipient: String,
200 },
201}
202
203#[derive(Debug, Subcommand)]
204pub enum PeopleCommand {
205 Search {
207 query: String,
208 #[arg(long, default_value_t = 20, value_parser = clap::value_parser!(u16).range(1..=50))]
209 limit: u16,
210 },
211}
212
213#[derive(Debug, Args, Clone)]
214pub struct PageArgs {
215 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=50))]
217 pub limit: u16,
218 #[arg(long)]
220 pub cursor: Option<String>,
221 #[arg(long)]
223 pub fields: Option<String>,
224}
225
226#[derive(Debug, Args, Clone)]
227pub struct OffsetPageArgs {
228 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=100))]
230 pub limit: u16,
231 #[arg(long, default_value_t = 0)]
233 pub offset: usize,
234 #[arg(long)]
236 pub fields: Option<String>,
237}
238
239#[derive(Debug, Subcommand)]
240pub enum MessagesCommand {
241 Status {
243 #[arg(long)]
244 chat: String,
245 #[arg(long)]
246 client_message_id: String,
247 },
248 List {
250 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
251 chat: Option<String>,
252 #[arg(long, requires = "channel", required_unless_present = "chat")]
253 team: Option<String>,
254 #[arg(long, requires = "team")]
255 channel: Option<String>,
256 #[command(flatten)]
257 page: PageArgs,
258 },
259 Send {
261 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
262 chat: Option<String>,
263 #[arg(long, requires = "channel", required_unless_present = "chat")]
264 team: Option<String>,
265 #[arg(long, requires = "team")]
266 channel: Option<String>,
267 #[arg(long)]
269 body: String,
270 },
271}
272
273#[derive(Debug, Args)]
274pub struct TuiArgs {
275 #[arg(long)]
277 pub demo: bool,
278 #[arg(long, requires = "demo")]
280 pub snapshot: bool,
281 #[arg(long, default_value_t = 100, hide = true)]
282 pub width: u16,
283 #[arg(long, default_value_t = 30, hide = true)]
284 pub height: u16,
285}
286
287#[derive(Debug, Subcommand)]
288pub enum DesktopCommand {
289 Status(DesktopArgs),
291 Connect(DesktopArgs),
293 Login(DesktopArgs),
295 Disconnect(DesktopArgs),
297 Recover(DesktopArgs),
299 ClearFlags(DesktopArgs),
301}
302
303#[derive(Debug, Args)]
304pub struct DesktopArgs {
305 #[arg(long, value_enum)]
307 pub desktop_client: Option<crate::config::DesktopClientKind>,
308 #[arg(long)]
310 pub visible: bool,
311 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
313 pub port: Option<u16>,
314}