A Rust alternative to bash-language-server, shipped as a single binary with no Node.js and minimal runtime dependencies.
bash-language-server errors had pushed my logs past 1 GB. My editor was slowing down. I wanted something self-contained.
- Hover documentation
- Completions (variables, functions, executables, builtins, snippets)
- Jump to definition
- Find references
- Rename
- Document and workspace symbols
- Diagnostics via shellcheck
- Formatting via shfmt
Diagnostics and formatting require additional tools:
Download from releases page, extract, and place bashls somewhere on your $PATH.
cargo install bashls
git clone https://github.com/k8s-1/bashls
cd bashls
cargo build --release
bashls works with any editor that supports LSP.
vim.lsp.config('bashls', {
cmd = { 'bashls' },
filetypes = { 'sh' },
root_markers = { '.git' },
-- init_options = {
-- bashIde = { shellcheckPath = '/usr/bin/shellcheck' },
-- },
})
vim.lsp.enable('bashls')[[language]]
name = "bash"
language-servers = ["bashls"]
[language-server.bashls]
command = "bashls"{
"lsp": {
"bash-language-server": {
"binary": {
"path": "bashls",
}
}
}
}(add-to-list 'eglot-server-programs
'(sh-mode . ("bashls")))Settings can be provided as LSP initialization options (under bashIde) or as environment variables (e.g. bashIde.shellcheckPath → SHELLCHECK_PATH).
Setting (bashIde.*) |
Default | Description |
|---|---|---|
shellcheckPath |
shellcheck |
Path to shellcheck binary. Set to empty string to disable. |
shellcheckArguments |
[] |
Additional arguments passed to shellcheck. |
shfmt.path |
shfmt |
Path to shfmt binary. Set to empty string to disable. |
shfmt.* |
See shfmt for remaining options. | |
globPattern |
**/*@(.sh|.inc|.bash|.command) |
Files the server treats as bash. |
backgroundAnalysisMaxFiles |
500 |
Max files to analyse in background for workspace-wide features. |
includeAllWorkspaceSymbols |
false |
Return functions and variables from all workspace files in symbol search, not just open files. |
enableSourceErrorDiagnostics |
false |
Show diagnostics when a source/. command cannot be resolved. |
logLevel |
info |
Log level. |
- No explainshell integration. Supporting this would require pulling in an HTTP/TLS stack (~50 crates); skipped intentionally to keep the dependency footprint small.
- Linux and macOS only. This is a bash language server — if you're on Windows, use WSL.
Measured against bash-language-server 5.6.0 using 50 .sh files from oh-my-bash as a corpus. Startup is measured cold (no prior Node.js activity); 1600 ms is the minimum observed across runs (average ~2600 ms). See examples/lsp_bench.rs for the full methodology and instructions to reproduce.
This project is released under the MIT License.
