2026-05-10 16:40:58 +02:00
# iLSP — Editor Setup Guide
iLSP is a self-hosted LSP proxy at `ilsp.i80.dk` that provides smart autocomplete for:
- **Bicep** — internal module registry, parameter names, allowed values, version tags
- **Python** — Jedi-powered completions and diagnostics
- **YAML pipelines** — Azure DevOps template references and GitHub Actions reusable workflows
No extra editor plugins are needed beyond the standard language-server clients you
already have. iLSP speaks standard LSP over WebSocket and works with any editor that
supports LSP WebSocket transport.
---
2026-05-11 11:44:31 +02:00
## IntelliJ IDEA setup (LSP4IJ)
2026-05-19 13:51:17 +02:00
Install the [LSP4IJ ](https://plugins.jetbrains.com/plugin/23257-lsp4ij ) plugin, then add language servers:
### Bicep
2026-05-11 11:44:31 +02:00
1. **Settings → Languages & Frameworks → LSP → Language Servers → + **
- Name: `iLSP Bicep`
2026-05-19 11:46:54 +02:00
- Server type: `Command` (not WebSocket — see note below)
2026-05-19 13:51:17 +02:00
- Command: `/Users/lrihni/Projects/iLSP/scripts/lsp_bridge_debug.sh wss://ilsp.i80.dk/bicep`
- Arguments: (leave blank)
- File pattern: `*.bicep;*.bicepparam`
### YAML (Azure DevOps + GitHub Actions)
2. **Settings → Languages & Frameworks → LSP → Language Servers → + **
- Name: `iLSP YAML`
- Server type: `Command`
- Command: `/Users/lrihni/Projects/iLSP/scripts/lsp_bridge_debug.sh wss://ilsp.i80.dk/yaml`
- Arguments: (leave blank)
- File pattern: `*.yaml;*.yml;azure-pipelines.yml`
### Python (optional)
3. **Settings → Languages & Frameworks → LSP → Language Servers → + **
- Name: `iLSP Python`
- Server type: `Command`
- Command: `/Users/lrihni/Projects/iLSP/scripts/lsp_bridge_debug.sh wss://ilsp.i80.dk/python`
- Arguments: (leave blank)
- File pattern: `*.py`
2026-05-19 11:46:54 +02:00
> **Note**: LSP4IJ's WebSocket mode doesn't handle LSP Content-Length framing correctly,
2026-05-19 13:51:17 +02:00
> causing "starting..." to hang or "Stream closed" errors. Use `lsp_bridge_debug.sh` wrapper
> which calls `lsp_bridge.py` and logs errors to `/tmp/lsp_bridge_debug.log` for debugging.
### Troubleshooting
If the language server doesn't start, check the debug log:
```bash
tail -f /tmp/lsp_bridge_debug.log
```
2026-05-11 11:44:31 +02:00
2026-05-19 13:51:17 +02:00
### Disable conflicting plugins
2026-05-11 11:44:31 +02:00
2026-05-19 13:51:17 +02:00
**Disable Azure Toolkit Bicep completions** — this is critical if you have the
2026-05-11 11:44:31 +02:00
Azure Toolkit plugin installed. Without this step, IDEA merges completions from
both LSP4IJ and Azure Toolkit, resulting in noisy suggestions (`resource` ,
`projectName` , Bicep schema types, etc.) appearing alongside iLSP results.
Go to **Settings → Languages & Frameworks → Azure Toolkit for IntelliJ **
and disable or uncheck Bicep language support. If there is no such option,
disable the Azure Toolkit plugin entirely for Bicep projects, or suppress
its completion contributor via **Settings → Editor → General → Code Completion **
(uncheck "Show suggestions from plugins that don't support the current language server").
> **Why**: LSP4IJ feeds completions through the LSP protocol where iLSP can
> filter them. Azure Toolkit injects completions directly into IDEA's completion
> system, bypassing the LSP layer entirely — iLSP cannot suppress those.
---
2026-05-10 16:40:58 +02:00
## Neovim setup
```lua
-- In your LSP config (e.g. ~/.config/nvim/lua/lsp.lua)
-- Bicep
vim.lsp.start({
name = "ilsp-bicep",
cmd = vim.lsp.rpc.connect("wss://ilsp.i80.dk/bicep"),
root_dir = vim.fs.dirname(vim.fs.find({ "bicepconfig.json", ".git" }, { upward = true })[1]),
filetypes = { "bicep" },
})
-- YAML (pipeline files)
vim.lsp.start({
name = "ilsp-yaml",
cmd = vim.lsp.rpc.connect("wss://ilsp.i80.dk/yaml"),
root_dir = vim.fs.dirname(vim.fs.find({ ".git" }, { upward = true })[1]),
filetypes = { "yaml" },
})
-- Python
vim.lsp.start({
name = "ilsp-python",
cmd = vim.lsp.rpc.connect("wss://ilsp.i80.dk/python"),
root_dir = vim.fs.dirname(vim.fs.find({ "pyproject.toml", ".git" }, { upward = true })[1]),
filetypes = { "python" },
})
```
## VS Code setup
Install the [LSP WebSocket ](https://marketplace.visualstudio.com/items?itemName=example.lsp-ws ) extension (or equivalent), then add to `settings.json` :
```json
{
"lspWebSocket.servers": [
{ "languageId": "bicep", "url": "wss://ilsp.i80.dk/bicep" },
{ "languageId": "yaml", "url": "wss://ilsp.i80.dk/yaml" },
{ "languageId": "python","url": "wss://ilsp.i80.dk/python" }
]
}
```
---
## What iLSP adds on top of the standard schema
### Bicep — internal module registry
The standard Bicep LSP knows nothing about your internal ACR registry.
iLSP intercepts completion requests and injects:
| Context | What you get |
|---------|-------------|
| `'br/modules:<cursor>'` | All 27 internal modules (`appservice` , `roleassignments` , …) |
| `'br/modules:roleassignments:<cursor>'` | Available versions (`1.1.x` , `2.0.x` , `latest` , …) |
| `params {` inside a module block | Parameter names with types, required/optional, defaults |
| parameter value positions | Allowed values for enum-type params |
Items from the internal catalog always sort to the **top ** of the completion list.
### YAML pipelines — AzDO template completions
When you type `- template:` in an `azure-pipelines.yml` , iLSP recognises the AzDO
pipeline format and injects completions from the `pipeline-templates` Bitbucket repo:
```yaml
steps:
- template: tasks/k8s/deploy.yaml@pipeline -templates
# ↑ cursor here → get all task templates with @pipeline -templates label
parameters:
environment: | # ← cursor here → get param names for deploy.yaml
targetNamespace: # ← cursor here → get allowed values if defined
```
**Format detection** — iLSP auto-detects AzDO vs GHA:
- `- template:` or `stages:` / `trigger:` → AzDO mode
- `on:` / `workflow_call` / `runs-on:` → GHA mode
No extra configuration needed in your editor.
### YAML pipelines — GitHub Actions reusable workflows
In `.github/workflows/*.yml` files that call LRU-Digital reusable workflows:
```yaml
jobs:
deploy:
uses: LRU-Digital/infra/.github/workflows/deploy-k8s.yml@main
# ↑ cursor here → get all reusable workflows
with:
environment: | # ← cursor here → get input names for deploy-k8s.yml
```
---
## Updating the catalogs
Catalogs are baked into the Docker image at build time. To update them:
```bash
cd ~/Projects/iLSP
# 1. Regenerate catalogs from local repos
python3 scripts/sync_pipeline_templates.py # → pipeline_templates_catalog.json
python3 scripts/sync_iac_module_sources.py # → iac_source_catalog.json (from DevOpsMCP)
python3 scripts/sync_bicep_modules.py # → bicep_modules_catalog.json
# 2. Push and deploy
bash scripts/push_catalogs.sh
```
The `/reload` endpoint on the running service reloads catalogs from volume-mounted
files if present, so you can update without a full redeploy for pipeline templates.
---
## Health check
```bash
curl https://ilsp.i80.dk/health
# → {"status":"ok","bicep_modules":27,"iac_source_modules":26,"pipeline_templates":48,"yaml_lsp":true,...}
```
| Field | What it means |
|-------|--------------|
| `bicep_modules` | Modules in the ACR registry catalog |
| `iac_source_modules` | Modules with source-level param docs |
| `pipeline_templates` | AzDO + GHA templates available for YAML completion |
| `yaml_lsp` | yaml-language-server detected and working |
---
## Smoke tests
```bash
# Against production
python3 scripts/smoke_test_completions.py
# Against local dev container
python3 scripts/smoke_test_completions.py http://localhost:2089
```
Tests 1– 5 cover Bicep, tests 6– 7 cover YAML pipeline templates.