# Better Claude Config (BCC) A small, cross-platform GUI for editing the `mcpServers` block of Claude Desktop and Claude Code installs — without ever hand-writing JSON. BCC only ever touches `mcpServers` (and its own `_disabledMcpServers` parking key). Every other key in your config is preserved verbatim, in its original order. Each write is atomic and makes a timestamped backup first. ## Download (no Python required) Pre-built self-contained binaries are attached to every [GitHub Release](../../releases): | Platform | Download | Run | |----------|----------|-----| | macOS | `BetterClaudeConfig-macOS.zip` | Unzip → drag **BetterClaudeConfig.app** to Applications | | Windows | `BetterClaudeConfig-Windows.zip` | Unzip → double-click **BetterClaudeConfig.exe** | | Linux | `BetterClaudeConfig-Linux.tar.gz` | Extract → run **BetterClaudeConfig** | > **macOS Gatekeeper note:** the app is not notarized. On first launch, right-click → **Open**, or run `xattr -cr /Applications/BetterClaudeConfig.app` in a terminal. ## Verifying your download BCC isn't code-signed — there's no budget for a paid certificate (macOS Developer ID, Windows Authenticode). Instead, every release publishes a `SHA256SUMS` file listing the checksum of each archive, detached-signed with Ed25519 as `SHA256SUMS.sig`. Both are attached to the release alongside the binaries. **What this proves:** the file you downloaded is byte-for-byte what we published, and the manifest itself was signed by our release key. **What this does NOT do:** it does not make the binary "safe," and it does **not** remove the macOS Gatekeeper or Windows SmartScreen warning — those are only suppressed by a paid OS-vendor certificate, which this project doesn't have. Verifying checksums is about detecting tampering in transit or on a mirror, not about vouching for the software. This manifest is signed with BCC's **release key**, which is a different key from the one that signs the MCP server catalog — see [Signing keys](#signing-keys) below for why, and for the public key value to use with `--pubkey-b64` below. ### macOS / Linux ```bash # From inside the folder you downloaded the release files into: sha256sum -c SHA256SUMS ``` If your `sha256sum` complains about missing files, download `SHA256SUMS` into the same directory as the archive you downloaded — it lists every platform's archive, and only the one(s) present will be checked. To also verify the manifest's signature (optional, requires Python + `pip install cryptography` and a checkout of this repo): ```bash python3 scripts/sign_checksums.py verify \ --sums SHA256SUMS --sig SHA256SUMS.sig \ --pubkey-b64 "" ``` ### Windows (PowerShell) ```powershell Get-FileHash .\BetterClaudeConfig-Windows.zip -Algorithm SHA256 ``` Compare the printed hash (case-insensitively) against the matching line in `SHA256SUMS`. ### If a release has no `SHA256SUMS.sig` The signing key is a repo secret that has to be configured manually; if a release is missing the `.sig` file, the checksums themselves are still valid and safe to check against — the release workflow only skips signing, never checksum generation. ## Signing keys BCC uses **two separate Ed25519 keypairs**, deliberately never the same key, because they protect different things and live in different places: | | Catalog key | Release key | |---|---|---| | Signs | `data/catalog.json` (the MCP server catalog every user's app trusts) | `SHA256SUMS` (the checksum manifest for release binaries) | | Verified by | `bcc_core.CATALOG_PUBKEYS` | `scripts/sign_checksums.RELEASE_PUBKEYS` | | Lives | Offline, passphrase-encrypted, maintainer's machine only (OS keychain or an encrypted file outside the repo — see the [Catalog Console](#files), issue #62) | A Gitea Actions repo secret, `RELEASE_SIGNING_KEY` — **intentionally CI-resident** | | Generated with | `python catalog_console.py keygen` | `python catalog_console.py keygen --release` | | Exported for CI with | *(never — there is no supported way to export this key)* | `python catalog_console.py show-seed-b64 --release` | **Why two keys:** the catalog key is the root of trust for what BCC actually *executes* on a user's machine — every `command`/`args` pair in the shipped catalog is only there because this key signed it. If that key and the release-checksum key were the same (as they briefly were — see [issue #68](../../issues/68)), then anything that can exfiltrate a Gitea Actions secret (a malicious workflow-file PR, a compromised runner, a leaky log) could sign a catalog every user's copy of BCC would trust, not just a checksum manifest. Splitting them means **a CI/secret compromise burns the release key, never the catalog key** — checksums for a future release could be forged, which is bad, but no attacker gains the ability to make BCC run arbitrary commands on installs that trust the catalog. That asymmetry is the entire point of having two keys instead of one. The catalog key is **never** meant to leave the maintainer's machine: it's generated, stored, unlocked, and used to sign entirely inside the Catalog Console (`catalog_console.py`), and `catalog_console.py show-seed-b64` refuses to run without `--release` specifically so the catalog seed can't be exported by habit or muscle memory. **Release signing public key** (Ed25519, base64, raw 32 bytes) — this is the RELEASE key, which signs `SHA256SUMS` (release checksums). It does **not** sign `data/catalog.json` and is not the key `bcc_core.CATALOG_PUBKEYS` trusts: ``` 6BnPgJEHJFyVltFoLTCNadIsehjy00iiW8IRlC1TfhA= ``` The catalog public key (Ed25519, base64, raw 32 bytes) — this is the key that signs `data/catalog.json` and is trusted via `bcc_core.CATALOG_PUBKEYS` and the CI trust anchor in `.github/workflows/ci.yml`. It is listed here for completeness, not because you need it to verify a download — use the *release* key above for that: ``` 0s24PmkZcTT5yxNDdyTPHl5fyxArrHNPJKBjnXoQd8k= ``` Both keys above were rotated 2026-07 — see [issue #68](../../issues/68) finding 5. The prior (shared) key is retired and is deliberately **not** kept in either trust list; retaining a burned key would defeat the point of rotating it. ## Run from source ```bash pip install -r requirements.txt python bcc.py ``` (Python 3.10+, PySide6 6.6+.) ## What it does - **Auto-discovers installs** — scans the platform's app-support folder for any `Claude*` directory (so `Claude` and `Claude-Work` both show up) **and** finds Claude Code's user-scope config at `~/.claude.json` (the file `claude mcp add` writes). Use **Add config…** to point at any other file manually — e.g. a project's `.mcp.json`. - **Form-based editing** — name, command, args (one per line), env vars, or for remote servers: URL, transport, and headers. No raw JSON. - **Paste JSON — even broken JSON** — drop in any snippet from an MCP doc (full `mcpServers` block, inner map, or a single bare server object); it's parsed and merged. The paste box parses as you type and auto-repairs the stuff docs and chat windows love to break: markdown fences, surrounding prose, comments, trailing or missing commas, smart quotes, single quotes, unquoted keys, and unclosed braces — and tells you exactly what it fixed before you commit. - **Drag & drop** a `.json` file onto the window to import servers from it. - **Copy to ▸** — copy the selected server straight into your *other* install. - **Active / Disabled sections** — servers are shown in two labelled lists with live counts, so a server that's switched off in the config is obvious at a glance. Toggle a server's checkbox to move it between sections (disabled servers are parked under `_disabledMcpServers`, which Claude ignores). - **Dependency check + diagnostics** — each server shows whether its `command` is actually found on PATH: - ● green — found on the normal PATH; will work anywhere. - ▲ amber (**PATH-risk**) — found, but *only* in a location BCC added on top of the inherited PATH. It'll work when you launch Claude from a terminal, but a double-clicked `.app` may not see it. This is the usual cause of "the tool says it's fine but Claude won't start the server." One click on **Use full path ↳** rewrites the bare command (`npx`) to its absolute path so any launch finds it. - ● red (**broken**) — not found anywhere. - ◆ blue — remote (url) server. **Test connection** does a live reachability check on a background thread (any HTTP response = reachable). Each section header shows a **broken / PATH-risk count badge**, and selecting a flagged server auto-opens a **Details** panel with a full, copy-pasteable report: which command resolved to what, tailored install hints, and the exact PATH that was searched (with `+` marking the dirs BCC added). **Re-check** re-scans PATH after you install something; **Copy diagnostics** grabs the whole report for a bug report. After saving, **restart that Claude install** for changes to take effect. ## Config locations it scans **Claude Desktop** | OS | Base it scans for `Claude*` | |---------|----------------------------------| | macOS | `~/Library/Application Support` | | Windows | `%APPDATA%` | | Linux | `~/.config` | **Claude Code** (all platforms): `~/.claude.json` (user scope). If servers are found parked in `~/.claude/settings.json` — where Claude Code ignores them — that file is also listed, marked *legacy*, so you can copy them over. ## Files - `bcc.py` — the GUI. - `bcc_core.py` — all the file/JSON/validation/dependency logic (no GUI deps). - `test_core.py` — unit suite for the core (`python test_core.py`). - `bcc.spec` — PyInstaller build spec (cross-platform). - `scripts/build_icons.py` — regenerates `icons/app.icns` and `icons/app.ico` from source PNGs. - `scripts/sign_checksums.py` — generates and Ed25519-signs the release `SHA256SUMS` manifest (see [Verifying your download](#verifying-your-download)). - `catalog_console.py` / `catalog_review.py` — **maintainer-only**, never shipped to users (excluded from `bcc.spec`; see `tests/test_catalog_console_packaging.py`). The Catalog Console: review + sign `data/catalog.json`, and generate/manage both signing keys (`keygen`, `keygen --release`) — see [Signing keys](#signing-keys). ## Building from source ```bash pip install -r requirements-dev.txt python scripts/build_icons.py # regenerate icons if needed pyinstaller bcc.spec # macOS → dist/BetterClaudeConfig.app # Windows → dist/BetterClaudeConfig.exe # Linux → dist/BetterClaudeConfig ``` Releases are built automatically by GitHub Actions (`.github/workflows/release.yml`) when a version tag is pushed: ```bash git tag v1.0.0 && git push --tags ``` ## Rebrand The accent color is one constant (`ACCENT`) at the top of `bcc.py`. ## License MIT — see [LICENSE](LICENSE).