README.md

September 3, 2026 · View on GitHub

██╗   ██╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗   ███████╗███████╗██╗  ██╗
██║   ██║██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝   ╚══███╔╝██╔════╝██║  ██║
██║   ██║███████╗██║     ██║   ██║██║  ██║█████╗█████╗ ███╔╝ ███████╗███████║
╚██╗ ██╔╝╚════██║██║     ██║   ██║██║  ██║██╔══╝╚════╝███╔╝  ╚════██║██╔══██║
 ╚████╔╝ ███████║╚██████╗╚██████╔╝██████╔╝███████╗   ███████╗███████║██║  ██║
  ╚═══╝  ╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝   ╚══════╝╚══════╝╚═╝  ╚═╝

CI Docs License: MIT

[VS CODE EXTENSION // NEON GRAMMAR // COMPLETE BUILTIN SURFACE // LSP]

"Open a .zshrc. The whole shell lights up — every builtin, every world-first extension."

VS Code / VSCodium support for zshrs — the first-ever Rust rewrite of zsh: a compiled, JIT'd, massively parallel shell. A standalone TextMate grammar (it owns the zshrs language id — not a shellscript reskin), filetype detection for zsh dotfiles, language-server integration via zshrs --lsp, one-key running, and full debugging (breakpoints, stepping, variables) via zshrs --dap.

Read the Docs · Engineering Report · zshrs · vscode-stryke


[0x00] OVERVIEW

vscode-zsh is the VS Code / VSCodium extension for zshrs. It provides:

  • Filetype detection — zsh dotfiles (.zshrc, .zshenv, .zprofile, .zlogin, .zlogout, .zpreztorc), *.zsh / *.zsh-theme files, and files whose first line is a zsh / zshrs shebang (#!/usr/bin/env zsh).
  • Syntax highlighting — a standalone TextMate grammar (source.zshrs) with its own language id, so it owns the language rather than reskinning the built-in shell grammar.
  • Language serverzshrs --lsp via vscode-languageclient (diagnostics, hover, completion — whatever the server provides).
  • Runzshrs: Run File (Ctrl+F5) executes the active script in a terminal.
  • Debugging — breakpoints, stepping, call stack, variables, and watch via zshrs's native connect-back debug adapter (zshrs --dap), bridged to VS Code.

The grammar is generated (scripts/gen_grammar.sh) directly from the zshrs binary's own reflection tables (zshrs --dump-reflection), so it carries the language's real surface and never drifts:

  • 138 builtins.builtins keys, minus keyword names, minus extension names
  • 112 extensions.extensions keys, given their own scope (the zshrs world-first additions)
  • 245 special variables.special_vars keys

Created by MenkeTechnologies.


[0x01] FEATURE MATRIX

CapabilityStatus
Filetype detection — dotfilesImplementedcontributes.languages filenames map
Filetype detection — *.zsh / *.zsh-themeImplementedcontributes.languages extension map
Filetype detection — shebangImplementedfirstLine regex ^#!.*\bzsh\b
Syntax highlightingImplemented — TextMate grammar (source.zshrs), own language id
Comments / brackets / autocloseImplementedlanguage-configuration.json
IndentationImplemented — brace-based indentationRules
Language serverImplementedzshrs --lsp via vscode-languageclient
RunImplementedzshrs: Run File (Ctrl+F5 / editor-title ▶) runs zshrs <file> in a terminal
DebuggingImplemented — breakpoints, step over/into/out, call stack, scopes, variables, watch/hover, via zshrs --dap (native connect-back DAP, bridged to VS Code)
Configzshrs.path, zshrs.lsp.enabled, zshrs.lsp.args

The extension resolves the zshrs binary from $PATH plus the common install locations (~/.cargo/bin, /opt/homebrew/bin, /usr/local/bin, ~/.local/bin) — so it works even when the editor is launched from the macOS Dock / Finder, which doesn't inherit your shell $PATH. Build zshrs with cargo build (installs to ~/.cargo/bin). If it lives elsewhere, set zshrs.path to the absolute path.


[0x02] INSTALL

This extension is not yet on the Marketplace. Build and install the .vsix locally:

git clone https://github.com/MenkeTechnologies/vscode-zsh
cd vscode-zsh
npm install
npx @vscode/vsce package          # produces vscode-zsh-<version>.vsix
code --install-extension vscode-zsh-*.vsix

Or drop the folder into your extensions dir for development:

git clone https://github.com/MenkeTechnologies/vscode-zsh \
    ~/.vscode/extensions/vscode-zsh

Open any .zshrc or .zsh file — it lights up. The language server starts automatically when zshrs is on $PATH.


[0x03] RUN & DEBUG

Run — open a zsh script and press Ctrl+F5, click the in the editor title bar, or run zshrs: Run File from the command palette. The file is saved and executed as zshrs <file> in an integrated terminal.

Debug — set breakpoints in the gutter and press F5, click the debug icon in the editor title bar, or run zshrs: Debug File from the command palette. No launch.json is required: F5 on a zsh script debugs the active file. You get breakpoints, step over/into/out, call stack, scopes, variables, watch expressions, and hover-to-evaluate.

zshrs's debug adapter (zshrs --dap HOST:PORT) is connect-back — it dials into a listener the IDE provides (the same model it uses in JetBrains). The extension runs that listener, spawns zshrs --dap 127.0.0.1:<port>, and pipes it to VS Code's debugger, so it works the same as any other VS Code debug session.

For a saved configuration, add to .vscode/launch.json:

{
  "type": "zshrs",
  "request": "launch",
  "name": "zshrs: Debug Current File",
  "program": "${file}",
  "cwd": "${workspaceFolder}",
  "stopOnEntry": false,
  "args": []
}

Launch attributes: program, args, cwd, stopOnEntry, and zshrsPath (override the binary for one session). The binary is resolved the same way as the language server, so it works under the macOS GUI $PATH.


[0x04] SYNTAX // SCOPES

The grammar maps zshrs tokens to standard TextMate scopes, so every VS Code theme colors them:

Token groupScopeSample
Control flowkeyword.control.zshrsif then fi for while case esac function return
Declarationsstorage.modifier.zshrstypeset local export declare readonly integer float
Builtins (138)support.function.builtin.zshrsbindkey autoload zstyle compadd setopt zle
Extensions (112)support.function.extension.zshrsbase64 async await barrier clone
Special variables (245)variable.language.zshrsPATH HOME PWD RANDOM
Sigil variablesvariable.other.zshrs$foo ${bar} $1 $? $@ $# $$ $! $*
Operators / pipes / redirectskeyword.operator.zshrs| || && ;; > >> << >& =~

Strings (single / double / backtick), here-docs (<<EOF, <<-, <<'EOF'), $var / ${...} interpolation, escapes, command substitution $(...), and numbers are all scoped too.


[0x05] LANGUAGE SERVER

The extension launches zshrs --lsp (stdio JSON-RPC) through vscode-languageclient. Configure it in Settings:

SettingDefaultEffect
zshrs.pathzshrsPath to the zshrs executable
zshrs.lsp.enabledtrueStart the language server (set false for highlighting only)
zshrs.lsp.args["--lsp"]Args passed to start the server

If the binary is missing, the extension shows one non-fatal warning and syntax highlighting keeps working.


[0x06] REGENERATING THE GRAMMAR

The builtin / extension / special-variable surface is generated from the live binary so it never drifts. After a zshrs upgrade:

./scripts/gen_grammar.sh        # rewrites syntaxes/zshrs.tmLanguage.json
npm run gen                      # same thing via npm

Verify it still tokenizes correctly with the real VS Code grammar engine, and run the extension's unit tests — the same commands CI runs:

npm install
node scripts/tokenize_test.js       # vscode-textmate + vscode-oniguruma scope assertions
node --test scripts/resolver_test.js scripts/activate_test.js scripts/dapbridge_test.js

resolver_test.js covers binary resolution against a temporary PATH, activate_test.js drives extension.js against a stub vscode module (the LSP is spawned as bare zshrs --lsp; a missing binary never constructs the client; run + debug are registered under the zshrs debug type; the config provider fills in the active file for F5 with no launch.json), and dapbridge_test.js pipes a DAP initialize through the bridge to a real zshrs --dap, skipping when the binary is absent.


[0x07] LAYOUT

vscode-zsh/
├── package.json                    # extension manifest — languages, grammars, configuration,
│                                   #   commands, keybindings, menus, breakpoints, debuggers
├── language-configuration.json     # comments, brackets, autoclose, indent rules
├── extension.js                    # activation: LSP client (zshrs --lsp), the zshrs.run /
│                                   #   zshrs.debug commands, and the debug adapter factory
├── lib/resolveBinary.js            # vscode-free resolver: $PATH + the common install dirs
├── lib/dapBridge.js                # vscode-free rendezvous server bridging VS Code's DAP
│                                   #   client to zshrs's connect-back `zshrs --dap HOST:PORT`
├── syntaxes/zshrs.tmLanguage.json  # generated grammar — builtins, extensions, special vars
├── scripts/gen_grammar.sh          # regenerates the grammar from the zshrs binary
├── scripts/tokenize_test.js        # tokenizes a sample with vscode-textmate + asserts scopes
├── scripts/resolver_test.js        # binary resolution against a temp PATH
├── scripts/dapbridge_test.js       # the bridge piping two sockets end to end
├── scripts/activate_test.js        # activation against a stub `vscode` module
└── tests/                          # repo hygiene checks for README, docs and the workflow

[0x08] LICENSE

MIT © MenkeTechnologies