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 about = "Microsoft Teams from your terminal, for humans and agents",
11 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"
12)]
13pub struct Cli {
14 #[arg(long, global = true, env = "TEAMS_PROFILE")]
16 pub profile: Option<String>,
17 #[arg(short = 'o', long, global = true, value_enum, default_value = "auto")]
19 pub output: OutputFormat,
20 #[arg(long, global = true)]
22 pub quiet: bool,
23 #[arg(long, short = 'y', global = true)]
25 pub yes: bool,
26 #[arg(long, global = true, hide = true)]
28 pub json: bool,
29 #[command(subcommand)]
30 pub command: Option<Command>,
31}
32
33#[derive(Debug, Subcommand)]
34pub enum Command {
35 Init(InitArgs),
37 Auth {
39 #[command(subcommand)]
40 command: AuthCommand,
41 },
42 Profile {
44 #[command(subcommand)]
45 command: ProfileCommand,
46 },
47 Config {
49 #[command(subcommand)]
50 command: ConfigCommand,
51 },
52 Whoami,
54 List(OffsetPageArgs),
56 Channels {
58 #[command(subcommand)]
59 command: ChannelsCommand,
60 },
61 Chats {
63 #[command(subcommand)]
64 command: ChatsCommand,
65 },
66 Messages {
68 #[command(subcommand)]
69 command: MessagesCommand,
70 },
71 Tui(TuiArgs),
73 Doctor {
75 #[arg(long)]
77 offline: bool,
78 },
79 Capabilities,
81 Schema {
83 #[arg(long)]
84 command: Option<String>,
85 },
86 Completions { shell: Shell },
88}
89
90#[derive(Debug, Args)]
91pub struct InitArgs {
92 #[arg(long, value_enum, default_value = "graph")]
94 pub backend: crate::config::BackendKind,
95 #[arg(long, value_parser = clap::value_parser!(u16).range(1024..))]
97 pub desktop_port: Option<u16>,
98 #[arg(long)]
100 pub client_id: Option<String>,
101 #[arg(long)]
103 pub tenant: Option<String>,
104 #[arg(long)]
106 pub no_login: bool,
107 #[arg(long)]
109 pub device_code: bool,
110 #[arg(long)]
112 pub channel_history: bool,
113 #[arg(long, env = "TEAMS_READ_ONLY")]
115 pub read_only: bool,
116}
117
118#[derive(Debug, Subcommand)]
119pub enum ConfigCommand {
120 Show,
122 Path,
124}
125
126#[derive(Debug, Subcommand)]
127pub enum AuthCommand {
128 Login {
130 #[arg(long)]
132 device_code: bool,
133 #[arg(long)]
135 channel_history: bool,
136 },
137 Logout,
139 Status {
141 #[arg(long)]
143 offline: bool,
144 },
145}
146
147#[derive(Debug, Subcommand)]
148pub enum ProfileCommand {
149 List,
151 Use { name: String },
153 Remove { name: String },
155}
156
157#[derive(Debug, Subcommand)]
158pub enum ChannelsCommand {
159 List {
161 team: String,
162 #[command(flatten)]
163 page: OffsetPageArgs,
164 },
165}
166
167#[derive(Debug, Subcommand)]
168pub enum ChatsCommand {
169 List(PageArgs),
170}
171
172#[derive(Debug, Args, Clone)]
173pub struct PageArgs {
174 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=50))]
176 pub limit: u16,
177 #[arg(long)]
179 pub cursor: Option<String>,
180 #[arg(long)]
182 pub fields: Option<String>,
183}
184
185#[derive(Debug, Args, Clone)]
186pub struct OffsetPageArgs {
187 #[arg(long, default_value_t = 50, value_parser = clap::value_parser!(u16).range(1..=100))]
189 pub limit: u16,
190 #[arg(long, default_value_t = 0)]
192 pub offset: usize,
193 #[arg(long)]
195 pub fields: Option<String>,
196}
197
198#[derive(Debug, Subcommand)]
199pub enum MessagesCommand {
200 List {
202 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
203 chat: Option<String>,
204 #[arg(long, requires = "channel", required_unless_present = "chat")]
205 team: Option<String>,
206 #[arg(long, requires = "team")]
207 channel: Option<String>,
208 #[command(flatten)]
209 page: PageArgs,
210 },
211 Send {
213 #[arg(long, conflicts_with = "team", required_unless_present = "team")]
214 chat: Option<String>,
215 #[arg(long, requires = "channel", required_unless_present = "chat")]
216 team: Option<String>,
217 #[arg(long, requires = "team")]
218 channel: Option<String>,
219 #[arg(long)]
221 body: String,
222 },
223}
224
225#[derive(Debug, Args)]
226pub struct TuiArgs {
227 #[arg(long)]
229 pub demo: bool,
230 #[arg(long, requires = "demo")]
232 pub snapshot: bool,
233 #[arg(long, default_value_t = 100, hide = true)]
234 pub width: u16,
235 #[arg(long, default_value_t = 30, hide = true)]
236 pub height: u16,
237}