@@ -732,6 +732,26 @@ enum Command {
732732 builtins : Vec < String > ,
733733 } ,
734734
735+ /// Start ACP server over HTTP and WebSocket
736+ #[ command( about = "Start ACP server over HTTP and WebSocket" ) ]
737+ Serve {
738+ #[ arg( long, default_value = "127.0.0.1" ) ]
739+ host : String ,
740+
741+ #[ arg( long, default_value = "3284" ) ]
742+ port : u16 ,
743+
744+ #[ arg(
745+ long = "with-builtin" ,
746+ value_name = "NAME" ,
747+ help = "Add builtin extensions by name (e.g., 'developer' or multiple: 'developer,github')" ,
748+ long_help = "Add one or more builtin extensions that are bundled with goose by specifying their names, comma-separated" ,
749+ value_delimiter = ',' ,
750+ action = clap:: ArgAction :: Append
751+ ) ]
752+ builtins : Vec < String > ,
753+ } ,
754+
735755 /// Start or resume interactive chat sessions
736756 #[ command(
737757 about = "Start or resume interactive chat sessions" ,
@@ -1009,6 +1029,7 @@ fn get_command_name(command: &Option<Command>) -> &'static str {
10091029 Some ( Command :: Info { .. } ) => "info" ,
10101030 Some ( Command :: Mcp { .. } ) => "mcp" ,
10111031 Some ( Command :: Acp { .. } ) => "acp" ,
1032+ Some ( Command :: Serve { .. } ) => "serve" ,
10121033 Some ( Command :: Session { .. } ) => "session" ,
10131034 Some ( Command :: Project { } ) => "project" ,
10141035 Some ( Command :: Projects ) => "projects" ,
@@ -1038,6 +1059,35 @@ async fn handle_mcp_command(server: McpCommand) -> Result<()> {
10381059 Ok ( ( ) )
10391060}
10401061
1062+ async fn handle_serve_command ( host : String , port : u16 , builtins : Vec < String > ) -> Result < ( ) > {
1063+ use goose:: config:: paths:: Paths ;
1064+ use goose_acp:: server_factory:: { AcpServer , AcpServerFactoryConfig } ;
1065+ use std:: net:: SocketAddr ;
1066+ use std:: sync:: Arc ;
1067+ use tracing:: info;
1068+
1069+ let builtins = if builtins. is_empty ( ) {
1070+ vec ! [ "developer" . to_string( ) ]
1071+ } else {
1072+ builtins
1073+ } ;
1074+
1075+ let server = Arc :: new ( AcpServer :: new ( AcpServerFactoryConfig {
1076+ builtins,
1077+ data_dir : Paths :: data_dir ( ) ,
1078+ config_dir : Paths :: config_dir ( ) ,
1079+ } ) ) ;
1080+ let router = goose_acp:: transport:: create_router ( server) ;
1081+
1082+ let addr: SocketAddr = format ! ( "{}:{}" , host, port) . parse ( ) ?;
1083+ info ! ( "Starting ACP server on {}" , addr) ;
1084+
1085+ let listener = tokio:: net:: TcpListener :: bind ( addr) . await ?;
1086+ axum:: serve ( listener, router) . await ?;
1087+
1088+ Ok ( ( ) )
1089+ }
1090+
10411091async fn handle_session_subcommand ( command : SessionCommand ) -> Result < ( ) > {
10421092 match command {
10431093 SessionCommand :: List {
@@ -1708,6 +1758,11 @@ pub async fn cli() -> anyhow::Result<()> {
17081758 Some ( Command :: Info { verbose } ) => handle_info ( verbose) ,
17091759 Some ( Command :: Mcp { server } ) => handle_mcp_command ( server) . await ,
17101760 Some ( Command :: Acp { builtins } ) => goose_acp:: server:: run ( builtins) . await ,
1761+ Some ( Command :: Serve {
1762+ host,
1763+ port,
1764+ builtins,
1765+ } ) => handle_serve_command ( host, port, builtins) . await ,
17111766 Some ( Command :: Session {
17121767 command : Some ( cmd) , ..
17131768 } ) => handle_session_subcommand ( cmd) . await ,
0 commit comments