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 Messages {
71 #[command(subcommand)]
72 command: MessagesCommand,
73 },
74 Tui(TuiArgs),
76 Doctor {
78 #[arg(long)]
80 offline: bool,
81 },
82 Desktop {
84 #[command(subcommand)]
85 command: DesktopCommand,
86 },
87 Capabilities,
89 Schema {
91 #[arg(long)]
92 command: Option<String>,
93 },
94 Completions { shell: Shell },
96 #[command(hide = true, name = "desktop-helper")]
98 DesktopHelper,
99}
100
101#[derive(Debug, Args)]
102pub struct InitArgs {
103 #[arg(long, value_enum, default_value = "graph")]
105 pub backend: crate::config::BackendKind,
106 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
108 pub desktop_port: Option<u16>,
109 #[arg(long, value_enum)]
111 pub desktop_account: Option<crate::config::DesktopAccount>,
112 #[arg(long, value_enum)]
114 pub desktop_client: Option<crate::config::DesktopClientKind>,
115 #[arg(long)]
117 pub client_id: Option<String>,
118 #[arg(long)]
120 pub tenant: Option<String>,
121 #[arg(long)]
123 pub no_login: bool,
124 #[arg(long)]
126 pub device_code: bool,
127 #[arg(long)]
129 pub channel_history: bool,
130 #[arg(long, env = "TEAMS_READ_ONLY")]
132 pub read_only: bool,
133 #[arg(long)]
135 pub allow_send: bool,
136}
137
138#[derive(Debug, Subcommand)]
139pub enum ConfigCommand {
140 Show,
142 Path,
144}
145
146#[derive(Debug, Subcommand)]
147pub enum AuthCommand {
148 Login {
150 #[arg(long)]
152 device_code: bool,
153 #[arg(long)]
155 channel_history: bool,
156 },
157 Logout,
159 Status {
161 #[arg(long)]
163 offline: bool,
164 },
165}
166
167#[derive(Debug, Subcommand)]
168pub enum ProfileCommand {
169 List,
171 Use { name: String },
173 Remove { name: String },
175}
176
177#[derive(Debug, Subcommand)]
178pub enum ChannelsCommand {
179 List {
181 team: String,
182 #[command(flatten)]
183 page: OffsetPageArgs,
184 },
185}
186
187#[derive(Debug, Subcommand)]
188pub enum ChatsCommand {
189 List(PageArgs),
190}
191
192#[derive(Debug, Args, Clone)]
193pub struct PageArgs {
194 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=50))]
196 pub limit: u16,
197 #[arg(long)]
199 pub cursor: Option<String>,
200 #[arg(long)]
202 pub fields: Option<String>,
203}
204
205#[derive(Debug, Args, Clone)]
206pub struct OffsetPageArgs {
207 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=100))]
209 pub limit: u16,
210 #[arg(long, default_value_t = 0)]
212 pub offset: usize,
213 #[arg(long)]
215 pub fields: Option<String>,
216}
217
218#[derive(Debug, Subcommand)]
219pub enum MessagesCommand {
220 Status {
222 #[arg(long)]
223 chat: String,
224 #[arg(long)]
225 client_message_id: String,
226 },
227 List {
229 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
230 chat: Option<String>,
231 #[arg(long, requires = "channel", required_unless_present = "chat")]
232 team: Option<String>,
233 #[arg(long, requires = "team")]
234 channel: Option<String>,
235 #[command(flatten)]
236 page: PageArgs,
237 },
238 Send {
240 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
241 chat: Option<String>,
242 #[arg(long, requires = "channel", required_unless_present = "chat")]
243 team: Option<String>,
244 #[arg(long, requires = "team")]
245 channel: Option<String>,
246 #[arg(long)]
248 body: String,
249 },
250}
251
252#[derive(Debug, Args)]
253pub struct TuiArgs {
254 #[arg(long)]
256 pub demo: bool,
257 #[arg(long, requires = "demo")]
259 pub snapshot: bool,
260 #[arg(long, default_value_t = 100, hide = true)]
261 pub width: u16,
262 #[arg(long, default_value_t = 30, hide = true)]
263 pub height: u16,
264}
265
266#[derive(Debug, Subcommand)]
267pub enum DesktopCommand {
268 Status(DesktopArgs),
270 Connect(DesktopArgs),
272 Login(DesktopArgs),
274 Disconnect(DesktopArgs),
276 Recover(DesktopArgs),
278}
279
280#[derive(Debug, Args)]
281pub struct DesktopArgs {
282 #[arg(long, value_enum)]
284 pub desktop_client: Option<crate::config::DesktopClientKind>,
285 #[arg(long)]
287 pub visible: bool,
288 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
290 pub port: Option<u16>,
291}