| 1530 | } |
| 1531 | |
| 1532 | int cbm_remove_codex_mcp(const char *config_path) { |
| 1533 | if (!config_path) { |
| 1534 | return CLI_ERR; |
| 1535 | } |
| 1536 | |
| 1537 | size_t len = 0; |
| 1538 | char *content = read_file_str(config_path, &len); |
| 1539 | if (!content) { |
| 1540 | return CLI_TRUE; |
| 1541 | } |
| 1542 | |
| 1543 | char *existing = strstr(content, CODEX_CMM_SECTION); |
| 1544 | if (!existing) { |
| 1545 | free(content); |
| 1546 | return CLI_TRUE; |
| 1547 | } |
| 1548 | |
| 1549 | char *section_end = existing + strlen(CODEX_CMM_SECTION); |
| 1550 | char *next_section = strstr(section_end, "\n["); |
| 1551 | if (next_section) { |
| 1552 | next_section++; |
| 1553 | } |
| 1554 | |
| 1555 | /* Remove leading newline if present */ |
| 1556 | if (existing > content && *(existing - CLI_SKIP_ONE) == '\n') { |
| 1557 | existing--; |
| 1558 | } |
| 1559 | |
| 1560 | size_t prefix_len = (size_t)(existing - content); |
| 1561 | const char *suffix = next_section ? next_section : ""; |
| 1562 | size_t suffix_len = strlen(suffix); |
| 1563 | size_t new_len = prefix_len + suffix_len; |
| 1564 | char *result = malloc(new_len + CLI_SKIP_ONE); |
| 1565 | if (!result) { |
| 1566 | free(content); |
| 1567 | return CLI_ERR; |
| 1568 | } |
| 1569 | memcpy(result, content, prefix_len); |
| 1570 | memcpy(result + prefix_len, suffix, suffix_len); |
| 1571 | result[new_len] = '\0'; |
| 1572 | |
| 1573 | int rc = write_file_str(config_path, result); |
| 1574 | free(content); |
| 1575 | free(result); |
| 1576 | return rc; |
| 1577 | } |
| 1578 | |
| 1579 | /* ── SessionStart reminder hook (Codex / Gemini / Antigravity) ────── |
| 1580 | * Same methodology as the Claude Code SessionStart hook: a non-blocking |
nothing calls this directly
no test coverage detected