33import sys
44import time
55from argparse import ArgumentParser , Namespace
6+ from ipaddress import ip_address
67from pathlib import Path
78
89import platformdirs
@@ -100,6 +101,13 @@ def parse_args() -> Namespace:
100101 help = "Run in non-interactive CLI mode" ,
101102 parents = [common_parser ()],
102103 )
104+ cli_parser .add_argument (
105+ "--with-server" ,
106+ action = "store_true" ,
107+ default = False ,
108+ help = "Start the rogue server alongside the CLI" ,
109+ )
110+ set_server_args (cli_parser )
103111 set_cli_args (cli_parser )
104112
105113 # TUI mode
@@ -119,6 +127,20 @@ def parse_args() -> Namespace:
119127 return parser .parse_args ()
120128
121129
130+ def build_local_server_url (host : str , port : int ) -> str :
131+ """Build an HTTP URL for a server bound to host:port, normalizing wildcards."""
132+ http_host = host
133+ if http_host in ("0.0.0.0" , "::" ): # nosec B104
134+ http_host = "127.0.0.1"
135+ else :
136+ try :
137+ if ip_address (http_host ).version == 6 :
138+ http_host = f"[{ http_host } ]"
139+ except ValueError :
140+ pass # hostname, leave as-is
141+ return f"http://{ http_host } :{ port } "
142+
143+
122144def start_example_agent (
123145 example_name : str ,
124146 host : str ,
@@ -279,7 +301,32 @@ def main() -> None:
279301 if args .mode == "server" :
280302 run_server (args , background = False )
281303 elif args .mode == "cli" :
282- exit_code = asyncio .run (run_cli (args ))
304+ server_process = None
305+ if args .with_server :
306+ server_process = run_server (
307+ args ,
308+ background = True ,
309+ log_file = log_file_path ,
310+ )
311+ if not server_process :
312+ logger .error ("Failed to start rogue server. Exiting." )
313+ sys .exit (1 )
314+ # Point the CLI at the embedded server.
315+ args .rogue_server_url = build_local_server_url (
316+ args .host ,
317+ args .port ,
318+ )
319+ logger .info (
320+ "Rogue server started for CLI" ,
321+ extra = {"rogue_server_url" : args .rogue_server_url },
322+ )
323+
324+ try :
325+ exit_code = asyncio .run (run_cli (args ))
326+ finally :
327+ if server_process :
328+ server_process .terminate ()
329+ server_process .join ()
283330 sys .exit (exit_code )
284331 elif args .mode == "tui" :
285332 if not RogueTuiInstaller ().install_rogue_tui ():
0 commit comments