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 tui --demo Explore without an account\n teams doctor Diagnose configuration and access\n teams schema --command 'messages send'\n Inspect the automation contract"
13)]
14pub struct Cli {
15 #[arg(long, global = true, env = "TEAMS_PROFILE")]
17 pub profile: Option<String>,
18 #[arg(short = 'o', long, global = true, value_enum, default_value = "auto")]
20 pub output: OutputFormat,
21 #[arg(long, global = true)]
23 pub quiet: bool,
24 #[arg(long, short = 'y', global = true)]
26 pub yes: bool,
27 #[arg(long, global = true, hide = true)]
29 pub json: bool,
30 #[command(subcommand)]
31 pub command: Option<Command>,
32}
33
34#[derive(Debug, Subcommand)]
35pub enum Command {
36 Init(InitArgs),
38 Auth {
40 #[command(subcommand)]
41 command: AuthCommand,
42 },
43 Profile {
45 #[command(subcommand)]
46 command: ProfileCommand,
47 },
48 Config {
50 #[command(subcommand)]
51 command: ConfigCommand,
52 },
53 Whoami,
55 List(OffsetPageArgs),
57 Channels {
59 #[command(subcommand)]
60 command: ChannelsCommand,
61 },
62 Chats {
64 #[command(subcommand)]
65 command: ChatsCommand,
66 },
67 Messages {
69 #[command(subcommand)]
70 command: MessagesCommand,
71 },
72 Tui(TuiArgs),
74 Doctor {
76 #[arg(long)]
78 offline: bool,
79 },
80 Capabilities,
82 Schema {
84 #[arg(long)]
85 command: Option<String>,
86 },
87 Completions { shell: Shell },
89 #[command(hide = true, name = "desktop-helper")]
91 DesktopHelper,
92}
93
94#[derive(Debug, Args)]
95pub struct InitArgs {
96 #[arg(long, value_enum, default_value = "graph")]
98 pub backend: crate::config::BackendKind,
99 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
101 pub desktop_port: Option<u16>,
102 #[arg(long, value_enum)]
104 pub desktop_account: Option<crate::config::DesktopAccount>,
105 #[arg(long)]
107 pub client_id: Option<String>,
108 #[arg(long)]
110 pub tenant: Option<String>,
111 #[arg(long)]
113 pub no_login: bool,
114 #[arg(long)]
116 pub device_code: bool,
117 #[arg(long)]
119 pub channel_history: bool,
120 #[arg(long, env = "TEAMS_READ_ONLY")]
122 pub read_only: bool,
123 #[arg(long)]
125 pub allow_send: bool,
126}
127
128#[derive(Debug, Subcommand)]
129pub enum ConfigCommand {
130 Show,
132 Path,
134}
135
136#[derive(Debug, Subcommand)]
137pub enum AuthCommand {
138 Login {
140 #[arg(long)]
142 device_code: bool,
143 #[arg(long)]
145 channel_history: bool,
146 },
147 Logout,
149 Status {
151 #[arg(long)]
153 offline: bool,
154 },
155}
156
157#[derive(Debug, Subcommand)]
158pub enum ProfileCommand {
159 List,
161 Use { name: String },
163 Remove { name: String },
165}
166
167#[derive(Debug, Subcommand)]
168pub enum ChannelsCommand {
169 List {
171 team: String,
172 #[command(flatten)]
173 page: OffsetPageArgs,
174 },
175}
176
177#[derive(Debug, Subcommand)]
178pub enum ChatsCommand {
179 List(PageArgs),
180}
181
182#[derive(Debug, Args, Clone)]
183pub struct PageArgs {
184 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=50))]
186 pub limit: u16,
187 #[arg(long)]
189 pub cursor: Option<String>,
190 #[arg(long)]
192 pub fields: Option<String>,
193}
194
195#[derive(Debug, Args, Clone)]
196pub struct OffsetPageArgs {
197 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=100))]
199 pub limit: u16,
200 #[arg(long, default_value_t = 0)]
202 pub offset: usize,
203 #[arg(long)]
205 pub fields: Option<String>,
206}
207
208#[derive(Debug, Subcommand)]
209pub enum MessagesCommand {
210 List {
212 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
213 chat: Option<String>,
214 #[arg(long, requires = "channel", required_unless_present = "chat")]
215 team: Option<String>,
216 #[arg(long, requires = "team")]
217 channel: Option<String>,
218 #[command(flatten)]
219 page: PageArgs,
220 },
221 Send {
223 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
224 chat: Option<String>,
225 #[arg(long, requires = "channel", required_unless_present = "chat")]
226 team: Option<String>,
227 #[arg(long, requires = "team")]
228 channel: Option<String>,
229 #[arg(long)]
231 body: String,
232 },
233}
234
235#[derive(Debug, Args)]
236pub struct TuiArgs {
237 #[arg(long)]
239 pub demo: bool,
240 #[arg(long, requires = "demo")]
242 pub snapshot: bool,
243 #[arg(long, default_value_t = 100, hide = true)]
244 pub width: u16,
245 #[arg(long, default_value_t = 30, hide = true)]
246 pub height: u16,
247}