| id | 132 |
|---|---|
| title | Package mdsmith LSP as a Claude Code plugin |
| status | ✅ |
| model | sonnet |
| summary | Ship a `.claude-plugin/marketplace.json` plus a plugin manifest declaring `lspServers` so Claude Code can install mdsmith from this repository and auto-spawn `mdsmith lsp` on `.md` files, exposing diagnostics, definitions, references, symbols, implementations, and call hierarchy to the agent without manual editor setup. |
Let a Claude Code user install mdsmith from this
repository with two standard /plugin commands.
First, register the catalog one-time with /plugin marketplace add jeduden/mdsmith. Then install the
plugin with /plugin install mdsmith-lsp@mdsmith.
After install, the agent sees Markdown diagnostics
inline after every edit. The agent can also use
go-to-definition, find references, symbol search,
and call hierarchy across the docs.
Claude Code's code intelligence bundles
LSP plugins for a fixed set of languages
(gopls-lsp, pyright-lsp, typescript-lsp, …).
Markdown is not on the list. The same docs note
that users can create their own LSP plugin
for languages outside the bundle.
Plan 121 shipped mdsmith lsp over stdio with
diagnostics and code actions. Plan 131 added the
six navigation methods Claude Code consumes
(documentSymbol, definition, implementation,
references, workspace/symbol, callHierarchy).
The server is wire-ready; only the Claude Code
discovery layer is missing. Today a user has to
hand-edit settings to spawn the binary.
- Committing per-platform
mdsmithbinaries inside the plugin repo. The plugin instead spawnsnpx -y -p @mdsmith/cli mdsmith lsp, leaning on the npm package shipped by plan 130 — first launch fetches the platform binary subpackage from npm and caches it locally. - Authoring tools (slash commands, agents, hooks). Scope is the LSP wiring only.
- Submitting to the official Anthropic marketplace.
This plan only ships a self-hosted marketplace
inside
jeduden/mdsmith; submission is a separate decision.
.claude-plugin/
marketplace.json # marketplace catalog at repo root
editors/
claude-code/
.claude-plugin/
plugin.json # plugin manifest with lspServers
README.md # install + binary prerequisite
vscode/ # existing VS Code extension
The marketplace at the repo root lists one plugin
sourced from ./editors/claude-code/. This mirrors
the per-editor split already in place under
editors/ and keeps the VS Code
extension untouched.
{
"$schema": "https://json.schemastore.org/claude-code-plugin-marketplace.json",
"name": "mdsmith",
"owner": {
"name": "Jan-Eric Duden",
"url": "https://github.com/jeduden"
},
"description": "Markdown linter for Claude Code via LSP",
"plugins": [
{
"name": "mdsmith-lsp",
"source": "./editors/claude-code",
"description": "Inline mdsmith diagnostics and Markdown navigation"
}
]
}The manifest uses the inline lspServers form so
the plugin ships in a single file. extensionToLanguage
maps both common Markdown extensions to the
markdown language identifier.
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "mdsmith-lsp",
"description": "Inline mdsmith diagnostics and Markdown navigation via LSP",
"homepage": "https://github.com/jeduden/mdsmith",
"repository": "https://github.com/jeduden/mdsmith",
"license": "MIT",
"keywords": ["markdown", "linter", "lsp"],
"lspServers": {
"mdsmith": {
"command": "npx",
"args": ["-y", "-p", "@mdsmith/cli", "mdsmith", "lsp"],
"extensionToLanguage": {
".md": "markdown",
".markdown": "markdown"
}
}
}
}npx is bundled with npm, which standard Node.js
installers ship and Claude Code already requires.
First launch downloads @mdsmith/cli plus the
platform binary subpackage (e.g.
@mdsmith/linux-x64) from npm and caches them; the
explicit -p @mdsmith/cli mdsmith form makes the
bin selection unambiguous. npx prepends its
package bin dir to the spawned command's $PATH,
so the package's mdsmith always wins regardless of
any system install. Users who want a pinned version
edit args to use @mdsmith/cli@<ver> in place of
@mdsmith/cli.
Two install paths, both standard Claude Code flows:
/plugin marketplace add jeduden/mdsmiththen/plugin install mdsmith-lsp@mdsmith(browse and install from the catalog).- Direct:
/plugin install mdsmith-lsp@mdsmithafter the marketplace is added.
After install, /reload-plugins activates the
server. Subsequent .md opens trigger
textDocument/didOpen and the diagnostics flow.
The plugin manifest is additive. The repo's existing VS Code extension, npm scripts, and CI are untouched. Users on other editors keep using the documented stdio invocation.
- Add
.claude-plugin/marketplace.jsonat the repository root with one plugin entry pointing to./editors/claude-code. - Add
editors/claude-code/.claude-plugin/plugin.jsondeclaring the inlinelspServersblock above. - Add
editors/claude-code/README.mdwith: install command, binary prerequisite, pointer to the install guide for the binary, troubleshooting (the sameExecutable not found in $PATHfailure mode the Claude Code docs warn about). - Add a "Claude Code" section to
docs/guides/install.mdlisting the two/plugincommands and linking to the new editor README. - No change to
.mdsmith.yml's
directory-structure.allowedlist is needed: the rule only applies to Markdown files, and the new.claude-plugin/tree contains JSON only.editors/**is already allowed, so the Markdown README undereditors/claude-code/does not need a separate entry either. Add a tight per-glob override underoverrides:foreditors/claude-code/**/*.md(line-length 72, max-file-length 80, paragraph-structure 3 sentences / 25 words, paragraph-readability 12, token-budget 2000) so the new plugin README stays terse. This change is config-touching, so surface the diff before applying per CLAUDE.md. - Validate the manifest locally with
claude plugin validate ./editors/claude-code(or/plugin validateinside an active Claude Code session). - Smoke-test end-to-end: in a scratch repo, run
/plugin marketplace add ./(pointing at a local clone),/plugin install mdsmith-lsp@mdsmith, open a.mdfile with a known violation, confirm the diagnostic appears in Claude Code's output, and confirm a navigation request (e.g.definitionon an anchor link) round-trips. - Add the plugin install path to
docs/reference/cli/lsp.mdalongside the existing VS Code pointer.
-
/plugin marketplace add jeduden/mdsmithregisters the marketplace without errors. -
/plugin install mdsmith-lsp@mdsmithinstalls the plugin to user scope. - After install and
/reload-plugins, opening a.mdfile with a known MDS rule violation surfaces the diagnostic to the agent (visible via Ctrl+O when the "diagnostics found" indicator appears). - After install, the agent can run
textDocument/definitionon an anchor link and receive the heading location. -
claude plugin validatereports no errors on the new manifests. -
mdsmith check .passes against the new.claude-plugin/marketplace.jsonlocation without any change todirectory-structure.allowed(the rule only fires on Markdown files, and the new tree contains JSON only). - When Node.js is absent from
$PATH, the/pluginErrors tab showsExecutable not found in $PATH(no silent hang, no generic crash).mdsmithitself is fetched via npx so its absence is no longer a failure mode. -
docs/guides/install.mddocuments the Claude Code install path and the binary prerequisite. -
mdsmith check .passes with the new files. - All tests pass:
go test ./....
- Marketplace location. Hosting under
jeduden/mdsmithgates discovery on the upstream repo. A separatejeduden/mdsmith-claude-pluginrepo would decouple plugin releases from binary releases but doubles the maintenance surface. Default to in-repo; revisit if release cadences diverge. - Plugin name collisions.
mdsmith-lspmatches the official plugin naming convention (<tool>-lsp). Confirm the name is unclaimed if the plugin is later submitted to the official Anthropic marketplace. - Binary version pinning. The plugin will use
whatever
mdsmithversion is on$PATH. If a future LSP capability requires a specific version, the plugin would need a version probe oninitialize. Out of scope here.