systemprompt_cli/commands/admin/setup/
mod.rs1pub mod ai_config;
9pub mod catalog;
10pub mod common;
11pub mod ddl;
12mod docker;
13pub mod docker_compose;
14mod docker_database;
15pub mod postgres;
16mod profile;
17mod profile_sections;
18mod secrets;
19mod types;
20mod wizard;
21mod wizard_dry_run;
22mod wizard_prompts;
23
24use crate::shared::CommandOutput;
25use anyhow::Result;
26use clap::Args;
27
28pub use secrets::SecretsData;
29pub use types::*;
30
31#[derive(Debug, Args)]
32#[expect(
33 clippy::struct_excessive_bools,
34 reason = "each bool is an independent clap CLI flag, not a state machine"
35)]
36pub struct SetupArgs {
37 #[arg(
38 short,
39 long,
40 help = "Target environment name (e.g., dev, staging, prod)"
41 )]
42 pub environment: Option<String>,
43
44 #[arg(
45 long,
46 help = "Use Docker for PostgreSQL (default: use existing installation)"
47 )]
48 pub docker: bool,
49
50 #[arg(
51 long,
52 env = "SYSTEMPROMPT_DB_HOST",
53 default_value = "localhost",
54 help = "PostgreSQL host"
55 )]
56 pub db_host: String,
57
58 #[arg(
59 long,
60 env = "SYSTEMPROMPT_DB_PORT",
61 default_value = "5432",
62 help = "PostgreSQL port"
63 )]
64 pub db_port: u16,
65
66 #[arg(
67 long,
68 env = "SYSTEMPROMPT_DB_USER",
69 help = "PostgreSQL user (default: systemprompt_`<env>`)"
70 )]
71 pub db_user: Option<String>,
72
73 #[arg(
74 long,
75 env = "SYSTEMPROMPT_DB_PASSWORD",
76 help = "PostgreSQL password (auto-generated if not provided)"
77 )]
78 pub db_password: Option<String>,
79
80 #[arg(
81 long,
82 env = "SYSTEMPROMPT_DB_NAME",
83 help = "PostgreSQL database name (default: systemprompt_`<env>`)"
84 )]
85 pub db_name: Option<String>,
86
87 #[arg(long, env = "GEMINI_API_KEY", help = "Google AI (Gemini) API key")]
88 pub gemini_key: Option<String>,
89
90 #[arg(long, env = "ANTHROPIC_API_KEY", help = "Anthropic (Claude) API key")]
91 pub anthropic_key: Option<String>,
92
93 #[arg(long, env = "OPENAI_API_KEY", help = "OpenAI (GPT) API key")]
94 pub openai_key: Option<String>,
95
96 #[arg(long, env = "GITHUB_TOKEN", help = "GitHub token (optional)")]
97 pub github_token: Option<String>,
98
99 #[arg(
100 long,
101 env = "SYSTEMPROMPT_DEFAULT_PROVIDER",
102 help = "Provider to make the default (gemini | anthropic | openai); must have a key. \
103 In interactive mode the selected provider is used instead."
104 )]
105 pub default_provider: Option<String>,
106
107 #[arg(long, help = "Run database migrations after setup")]
108 pub migrate: bool,
109
110 #[arg(
111 long,
112 conflicts_with = "migrate",
113 help = "Skip migrations (non-interactive default)"
114 )]
115 pub no_migrate: bool,
116
117 #[arg(long, help = "Preview setup without creating files or making changes")]
118 pub dry_run: bool,
119
120 #[arg(short = 'y', long, help = "Skip confirmation prompts")]
121 pub yes: bool,
122
123 #[arg(
124 long,
125 help = "Overwrite existing profile/secrets files (default: preserve them)"
126 )]
127 pub force: bool,
128}
129
130impl SetupArgs {
131 pub fn effective_db_user(&self, env_name: &str) -> String {
132 self.db_user
133 .clone()
134 .unwrap_or_else(|| format!("systemprompt_{}", env_name))
135 }
136
137 pub fn effective_db_name(&self, env_name: &str) -> String {
138 self.db_name
139 .clone()
140 .unwrap_or_else(|| format!("systemprompt_{}", env_name))
141 }
142
143 pub const fn has_ai_provider(&self) -> bool {
144 self.gemini_key.is_some() || self.anthropic_key.is_some() || self.openai_key.is_some()
145 }
146}
147
148pub async fn execute(
149 args: SetupArgs,
150 ctx: &crate::context::CommandContext,
151) -> Result<CommandOutput> {
152 wizard::execute(args, ctx.prompter(), &ctx.cli).await
153}