autozimu/LanguageClient-neovim
Language Server Protocol (LSP) support for vim and neovim.
Slowing — last commit 8mo ago
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 8mo ago; Scorecard "Branch-Protection" is 0/10
- ⚠Slowing — last commit 8mo ago
- ⚠Concentrated ownership — top contributor handles 60% of recent commits
- ⚠Scorecard: default branch unprotected (0/10)
- ✓Last commit 8mo ago
- ✓18 active contributors
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
What would improve this?
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Computed from maintenance signals — commit recency, contributor breadth, bus factor, license, CI, tests, cross-checked against OpenSSF Scorecard
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Safe to depend on" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/autozimu/languageclient-neovim)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card
This card auto-renders when someone shares https://repopilot.app/r/autozimu/languageclient-neovim on X, Slack, or LinkedIn.
Ask AI about autozimu/languageclient-neovim
Grounded in the actual source code. Pick a starter question or write your own.
Onboarding doc
Onboarding: autozimu/LanguageClient-neovim
Generated by RepoPilot · 2026-06-24 · Source
🎯Verdict
WAIT — Slowing — last commit 8mo ago
- Last commit 8mo ago
- 18 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 8mo ago
- ⚠ Concentrated ownership — top contributor handles 60% of recent commits
- ⚠ Scorecard: default branch unprotected (0/10)
<sub>Computed from maintenance signals — commit recency, contributor breadth, bus factor, license, CI, tests, cross-checked against OpenSSF Scorecard</sub>
⚡TL;DR
LanguageClient-neovim is a Language Server Protocol (LSP) client for Vim and Neovim that enables IDE-like features (completion, diagnostics, rename, goto definition, code actions) by communicating with external language servers. It bridges the gap between editor and language-specific servers like Rust's RLS, enabling non-blocking async features like real-time linting, symbol navigation, and refactoring across 22+ programming languages. Hybrid Rust/Vim/Python architecture: Core LSP client logic is in Rust (src/ implied, main binary compiled and installed via install.sh), Vim scripting layer in plugin/ and autoload/ (LanguageClient.vim, LSP.vim) exposes commands and keybindings, Python3 rplugin/ integrations (denite sources, deoplete sources) provide UI for completion, symbols, code actions. Config flows through g:LanguageClient_serverCommands in .vimrc.
👥Who it's for
Vim and Neovim users who want IDE capabilities without heavy editor overhead—particularly developers working in Rust, Python, Java, and other LSP-supporting languages who prefer keyboard-driven workflows and want tight integration with language-specific tooling via the standardized LSP protocol.
🌱Maturity & risk
UNMAINTAINED and deprecated. The project explicitly states in README.md that it is no longer actively maintained and users should migrate to Neovim's native LSP client. No recent commits are visible, and issues/PRs are not reviewed. It served as a bridge solution before Neovim built LSP support natively.
Critical risk: project is officially unmaintained with no active governance. Rust dependencies are locked to 2020-era versions (jsonrpc-core 15, lsp-types 0.83, notify 4.x), creating potential security and compatibility gaps. The Python3 rplugin layer (denite, deoplete integrations) depends on external completion frameworks that have their own maintenance burdens. Migration path off this codebase is strongly recommended.
Active areas of work
Nothing—the project is in maintenance-only or abandoned state. The branch 'next' (referenced in install instructions) was the last active development branch. CHANGELOG.md and TODO.md exist but appear frozen. No active CI beyond legacy CircleCI and Travis configurations.
🚀Get running
Clone the 'next' branch: git clone --branch next https://github.com/autozimu/LanguageClient-neovim.git. Run bash install.sh to compile the Rust binary. Add the vim-plug declaration to your .vimrc with 'do': 'bash install.sh' post-install hook. Set g:LanguageClient_serverCommands to point to your language servers (e.g., rustup, pyls, gopls). Test with :LanguageClientStart in a buffer.
Daily commands:
This is not a runnable service—it's a Vim plugin. After bash install.sh compiles the binary: Open Neovim, ensure g:LanguageClient_serverCommands is configured (e.g., {'rust': ['rls'], 'python': ['pyls']}), open a file in a supported language, and call :LanguageClientStart. Commands like :call LanguageClient#textDocument_hover() trigger LSP methods. See doc/LanguageClient.txt for command reference.
🗺️Map of the codebase
src/main.rs— Entry point for the LSP client daemon; initializes the RPC server and message loop that handles all vim/neovim communication.src/language_client.rs— Core LSP client logic managing server lifecycle, message routing, and state for all language servers.src/rpchandler.rs— Handles incoming RPC calls from vim/neovim and dispatches them to appropriate handlers; critical for request/response flow.src/rpcclient.rs— RPC communication layer with language servers; manages JSON-RPC protocol encoding/decoding and message transport.src/language_server_protocol.rs— LSP protocol type definitions and message structures; defines the contract between client and language servers.plugin/LanguageClient.vim— Vim plugin entry point; provides user-facing commands and integrations with vim/neovim UI.Cargo.toml— Rust project manifest defining all dependencies and build configuration for the LSP client.
🧩Components & responsibilities
- Vim Plugin (VimL) (VimL, msgpack-rpc) — User-facing commands, keymaps, UI integration (signs, highlights, popups); RPC client to daemon.
- Failure mode: If plugin fails to
🛠️How to make changes
Add Support for a New Language Server
- Define language server command and default initialization options in .vim/settings.json (
.vim/settings.json) - Add language server entry to server_command.rs and implement command resolution logic (
src/config/server_command.rs) - If language-specific features are needed, create new extension file in src/extensions/ (e.g., src/extensions/mylang.rs) (
src/extensions/mod.rs) - Register the extension module in src/extensions/mod.rs and wire it into LanguageClient (
src/language_client.rs)
Add a New Language-Specific Custom Handler
- Create or edit the language extension file (e.g., src/extensions/rust_analyzer.rs) (
src/extensions/rust_analyzer.rs) - Implement custom notification or request handler using the extension trait pattern (
src/language_client.rs) - Register handler in LanguageClient::handle_server_message or handle_server_request (
src/rpchandler.rs)
Add a New Vim/Neovim User Command
- Add command definition in plugin/LanguageClient.vim under the command section (
plugin/LanguageClient.vim) - Implement the command handler in autoload/LanguageClient.vim (
autoload/LanguageClient.vim) - Route the command to the Rust backend via RPC by calling LanguageClient_*() functions (
src/rpchandler.rs)
Add a New LSP Feature Handler
- Add message type or method constant to src/language_server_protocol.rs (
src/language_server_protocol.rs) - Implement handler logic in src/language_client.rs using handle_request or handle_notification patterns (
src/language_client.rs) - Register the handler in src/rpchandler.rs to route incoming requests appropriately (
src/rpchandler.rs) - Add corresponding vim command in plugin/LanguageClient.vim if user-facing integration is needed (
plugin/LanguageClient.vim)
🔧Why these technologies
- Rust — Performance-critical RPC daemon needs low-latency message handling and async I/O; Rust provides memory safety without GC overhead.
- JSON-RPC 2.0 — LSP specification mandate; standard protocol for editor-server communication ensures interoperability with any LSP-compliant language server.
- VimL + Python3 — Vim/Neovim native plugin interface; VimL for commands/UI, Python for denite/deoplete integration with plugin ecosystem.
- Tokio/Async I/O — Multiplexing many concurrent language server connections requires non-blocking I/O; Tokio provides efficient async runtime.
⚖️Trade-offs already made
-
Separate Rust daemon process instead of pure VimL/Python
- Why: VimL/Python too slow for low-latency LSP operations; Rust daemon enables sub-100ms completion and hover requests.
- Consequence: Adds process management complexity; requires binary build and installation; but enables production-grade performance.
-
Single daemon managing multiple servers and clients
- Why: Centralized state management and coordination; shared resource pools reduce overhead.
- Consequence: One daemon crash affects all language servers; requires robust error handling and recovery; but reduces per-server memory/CPU.
-
Synchronous RPC calls to vim/neovim from daemon
- Why: Simplifies request-response semantics; vim msgpack-rpc is synchronous.
- Consequence: Blocking daemon on slow vim operations; could cause perceived LSP latency if vim is slow, but vim calls are typically fast.
🚫Non-goals (don't propose these)
- Not a general-purpose Rust LSP library; tightly coupled to vim/neovim UI
- Does not implement DAP (Debug Adapter Protocol); focused solely on LSP
- Does not provide built-in language server binaries; users must install servers separately
- Not intended for real-time collaborative editing scenarios
- Does not support remote LSP servers over network (only local processes)
🪤Traps & gotchas
- Branch confusion: Instructions reference 'next' branch, but master exists too (Python-only legacy). Using wrong branch will not compile. 2. Server command format: g:LanguageClient_serverCommands must point to executable language servers (rls, pyls, etc.) installed separately—plugin does not bundle these. Missing or incorrectly pathed servers silently fail. 3. Async dispatch: Python3 rplugin requires Python 3 support compiled into Neovim (
has('python3')must be true); falls back to sync mode if absent, causing UI freezing. 4. Editor version lock: Code assumes neovim or vim with python3 and plugin/rplugin support; very old versions will not work. 5. No tests: Cargo.toml has no [dev-dependencies] section visible; no test suite, so changes risk silent breakage.
🏗️Architecture
💡Concepts to learn
- Language Server Protocol (LSP) — LSP is the standardized protocol this entire project is built around—understanding the request/response lifecycle (textDocument/hover, textDocument/references, etc.) is essential to understanding what LanguageClient-neovim does.
- JSON-RPC 2.0 — LSP is implemented over JSON-RPC; the codebase uses jsonrpc-core to serialize/deserialize messages. Understanding request IDs, batch calls, and async responses is critical for debugging protocol flow.
- Neovim Remote Plugins (rplugin) — The Python3 rplugin system allows the Vim plugin to dispatch work to background Python processes; denite and deoplete integrations use this for non-blocking UI. Understanding how rplugin works is needed to modify or extend UI features.
- Stdin/Stdout Process Communication — The Rust binary communicates with language servers via pipes (stdin/stdout), not sockets. Understanding stream buffering, line-based vs. content-length protocols, and message framing is essential for debugging protocol failures.
- Vim Script Channel & Job API — The autoload/LanguageClient.vim layer uses Vim's job and channel APIs to spawn the Rust binary and read responses asynchronously. Debugging any integration issue requires understanding these APIs.
- Denite Source Plugin Interface — To add new symbol search, reference lookup, or code action UIs, you must implement the denite source protocol (rplugin/python3/denite/source/ directory). Understanding the gather() and define_syntax() hooks is required.
🔗Related repos
neovim/nvim-lspconfig— Neovim's native built-in LSP client and configuration layer—the official successor that made LanguageClient-neovim obsolete.vim-lsp/vim-lsp— Pure Vim script LSP client for Vim 8+; similar problem domain but targets stock Vim without Python, offering an alternative lightweight path.prabirshrestha/async.vim— Async execution library for Vim that LanguageClient-neovim likely depends on indirectly for non-blocking I/O; foundational for Vim LSP tooling.Shougo/deoplete.nvim— Completion framework that LanguageClient-neovim plugs into via rplugin/python3/deoplete/sources; users integrate the two together.Shougo/denite.nvim— Fuzzy finder and UI framework for symbol search, references, and code actions; LanguageClient-neovim provides denite sources for LSP queries.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for LSP server communication (src/rpcclient.rs and src/rpchandler.rs)
The repo lacks dedicated tests for the core RPC communication layer. Given that rpcclient.rs and rpchandler.rs are critical for LSP protocol handling, adding integration tests would catch regressions in message serialization, error handling, and protocol compliance. This is especially important since the project is unmaintained and needs defensive testing.
- [ ] Create tests/rpc_integration_test.rs with mock LSP server scenarios
- [ ] Test JSON-RPC request/response cycles in src/rpcclient.rs
- [ ] Test error handling and malformed message scenarios in src/rpchandler.rs
- [ ] Add tests for crossbeam channel communication between RPC threads
- [ ] Update Cargo.toml dev-dependencies if needed (e.g., add mockall or similar)
Migrate CI from CircleCI and Travis to GitHub Actions workflow
The project still uses outdated .circleci/config.yml and .travis.yml configurations. GitHub Actions is now the standard for GitHub-hosted projects and would provide better integration with the existing .github/ISSUE_TEMPLATE directory. This modernizes the CI/CD pipeline without adding new infrastructure.
- [ ] Create .github/workflows/ci.yml with Rust build, test, and lint jobs (replacing .circleci and .travis.yml logic)
- [ ] Add separate workflow .github/workflows/release.yml that runs cargo build and uses the package.metadata.release configuration
- [ ] Ensure the workflow tests against both vim and neovim environments (reference ci/install.sh and ci/script.sh)
- [ ] Add workflow status badges to README.md pointing to GitHub Actions
- [ ] Remove or deprecate .circleci/config.yml and .travis.yml files
Add unit tests for language server extensions (src/extensions/*.rs)
The extensions directory (clangd.rs, gopls.rs, java.rs, rust_analyzer.rs) contains server-specific configuration logic but appears to lack dedicated tests. These extensions are critical for proper LSP initialization and language-specific behavior. Testing them would prevent subtle bugs when users configure different language servers.
- [ ] Create tests/extensions_test.rs to test src/extensions/mod.rs configuration loading
- [ ] Add tests for rust_analyzer.rs initialization and custom capabilities
- [ ] Add tests for gopls.rs workspace initialization
- [ ] Add tests for clangd.rs argument parsing
- [ ] Add tests for java.rs classpath and project configuration handling
- [ ] Include tests for missing or misconfigured server scenarios
🌿Good first issues
- Add test coverage for autoload/LanguageClient.vim functions: the Vim script layer has no unit tests despite being the primary integration point. Start with test cases for the JSON-RPC marshaling functions (likely in the autoload/ directory).
- Document the Python3 rplugin architecture in doc/LanguageClient.txt: the interaction between denite/deoplete sources and the core Rust binary is undocumented, causing confusion for contributors wanting to add new UI sources.
- Create a Makefile target for local testing (e.g.,
make test-local) that spins up a minimal Neovim instance with a test language server (like a mock pyls) and validates hover, completion, and goto-definition flows end-to-end. Currently all testing is manual.
⭐Top contributors
Click to expand
Top contributors
- @martskins — 60 commits
- @autozimu — 18 commits
- @dependabot[bot] — 3 commits
- @jcavar — 2 commits
- @rski — 2 commits
📝Recent commits
Click to expand
Recent commits
103a881— Add project status note to readme (martskins)cf6dd11— Bump crossbeam-deque from 0.7.3 to 0.7.4 (dependabot[bot])fd4380b— Bump crossbeam-channel from 0.4.3 to 0.4.4 (dependabot[bot])f912679— Bump regex from 1.3.9 to 1.5.5 (dependabot[bot])a42594c— (cargo-release) version 0.1.161 (martskins)1f0ff21— Fix workspace/configuration support on intialize call (#1171) (martskins)8010205— Add support to specify server name and initialization options in server command (#1116) (martskins)7892d85— Add Gitter badge (#1168) (gitter-badger)6b05cb4— Grammar updates (#1166) (jcavar)2251fc4— Fix typos in doc/LanguageClient.txt (#1167) (gaeulbyul)
🔒Security observations
The LanguageClient-neovim codebase has moderate security concerns. Primary risks include: (1) unmaintained status with outdated dependencies that will not receive security patches, (2) potential supply chain vulnerabilities through installation scripts, and (3) older dependency versions with known CVEs. The Rust-based implementation is generally safer than the legacy Python version, but the lack of active maintenance is the most critical issue. The project should either be archived with clear migration guidance or actively maintained with regular dependency updates and security audits. Users should be cautious about relying on this project in production environments without additional security measures.
- Medium · Outdated and Vulnerable Dependencies —
Cargo.toml - [dependencies] section. Several dependencies are pinned to older versions with known vulnerabilities. Notably: log4rs (0.x without specific version), clap 2.x (outdated), crossbeam 0.7.3 (outdated), jsonrpc-core 15 (outdated), and lsp-types 0.83 (outdated). These versions may contain known CVEs. Fix: Update all dependencies to their latest stable versions. Run 'cargo update' and review security advisories via 'cargo audit'. Consider using cargo-deny for dependency scanning in CI/CD. - Medium · Unmaintained Project with Active Dependencies —
README.md, Cargo.toml. The project is explicitly marked as unmaintained in the README, yet it contains multiple dependencies that may receive security updates. Security patches to dependencies will not be applied to this codebase, leaving it vulnerable to supply chain attacks and known CVEs. Fix: Either resume active maintenance or archive the repository. If archived, provide migration guidance to users. Consider publishing a security advisory. - Medium · Insecure Shell Script Deployment —
install.sh, install.ps1. The presence of install.sh and install.ps1 scripts suggests users may execute arbitrary shell code for installation. Without proper verification mechanisms (code signing, checksums), this poses a risk of supply chain attacks. Fix: Implement integrity verification (SHA256 checksums), digitally sign releases, and provide instructions for users to verify downloaded binaries. Host installation scripts on secure channels with HTTPS only. - Low · Hardcoded Configuration in Test Data —
tests/data/.vim/, tests/data/.vimrc, tests/data/sample-cpp/.vim/settings.json. Test directories contain .vim configuration files and settings.json that may contain example credentials or sensitive paths that could be accidentally committed. Fix: Ensure test configuration files never contain real credentials. Use environment variables or fixture data without sensitive information. Add to .gitignore if needed. - Low · Potential Command Injection via Shell Expansion —
Cargo.toml - shellexpand dependency, src/language_client.rs (likely usage). The shellexpand (2.0.0) dependency is used but older versions had potential security issues with shell metacharacter handling. This could lead to command injection if user input is expanded. Fix: Update shellexpand to the latest version and audit all usages to ensure untrusted user input is not directly passed to shell expansion functions. Use allowlists for expandable variables. - Low · Missing CORS/CSP Headers in Configuration —
.vscode/settings.json, .vim/settings.json. The .vscode/settings.json and .vim/settings.json may contain workspace-level configurations. If this project runs a server component, missing security headers could enable XSS or CSRF attacks. Fix: Review any server components for proper security headers (CSP, X-Frame-Options, X-Content-Type-Options). Implement Content Security Policy if serving web content.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/autozimu/LanguageClient-neovim shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live autozimu/LanguageClient-neovim
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/autozimu/LanguageClient-neovim.
What it runs against: a local clone of autozimu/LanguageClient-neovim — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in autozimu/LanguageClient-neovim | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch next exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 255 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of autozimu/LanguageClient-neovim. If you don't
# have one yet, run these first:
#
# git clone https://github.com/autozimu/LanguageClient-neovim.git
# cd LanguageClient-neovim
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of autozimu/LanguageClient-neovim and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "autozimu/LanguageClient-neovim(\\.git)?\\b" \\
&& ok "origin remote is autozimu/LanguageClient-neovim" \\
|| miss "origin remote is not autozimu/LanguageClient-neovim (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify next >/dev/null 2>&1 \\
&& ok "default branch next exists" \\
|| miss "default branch next no longer exists"
# 4. Critical files exist
test -f "src/main.rs" \\
&& ok "src/main.rs" \\
|| miss "missing critical file: src/main.rs"
test -f "src/language_client.rs" \\
&& ok "src/language_client.rs" \\
|| miss "missing critical file: src/language_client.rs"
test -f "src/rpchandler.rs" \\
&& ok "src/rpchandler.rs" \\
|| miss "missing critical file: src/rpchandler.rs"
test -f "src/rpcclient.rs" \\
&& ok "src/rpcclient.rs" \\
|| miss "missing critical file: src/rpcclient.rs"
test -f "src/language_server_protocol.rs" \\
&& ok "src/language_server_protocol.rs" \\
|| miss "missing critical file: src/language_server_protocol.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 255 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~225d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/autozimu/LanguageClient-neovim"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.
Embed this chat in your README →
Drop this iframe anywhere — the widget runs against the same live analysis cache as the main app.
<iframe src="https://repopilot.app/embed/autozimu/languageclient-neovim" width="100%" height="500" style="border:1px solid #d0d7de; border-radius:8px;" allow="microphone" loading="lazy" ></iframe>