| 2180 | } |
| 2181 | |
| 2182 | static int main_run_daemon_ctl(int argc, char **argv, const cbm_daemon_ipc_endpoint_t *endpoint, |
| 2183 | const cbm_daemon_build_identity_t *identity, |
| 2184 | const char *executable_path) { |
| 2185 | const char *subcommand = NULL; |
| 2186 | bool open_browser = false; |
| 2187 | int requested_port = 0; |
| 2188 | bool arguments_valid = true; |
| 2189 | for (int index = 1; index < argc; index++) { |
| 2190 | if (strcmp(argv[index], "daemon") == 0) { |
| 2191 | continue; |
| 2192 | } |
| 2193 | if (strcmp(argv[index], "start") == 0 || strcmp(argv[index], "stop") == 0 || |
| 2194 | strcmp(argv[index], "status") == 0) { |
| 2195 | subcommand = argv[index]; |
| 2196 | } else if (strcmp(argv[index], "--open") == 0) { |
| 2197 | open_browser = true; |
| 2198 | } else if (strncmp(argv[index], "--port=", 7) == 0) { |
| 2199 | requested_port = atoi(argv[index] + 7); |
| 2200 | if (requested_port <= 0 || requested_port >= MAIN_MAX_PORT) { |
| 2201 | (void)fprintf(stderr, "error: --port requires a value between 1 and 65535\n"); |
| 2202 | return EXIT_FAILURE; |
| 2203 | } |
| 2204 | } else { |
| 2205 | (void)fprintf(stderr, "error: unknown daemon option: %s\n", argv[index]); |
| 2206 | arguments_valid = false; |
| 2207 | break; |
| 2208 | } |
| 2209 | } |
| 2210 | if (!arguments_valid || !subcommand) { |
| 2211 | (void)fprintf(stderr, "usage: codebase-memory-mcp daemon <start|stop|status> " |
| 2212 | "[--open] [--port=N]\n"); |
| 2213 | return EXIT_FAILURE; |
| 2214 | } |
| 2215 | |
| 2216 | cbm_daemon_runtime_status_t status; |
| 2217 | bool active = cbm_daemon_runtime_request_status(endpoint, identity, |
| 2218 | MAIN_DAEMON_CTL_PROBE_TIMEOUT_MS, &status); |
| 2219 | |
| 2220 | if (strcmp(subcommand, "status") == 0) { |
| 2221 | if (!active) { |
| 2222 | printf("daemon: not running\n"); |
| 2223 | printf("hint: `codebase-memory-mcp daemon start` keeps a daemon warm so CLI " |
| 2224 | "commands and hooks skip the per-command startup cost.\n"); |
| 2225 | return EXIT_FAILURE; |
| 2226 | } |
| 2227 | printf("daemon: active (%s)\n", status.permanent ? "permanent" : "session-managed"); |
| 2228 | printf(" pid: %lu\n", (unsigned long)status.daemon_pid); |
| 2229 | printf(" build: %s (%.12s...)\n", status.semantic_version, status.build_fingerprint); |
| 2230 | if (status.stopping) { |
| 2231 | printf(" state: stopping\n"); |
| 2232 | } |
| 2233 | main_daemon_ctl_print_clients(status.client_pids, status.client_count, |
| 2234 | status.committed_clients); |
| 2235 | main_daemon_ctl_print_ui_configuration(); |
| 2236 | return EXIT_SUCCESS; |
| 2237 | } |
| 2238 | |
| 2239 | if (strcmp(subcommand, "stop") == 0) { |
no test coverage detected