@@ -13,6 +13,7 @@ use std::time::Duration;
1313use anyhow:: Context ;
1414use anyhow:: Result ;
1515use anyhow:: bail;
16+ use clap:: ArgAction ;
1617use clap:: Parser ;
1718use clap:: Subcommand ;
1819use codex_app_server_protocol:: AddConversationListenerParams ;
@@ -67,6 +68,19 @@ struct Cli {
6768 #[ arg( long, env = "CODEX_BIN" , default_value = "codex" ) ]
6869 codex_bin : String ,
6970
71+ /// Forwarded to the `codex` CLI as `--config key=value`. Repeatable.
72+ ///
73+ /// Example:
74+ /// `--config 'model_providers.mock.base_url="http://localhost:4010/v2"'`
75+ #[ arg(
76+ short = 'c' ,
77+ long = "config" ,
78+ value_name = "key=value" ,
79+ action = ArgAction :: Append ,
80+ global = true
81+ ) ]
82+ config_overrides : Vec < String > ,
83+
7084 #[ command( subcommand) ]
7185 command : CliCommand ,
7286}
@@ -121,30 +135,43 @@ enum CliCommand {
121135}
122136
123137fn main ( ) -> Result < ( ) > {
124- let Cli { codex_bin, command } = Cli :: parse ( ) ;
138+ let Cli {
139+ codex_bin,
140+ config_overrides,
141+ command,
142+ } = Cli :: parse ( ) ;
125143
126144 match command {
127- CliCommand :: SendMessage { user_message } => send_message ( codex_bin, user_message) ,
128- CliCommand :: SendMessageV2 { user_message } => send_message_v2 ( codex_bin, user_message) ,
145+ CliCommand :: SendMessage { user_message } => {
146+ send_message ( & codex_bin, & config_overrides, user_message)
147+ }
148+ CliCommand :: SendMessageV2 { user_message } => {
149+ send_message_v2 ( & codex_bin, & config_overrides, user_message)
150+ }
129151 CliCommand :: TriggerCmdApproval { user_message } => {
130- trigger_cmd_approval ( codex_bin, user_message)
152+ trigger_cmd_approval ( & codex_bin, & config_overrides , user_message)
131153 }
132154 CliCommand :: TriggerPatchApproval { user_message } => {
133- trigger_patch_approval ( codex_bin, user_message)
155+ trigger_patch_approval ( & codex_bin, & config_overrides , user_message)
134156 }
135- CliCommand :: NoTriggerCmdApproval => no_trigger_cmd_approval ( codex_bin) ,
157+ CliCommand :: NoTriggerCmdApproval => no_trigger_cmd_approval ( & codex_bin, & config_overrides ) ,
136158 CliCommand :: SendFollowUpV2 {
137159 first_message,
138160 follow_up_message,
139- } => send_follow_up_v2 ( codex_bin, first_message, follow_up_message) ,
140- CliCommand :: TestLogin => test_login ( codex_bin) ,
141- CliCommand :: GetAccountRateLimits => get_account_rate_limits ( codex_bin) ,
142- CliCommand :: ModelList => model_list ( codex_bin) ,
161+ } => send_follow_up_v2 (
162+ & codex_bin,
163+ & config_overrides,
164+ first_message,
165+ follow_up_message,
166+ ) ,
167+ CliCommand :: TestLogin => test_login ( & codex_bin, & config_overrides) ,
168+ CliCommand :: GetAccountRateLimits => get_account_rate_limits ( & codex_bin, & config_overrides) ,
169+ CliCommand :: ModelList => model_list ( & codex_bin, & config_overrides) ,
143170 }
144171}
145172
146- fn send_message ( codex_bin : String , user_message : String ) -> Result < ( ) > {
147- let mut client = CodexClient :: spawn ( codex_bin) ?;
173+ fn send_message ( codex_bin : & str , config_overrides : & [ String ] , user_message : String ) -> Result < ( ) > {
174+ let mut client = CodexClient :: spawn ( codex_bin, config_overrides ) ?;
148175
149176 let initialize = client. initialize ( ) ?;
150177 println ! ( "< initialize response: {initialize:?}" ) ;
@@ -165,46 +192,61 @@ fn send_message(codex_bin: String, user_message: String) -> Result<()> {
165192 Ok ( ( ) )
166193}
167194
168- fn send_message_v2 ( codex_bin : String , user_message : String ) -> Result < ( ) > {
169- send_message_v2_with_policies ( codex_bin, user_message, None , None )
195+ fn send_message_v2 (
196+ codex_bin : & str ,
197+ config_overrides : & [ String ] ,
198+ user_message : String ,
199+ ) -> Result < ( ) > {
200+ send_message_v2_with_policies ( codex_bin, config_overrides, user_message, None , None )
170201}
171202
172- fn trigger_cmd_approval ( codex_bin : String , user_message : Option < String > ) -> Result < ( ) > {
203+ fn trigger_cmd_approval (
204+ codex_bin : & str ,
205+ config_overrides : & [ String ] ,
206+ user_message : Option < String > ,
207+ ) -> Result < ( ) > {
173208 let default_prompt =
174209 "Run `touch /tmp/should-trigger-approval` so I can confirm the file exists." ;
175210 let message = user_message. unwrap_or_else ( || default_prompt. to_string ( ) ) ;
176211 send_message_v2_with_policies (
177212 codex_bin,
213+ config_overrides,
178214 message,
179215 Some ( AskForApproval :: OnRequest ) ,
180216 Some ( SandboxPolicy :: ReadOnly ) ,
181217 )
182218}
183219
184- fn trigger_patch_approval ( codex_bin : String , user_message : Option < String > ) -> Result < ( ) > {
220+ fn trigger_patch_approval (
221+ codex_bin : & str ,
222+ config_overrides : & [ String ] ,
223+ user_message : Option < String > ,
224+ ) -> Result < ( ) > {
185225 let default_prompt =
186226 "Create a file named APPROVAL_DEMO.txt containing a short hello message using apply_patch." ;
187227 let message = user_message. unwrap_or_else ( || default_prompt. to_string ( ) ) ;
188228 send_message_v2_with_policies (
189229 codex_bin,
230+ config_overrides,
190231 message,
191232 Some ( AskForApproval :: OnRequest ) ,
192233 Some ( SandboxPolicy :: ReadOnly ) ,
193234 )
194235}
195236
196- fn no_trigger_cmd_approval ( codex_bin : String ) -> Result < ( ) > {
237+ fn no_trigger_cmd_approval ( codex_bin : & str , config_overrides : & [ String ] ) -> Result < ( ) > {
197238 let prompt = "Run `touch should_not_trigger_approval.txt`" ;
198- send_message_v2_with_policies ( codex_bin, prompt. to_string ( ) , None , None )
239+ send_message_v2_with_policies ( codex_bin, config_overrides , prompt. to_string ( ) , None , None )
199240}
200241
201242fn send_message_v2_with_policies (
202- codex_bin : String ,
243+ codex_bin : & str ,
244+ config_overrides : & [ String ] ,
203245 user_message : String ,
204246 approval_policy : Option < AskForApproval > ,
205247 sandbox_policy : Option < SandboxPolicy > ,
206248) -> Result < ( ) > {
207- let mut client = CodexClient :: spawn ( codex_bin) ?;
249+ let mut client = CodexClient :: spawn ( codex_bin, config_overrides ) ?;
208250
209251 let initialize = client. initialize ( ) ?;
210252 println ! ( "< initialize response: {initialize:?}" ) ;
@@ -228,11 +270,12 @@ fn send_message_v2_with_policies(
228270}
229271
230272fn send_follow_up_v2 (
231- codex_bin : String ,
273+ codex_bin : & str ,
274+ config_overrides : & [ String ] ,
232275 first_message : String ,
233276 follow_up_message : String ,
234277) -> Result < ( ) > {
235- let mut client = CodexClient :: spawn ( codex_bin) ?;
278+ let mut client = CodexClient :: spawn ( codex_bin, config_overrides ) ?;
236279
237280 let initialize = client. initialize ( ) ?;
238281 println ! ( "< initialize response: {initialize:?}" ) ;
@@ -265,8 +308,8 @@ fn send_follow_up_v2(
265308 Ok ( ( ) )
266309}
267310
268- fn test_login ( codex_bin : String ) -> Result < ( ) > {
269- let mut client = CodexClient :: spawn ( codex_bin) ?;
311+ fn test_login ( codex_bin : & str , config_overrides : & [ String ] ) -> Result < ( ) > {
312+ let mut client = CodexClient :: spawn ( codex_bin, config_overrides ) ?;
270313
271314 let initialize = client. initialize ( ) ?;
272315 println ! ( "< initialize response: {initialize:?}" ) ;
@@ -295,8 +338,8 @@ fn test_login(codex_bin: String) -> Result<()> {
295338 }
296339}
297340
298- fn get_account_rate_limits ( codex_bin : String ) -> Result < ( ) > {
299- let mut client = CodexClient :: spawn ( codex_bin) ?;
341+ fn get_account_rate_limits ( codex_bin : & str , config_overrides : & [ String ] ) -> Result < ( ) > {
342+ let mut client = CodexClient :: spawn ( codex_bin, config_overrides ) ?;
300343
301344 let initialize = client. initialize ( ) ?;
302345 println ! ( "< initialize response: {initialize:?}" ) ;
@@ -307,8 +350,8 @@ fn get_account_rate_limits(codex_bin: String) -> Result<()> {
307350 Ok ( ( ) )
308351}
309352
310- fn model_list ( codex_bin : String ) -> Result < ( ) > {
311- let mut client = CodexClient :: spawn ( codex_bin) ?;
353+ fn model_list ( codex_bin : & str , config_overrides : & [ String ] ) -> Result < ( ) > {
354+ let mut client = CodexClient :: spawn ( codex_bin, config_overrides ) ?;
312355
313356 let initialize = client. initialize ( ) ?;
314357 println ! ( "< initialize response: {initialize:?}" ) ;
@@ -327,8 +370,12 @@ struct CodexClient {
327370}
328371
329372impl CodexClient {
330- fn spawn ( codex_bin : String ) -> Result < Self > {
331- let mut codex_app_server = Command :: new ( & codex_bin)
373+ fn spawn ( codex_bin : & str , config_overrides : & [ String ] ) -> Result < Self > {
374+ let mut cmd = Command :: new ( codex_bin) ;
375+ for override_kv in config_overrides {
376+ cmd. arg ( "--config" ) . arg ( override_kv) ;
377+ }
378+ let mut codex_app_server = cmd
332379 . arg ( "app-server" )
333380 . stdin ( Stdio :: piped ( ) )
334381 . stdout ( Stdio :: piped ( ) )
0 commit comments