# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash # Install runtime dependency pip install -r requirements.txt python bcc.py # run the GUI # Test & lint (no GUI / PySide6 needed — tests only exercise bcc_core) pip install -r requirements-dev.txt python -m pytest # unit tests in tests/ ruff check . # lint ruff format . # format (CI enforces ruff format --check) # Build a self-contained binary python scripts/build_icons.py # regenerate icons/app.icns + icons/app.ico if needed pyinstaller bcc.spec # macOS → dist/BetterClaudeConfig.app # Windows → dist/BetterClaudeConfig.exe # Linux → dist/BetterClaudeConfig ``` Requires Python 3.10+. Runtime dependency: `PySide6>=6.6`. Tooling config (ruff, pytest, project metadata) lives in `pyproject.toml`. CI (`.github/workflows/ci.yml`) runs lint + tests on every push/PR; releases build on tag push (`release.yml`). ## Architecture The codebase is split into two layers: **`bcc_core.py`** — All logic with no GUI imports. Contains: - `Profile` / `ServerEntry` dataclasses (the data model) - `discover_profiles()` — scans the platform's app-support directory for `Claude*` folders (Claude Desktop) **and** always adds `~/.claude.json` (Claude Code user scope — what `claude mcp add` writes). `~/.claude/settings.json` is NOT a server config (it rejects `mcpServers` with a schema error) and is only surfaced, labelled legacy, if servers are found parked in it. Project-scope `.mcp.json` files can be opened via Add config… - `load_config` / `extract_servers` / `apply_servers` / `write_config` — the read/write pipeline; writes are atomic with rotating timestamped backups in `.bcc_backups/` - `parse_pasted_json()` / `parse_pasted_json_verbose()` — accepts three JSON shapes (full config, inner map, or bare server object). Input does not have to be valid JSON: `repair_json_text()` auto-fixes markdown fences, surrounding prose, `//` `/* */` `#` comments, trailing/missing commas, smart quotes, single quotes, unquoted keys, Python/JS literals, and unclosed braces. The verbose variant also returns human-readable notes describing every repair applied (shown live in the paste dialog) - `check_dependency()` / `diagnostics_text()` / `pin_command_path()` — PATH resolution logic; distinguishes "found on normal PATH" (ok) vs "found only on augmented PATH" (warn) vs "not found" (missing). Uses an `lru_cache`-memoized `augmented_path()` that extends the inherited PATH with common runtime locations (nvm, homebrew, cargo, volta, etc.) - `test_remote()` — synchronous HTTP reachability check, intended to run off the UI thread **`bcc.py`** — PySide6 GUI that is a thin shell over `bcc_core`. Key classes: - `MainWindow` — manages the profile combo, two server tables (active/disabled), action bar, and dirty state - `ServerEditor` — right-panel form with a `QStackedWidget` for stdio vs remote pages; calls `core.check_dependency()` on every field change - `KeyValueTable` — reusable widget for env vars and headers - `ConnTester(QThread)` — background thread for remote reachability tests **The cardinal rule**: `apply_servers()` only ever writes to `mcpServers` and `_disabledMcpServers`. All other keys in the user's config are preserved verbatim and in their original order. Disabled servers are parked under `_disabledMcpServers` (which Claude Desktop ignores) so they can be re-enabled without losing their definition. ## Packaging - **`bcc.spec`** — PyInstaller spec; handles macOS (onedir → `.app` bundle) and Windows/Linux (onefile). Platform-aware icon selection. - **`icons/app.icns`** (macOS) and **`icons/app.ico`** (Windows) are pre-generated and committed; source PNGs are in `icons/twin-gears/rounded/`. - **`scripts/build_icons.py`** — regenerates both icon files from source PNGs. Uses `iconutil` (macOS-only) for `.icns`, Pillow for `.ico`. - **`.github/workflows/release.yml`** — builds on all three platforms on tag push, publishes as GitHub Release assets. To release: `git tag vX.Y.Z && git push --tags`. ## Key constants - `ACCENT` at the top of `bcc.py` — the one constant to change for a rebrand - `KNOWN_FIELDS` in `bcc_core.py` — fields the editor renders; anything else on a server object is preserved as `_extra` in `ServerEditor` - `DISABLED_KEY = "_disabledMcpServers"` — the parking key for disabled servers - `MAX_BACKUPS = 15` — rolling backup limit per config file