| 2124 | } |
| 2125 | |
| 2126 | static int main_run_daemon_ctl(int argc, char **argv, const cbm_daemon_ipc_endpoint_t *endpoint, |
| 2127 | const cbm_daemon_build_identity_t *identity, |
| 2128 | const char *executable_path) { |
| 2129 | const char *subcommand = NULL; |
| 2130 | bool open_browser = false; |
| 2131 | int requested_port = 0; |
| 2132 | bool arguments_valid = true; |
| 2133 | for (int index = 1; index < argc; index++) { |
| 2134 | if (strcmp(argv[index], "daemon") == 0) { |
| 2135 | continue; |
| 2136 | } |
| 2137 | if (strcmp(argv[index], "start") == 0 || strcmp(argv[index], "stop") == 0 || |
| 2138 | strcmp(argv[index], "status") == 0) { |
| 2139 | subcommand = argv[index]; |
| 2140 | } else if (strcmp(argv[index], "--open") == 0) { |
| 2141 | open_browser = true; |
| 2142 | } else if (strncmp(argv[index], "--port=", 7) == 0) { |
| 2143 | requested_port = atoi(argv[index] + 7); |
| 2144 | if (requested_port <= 0 || requested_port >= MAIN_MAX_PORT) { |
| 2145 | (void)fprintf(stderr, "error: --port requires a value between 1 and 65535\n"); |
| 2146 | return EXIT_FAILURE; |
| 2147 | } |
| 2148 | } else { |
| 2149 | (void)fprintf(stderr, "error: unknown daemon option: %s\n", argv[index]); |
| 2150 | arguments_valid = false; |
| 2151 | break; |
| 2152 | } |
| 2153 | } |
| 2154 | if (!arguments_valid || !subcommand) { |
| 2155 | (void)fprintf(stderr, "usage: codebase-memory-mcp daemon <start|stop|status> " |
| 2156 | "[--open] [--port=N]\n"); |
| 2157 | return EXIT_FAILURE; |
| 2158 | } |
| 2159 | |
| 2160 | cbm_daemon_runtime_status_t status; |
| 2161 | bool active = cbm_daemon_runtime_request_status(endpoint, identity, |
| 2162 | MAIN_DAEMON_CTL_PROBE_TIMEOUT_MS, &status); |
| 2163 | |
| 2164 | if (strcmp(subcommand, "status") == 0) { |
| 2165 | if (!active) { |
| 2166 | printf("daemon: not running\n"); |
| 2167 | printf("hint: `codebase-memory-mcp daemon start` keeps a daemon warm so CLI " |
| 2168 | "commands and hooks skip the per-command startup cost.\n"); |
| 2169 | return EXIT_FAILURE; |
| 2170 | } |
| 2171 | printf("daemon: active (%s)\n", status.permanent ? "permanent" : "session-managed"); |
| 2172 | printf(" pid: %lu\n", (unsigned long)status.daemon_pid); |
| 2173 | printf(" build: %s (%.12s...)\n", status.semantic_version, status.build_fingerprint); |
| 2174 | if (status.stopping) { |
| 2175 | printf(" state: stopping\n"); |
| 2176 | } |
| 2177 | main_daemon_ctl_print_clients(status.client_pids, status.client_count, |
| 2178 | status.committed_clients); |
| 2179 | main_daemon_ctl_print_ui_configuration(); |
| 2180 | return EXIT_SUCCESS; |
| 2181 | } |
| 2182 | |
| 2183 | if (strcmp(subcommand, "stop") == 0) { |
no test coverage detected