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 Connect a personal or work account\n teams Reopen your inbox after setup
13 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"
14)]
15pub struct Cli {
16 #[arg(long, global = true, env = "TEAMS_PROFILE")]
18 pub profile: Option<String>,
19 #[arg(short = 'o', long, global = true, value_enum, default_value = "auto")]
21 pub output: OutputFormat,
22 #[arg(long, global = true)]
24 pub quiet: bool,
25 #[arg(long, short = 'y', global = true)]
27 pub yes: bool,
28 #[arg(long, global = true, hide = true)]
30 pub json: bool,
31 #[command(subcommand)]
32 pub command: Option<Command>,
33}
34
35#[derive(Debug, Subcommand)]
36pub enum Command {
37 Init(InitArgs),
39 Auth {
41 #[command(subcommand)]
42 command: AuthCommand,
43 },
44 Profile {
46 #[command(subcommand)]
47 command: ProfileCommand,
48 },
49 Config {
51 #[command(subcommand)]
52 command: ConfigCommand,
53 },
54 Whoami,
56 List(OffsetPageArgs),
58 Channels {
60 #[command(subcommand)]
61 command: ChannelsCommand,
62 },
63 Chats {
65 #[command(subcommand)]
66 command: ChatsCommand,
67 },
68 People {
70 #[command(subcommand)]
71 command: PeopleCommand,
72 },
73 Messages {
75 #[command(subcommand)]
76 command: MessagesCommand,
77 },
78 Tui(TuiArgs),
80 Doctor {
82 #[arg(long)]
84 offline: bool,
85 },
86 Desktop {
88 #[command(subcommand)]
89 command: DesktopCommand,
90 },
91 Capabilities,
93 Schema {
95 #[arg(long)]
96 command: Option<String>,
97 },
98 Completions { shell: Shell },
100 #[command(hide = true, name = "desktop-helper")]
102 DesktopHelper,
103}
104
105#[derive(Debug, Args)]
106pub struct InitArgs {
107 #[arg(long, value_enum)]
109 pub credential_store: Option<crate::config::CredentialStore>,
110 #[arg(long)]
112 pub pass_store_dir: Option<std::path::PathBuf>,
113 #[arg(long, value_enum)]
115 pub backend: Option<crate::config::BackendKind>,
116 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
118 pub desktop_port: Option<u16>,
119 #[arg(long, value_enum)]
121 pub desktop_account: Option<crate::config::DesktopAccount>,
122 #[arg(long, value_enum)]
124 pub desktop_client: Option<crate::config::DesktopClientKind>,
125 #[arg(long)]
127 pub client_id: Option<String>,
128 #[arg(long)]
130 pub tenant: Option<String>,
131 #[arg(long)]
133 pub no_login: bool,
134 #[arg(long)]
136 pub device_code: bool,
137 #[arg(long)]
139 pub channel_history: bool,
140 #[arg(long, env = "TEAMS_READ_ONLY")]
142 pub read_only: bool,
143 #[arg(long)]
145 pub allow_send: bool,
146 #[arg(long)]
148 pub auto_start: bool,
149}
150
151#[derive(Debug, Subcommand)]
152pub enum ConfigCommand {
153 Show,
155 Path,
157}
158
159#[derive(Debug, Subcommand)]
160pub enum AuthCommand {
161 Login {
163 #[arg(long)]
165 device_code: bool,
166 #[arg(long)]
168 channel_history: bool,
169 },
170 Logout,
172 Status {
174 #[arg(long)]
176 offline: bool,
177 },
178}
179
180#[derive(Debug, Subcommand)]
181pub enum ProfileCommand {
182 List,
184 Use { name: String },
186 Remove { name: String },
188}
189
190#[derive(Debug, Subcommand)]
191pub enum ChannelsCommand {
192 List {
194 team: String,
195 #[command(flatten)]
196 page: OffsetPageArgs,
197 },
198}
199
200#[derive(Debug, Subcommand)]
201pub enum ChatsCommand {
202 List(PageArgs),
203 Create {
205 #[arg(long)]
207 recipient: String,
208 },
209}
210
211#[derive(Debug, Subcommand)]
212pub enum PeopleCommand {
213 Search {
215 query: String,
216 #[arg(long, default_value_t = 20, value_parser = clap::value_parser!(u16).range(1..=50))]
217 limit: u16,
218 },
219}
220
221#[derive(Debug, Args, Clone)]
222pub struct PageArgs {
223 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=50))]
225 pub limit: u16,
226 #[arg(long)]
228 pub cursor: Option<String>,
229 #[arg(long)]
231 pub fields: Option<String>,
232}
233
234#[derive(Debug, Args, Clone)]
235pub struct OffsetPageArgs {
236 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=100))]
238 pub limit: u16,
239 #[arg(long, default_value_t = 0)]
241 pub offset: usize,
242 #[arg(long)]
244 pub fields: Option<String>,
245}
246
247#[derive(Debug, Subcommand)]
248pub enum MessagesCommand {
249 Status {
251 #[arg(long)]
252 chat: String,
253 #[arg(long)]
254 client_message_id: String,
255 },
256 List {
258 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
259 chat: Option<String>,
260 #[arg(long, requires = "channel", required_unless_present = "chat")]
261 team: Option<String>,
262 #[arg(long, requires = "team")]
263 channel: Option<String>,
264 #[command(flatten)]
265 page: PageArgs,
266 },
267 Send {
269 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
270 chat: Option<String>,
271 #[arg(long, requires = "channel", required_unless_present = "chat")]
272 team: Option<String>,
273 #[arg(long, requires = "team")]
274 channel: Option<String>,
275 #[arg(long)]
277 body: String,
278 },
279}
280
281#[derive(Debug, Args)]
282pub struct TuiArgs {
283 #[arg(long)]
285 pub demo: bool,
286 #[arg(long, requires = "demo")]
288 pub snapshot: bool,
289 #[arg(long, default_value_t = 100, hide = true)]
290 pub width: u16,
291 #[arg(long, default_value_t = 30, hide = true)]
292 pub height: u16,
293}
294
295#[derive(Debug, Subcommand)]
296pub enum DesktopCommand {
297 Status(DesktopArgs),
299 Connect(DesktopArgs),
301 Login(DesktopArgs),
303 Disconnect(DesktopArgs),
305 Recover(DesktopArgs),
307 ClearFlags(DesktopArgs),
309}
310
311#[derive(Debug, Args)]
312pub struct DesktopArgs {
313 #[arg(long, value_enum)]
315 pub desktop_client: Option<crate::config::DesktopClientKind>,
316 #[arg(long)]
318 pub visible: bool,
319 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
321 pub port: Option<u16>,
322}