use std::path::PathBuf;
use clap::{Parser, Subcommand, ValueEnum};
const EXIT_CODES_HELP: &str = "\
Exit codes:
0 success
1 unexpected error (I/O, transport, bug)
2 invalid input or configuration
3 authentication failed (check credentials, run 'mkt doctor')
4 resource or provider not found
5 rate limited (transient — retry after the suggested delay)
6 feature not supported by the provider (see 'mkt providers')
7 provider API rejected the request
With --output json, data goes to stdout and errors are emitted on stderr as
a single JSON object: {\"ok\":false,\"error\":{\"type\",\"message\",\"suggestion\"}}.
Use --dry-run on any mutating command to preview without executing.";
#[derive(Parser, Debug)]
#[command(name = "mkt", version, about, long_about = None, after_help = EXIT_CODES_HELP)]
pub struct Cli {
#[arg(long, env = "MKT_PROFILE", default_value = "default", global = true)]
pub profile: String,
#[arg(
short = 'o',
long,
env = "MKT_OUTPUT",
default_value = "table",
value_enum,
global = true
)]
pub output: OutputFormatArg,
#[arg(short = 'v', long, global = true, conflicts_with = "quiet")]
pub verbose: bool,
#[arg(short = 'q', long, global = true)]
pub quiet: bool,
#[arg(long, global = true)]
pub dry_run: bool,
#[arg(long, global = true)]
pub config: Option<PathBuf>,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum OutputFormatArg {
Table,
Json,
Csv,
}
impl From<OutputFormatArg> for mkt_core::output::OutputFormat {
fn from(arg: OutputFormatArg) -> Self {
match arg {
OutputFormatArg::Table => Self::Table,
OutputFormatArg::Json => Self::Json,
OutputFormatArg::Csv => Self::Csv,
}
}
}
#[derive(Subcommand, Debug)]
pub enum Commands {
#[cfg(feature = "meta")]
Meta {
#[command(subcommand)]
domain: MetaDomain,
},
#[cfg(feature = "google")]
Google {
#[command(subcommand)]
domain: GoogleDomain,
},
#[cfg(feature = "tiktok")]
Tiktok {
#[command(subcommand)]
domain: TiktokDomain,
},
#[cfg(feature = "linkedin")]
Linkedin {
#[command(subcommand)]
domain: LinkedinDomain,
},
Providers,
Doctor,
Profile {
#[command(subcommand)]
action: ProfileAction,
},
Completions {
shell: clap_complete::Shell,
},
#[cfg(feature = "mcp")]
Mcp {
#[command(subcommand)]
action: McpAction,
},
}
#[cfg(feature = "mcp")]
#[derive(Subcommand, Debug)]
pub enum McpAction {
Serve,
}
#[cfg(feature = "meta")]
#[derive(Subcommand, Debug)]
pub enum MetaDomain {
Campaign {
#[command(subcommand)]
action: CampaignAction,
},
Adset {
#[command(subcommand)]
action: AdsetAction,
},
Audience {
#[command(subcommand)]
action: AudienceAction,
},
Insight {
#[command(subcommand)]
action: InsightAction,
},
Post {
#[command(subcommand)]
action: PostAction,
},
Creative {
#[command(subcommand)]
action: CreativeAction,
},
Media {
#[command(subcommand)]
action: MediaAction,
},
Raw {
#[command(subcommand)]
action: RawAction,
},
}
#[cfg(feature = "google")]
#[derive(Subcommand, Debug)]
pub enum GoogleDomain {
Campaign {
#[command(subcommand)]
action: CampaignAction,
},
Insight {
#[command(subcommand)]
action: InsightAction,
},
}
#[cfg(feature = "tiktok")]
#[derive(Subcommand, Debug)]
pub enum TiktokDomain {
Campaign {
#[command(subcommand)]
action: CampaignAction,
},
Audience {
#[command(subcommand)]
action: AudienceAction,
},
Insight {
#[command(subcommand)]
action: InsightAction,
},
}
#[cfg(feature = "linkedin")]
#[derive(Subcommand, Debug)]
pub enum LinkedinDomain {
Campaign {
#[command(subcommand)]
action: CampaignAction,
},
Insight {
#[command(subcommand)]
action: InsightAction,
},
}
#[derive(Subcommand, Debug)]
pub enum CampaignAction {
List {
#[arg(long)]
status: Option<String>,
#[arg(long)]
name: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
Get {
id: String,
},
Create {
#[arg(long)]
name: String,
#[arg(long)]
objective: String,
#[arg(long)]
status: Option<String>,
#[arg(long)]
daily_budget: Option<f64>,
#[arg(long)]
extra: Option<String>,
#[arg(long)]
file: Option<PathBuf>,
},
Update {
id: String,
#[arg(long)]
name: Option<String>,
#[arg(long)]
status: Option<String>,
},
Delete {
id: String,
},
}
#[derive(Subcommand, Debug)]
pub enum AdsetAction {
List {
#[arg(long)]
campaign: String,
},
Create {
#[arg(long)]
campaign: String,
#[arg(long)]
name: String,
#[arg(long)]
status: Option<String>,
#[arg(long)]
targeting: Option<String>,
#[arg(long)]
daily_budget: Option<f64>,
#[arg(long)]
optimization_goal: Option<String>,
#[arg(long)]
billing_event: Option<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum AudienceAction {
List,
Create {
#[arg(long)]
name: String,
#[arg(long)]
description: Option<String>,
},
AddUsers {
id: String,
#[arg(long)]
email: Vec<String>,
#[arg(long)]
phone: Vec<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum InsightAction {
Get {
#[arg(long, value_delimiter = ',')]
metrics: Vec<String>,
#[arg(long, value_delimiter = ',')]
breakdowns: Vec<String>,
#[arg(long)]
range: Option<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum PostAction {
Create {
#[arg(long, default_value = "facebook")]
platform: String,
#[arg(long)]
message: Option<String>,
#[arg(long)]
image_url: Option<String>,
#[arg(long)]
link: Option<String>,
},
Promote {
id: String,
#[arg(long)]
adset: String,
#[arg(long)]
name: Option<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum CreativeAction {
Create {
#[arg(long)]
name: String,
#[arg(long)]
body: Option<String>,
#[arg(long)]
image_url: Option<String>,
#[arg(long)]
link_url: Option<String>,
},
DarkPost {
#[arg(long)]
message: String,
#[arg(long)]
link: Option<String>,
#[arg(long)]
image_url: Option<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum MediaAction {
UploadImage {
#[arg(long)]
file: Option<PathBuf>,
#[arg(long)]
url: Option<String>,
},
UploadVideo {
#[arg(long)]
file: Option<PathBuf>,
#[arg(long)]
url: Option<String>,
#[arg(long)]
title: Option<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum RawAction {
Get {
path: String,
#[arg(long, value_delimiter = ',')]
fields: Vec<String>,
},
Post {
path: String,
#[arg(long)]
body: Option<String>,
},
}
#[derive(Subcommand, Debug)]
pub enum ProfileAction {
Set {
name: String,
#[arg(long)]
provider: Option<String>,
#[arg(long)]
access_token: Option<String>,
#[arg(long)]
ad_account: Option<String>,
#[arg(long)]
page_id: Option<String>,
#[arg(long)]
ig_user_id: Option<String>,
},
List,
Show {
name: String,
},
}