diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000000..f44b5f3c24 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,15 @@ +{ + "name": "codebase-memory", + "description": "The codebase-memory-mcp code knowledge graph server, as a Claude Code plugin.", + "owner": { + "name": "DeusData", + "url": "https://github.com/DeusData" + }, + "plugins": [ + { + "name": "codebase-memory", + "source": "./plugin", + "description": "Codebase knowledge graph for AI agents: sub-ms queries, 99% fewer tokens." + } + ] +} diff --git a/.gitignore b/.gitignore index 1533c93e00..c388fa360f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,8 @@ Thumbs.db # MCP config (user-local, generated by install command) .mcp.json +# ...except the Claude Code plugin's server definition, which is published +!plugin/.mcp.json # MCP Registry auth tokens .mcpregistry_* diff --git a/README.md b/README.md index 1a83289eed..9b1ef59053 100644 --- a/README.md +++ b/README.md @@ -578,6 +578,30 @@ Working in a clone? Use `.` in place of the flake URL, e.g. `nix run .#codebase- You: "Install this MCP server: https://github.com/DeusData/codebase-memory-mcp" ``` +### Install via Claude Code plugin + +This repository is also a Claude Code plugin marketplace, so you can find and +add the server from inside Claude Code: + +```bash +claude plugin marketplace add DeusData/codebase-memory-mcp +claude plugin install codebase-memory@codebase-memory +``` + +The plugin registers the MCP server only. It starts the server with +`npx -y codebase-memory-mcp@`, pinned to the current release; the first +start downloads that release's binary through the npm package, which verifies +it against the release checksums. The skill, the three graph agents and the +context hooks are not part of the plugin: they come from +`codebase-memory-mcp install`. + +Use one or the other. `install` registers the same server for Claude Code, so +with both you run it twice, under two tool namespaces +(`mcp__codebase-memory-mcp__*` and +`mcp__plugin_codebase-memory_codebase-memory-mcp__*`). Choose `install` for the +full Claude Code setup; choose the plugin to add just the server without +running an installer. + ### Build from Source
diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json new file mode 100644 index 0000000000..0960a2b718 --- /dev/null +++ b/plugin/.claude-plugin/plugin.json @@ -0,0 +1,9 @@ +{ + "name": "codebase-memory", + "version": "0.12.1", + "description": "Codebase knowledge graph for AI agents: sub-ms queries, 99% fewer tokens.", + "author": { + "name": "DeusData", + "url": "https://github.com/DeusData" + } +} diff --git a/plugin/.mcp.json b/plugin/.mcp.json new file mode 100644 index 0000000000..07fbe13c1e --- /dev/null +++ b/plugin/.mcp.json @@ -0,0 +1,9 @@ +{ + "mcpServers": { + "codebase-memory-mcp": { + "type": "stdio", + "command": "npx", + "args": ["-y", "codebase-memory-mcp@0.12.1"] + } + } +} diff --git a/tests/test_version_metadata_contract.sh b/tests/test_version_metadata_contract.sh index b74203bf6b..54d7879442 100644 --- a/tests/test_version_metadata_contract.sh +++ b/tests/test_version_metadata_contract.sh @@ -109,6 +109,8 @@ SURFACES=( "pkg/chocolatey/tools/chocolateyInstall.ps1|release" "pkg/scoop/codebase-memory-mcp.json|release" "pkg/homebrew/Formula/codebase-memory-mcp.rb|release" + "plugin/.claude-plugin/plugin.json|release" + "plugin/.mcp.json|release" "pkg/aur/PKGBUILD|pin:0.8.1" "pkg/aur/.SRCINFO|pin:0.8.1" ) @@ -163,6 +165,12 @@ versions_in() { # cannot see it, because the version keyword is in the function NAME. grep -oE 'return "[0-9]+\.[0-9]+\.[0-9]+"' "$path" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' + # npm package-spec form: the Claude Code plugin launches the server as + # `npx -y codebase-memory-mcp@X.Y.Z`, and that pin is the version every + # plugin user actually runs. No declaration keyword sits next to it, so + # without this form plugin/.mcp.json reads as a surface with no claim. + grep -oE 'codebase-memory-mcp@[0-9]+\.[0-9]+\.[0-9]+' "$path" | + grep -oE '[0-9]+\.[0-9]+\.[0-9]+$' } | sort -u } @@ -280,7 +288,9 @@ fi # this contract exists to prevent, and every check above would still pass. The # sweep pattern is deliberately BROADER than the extractors in section 3: if the # two shared a regex, a claim form the extractors cannot see would be invisible -# to the sweep as well. +# to the sweep as well. The Claude Code plugin tree (plugin/, .claude-plugin/) is +# swept too: a later plugin file that pins `codebase-memory-mcp@X.Y.Z` (a hook +# command, say) must be registered here, or it would go stale unchecked. while IFS= read -r path; do [[ -z "$path" ]] && continue for entry in "${SURFACES[@]}"; do @@ -293,8 +303,8 @@ while IFS= read -r path; do "SURFACES so it stays in step with the release, or to EXEMPT with a" \ "note saying what its number actually is." done < <( - git grep -IlE '(version|pkgver|releases/(download|tag)/v)[^0-9]{0,16}[0-9]+\.[0-9]+\.[0-9]+|return "[0-9]+\.[0-9]+\.[0-9]+"' \ - -- server.json pkg tests/test_version_metadata_contract.sh 2>/dev/null || true + git grep -IlE '(version|pkgver|releases/(download|tag)/v)[^0-9]{0,16}[0-9]+\.[0-9]+\.[0-9]+|return "[0-9]+\.[0-9]+\.[0-9]+"|codebase-memory-mcp@[0-9]+\.[0-9]+\.[0-9]+' \ + -- server.json pkg plugin .claude-plugin tests/test_version_metadata_contract.sh 2>/dev/null || true ) if ((failures > 0)); then