Ansible deserves proper language server

I’ve restarted creating ansible yaml content and realized that some quality of life tooling is missing for ansible yaml content developers. That is why I’ve decided to create ansible language protocol server (LSP) with all the features that are missing in the official one (from my point of view).

Here is a link to public repo:

https://github.com/kksat/zals

There are also VS Code (and Open VSX) plugins:

https://marketplace.visualstudio.com/items?itemName=kksat.zals

Open VSX Registry (VS Code forks, e.g. Cursor)

This extension is a drop-in replacement for official Red Hat ansible VS Code extension, but also can be used alogn side it:

https://marketplace.visualstudio.com/items?itemName=redhat.ansible

All the ansible yaml language features available in both extensions (mine and official):

  • Syntax highlighting
  • Integration with ansible-lint
  • Smart autocompletion
  • Documentation reference (in official extension this feature is only for modules, see below for zals)
  • Jump to module code

What is not supported in my extension:

  • all that is not related to ansible yaml content
  • lightspeed (certainly not)
  • mcp server (certainly not)
  • ansible execution environments (unlikely in the future)
  • content creation tools (not yet)
  • nothing related to ansible-dev-tools package (no idea)

What does this extension bring? Why would anyone use it? Because of its features. All screenshots and screen recordins are from VS Code. I am preparing neovim plugin as well.

Variables:

  1. Variable hover

  2. Find all references of variable:

find all reference of a variable

  1. Find all references of variable key:

    find all references of a variable key
    Here only variables ansible_facts['distribution'] are shown, this will also work with ansible_facts.distribution(both ways)

  2. Add and remove debug statements for variables

    add debug statement for variable

    remove debug statement for variable

    Roles:

  3. Role hover - opens role readme file when you hover over role name in import_role or include_role

  4. Role parameter hover - get extract from argument_specs file when you hover over role parameters (both for import_role and include_role)

  5. Go to role definition. Here role definition is argument_spec file:

    go to role definition

  6. Go to role implementation. Here role implementation is role tasks/main file:

    go to role implementation

  7. Go to definition for role parameters - again this is argument_specs file:

    go to role parameter definition

  8. Go to implementaton for role parameters - open defaults/main or vars/main role file where parameter value is set:

    Workspace features:

  9. Find symbols in the workspace - fuzzy search across all playbooks, roles, tasks in your workspace:

    find symbols in workspace

More to follow!

If you have an idea in mind - please let me know. The current roadmap: variable rename, extracting tasks to roles, memory usage optimization.

More information about implementation.
This is native binary (win, mac, linux) written in zig. Size is about 5 Mb. Does not depend on anything with exception of ansible-core and ansible-lint. When it starts it needs < 10 seconds to read and parse collection with 1000 files. After that it does not reread from disk.
Memory footprint for this extension is 40 MB current / 155 MB peak on my mac for the project
that contains roughly 5,542 YAML files and 11,104 total files (excluding Git, virtualenvs, and common caches).
Almost all operations (with few exceptions) are performed in around 10 ms, this was one of the reasons I’ve used zig (compiled language). I wanted nice UX and not break user flow.

If you find this extension and lsp useful, I would highly appreciate it if you write a quick review and submit your rating using these links:

https://marketplace.visualstudio.com/items?itemName=kksat.zals&ssr=false#review-details

https://open-vsx.org/extension/kksat/zals/reviews

You can always contact me directly

Thank you for you attention.

4 Likes

I was fortunate to get some time with @kks (than you again for sharing), where the plugin was demonstrated on my own open source content and i was very impressed.
The speed of response once, the variable hover is amazing and can really help with some of those more complex setups that i’ve seen (and created).
The insert debug and creating a separate task files (all with the ability to undo & redo ) are brilliant.
Excited to get some time to look at this, some of the functions currently there and already being thought about for the next stage are brilliant.

I know that anyone testing feedback will be appreciated.

Thank you again

1 Like

Hey Kirill- This is really cool.

The ansible engineering team is working on a pretty signiciant changes to the VsCode extension and trying to get it our for a preview.

It’s a completely different architecture than what we have today.

Do you have any interest in working together on the LSP part of it rather than a seperate LS and extension?

The code is in a branch GitHub - ansible/vscode-ansible at next · GitHub while we priortize the work and get it moving forward. The docs are forward looking and haven’t been released yet as there’s a conversation happening with other docs owners to determine how and where they might eventually be put. If you want a peak, they are here: Language Server | Ansible Developer Tools

Let me know what you think-

Brad (cidrblock)

I certainly have some interest. I am just not sure if our priorities and approaches are aligned.
I want native binary due to speed, zero dependency for simplicity. I want LSP to be separately portable, not just part of the extesion. I am even thinking of using ansible static link Release Announcement: ansible-static-lint v0.7.0 instead of ansible-lint or creating my own solution for linting and ansible-doc alternative for hover.

We might for sure exchange ideas. For me next big thing - variable renames across workspace.

We’d be open to releasing the language server separately. It already speaks LSP and has no direct dependency on the VS Code extension, although it does use shared service code from the monorepo, so we’d need to package that dependency and define the standalone runtime requirements.

In the next branch, module and option hover use cached plugin documentation populated from ansible-doc --metadata-dump rather than scraping docs from files with regex. Cache misses can still invoke ansible-doc for an individual plugin. This makes the hover path more structured, but it doesn’t eliminate the Ansible runtime/tooling dependency.

If I get a second, I’ll compare the 2 implmentations to see where each stands…

Your LS has some goodstuff in it. I asked an agent to do a parity comparison.

FWIW (agent generated, human directed)

Ansible Language Server Feature Comparison

Scope: This document compares the language-server capabilities in the next branch of vscode-ansible with ZALS, the Zig-based Ansible language server. It is a feature inventory, not a benchmark or assessment of feature quality.

Distribution and transport

The next language server implements LSP and has a CLI entry point, but it is currently bundled with the VS Code extension. It also uses shared @ansible/developer-services code.

ZALS is designed and distributed as a standalone Zig binary that communicates over LSP/stdio.

Language features

Completion: The next server provides context-sensitive completion for Ansible keywords, modules, options, and related content. ZALS supports completion for keywords, modules, options, values, redirects, and aliases.

Hover and documentation: In next, module and option hover use the shared documentation cache, populated from ansible-doc --metadata-dump. When documentation is missing from the cache, the service can fall back to a per-plugin ansible-doc --json call. ZALS documents hover for keywords, modules, options, variables, roles, role parameters, and collections. ZALS also documents hybrid documentation loading; a direct performance comparison would require measurement.

Diagnostics and linting: The next server uses ansible-lint, with validation able to fall back to ansible-playbook --syntax-check. ZALS also uses ansible-lint and falls back to syntax checking. It additionally provides bundled JSON-schema validation.

Navigation: The next server supports go-to-definition for Ansible constructs such as modules and related content. ZALS supports definitions for modules, variables, roles, task and vars files, collections, role argument specs, and metadata. ZALS also implements find-references for variables, roles, task/vars files, and collections, as well as implementation navigation for role main task files and concrete variable bindings. Those capabilities are not currently advertised by the next server.

Symbols and code actions: The next server supports semantic tokens, but does not currently advertise document or workspace symbol providers. ZALS supports semantic tokens, document symbols, and workspace symbols. It also provides debug-task actions and extract-tasks refactoring; code actions are not currently advertised by the next server.

Workspace and configuration

The next server supports workspace folders and client-provided settings, including settings for linting and the Ansible executable. ZALS supports workspace folders and watched files, with configuration for Ansible, linting, Python, and selected environments.

Summary

ZALS currently documents a broader standalone LSP feature set, particularly for find-references, implementation navigation, symbols, schema-based diagnostics, and code actions.

The next server already provides Ansible-aware completion, diagnostics, definition navigation, and cached plugin documentation for hover. It is a separate package in the monorepo, but its current build and distribution remain tied to the extension and the shared developer-services package.

Qualifications

  • Standalone does not mean dependency-free. ZALS’s documented runtime requirements include Ansible tooling; ansible-lint is optional.
  • Cached hover alone does not establish which server is faster. A fair comparison requires measuring both implementations with comparable environments and workloads.
  • Feature presence does not establish parity. This summary records documented or implemented capabilities; it does not compare accuracy, completeness, stability, or user experience.

References

  • next LSP capability registration
  • next hover implementation
  • next documentation cache and fallback
  • next language-server package manifest
  • ZALS README
  • ZALS LSP capabilities
  • ZALS documented deviations

and one for an SAE build: