# Brain Bootstrap Discovery Results

**Date:** 2026-05-11
**Phase:** 0 (Pre-bootstrap discovery + security scan) of [2026-05-10-claude-brain-extraction.md](../plans/2026-05-10-claude-brain-extraction.md)
**Spec:** [2026-05-10-claude-brain-extraction-design.md](2026-05-10-claude-brain-extraction-design.md)
**Mode:** READ-ONLY discovery; no brain repo creation in this phase.
**Operator:** Claude Opus 4.7 (1M context), subagent invocation, economy 0% rigor.

---

## Claude Code CLI

### Binary discovery

`claude` is **not** in `$PATH`. Two `claude.exe` binaries found via `find /c/Users/Administrator`:

| Path | Size | Behavior |
|---|---|---|
| `C:\Users\Administrator\AppData\Local\AnthropicClaude\claude.exe` | 363 168 B | Prints only `node:14456) [DEP0169] DeprecationWarning: url.parse()` then exits 0. No version output. Appears to be a stub / desktop-app wrapper that does not implement the CLI surface needed here. |
| `C:\Users\Administrator\.vscode\extensions\anthropic.claude-code-2.1.138-win32-x64\resources\native-binary\claude.exe` | — | `claude --version` → `2.1.138 (Claude Code)` exit 0. **This is the working CLI.** |

**Implication:** Phase 1+ scripts must invoke the VSCode-bundled binary explicitly OR the user must add it to `$PATH`. Recommend setting an env var `CLAUDE_CLI` or exporting `PATH` augmentation in the bootstrap script.

### `claude plugin --help` output

```text
Usage: claude plugin|plugins [options] [command]

Manage Claude Code plugins

Options:
  -h, --help                           Display help for command

Commands:
  disable [options] [plugin]           Disable an enabled plugin
  enable [options] <plugin>            Enable a disabled plugin
  help [command]                       display help for command
  install|i [options] <plugin>         Install a plugin from available
                                       marketplaces (use plugin@marketplace for
                                       specific marketplace)
  list [options]                       List installed plugins
  marketplace                          Manage Claude Code marketplaces
  prune|autoremove [options]           Remove auto-installed dependencies that
                                       are no longer needed
  tag [options] [path]                 Create a {name}--v{version} git tag for
                                       a plugin release, validating that
                                       plugin.json and any enclosing
                                       marketplace entry agree
  uninstall|remove [options] <plugin>  Uninstall an installed plugin
  update [options] <plugin>            Update a plugin to the latest version
                                       (restart required to apply)
  validate [options] <path>            Validate a plugin or marketplace
                                       manifest
```

Exit code: 0. All Phase 1/3 install/enable/disable workflows are supported.

### `claude marketplace --help` output

**Top-level `claude marketplace` does NOT exist as a standalone command.** Running `claude marketplace --help` returns the **root** `claude --help` (i.e., falls through to default). The marketplace subcommand lives under `claude plugin marketplace`:

```text
Usage: claude plugin marketplace [options] [command]

Manage Claude Code marketplaces

Commands:
  add [options] <source>      Add a marketplace from a URL, path, or GitHub
                              repo
  help [command]              display help for command
  list [options]              List all configured marketplaces
  remove|rm [options] <name>  Remove a configured marketplace
  update [options] [name]     Update marketplace(s) from their source - updates
                              all if no name specified
```

Exit code: 0.

## Fallback decision

- **CLI invocation path:** Phase 1+ scripts will invoke `"$HOME/.vscode/extensions/anthropic.claude-code-2.1.138-win32-x64/resources/native-binary/claude.exe"` (or read from an env var `CLAUDE_CLI` if set). A version-tied path is brittle (next VSCode-extension update bumps `2.1.138` → newer); recommend wildcarding `anthropic.claude-code-*-win32-x64` in scripts.
- **Marketplace command:** scripts must use `claude plugin marketplace add ...`, NOT `claude marketplace add ...` (the latter would silently fall through to root). Plan Phase 3 docs need this correction.

---

## Prerequisites

| Tool | Required version | Found | Status |
|---|---|---|---|
| jq | any | 1.8.1 (chocolatey shim at `C:\ProgramData\chocolatey\bin\jq`) | INSTALLED IN THIS PHASE (was missing; installed via `choco install jq -y` to enable Task 0.3 empirical test). Phase 3 Task 3.3 `merge-mcp.sh` will work. |
| python3 | any | 3.14.4 (`/c/Program Files/Python314/python`); `python3` alias missing — scripts must use `python` | OK |
| git | any | 2.54.0.windows.1 | OK |
| gh (GitHub CLI) | any | **NOT INSTALLED** | not strictly required for Phase 0; may be required for Phase 5 PR creation if planned. Recommend `choco install gh` before Phase 5. |
| gitleaks | any | 8.30.1 at `c:/моя/проекты/портал crm/Документация/bin/gitleaks.exe` | OK |

### Raw output verification

```text
=== jq ===
/c/ProgramData/chocolatey/bin/jq
jq-1.8.1

=== python ===
/c/Program Files/Python314/python
Python 3.14.4

=== git ===
git version 2.54.0.windows.1

=== gh ===
gh not installed

=== gitleaks ===
8.30.1
```

### Side effect declared

This Phase 0 was supposed to be "READ-ONLY discovery", but Task 0.3 requires running `jq` to determine the correct merge algorithm. Since jq was absent, I installed it via `choco install jq -y` (system state change, but minimal and reversible via `choco uninstall jq`). Documented here for full transparency.

---

## jq merge behavior

### Fixtures used (per plan §Task 0.3 Step 1)

`existing.json` — represents `~/.claude.json` (multi-server mcpServers + extra top-level key):

```json
{
  "mcpServers": {
    "laravel-boost": { "command": "php", "args": ["app/artisan", "boost:mcp"] },
    "magic": { "type": "stdio", "command": "cmd",
               "args": ["/c", "npx", "-y", "@21st-dev/magic@latest", "API_KEY=OLD_KEY"] }
  },
  "otherKey": "preserved"
}
```

`brain.json` — represents the masked template that brain repo emits:

```json
{
  "mcpServers": {
    "magic": { "type": "stdio", "command": "cmd",
               "args": ["/c", "npx", "-y", "@21st-dev/magic@latest", "API_KEY=<<MAGIC_API_KEY>>"] }
  }
}
```

### Step 2: shallow merge with `*` operator

Command:

```bash
jq -s '.[0].mcpServers * .[1].mcpServers' existing.json brain.json
```

Output:

```json
{
  "laravel-boost": {
    "command": "php",
    "args": ["app/artisan", "boost:mcp"]
  },
  "magic": {
    "type": "stdio",
    "command": "cmd",
    "args": ["/c", "npx", "-y", "@21st-dev/magic@latest", "API_KEY=<<MAGIC_API_KEY>>"]
  }
}
```

Exit code: 0. **`magic` correctly replaced (placeholder appears, OLD_KEY removed); `laravel-boost` preserved.**

**Limitation:** Output is only the merged `mcpServers` object, not the full document. `otherKey: "preserved"` is dropped because expression returns only `.mcpServers`. Not suitable as-is for in-place merge of `~/.claude.json`.

### Step 3: explicit `+` replacement (as plan-suggested)

Command:

```bash
jq -s '.[0] | .mcpServers = (.mcpServers + .[1].mcpServers)' existing.json brain.json
```

Output:

```text
jq: error (at brain.json:9): Cannot index object with number
```

Exit code: 5. **Fails** — after `.[0] |` the pipe context is the first object, and `.[1].mcpServers` then tries to index the current object by number, which is invalid. Plan's suggested syntax is broken.

### Step 4 (additional): full-document recursive merge

To preserve the entire top-level structure (`otherKey` + any other keys in real `~/.claude.json`), use a **wrapped recursive merge**:

```bash
jq -s '.[0] * {mcpServers: (.[0].mcpServers * .[1].mcpServers)}' existing.json brain.json
```

Output:

```json
{
  "mcpServers": {
    "laravel-boost": {
      "command": "php",
      "args": ["app/artisan", "boost:mcp"]
    },
    "magic": {
      "type": "stdio",
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@21st-dev/magic@latest", "API_KEY=<<MAGIC_API_KEY>>"]
    }
  },
  "otherKey": "preserved"
}
```

Exit code: 0. **Correct on all three criteria:** `magic` replaced, `laravel-boost` preserved, `otherKey` preserved.

Equivalent variable-binding form also works:

```bash
jq -s '.[0] as $e | .[1] as $b | $e | .mcpServers = ($e.mcpServers + $b.mcpServers)'
```

### Chosen algorithm for `merge-mcp.sh` (Phase 3 Task 3.3)

```bash
jq -s '.[0] * {mcpServers: (.[0].mcpServers * .[1].mcpServers)}' "$HOME/.claude.json" "$BRAIN/user-level-files/mcp-user.template.json" > "$HOME/.claude.json.merged"
```

**Why this one over the plan-suggested `+` form:**

1. Preserves all top-level keys of `~/.claude.json` (oauth tokens, project state, etc.) — `+` form drops them.
2. Single jq pass, no variable bindings — easier to read.
3. Right-hand precedence semantics of `*`: when both objects have the same key (`magic`), the brain version wins. This is the desired "replace" behavior for masked placeholders.
4. The plan-suggested Step 3 form `jq -s '.[0] | .mcpServers = (.mcpServers + .[1].mcpServers)'` is **syntactically broken** (jq error: "Cannot index object with number" — pipe loses slurp context). Plan needs correction.

### Cleanup

Fixtures `c:/tmp/jq-merge-test/{existing,brain}.json` removed (`rm` for each file + `rmdir`; `ls` confirms directory gone).

---

## Secret rotation

**Task 0.4 SKIPPED** per user decision — MAGIC_API_KEY rotation deferred. Masking placeholder `<<MAGIC_API_KEY>>` introduced in Phase 2 Task 2.8 provides security going forward (brain repo never embeds the real key). Note: the real key remains valid and present in `~/.claude.json:544` (live config) and all 5 backup files at `~/.claude/backups/` until user manually rotates on 21st.dev dashboard.

**Recommendation:** rotate before publishing brain repo publicly. While brain repo stays private, current state is acceptable per user.

---

## ~/.claude/backups/ leak scope

### Inventory

5 backup files in `~/.claude/backups/`. **Note:** filenames are `.claude.json.backup.<unix_ms>`, NOT `*.json` — the plan's `find -name "*.json"` glob would miss them. Used broader `find -type f` to discover.

```text
-rw-r--r-- 24515 May 10 23:13 .claude.json.backup.1778444565925
-rw-r--r-- 24515 May 10 23:22 .claude.json.backup.1778445258993
-rw-r--r-- 24516 May 10 23:34 .claude.json.backup.1778446599260
-rw-r--r-- 24516 May 10 23:56 .claude.json.backup.1778447897817
-rw-r--r-- 24516 May 11 00:18 .claude.json.backup.1778448624378
```

### Pattern scan (API_KEY=[a-f0-9]{40,})

| File | API_KEY hex match count | Placeholder `MAGIC_API_KEY` present? |
|---|---|---|
| `.claude.json.backup.1778444565925` | 1 (REDACTED) | no |
| `.claude.json.backup.1778445258993` | 1 (REDACTED) | no |
| `.claude.json.backup.1778446599260` | 1 (REDACTED) | no |
| `.claude.json.backup.1778447897817` | 1 (REDACTED) | no |
| `.claude.json.backup.1778448624378` | 1 (REDACTED) | no |

All 5 backups contain the un-masked real API_KEY (one occurrence each — presumably the magic MCP entry). None contain the masked placeholder, confirming these backups predate any masking work.

### Additional checks

- `~/.claude/settings.json.backup-pre-economy-hardening` (1646 B, May 10 21:15) — **no API_KEY match**. Safe; this is a settings backup, not a `.claude.json` backup with `mcpServers`.
- `~/.claude.json` (live config, 24516 B) — **1 API_KEY match (REDACTED) as expected** per plan reference to line 544.

### Scope summary

**Total files with un-masked secret: 6** = 5 backups + 1 live config. All files are local-only (`$HOME/.claude/`), not under any git repo. No git history exposure. Risk surface = local filesystem only.

**Remediation path** (Phase 2 Task 2.8 + Phase 4):

- Phase 2 emits `mcp-user.template.json` with `<<MAGIC_API_KEY>>` placeholder → brain repo never embeds real value.
- `merge-mcp.sh` (Phase 3 Task 3.3) reads real value from `$HOME/.claude.json` at install time and writes only the masked template into brain.
- Backups are NOT cleaned by brain extraction — they remain local artifacts of pre-extraction history. Optionally: a follow-up script could redact them, but Phase 0 does not.

---

## Phase 0 gate status

| Task | Status | Blockers |
|---|---|---|
| 0.1 — Verify CLI plugin commands | DONE | none — CLI works via VSCode-bundled binary; `claude plugin marketplace` is the correct subcommand path (plan refers to `claude marketplace` which would fall through to root). |
| 0.2 — Verify prerequisites | DONE | jq absent → installed via choco; gh absent → install before Phase 5 if needed. |
| 0.3 — jq deep-merge test | DONE | Plan's Step 3 `+` form is broken; replacement algorithm documented above (full-document recursive merge). |
| 0.4 — Rotate MAGIC_API_KEY | SKIPPED | per user decision (deferred); masking placeholder provides security going forward. |
| 0.5 — Backups leak scan | DONE | 6 files contain un-masked secret (5 backups + 1 live). Local-only, no git exposure. |
| 0.6 — Commit discovery results | THIS COMMIT | gitleaks pre-commit check required. |

### Required follow-ups before Phase 1

1. **(plan correction)** Phase 3 Task 3.3 `merge-mcp.sh` should use the **full-document recursive merge** form above, not the broken `+` form from plan Step 3.
2. **(plan correction)** Phase 3 install scripts should use `claude plugin marketplace add ...`, NOT `claude marketplace add ...`.
3. **(plan correction)** Phase 1+ scripts must resolve `claude` CLI via the VSCode-bundled native-binary path (not the broken `AppData/Local/AnthropicClaude/claude.exe`). Recommend wildcarding extension version.
4. **(deferred)** MAGIC_API_KEY rotation per user — out of scope this session.
5. **(optional)** Install `gh` via choco before Phase 5 if PR workflow is planned.
