Language Server Protocol implementation for xonsh
Project description
xonsh-lsp
A Language Server Protocol (LSP) implementation for xonsh, the Python-powered shell.
Features
- Syntax Highlighting (via tree-sitter-xonsh integration)
- Code Completion
- Environment variables (
$VAR,${expr}) - Subprocess commands from PATH
- Shell builtins (cd, echo, jobs, etc.)
- Xonsh builtins and aliases (source, xontrib, aliases, etc.)
- Python completions (via Jedi or external backend)
- Path completions with directory traversal
- Glob pattern completions (
`...`) - At-object completions (
@.env,@.imp) - Path literal completions (
p"...",pf"...")
- Environment variables (
- Diagnostics
- Syntax errors (via tree-sitter)
- Undefined environment variables (with quick fix)
- Unknown commands (hint severity)
- Empty subprocess warnings
- Python errors (via Jedi or external backend)
- Hover Information
- Environment variable values
- Xonsh operator documentation (
$(),!(),$[],![],@(),@$()) - Xonsh builtin documentation
- Command paths and
--helppreview - Python symbol information with signatures
- Path literal documentation
- Go to Definition
- Python definitions (via Jedi or external backend)
- Environment variable assignments
- Alias definitions
- Function definitions
- Find References
- Python references (via Jedi or external backend)
- Environment variable references
- Symbol references
- Signature Help
- Python function signatures (via Jedi or external backend)
- Parameter tracking
- Document Symbols
- Functions, classes, variables, modules
- Code Actions
- Quick fix for undefined environment variables
- Multi-Backend Support
- Built-in Jedi backend (default, no external dependencies)
- LSP proxy to Pyright, basedpyright, pylsp, ty, or any LSP server
- Transparent settings passthrough (editor → child backend)
- Fallback
backendSettingsviainitializationOptions
Installation
pip install xonsh-lsp
# or just run
uvx xonsh-lsp
To install with the built-in Jedi backend (recommended for standalone use):
pip install "xonsh-lsp[jedi]"
Jedi is optional — if you configure an external backend (Pyright, ty, etc.), you don't need Jedi installed.
Usage
Command Line
# Start with stdio (default, for editor integration)
xonsh-lsp
# Start with TCP
xonsh-lsp --tcp --host 127.0.0.1 --port 2087
# Debug mode
xonsh-lsp --log-level DEBUG
# Use Pyright as the Python backend
xonsh-lsp --python-backend pyright
# Use ty as the Python backend
xonsh-lsp --python-backend ty
# Use a custom LSP server command
xonsh-lsp --python-backend lsp-proxy --backend-command my-lsp-server --stdio
Neovim Integration
Currently this LSP server is in beta stage; adding it to canonical Neovim echosystem tools is planned but may take some time. For now, a manual approach is recomended
Add to your Neovim configuration (using nvim-lspconfig):
local lspconfig = require('lspconfig')
local configs = require('lspconfig.configs')
-- Register xonsh-lsp
if not configs.xonsh_lsp then
configs.xonsh_lsp = {
default_config = {
cmd = { 'xonsh-lsp' }, -- <-- manage server installation manually
filetypes = { 'xonsh', 'xsh' },
root_dir = function(fname)
return lspconfig.util.find_git_ancestor(fname) or vim.fn.getcwd()
end,
settings = {},
},
}
end
-- Set up the LSP
lspconfig.xonsh_lsp.setup({
on_attach = function(client, bufnr) end,
capabilities = require('cmp_nvim_lsp').default_capabilities(),
})
-- Associate file types
vim.filetype.add({
extension = {
xsh = 'xonsh',
xonshrc = 'xonsh',
},
filename = {
['.xonshrc'] = 'xonsh',
},
})
Using Pyright as the Python backend
lspconfig.xonsh_lsp.setup({
init_options = {
pythonBackend = "pyright",
},
-- Your existing Pyright-style settings — forwarded transparently to the child backend
settings = {
python = {
pythonPath = "/path/to/python", -- or detected via your own on_attach
analysis = {
autoSearchPaths = true,
useLibraryCodeForTypes = true,
},
},
},
})
Using ty as the Python backend
lspconfig.xonsh_lsp.setup({
init_options = {
pythonBackend = "ty",
},
})
Your existing Python backend configuration (e.g. settings.python.*) is forwarded
transparently to the child LSP — xonsh-lsp does not try to detect or override paths itself.
Configuration
Python Backend
xonsh-lsp supports multiple Python analysis backends. The backend handles completions, hover, go-to-definition, references, signature help, and diagnostics for Python code within xonsh files.
| Backend | Command | Description |
|---|---|---|
jedi (default) |
built-in | Uses Jedi for static analysis. Works out of the box, no external process. |
pyright |
pyright-langserver --stdio |
Microsoft's Pyright type checker. Respects pyrightconfig.json. |
basedpyright |
basedpyright-langserver --stdio |
Community fork basedpyright with additional features. |
pylsp |
pylsp |
The Python LSP Server with plugin ecosystem. |
ty |
ty server |
Astral's ty type checker — extremely fast, written in Rust. |
lsp-proxy |
custom | Any LSP server via --backend-command. |
The backend can be set via CLI args or editor initializationOptions:
CLI:
xonsh-lsp --python-backend pyright
Editor initializationOptions:
{
"pythonBackend": "pyright"
}
Initialization Options
The full set of initializationOptions accepted by xonsh-lsp:
{
// Python analysis backend: "jedi", "pyright", "basedpyright", "pylsp", "ty", or "lsp-proxy"
"pythonBackend": "jedi",
// Custom command for the "lsp-proxy" backend (not needed for named backends)
"pythonBackendCommand": ["my-lsp-server", "--stdio"],
// Fallback settings sent to the backend during initialization.
// Normally you should configure your backend via the editor's settings
// (e.g. Neovim's `settings = { ... }`), which are forwarded transparently.
// Use this only if your editor doesn't support workspace/configuration.
"backendSettings": { }
}
Settings Passthrough
When the child backend requests its configuration (via workspace/configuration),
xonsh-lsp forwards the request to your editor and returns the editor's response.
This means your existing Python backend settings — pythonPath, python.analysis.*,
etc. — work exactly as if the backend were running standalone.
If the editor doesn't respond (or workspace/configuration is not supported),
xonsh-lsp falls back to backendSettings from initializationOptions.
How the LSP Proxy Works
When configured with an external backend, xonsh-lsp acts as LSP middleware:
- Receives requests from the editor (completions, hover, etc.)
- Preprocesses xonsh syntax to valid Python (e.g.,
$HOME→__xonsh_env__["HOME"]) - Forwards the preprocessed Python to the child LSP server
- Maps positions in the response back to the original xonsh source
- Merges results with xonsh-specific features (env vars, operators, commands)
Xonsh-specific features (environment variable completions, operator hover, subprocess diagnostics, etc.) are always handled natively — only Python analysis is delegated to the backend.
Diagnostics use a two-phase merge:
- Xonsh diagnostics (syntax errors, undefined env vars, unknown commands) are published immediately
- Python diagnostics from the backend arrive asynchronously and are merged with the cached xonsh diagnostics
Architecture
flowchart RL
subgraph xonsh-lsp
parser[tree-sitter-xonsh parser]
parser --> python[Python Regions]
parser --> xonsh[Xonsh Builtins]
parser --> subprocess[Subprocess Commands]
python --> backend{PythonBackend}
backend -->|default| jedi[JediBackend]
backend -->|proxy| proxy[LspProxyBackend]
proxy --> child[Child LSP: Pyright / ty / basedpyright / pylsp]
xonsh --> native1[Native Handler]
subprocess --> native2[Native Handler]
end
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests; especially flagging unsupported xonsh syntax since this LSP is young.
License
MIT
Related Projects
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xonsh_lsp-0.1.4.tar.gz.
File metadata
- Download URL: xonsh_lsp-0.1.4.tar.gz
- Upload date:
- Size: 54.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3455f876788a8e043e098752f41b6d9e338b1f756b8207d0000c9f568f9564e8
|
|
| MD5 |
c1f1d1cd24ee5364069721a502a08ef8
|
|
| BLAKE2b-256 |
af5ac1e34fe2289007c7903234724795088c81b4d9c8288c7f6a41169a14fc20
|
Provenance
The following attestation bundles were made for xonsh_lsp-0.1.4.tar.gz:
Publisher:
release.yml on FoamScience/xonsh-language-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xonsh_lsp-0.1.4.tar.gz -
Subject digest:
3455f876788a8e043e098752f41b6d9e338b1f756b8207d0000c9f568f9564e8 - Sigstore transparency entry: 936714215
- Sigstore integration time:
-
Permalink:
FoamScience/xonsh-language-server@617efb723a04b92865a354a75d987c749bac2102 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/FoamScience
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@617efb723a04b92865a354a75d987c749bac2102 -
Trigger Event:
push
-
Statement type:
File details
Details for the file xonsh_lsp-0.1.4-py3-none-any.whl.
File metadata
- Download URL: xonsh_lsp-0.1.4-py3-none-any.whl
- Upload date:
- Size: 49.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d81b0697b9c1a9d1cab410eafac91ce2d63baeffa479ccd2dec73f2529d860c
|
|
| MD5 |
0faa6b19878fcf3d634372a44d38c1e9
|
|
| BLAKE2b-256 |
7460075095cb080f129371c0d38843e1f4501c9630768ce09a355cc13b2d44e7
|
Provenance
The following attestation bundles were made for xonsh_lsp-0.1.4-py3-none-any.whl:
Publisher:
release.yml on FoamScience/xonsh-language-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xonsh_lsp-0.1.4-py3-none-any.whl -
Subject digest:
9d81b0697b9c1a9d1cab410eafac91ce2d63baeffa479ccd2dec73f2529d860c - Sigstore transparency entry: 936714218
- Sigstore integration time:
-
Permalink:
FoamScience/xonsh-language-server@617efb723a04b92865a354a75d987c749bac2102 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/FoamScience
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@617efb723a04b92865a354a75d987c749bac2102 -
Trigger Event:
push
-
Statement type: