Skip to main content
ProductivityRyan Robson4 min read

Teaching ccmcp Which Claude Code It's Running Against

Claude Code ships fast and quietly reshapes its own internals. My MCP manager used to bake those assumptions in as constants. v0.18.0 makes it detect the installed version and adapt.

Claude Code ships fast. New builds land most weeks, and every so often one quietly reshapes something underneath you — the on-disk layout, a settings key, a default model. Most of the time you never notice. But if you build tooling on top of Claude Code, those quiet changes are the whole problem.

I maintain ccmcp, a Go CLI and terminal UI for managing Claude Code's MCP servers and plugins. It reads and writes the same config files Claude Code does, lints your skills and agents against Claude Code's limits, and helps you keep a sprawling multi-project setup coherent. For most of its life it had a blind spot: it baked Claude Code's rules in as constants and code comments, with zero runtime awareness of which Claude Code was actually installed.

The skill-description character cap was pegged to a specific version by a comment. The model used for headless fixes was hardcoded in three different files. When I went looking for a claude --version check anywhere in the codebase, there wasn't one. The tool was guessing, and its guesses were frozen in time.

The fix is an idea, not a feature

Version 0.18.0 closes that blind spot, and the interesting part isn't any single capability — it's the shape of the solution.

Detect the installed version once. Resolve a capabilities bundle from it. Route every version-sensitive decision through that one bundle.

That constraint did more for the design than any individual line of code. When every version assumption has to flow through one resolver, you stop scattering magic numbers and start treating "which Claude Code is this?" as a first-class input.

What you actually get

  • It knows the version. ccmcp runs claude --version, caches the result keyed to the binary's modification time — so an upgrade is picked up immediately, but routine launches don't re-spawn a subprocess for nothing — and shows it as a · CC <ver> chip in the TUI header and a one-line note on ccmcp doctor. If claude isn't installed or the output is unparseable, it falls back to conservative defaults and never errors out. Best-effort, always.

  • The linter respects your settings. The skill-description cap now reads your actual skillListingMaxDescChars setting instead of a hardcoded number, so raising or lowering it no longer produces lint results that are simply wrong.

  • A new check catches a silent footgun. ccmcp doctor assets now flags a command that a same-named skill silently shadows — Claude Code runs the skill, so your command never fires, and nothing tells you. The interactive UI already surfaced this; now it's on the CI/lint surface too.

  • Model selection degrades gracefully. The headless fix/review model is resolved at runtime now, with a clear precedence — a --model flag, then a CCMCP_CLAUDE_MODEL environment variable, then a settings key, then the version-calibrated default. On recent Claude Code it also passes a fallback model, so if a model ID is ever retired, the flow recovers on its own instead of breaking.

I reviewed it like an adversary

Before tagging the release I ran the whole change through a recall-biased self-review — the kind where you're optimizing to catch bugs, not to feel good about the diff. It paid for itself.

It found a transient claude --version failure that would have cached an "unknown" result and pinned the tool to baseline behavior until the next upgrade changed the binary. It found a model override that resolved correctly but silently never applied on the default review path. It found a cache-write race between two ccmcp processes touching the same file. None of those would have shown up in a happy-path demo. All three are fixed, each with a regression test, and the suite sits at 374 passing tests.

That's the part I keep relearning as a solo developer: the bug that ships isn't usually the one you didn't think of. It's the one you thought about for four seconds and waved off. A review pass whose entire job is to be skeptical is worth more than any amount of confidence.

Get it

brew upgrade ccmcp
# first time:
brew install robworks-code/tap/ccmcp

It's open source — github.com/ringo380/ccmcp. The version-awareness layer lives in one small package, by design, so the next time Claude Code reshapes something underneath it, catching up is a single edit instead of an afternoon.

More in Productivity