@@ -7376,6 +7376,12 @@ static const char *detect_arch(void) {
73767376
73777377/* ── Agent config install/refresh (shared by install + update) ── */
73787378
7379+ /* Set by `install --clients=...` after validation and consumed by both the
7380+ * legacy detector and the registry-backed client path (#1558, #1798). */
7381+ static const char *g_client_selection = NULL;
7382+ static bool cli_clients_apply_selection(const char *spec, cbm_detected_agents_t *detected);
7383+ static bool cli_clients_selects_registry_client(const char *spec, cbm_agent_client_id_t client_id);
7384+ static void cli_clients_print_list(FILE *out);
73797385static void print_detected_registry_agents(const char *home, bool *any);
73807386
73817387/* Print detected agent names on a single line. */
@@ -8169,7 +8175,10 @@ static void print_detected_registry_agents(const char *home, bool *any) {
81698175 cbm_init_agent_registry_context(home, ®istry);
81708176 for (size_t index = 0U; index < cbm_agent_client_count(); index++) {
81718177 const cbm_agent_client_profile_t *profile = cbm_agent_client_at(index);
8172- if (profile && cbm_agent_client_detect(profile->id, ®istry.options)) {
8178+ if (profile &&
8179+ (!g_client_selection ||
8180+ cli_clients_selects_registry_client(g_client_selection, profile->id)) &&
8181+ cbm_agent_client_detect(profile->id, ®istry.options)) {
81738182 printf(" %s", profile->display_name);
81748183 *any = true;
81758184 }
@@ -8525,7 +8534,10 @@ static void install_agent_client_registry(const char *home, const char *binary_p
85258534 cbm_init_agent_registry_context(home, ®istry);
85268535 for (size_t index = 0U; index < cbm_agent_client_count(); index++) {
85278536 const cbm_agent_client_profile_t *profile = cbm_agent_client_at(index);
8528- if (!profile || !cbm_agent_client_detect(profile->id, ®istry.options)) {
8537+ if (!profile ||
8538+ (g_client_selection &&
8539+ !cli_clients_selects_registry_client(g_client_selection, profile->id)) ||
8540+ !cbm_agent_client_detect(profile->id, ®istry.options)) {
85298541 continue;
85308542 }
85318543 if (!g_install_plan) {
@@ -9365,13 +9377,6 @@ static void install_additional_agent_configs(const cbm_detected_agents_t *agents
93659377 }
93669378}
93679379
9368- /* #1558: set by `install --clients=...` after validation, consumed at the one
9369- * place detection happens. Validation runs in cbm_cmd_install so an unknown
9370- * token fails before anything is written, not midway through configuring. */
9371- static const char *g_client_selection = NULL;
9372- static bool cli_clients_apply_selection(const char *spec, cbm_detected_agents_t *detected);
9373- static void cli_clients_print_list(FILE *out);
9374-
93759380int cbm_install_agent_configs(const char *home, const char *binary_path, bool force, bool dry_run) {
93769381 g_agent_install_errors = 0;
93779382 cbm_detected_agents_t agents = cbm_detect_agents(home);
@@ -9499,9 +9504,9 @@ int cbm_install_handle_existing_indexes(const char *home, bool reset, bool dry_r
94999504 * Codex had to revert the OpenCode and Cursor integrations by hand, and the
95009505 * next install silently recreated them. `--clients=claude,codex` restricts it.
95019506 *
9502- * The table is the flag's vocabulary AND its documentation: 26 clients ship
9503- * here, with tokens nobody would guess (factory-droid, mistral-vibe,
9504- * copilot-cli), so `--clients=help` prints every token. A selector whose
9507+ * The tables are the flag's vocabulary AND its documentation, with tokens
9508+ * nobody would guess (factory-droid, mistral-vibe, copilot-cli), so
9509+ * `--clients=help` prints every token. A selector whose
95059510 * accepted values can only be learned from the source is not a usable
95069511 * selector, and an unrecognised token fails loudly with the list rather than
95079512 * silently configuring nothing. */
@@ -9549,10 +9554,40 @@ static void cli_clients_print_list(FILE *out) {
95499554 for (size_t i = 0; i < CLI_CLIENT_COUNT; i++) {
95509555 (void)fprintf(out, " %-16s %s\n", CLI_CLIENTS[i].token, CLI_CLIENTS[i].display);
95519556 }
9557+ for (size_t i = 0; i < cbm_agent_client_count(); i++) {
9558+ const cbm_agent_client_profile_t *profile = cbm_agent_client_at(i);
9559+ if (profile) {
9560+ (void)fprintf(out, " %-16s %s\n", profile->stable_id, profile->display_name);
9561+ }
9562+ }
95529563 (void)fprintf(out, "\nExample: --clients=claude,codex\n"
95539564 "Omit --clients to configure every detected client.\n");
95549565}
95559566
9567+ static bool cli_clients_spec_contains(const char *spec, const char *wanted_token) {
9568+ char buf[CLI_BUF_1K];
9569+ snprintf(buf, sizeof(buf), "%s", spec ? spec : "");
9570+ char *save = NULL;
9571+ for (char *tok = strtok_r(buf, ",", &save); tok; tok = strtok_r(NULL, ",", &save)) {
9572+ while (*tok == ' ') {
9573+ tok++;
9574+ }
9575+ size_t len = strlen(tok);
9576+ while (len > 0 && tok[len - 1] == ' ') {
9577+ tok[--len] = '\0';
9578+ }
9579+ if (strcmp(tok, wanted_token) == 0) {
9580+ return true;
9581+ }
9582+ }
9583+ return false;
9584+ }
9585+
9586+ static bool cli_clients_selects_registry_client(const char *spec, cbm_agent_client_id_t client_id) {
9587+ const cbm_agent_client_profile_t *profile = cbm_agent_client_by_id(client_id);
9588+ return profile && cli_clients_spec_contains(spec, profile->stable_id);
9589+ }
9590+
95569591/* Restrict `detected` to the comma-separated token list. Returns false (after
95579592 * printing the vocabulary) when a token is unknown, so a typo can never be
95589593 * mistaken for "that client was not installed". */
@@ -9581,6 +9616,9 @@ static bool cli_clients_apply_selection(const char *spec, cbm_detected_agents_t
95819616 break;
95829617 }
95839618 }
9619+ if (!matched) {
9620+ matched = cbm_agent_client_by_stable_id(tok) != NULL;
9621+ }
95849622 if (!matched) {
95859623 (void)fprintf(stderr, "error: unknown client: %s\n\n", tok);
95869624 cli_clients_print_list(stderr);
@@ -9606,6 +9644,9 @@ size_t cbm_cli_clients_count_for_testing(void) {
96069644const char *cbm_cli_clients_token_for_testing(size_t index) {
96079645 return index < CLI_CLIENT_COUNT ? CLI_CLIENTS[index].token : NULL;
96089646}
9647+ void cbm_cli_set_client_selection_for_testing(const char *spec) {
9648+ g_client_selection = spec;
9649+ }
96099650#endif
96109651
96119652/* ── Subcommand: install ──────────────────────────────────────── */
@@ -10018,7 +10059,7 @@ int cbm_cmd_install(int argc, char **argv) {
1001810059 }
1001910060 } else if (strcmp(argv[i], "--clients") == 0) {
1002010061 /* Bare `--clients` (and `--clients=help`/`list`) print the
10021- * vocabulary. 26 clients ship with tokens nobody would guess. */
10062+ * vocabulary, including tokens users would not readily guess. */
1002210063 cli_clients_print_list(stdout);
1002310064 return 0;
1002410065 } else if (strcmp(argv[i], "--skip-binary") == 0) {
0 commit comments