CyrusNuevoDia/skill-language-server
A language server for agent skills — /skill-name and $skill-name become real symbols - CyrusNuevoDia/skill-language-server
4 stars · 1 forks · 0 watchers
README
skill-language-server
Your skill library now has tooling.
completion w/ descriptions on / and $, plus client-aware frontmatter fields + values "did you mean" on typos; precise errors for frontmatter, names + unbalanced XML go to definition, find references + hover w/ name, description + path F2 rename w/ editor undo — folder, frontmatter name:, and every reference update as one edit local Markdown skill links: navigate, rename + safe broken-link fixes semantic highlighting on resolved references
Why Skills, CLAUDE.md/AGENTS.md, and agent files reference each other by name — a dependency graph with all the refactoring hazards of code and none of the tooling. Rename a skill by hand and stale references look like ordinary prose: nothing errors, the agent silently stops loading the skill. Quiet by design — a false reference in prose costs more than a missed one:
Fenced code blocks are never parsed; inline code spans are (that's how people write skill names in prose) /usr/bin, $PATH, docs/ — never references, never popups Near miss of a real skill (edit distance ≤ 2) → did you mean warning; other unresolved /name → info hint; unresolved $name → silent Built-in commands (/help, /compact, …) and your own .claude/commands/.codex/prompts are commands, not skills — never flagged
It's a language server, not a linter — pair with skill-lint or agnix for structural/security linting. Install Cursor / Antigravity / VSCodium · Zed · VS Code · Neovim · Helix · from source Once installed: cursor on any /skill-name, hit F2, type a new name — folder, frontmatter, and every reference update as one undo step. Cursor / Antigravity / VSCodium Install the extension — or cmd-shift-x → search Agent Skills Language Server. Same for Windsurf and anything else pointed at Open VSX. The extension bundles the server; nothing else to install. Zed Install the extension — or cmd-shift-x → search Skill Language Server. It fetches the server itself; nothing else to install. From a clone instead: command palette → zed: install dev extension → select ext/zed/. After server updates, editor: restart language server. VS Code Install the extension — or cmd-shift-x → search Agent Skills Language Server. The extension bundles the server; nothing else to install. Neovim (0.11+)
Install the server: npm install -g skill-language-server
Create ~/.config/nvim/lsp/skill-language-server.lua: return { cmd = { "skill-language-server", "--stdio" }, filetypes = { "markdown" }, root_markers = { ".claude", ".git" }, }
Add vim.lsp.enable("skill-language-server") to init.lua.
(Or from a clone, skipping steps 1–2: { dir = "/path/to/skill-language-server/ext/nvim" } in lazy.nvim.) Helix
Install the server: npm install -g skill-language-server
Add to languages.toml: [language-server.skill-language-server] command = "skill-language-server" args = ["--stdio"]
[[language]] name = "markdown" language-servers = ["skill-language-server"] # add e.g. "marksman" here if you use it
From source git clone https://github.com/CyrusNuevoDia/skill-language-server cd skill-language-server mise trust && mise install # bun, just (rust only for the Zed wasm) bun install just bin # → ~/.local/bin/skill-language-server (Neovim, Helix, Zed) For the VS Code–family editors, build and sideload the extension instead: just build-vscode code --install-extension dist/skill-language-server.vsix # or cursor / codium / … How it scans The server's world is the folder your editor opened — it never reads outside it. A rename touches exactly the tree you have open, never another checkout or your home directory. Open ~/.claude itself as a workspace to refactor your global library.
Skills = any **/skills/<name>/SKILL.md. Folder name is canonical; a disagreeing frontmatter name: is an error, not an alias References are scanned in .md files under .claude/, .agents/, .codex/, or skills/, plus every CLAUDE.md/AGENTS.md. Markdown elsewhere is never touched Live index where the editor supports LSP file watching; open buffers beat disk. Without watching, the index catches up on file open or restart .skillignore (gitignore syntax, workspace root) excludes paths from everything — ! negation re-includes, with git's usual rule that you can't re-include inside an excluded directory (dir/* + !dir/keep/ works; dir/ + !dir/keep/ doesn't) Multi-root workspaces: only the first folder is indexed
Cross-workspace renames are a deliberate two-step: rename where the skill lives, then open the other workspace — stale references surface as hints/warnings there. Blind spots: $ stragglers stay silent, and an old name that doubles as a built-in command reads as the built-in. Client compatibility Checked against client source as of 2026-07: VS Code, Zed, Helix, and Neovim all apply the folder RenameFile.
Neovim never sends willRenameFiles — explorer-drag renames don't rewrite references there; rename from a token or the frontmatter instead File watching: VS Code and Zed yes; Neovim yes except off by default on Linux; Helix only sees its own edits — reopen the file or restart the server after external changes
Development just fmt # ultracite fix --unsafe just check # tsc (server + VS Code extension) + ultracite lint + bun test just build # everything into dist/ — binary, .vsix, Zed wasm (wasm needs rust) The test suite is the contract: tests/helpers/harness.ts boots the real server over in-memory streams; tests/corpus.ts is the ground-truth reference set. Done = just check green. Three layers in src/: parse.ts (token grammar), workspace.ts (index), server.ts (LSP wiring). Editor shims in ext/{vscode,zed,nvim}. Releases via changesets: bun changeset with your change, merge to main, CI publishes. License MIT