@@ -7464,6 +7464,12 @@ static const char *detect_arch(void) {
74647464
74657465/* ── Agent config install/refresh (shared by install + update) ── */
74667466
7467+ /* Set by `install --clients=...` after validation and consumed by both the
7468+ * legacy detector and the registry-backed client path (#1558, #1798). */
7469+ static const char *g_client_selection = NULL;
7470+ static bool cli_clients_apply_selection(const char *spec, cbm_detected_agents_t *detected);
7471+ static bool cli_clients_selects_registry_client(const char *spec, cbm_agent_client_id_t client_id);
7472+ static void cli_clients_print_list(FILE *out);
74677473static void print_detected_registry_agents(const char *home, bool *any);
74687474
74697475/* Print detected agent names on a single line. */
@@ -8285,7 +8291,10 @@ static void print_detected_registry_agents(const char *home, bool *any) {
82858291 cbm_init_agent_registry_context(home, ®istry);
82868292 for (size_t index = 0U; index < cbm_agent_client_count(); index++) {
82878293 const cbm_agent_client_profile_t *profile = cbm_agent_client_at(index);
8288- if (profile && cbm_agent_client_detect(profile->id, ®istry.options)) {
8294+ if (profile &&
8295+ (!g_client_selection ||
8296+ cli_clients_selects_registry_client(g_client_selection, profile->id)) &&
8297+ cbm_agent_client_detect(profile->id, ®istry.options)) {
82898298 printf(" %s", profile->display_name);
82908299 *any = true;
82918300 }
@@ -8671,7 +8680,10 @@ static void install_agent_client_registry(const char *home, const char *binary_p
86718680 cbm_init_agent_registry_context(home, ®istry);
86728681 for (size_t index = 0U; index < cbm_agent_client_count(); index++) {
86738682 const cbm_agent_client_profile_t *profile = cbm_agent_client_at(index);
8674- if (!profile || !cbm_agent_client_detect(profile->id, ®istry.options)) {
8683+ if (!profile ||
8684+ (g_client_selection &&
8685+ !cli_clients_selects_registry_client(g_client_selection, profile->id)) ||
8686+ !cbm_agent_client_detect(profile->id, ®istry.options)) {
86758687 continue;
86768688 }
86778689 if (!g_install_plan) {
@@ -9545,13 +9557,6 @@ static void install_additional_agent_configs(const cbm_detected_agents_t *agents
95459557 }
95469558}
95479559
9548- /* #1558: set by `install --clients=...` after validation, consumed at the one
9549- * place detection happens. Validation runs in cbm_cmd_install so an unknown
9550- * token fails before anything is written, not midway through configuring. */
9551- static const char *g_client_selection = NULL;
9552- static bool cli_clients_apply_selection(const char *spec, cbm_detected_agents_t *detected);
9553- static void cli_clients_print_list(FILE *out);
9554-
95559560int cbm_install_agent_configs(const char *home, const char *binary_path, bool force, bool dry_run) {
95569561 g_agent_install_errors = 0;
95579562 cbm_detected_agents_t agents = cbm_detect_agents(home);
@@ -9679,9 +9684,9 @@ int cbm_install_handle_existing_indexes(const char *home, bool reset, bool dry_r
96799684 * Codex had to revert the OpenCode and Cursor integrations by hand, and the
96809685 * next install silently recreated them. `--clients=claude,codex` restricts it.
96819686 *
9682- * The table is the flag's vocabulary AND its documentation: 26 clients ship
9683- * here, with tokens nobody would guess (factory-droid, mistral-vibe,
9684- * copilot-cli), so `--clients=help` prints every token. A selector whose
9687+ * The tables are the flag's vocabulary AND its documentation, with tokens
9688+ * nobody would guess (factory-droid, mistral-vibe, copilot-cli), so
9689+ * `--clients=help` prints every token. A selector whose
96859690 * accepted values can only be learned from the source is not a usable
96869691 * selector, and an unrecognised token fails loudly with the list rather than
96879692 * silently configuring nothing. */
@@ -9730,10 +9735,40 @@ static void cli_clients_print_list(FILE *out) {
97309735 for (size_t i = 0; i < CLI_CLIENT_COUNT; i++) {
97319736 (void)fprintf(out, " %-16s %s\n", CLI_CLIENTS[i].token, CLI_CLIENTS[i].display);
97329737 }
9738+ for (size_t i = 0; i < cbm_agent_client_count(); i++) {
9739+ const cbm_agent_client_profile_t *profile = cbm_agent_client_at(i);
9740+ if (profile) {
9741+ (void)fprintf(out, " %-16s %s\n", profile->stable_id, profile->display_name);
9742+ }
9743+ }
97339744 (void)fprintf(out, "\nExample: --clients=claude,codex\n"
97349745 "Omit --clients to configure every detected client.\n");
97359746}
97369747
9748+ static bool cli_clients_spec_contains(const char *spec, const char *wanted_token) {
9749+ char buf[CLI_BUF_1K];
9750+ snprintf(buf, sizeof(buf), "%s", spec ? spec : "");
9751+ char *save = NULL;
9752+ for (char *tok = strtok_r(buf, ",", &save); tok; tok = strtok_r(NULL, ",", &save)) {
9753+ while (*tok == ' ') {
9754+ tok++;
9755+ }
9756+ size_t len = strlen(tok);
9757+ while (len > 0 && tok[len - 1] == ' ') {
9758+ tok[--len] = '\0';
9759+ }
9760+ if (strcmp(tok, wanted_token) == 0) {
9761+ return true;
9762+ }
9763+ }
9764+ return false;
9765+ }
9766+
9767+ static bool cli_clients_selects_registry_client(const char *spec, cbm_agent_client_id_t client_id) {
9768+ const cbm_agent_client_profile_t *profile = cbm_agent_client_by_id(client_id);
9769+ return profile && cli_clients_spec_contains(spec, profile->stable_id);
9770+ }
9771+
97379772/* Restrict `detected` to the comma-separated token list. Returns false (after
97389773 * printing the vocabulary) when a token is unknown, so a typo can never be
97399774 * mistaken for "that client was not installed". */
@@ -9762,6 +9797,9 @@ static bool cli_clients_apply_selection(const char *spec, cbm_detected_agents_t
97629797 break;
97639798 }
97649799 }
9800+ if (!matched) {
9801+ matched = cbm_agent_client_by_stable_id(tok) != NULL;
9802+ }
97659803 if (!matched) {
97669804 (void)fprintf(stderr, "error: unknown client: %s\n\n", tok);
97679805 cli_clients_print_list(stderr);
@@ -9787,6 +9825,9 @@ size_t cbm_cli_clients_count_for_testing(void) {
97879825const char *cbm_cli_clients_token_for_testing(size_t index) {
97889826 return index < CLI_CLIENT_COUNT ? CLI_CLIENTS[index].token : NULL;
97899827}
9828+ void cbm_cli_set_client_selection_for_testing(const char *spec) {
9829+ g_client_selection = spec;
9830+ }
97909831#endif
97919832
97929833/* ── Subcommand: install ──────────────────────────────────────── */
@@ -10204,7 +10245,7 @@ int cbm_cmd_install(int argc, char **argv) {
1020410245 }
1020510246 } else if (strcmp(argv[i], "--clients") == 0) {
1020610247 /* Bare `--clients` (and `--clients=help`/`list`) print the
10207- * vocabulary. 26 clients ship with tokens nobody would guess. */
10248+ * vocabulary, including tokens users would not readily guess. */
1020810249 cli_clients_print_list(stdout);
1020910250 return 0;
1021010251 } else if (strcmp(argv[i], "--skip-binary") == 0) {
0 commit comments