Skip to main content

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"...")
  • 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 --help preview
    • 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 backendSettings via initializationOptions

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:

  1. Receives requests from the editor (completions, hover, etc.)
  2. Preprocesses xonsh syntax to valid Python (e.g., $HOME__xonsh_env__["HOME"])
  3. Forwards the preprocessed Python to the child LSP server
  4. Maps positions in the response back to the original xonsh source
  5. 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

  • tree-sitter-xonsh - Tree-sitter grammar for xonsh
  • xonsh - The xonsh shell
  • pygls - Python LSP library
  • jedi - Python static analysis
  • ty - Extremely fast Python type checker and LSP
  • pyright - Static type checker for Python

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

xonsh_lsp-0.1.4.tar.gz (54.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xonsh_lsp-0.1.4-py3-none-any.whl (49.1 kB view details)

Uploaded Python 3

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

Hashes for xonsh_lsp-0.1.4.tar.gz
Algorithm Hash digest
SHA256 3455f876788a8e043e098752f41b6d9e338b1f756b8207d0000c9f568f9564e8
MD5 c1f1d1cd24ee5364069721a502a08ef8
BLAKE2b-256 af5ac1e34fe2289007c7903234724795088c81b4d9c8288c7f6a41169a14fc20

See more details on using hashes here.

Provenance

The following attestation bundles were made for xonsh_lsp-0.1.4.tar.gz:

Publisher: release.yml on FoamScience/xonsh-language-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for xonsh_lsp-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 9d81b0697b9c1a9d1cab410eafac91ce2d63baeffa479ccd2dec73f2529d860c
MD5 0faa6b19878fcf3d634372a44d38c1e9
BLAKE2b-256 7460075095cb080f129371c0d38843e1f4501c9630768ce09a355cc13b2d44e7

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page