VS Code extension for working with SaltStack: syntax highlighting, linting, formatting, snippets, navigation, and auto-completion for Salt SLS and Jinja2 files.
Features
Syntax Highlighting
- YAML + Jinja2 combined grammar for
.slsfiles - Salt-specific highlighting: state IDs, state modules, requisites,
salt,pillar,grains - Standalone Jinja2 grammar for
.jinja,.j2files
Linting (real-time diagnostics)
- Duplicate state IDs
- Unclosed Jinja blocks (
{% if %}without{% endif %}) - Tab characters (Salt/YAML requires spaces)
- Empty state blocks (state ID without module call)
- Requisite references to non-existent state IDs
- Trailing whitespace
Formatting (Shift+Alt+F or auto on save)
- Auto-format on save -- enabled by default via
editor.formatOnSave(extension sets itself as default formatter for SLS/Jinja) - Enforce
{%-on opening tags --{% if x %}->{%- if x %},{%set%}->{%- set %}(enabled by default,saltstack.format.enforceDashTags) - Preserves closing
-%}-- existing-%}is never removed:{%- if x -%}stays{%- if x -%} - Jinja tag spacing normalization:
{%if x%}->{%- if x %},{{var}}->{{ var }} - Comments
{# ... #}content is left untouched - Tabs to spaces
- Trailing whitespace removal
- Collapses multiple consecutive blank lines to one
- Ensures final newline
Navigation
- Outline (
Cmd+Shift+O) -- state IDs, modules, includes, Jinja imports/variables - Go-to-Definition (
Cmd+Click) -- Jinja imports/includes,salt://sources, SLS includes, requisite references (local and cross-file via the workspace index), pillar includes - Find All References -- right-click on a state ID to find every requisite that targets it across the whole workspace
- Pillar usage navigation -- Cmd+Click on a pillar key resolves to every place it's referenced in state files (including indirect access through
{% set X = pillar.Y %}aliases and{% from "X" import Y %}dict maps) - Hover on pillar keys -- shows the full key path, all access forms, and ready-to-run
salt '<minion>' state.apply <formula>commands grouped by formula - Hover -- documentation for 55+ state modules, all requisites, Salt builtins (
salt,pillar,grains), execution modules (sdb.get,defaults.merge,fast_yaml.hosts, etc.) — 85+ entries total
Auto-completion
- State modules (
file.managed,service.running, etc.) - Module parameters
- Requisites (
require,watch,onchanges, etc.) - Salt execution modules inside
salt['...']andsalt.
Snippets (90+)
- Salt state modules:
file.managed,pkg.installed,service.running,cmd.run,user.present,docker_container.running, etc. - Jinja constructs:
if,for,set,macro,block,from ... import, etc. - Salt/Pillar patterns:
sdb.get,sdb.get_or_set_hash,grains.filter_by,fast_yaml.hosts,saltutil.runner - Boilerplates:
sls-boilerplate,sls-full,map-jinja - Saltcheck:
saltcheck,assertEqual,assertNotEqual,assertIn,assertNotIn,assertGreater,assertLess,assertEmpty,assertNotEmpty,assertTrue,assertFalse(.tstfiles are recognized as SLS)
Workspace index
The extension maintains a project-wide index of all state IDs declared under stateRoots. The index powers cross-file go-to-definition for requisites and find-all-references. It rebuilds automatically when files change; you can force a rebuild via the command palette: SaltStack: Reindex Workspace.
Status bar
A status bar item shows which configured Salt root the active file lives under (Salt state: salt, Salt pillar: pillar/, etc.). Click it to reindex the workspace.
Pillar Support
- Auto-detects pillar files based on
saltstack.pillarRootssetting - Go-to-Definition for pillar includes (
{% include "defaults/..." %}) - Hover shows how to access pillar keys from states
- Disables state-specific completions in pillar context
Build
Requirements: Node.js >= 18, npm.
# Install dependencies
npm install
# Compile TypeScript
npm run compile
# Package as .vsix
npx @vscode/vsce@latest package --allow-missing-repository
For development with auto-rebuild on changes:
npm run watch
Install
code --install-extension saltstack-toolkit-<version>.vsix
Or in the IDE: Ctrl+Shift+P -> "Extensions: Install from VSIX..." -> select the .vsix file.
To update, build a new version and install again -- a higher version number installs without --force.
Settings
Add to your settings.json:
{
"saltstack.stateRoots": [
"/path/to/salt-states"
],
"saltstack.pillarRoots": [
"/path/to/pillars/pillar"
],
"saltstack.lint.enabled": true,
"saltstack.lint.duplicateStateIds": true,
"saltstack.lint.trailingWhitespace": true,
"saltstack.lint.tabs": true,
"saltstack.lint.jinjaBlocks": true,
"saltstack.format.enforceDashTags": true
}
stateRoots and pillarRoots accept both absolute paths and paths relative to the workspace root. These are used for Go-to-Definition resolution of salt://, {% from %}, {% include %}, and SLS include references.
License
MIT