Skip to main content
πŸ“’ New post: Editor Superpowers for Phobos β€” Introducing the Language Server and VS Code Extension β€” Read more β†’

VS Code Extension

The Phobos VS Code extension adds rich editor support for Phobos HCL pipeline templates (pipeline.hcl), release lifecycle templates (release_lifecycle.hcl), and Phobos variables files (*.pbvars β€” the input format Phobos reads at pipeline-creation time, analogous to Terraform's .tfvars). It is published to both the VS Code Marketplace and the Open VSX Registry, so the same VSIX serves VS Code, VSCodium, Cursor, Code OSS, Gitpod, Theia, and other VS Code-compatible editors. Every feature beyond syntax highlighting is powered by the Phobos Language Server, which is bundled in the GitLab-releases VSIXes and downloaded on first launch for registry installs β€” see Installation.

Have a question?

Check the FAQ to see if there's already an answer.

Features​

Language support​

  • Syntax highlighting β€” Full HCL grammar coloring for pipeline.hcl, release_lifecycle.hcl, and *.pbvars, plus Phobos-specific semantic tokens layered on top. Generic .hcl files are not claimed by default to avoid clashing with Terraform / Nomad / Packer in mixed-tool workspaces β€” opt in with phobos.editor.associateAllHclFiles.
  • Diagnostics β€” Real-time error, warning, and hint markers as you type. Covers parse errors, schema violations, cross-field constraints (interval requires attempts, deployments require environment, mount_point volumes must be declared), stage_order correctness, duplicate names, reserved keywords, dependency-name validation, dead action references (including typos in task-level attributes like success_condition), undefined var.* / jwt.* / vcs_token.* / volume.* references, structural typos in pipeline.* / this.* / phobos.* reference paths, required plugin "<name>" { } configuration blocks, plugin-alias resolution (unresolved plugin = <type>.<alias> refs, plus the ambiguity case where a type has only aliased instances), deprecations, and unused declarations. .pbvars files get cross-file diagnostics against the sibling template's variable "<name>" declarations β€” unknown names error out, type mismatches against the declared cty.Type produce friendly messages (e.g. variable "replicas" has type number but was assigned a value of type string), and unresolved references inside values surface HCL's own diagnostic. Enum-typed attributes accept variable references without false positives.
  • Hover documentation β€” Markdown-formatted docs on blocks, attributes, action labels (with inputs and outputs), named values (var.*, jwt.*, pipeline.*, this.*, …), and task-output references that resolve pipeline.stage.<s>.task.<t>.outputs.<o> back to the declaring block. In a .pbvars file, hover an attribute name to surface the sibling variable's description, declared type, and default-state.
  • Context-aware completion β€” Block types, attribute names, enumerated string values, HCL built-in functions, named-value namespaces, typed-output field navigation, sibling-name suggestions inside dependencies = [...], and plugin-instance suggestions inside action { plugin = <cursor> } offering every declared <type>.<alias> qualified name. .pbvars completion offers each variable name from the sibling template as a typed snippet β€” string inserts quotes-with-cursor-between, number inserts a 0 placeholder, bool inserts a true/false choice dropdown, object({...}) types pre-populate every declared field as its own tab stop with = signs aligned.
  • Signature help β€” Parameter hints on HCL built-in function calls.
  • Go-to-definition β€” Jump from any var.*, jwt.*, vcs_token.*, volume.*, pipeline.stage.*, this.action.*, this.alias.* reference, or action { plugin = <type>.<alias> } traversal to its declaration.
  • Find all references β€” Including cross-file propagation for workspace-level declarations and plugin-alias usages across every action { plugin = <type>.<alias> }.
  • Rename β€” Rename variable, jwt, and vcs_token declarations across every file in the workspace in one edit. Plugin aliases also rename in place β€” edits touch just the alias half of each usage so the type prefix stays anchored to the action-label.
  • Call hierarchy β€” Right-click a task, deployment, or nested pipeline to explore dependencies = [...] edges as a DAG (incoming and outgoing).
  • Document outline, folding, and selection-range expansion that follows the HCL AST.
  • Formatting β€” Format the whole document or on save using canonical HCL formatting. On-type formatting re-formats a block when you close it with }.
  • Inlay hints β€” Variable types and defaults, per-action plugin-instance badges (qualified <type>.<alias> when the action sets plugin = ..., bare type otherwise), per-task action + output counts (: 2 actions, 1 output), per-stage children counts (: 3 tasks, : 2 tasks, 1 pipeline), and deployment environments. Each category is independently toggleable.
  • Document links β€” Plugin sources in plugin_requirements become clickable links to the plugin registry.
  • Code actions β€” Install-plugin quick-fix, declare-missing-plugin-block quick-fix (inserts the block at the natural anchor after plugin_requirements), declare-aliased-plugin-block quick-fix (for unresolved plugin = <type>.<alias> refs), set-plugin-ref quick-fix (one option per declared alias when a type has only aliased instances), deprecation rewrites, extract-to-variable / inline-variable refactors, and source.fixAll for bulk deprecation migration.

UI​

  • Phobos activity-bar view with two tree panels (Templates, Installed Plugins).
  • Pipeline Graph webview β€” interactive DAG of stages, tasks, deployments, and dependencies for the active template.
  • Evaluated Context panel β€” live namespace / value tree at the cursor, updated as you move through the document.
  • Unified status-bar chip consolidating language-server state, CLI detection, plugin health, diagnostic counts, and deprecation count.

See Activity bar, Status bar, and Webviews below.

Installation​

The extension is distributed through three channels:

ChannelIncludes language serverNotes
VS Code Marketplace / Open VSX RegistryNo (downloads on demand)Universal VSIX, small (~1 MB). On first launch the extension prompts to download the language server and installs it into the editor's global storage.
GitLab releases (.vsix)YesPlatform-specific VSIXes with the phobos-language-server binary bundled. Best for air-gapped environments and internal deployments.
Built from sourceNoSee Building from source.
Language server is NOT bundled in registry installs

Only the .vsix files published on the vscode-phobos GitLab releases page ship with phobos-language-server bundled. Installs from the VS Code Marketplace and Open VSX Registry do not include the binary β€” the extension downloads and verifies it on first launch, or on demand via Phobos: Install or Update Language Server. Pick the channel that matches your deployment: a public registry for hands-off install on a networked machine, GitLab releases for air-gapped / internal-hosted deployments.

From a registry (VS Code Marketplace or Open VSX)​

The extension is published to both registries from a single source β€” pick the one your editor uses:

  • VS Code Marketplace β€” VS Code, Cursor, Kiro, and other Microsoft-licensed VS Code distributions.
  • Open VSX Registry β€” VSCodium, Code OSS, Gitpod, Theia, and other Eclipse-licensed VS Code forks that can't legally use the Microsoft Marketplace.

Both registries publish the same VSIX. Install through your editor's Extensions view (search "Phobos" β†’ Install) β€” neither bundles the language-server binary, so on first activation over a Phobos file the extension prompts:

Phobos language server not found. Install the latest version? [Install Latest] [Set Path…]

Choose Install Latest to download the platform-specific binary, verify its SHA-256 against the release manifest, and place it in VS Code's global storage. The language server starts automatically once the download completes. You can rerun or upgrade with the palette command Phobos: Install or Update Language Server.

note

Registry installs (Marketplace or Open VSX) need outbound HTTPS access to gitlab.com for the initial language-server download. For air-gapped environments, use the GitLab releases VSIX instead β€” it ships with the language server bundled.

From GitLab releases​

GitLab releases publish platform-specific VSIXes with the language-server binary bundled β€” the extension launches the server locally without any runtime download. Download the .vsix matching your platform from the vscode-phobos releases page, then install:

code --install-extension mc-phobos-<version>-<platform>.vsix

Or from inside VS Code: open the Extensions view (Ctrl+Shift+X), click the ... menu, and select Install from VSIX….

The available platform packages are:

File suffixPlatform
linux-x64Linux x86-64 (glibc)
linux-arm64Linux ARM 64-bit (glibc)
linux-armhfLinux ARM 32-bit (ARMv7, glibc)
alpine-x64Alpine Linux x86-64 (musl)
alpine-arm64Alpine Linux ARM 64-bit (musl)
darwin-x64macOS Intel
darwin-arm64macOS Apple Silicon
win32-x64Windows x86-64
win32-arm64Windows ARM 64-bit
note

Installing the wrong platform package leaves the bundled binary unusable. The extension falls back to the marketplace-style runtime install (if the other tiers also miss) so you can recover without reinstalling β€” see Language-server discovery.

Building from source​

When you build the extension from source the language server binary is not bundled. Install it separately using one of:

  • Runtime install β€” Launch the extension and run Phobos: Install or Update Language Server from the command palette.
  • Manual install β€” Download the appropriate binary from the language server releases page and place it on your PATH, or set phobos.languageServer.path to its absolute path.
Example: add the binary to PATH on Linux/macOS
# Replace VERSION with the release tag and PLATFORM with one of:
# linux_amd64, linux_arm64, linux_arm, linux_386,
# darwin_amd64, darwin_arm64
VERSION=0.1.0
PLATFORM=linux_amd64

BASE="https://gitlab.com/infor-cloud/martian-cloud/phobos/phobos-language-server/-/releases/${VERSION}/downloads"
curl -L -o phobos-language-server "${BASE}/phobos-language-server_${VERSION}_${PLATFORM}"
chmod +x phobos-language-server
sudo mv phobos-language-server /usr/local/bin/

Language-server discovery​

The extension resolves the phobos-language-server binary using a four-tier cascade. The first tier that finds a binary wins; higher tiers short-circuit lower ones.

  1. phobos.languageServer.path β€” Honored only in trusted workspaces. If the setting is present but points at a missing file, an error is surfaced (no silent fallthrough) so you can notice the misconfiguration.
  2. Bundled binary β€” <extension>/bin/phobos-language-server. Present in platform-specific GitLab-releases VSIXes; absent from marketplace VSIXes.
  3. Runtime-installed binary β€” <globalStorage>/bin/phobos-language-server, populated by the Phobos: Install or Update Language Server command. Survives extension updates.
  4. System PATH β€” phobos-language-server found by which.

If every tier misses, the extension prompts you to install the latest release.

Activity bar​

The Phobos icon in the activity bar (left sidebar) opens two tree views:

  • Templates β€” Every pipeline.hcl / release_lifecycle.hcl in the workspace, expanded to its document-symbol outline. Click a symbol to jump to the declaration. Click the refresh button in the view title to re-scan the workspace.
  • Installed Plugins β€” The language server's plugin inventory, grouped by plugin name. Expand a plugin to see actions, then actions to see inputs and outputs. Right-click a plugin and choose Browse Online to open its registry page in the browser.

Status bar​

A single Phobos chip lives in the right-hand status bar. It summarises every signal the extension tracks:

IndicatorMeaning
$(sync~spin) PhobosLanguage server starting
$(check) Phobos 0.4.2Healthy β€” server running, CLI detected, no diagnostics
$(info) Phobos … Β· NN informational diagnostics (across all open templates)
$(warning) Phobos … Β· NN warnings
$(error) Phobos … Β· NN errors
$(alert) Phobos CLI missingThe phobos CLI cannot be found
$(alert) Phobos stoppedLanguage server stopped (crashed / disabled)
$(alert) Phobos Β· N plugins failingN plugin subprocesses failed to start

Hover the chip to see a full Markdown breakdown (CLI path + version, plugin ready/failing counts, diagnostic counts per severity, active file kind, deprecation count). Click to open a QuickPick menu with targeted actions:

  • Open the Problems panel (when diagnostics are present)
  • Migrate deprecations in the active file
  • Restart the language server
  • Install or update the Phobos CLI
  • Install or update the language server
  • Show plugin output
  • Refresh plugins
  • Show the pipeline graph
  • Show the evaluated context
  • Open a project file (QuickPick across all templates)
  • View documentation

Disable the chip with phobos.statusBar.enabled: false β€” a window reload is required.

Webviews​

Pipeline Graph​

Phobos: Show Pipeline Graph opens a webview beside the editor that renders the active template as a layered DAG:

  • Stages appear as columns, with tasks, deployments, and nested pipelines as nodes inside them.
  • dependencies = [...] edges connect sibling nodes within a stage.
  • Pre / post phases are grouped inside their parent stage.
  • Clicking a node jumps to its declaration in the source file.

The graph refreshes when you save the active template or switch to a different Phobos file.

Evaluated Context​

Phobos: Show Evaluated Context opens a webview that lists every namespace the evaluator would expose at the cursor:

  • var.*, jwt.*, vcs_token.*, system.*, pipeline.*, and the current stage / task this.*.
  • Leaf values render their literal (for string / number / bool) and inferred type.
  • Unknown / dynamic values are flagged so you can see what only resolves at runtime.

The panel updates as you move the cursor, so you can inspect context at any position inside a stage / task / action body without leaving the editor.

Commands​

Every command is reachable from the Command Palette (Ctrl+Shift+P).

CommandPurpose
Phobos: Restart Language ServerRestart the LSP without reloading the whole VS Code window.
Phobos: Install or Update Language ServerDownload the latest phobos-language-server release into global storage and restart the client.
Phobos: Install or Update CLIInstall / update the phobos CLI via go install, a releases-page link, or a settings shortcut.
Phobos: View DocumentationOpen the hosted Phobos documentation in the default browser.
Phobos: Show Pipeline GraphOpen the DAG webview for the active template.
Phobos: Show Evaluated ContextOpen the evaluator-namespace webview for the cursor position.
Phobos: Open Project FileQuickPick across every pipeline.hcl / release_lifecycle.hcl in the workspace, badged by kind.
Phobos: Migrate Deprecations in Current FileApply every preferred deprecation fix in the active editor as a single undoable WorkspaceEdit.
Phobos: Refresh (Installed Plugins view title)Re-run plugin discovery on the server and refresh the tree.
Phobos: Refresh TemplatesRe-scan the workspace for template files and rebuild the Templates tree.
Phobos: Show Plugin OutputOpen the Phobos output channel where plugin-subprocess logs surface.

Configuration​

All settings live under the phobos namespace in VS Code. Open Settings (Ctrl+,) and search for phobos, or add them directly to settings.json.

Core​

SettingTypeDefaultDescription
phobos.languageServer.enablebooleantrueEnable / disable the language server entirely. When false, only syntax highlighting is available.
phobos.languageServer.pathstring | nullnullAbsolute path to the phobos-language-server binary. Honoured only in trusted workspaces. See Language-server discovery for the full cascade when unset.
phobos.languageServer.tcp.portnumber | nullnullConnect to an already-running language server over TCP instead of spawning a subprocess. See Development mode. Refused in untrusted workspaces.
phobos.cliPathstring | nullnullAbsolute path to the phobos CLI. Unset = PATH resolution. Used by the extension for plugin install, SSO login, and similar flows.
phobos.profilestring | nullnullPhobos profile name. Every extension-issued phobos … command is prefixed with -p <profile>.
phobos.instance.hoststring | nullnullPhobos registry UI host (e.g. phobos.example.com). Used by the Browse Online action on plugin tree items. When unset, inferred from .phobos/settings.json in the workspace.
phobos.editor.associateAllHclFilesbooleanfalseTreat every .hcl file in the workspace as a Phobos document. Off by default to avoid clashing with Terraform / Nomad / Packer extensions that also claim the .hcl extension. The canonical Phobos files (pipeline.hcl, release_lifecycle.hcl) and *.pbvars are always associated regardless of this setting. Toggling on claims every currently-open .hcl document immediately and routes future opens through the same path. Toggling off only affects future opens (existing docs keep their phobos language until you reload the window β€” VS Code provides no API to revert a doc's language assignment in place).
caution

On Windows, use forward slashes or escape backslashes in path settings: "C:/tools/phobos-language-server.exe" or "C:\\tools\\phobos-language-server.exe".

Inlay hints​

SettingDefaultDescription
phobos.inlayHints.enabledtrueMaster switch. When false, every sub-setting below is ignored.
phobos.inlayHints.variableTypestrueShow : string, : number, etc. after untyped variable defaults.
phobos.inlayHints.variableDefaultstrueShow the resolved default value next to var.<name> references where the default is a literal.
phobos.inlayHints.actionPluginstrueShow the resolved plugin instance next to each action "<plugin>_<name>" label β€” : docker.builder when plugin = docker.builder is set, : docker otherwise.
phobos.inlayHints.actionCountstrueShow per-task action + output counts (: 2 actions, 1 output). The outputs half is hidden when the task has none.
phobos.inlayHints.deploymentstrueShow environment = "…" after deployment blocks in lifecycle templates.
phobos.inlayHints.stagestrueShow a children-count summary after each stage "<name>" label (: 3 tasks, : 2 tasks, 1 pipeline). Main-phase direct children only.
tip

VS Code's global editor.inlayHints.enabled setting also needs to be on for any inlay hint to render.

SettingDefaultDescription
phobos.documentLinks.enabledtrueMaster switch for document links.
phobos.documentLinks.pluginDocstrueLink plugin_requirements.*.source values to the plugin registry.
phobos.semanticTokens.enabledtrueEnable LSP semantic tokens (layered on top of the TextMate grammar).
phobos.diagnostics.unusedAsHintfalseRender "unused variable / jwt / vcs_token / volume" diagnostics as Hint (dimmed, no Problems-panel count) instead of Information.
phobos.statusBar.enabledtrueShow the unified Phobos status-bar chip. Toggling requires a window reload.

Workspace Trust​

Phobos templates can reference plugins installed at ~/.phobos.d/plugins/, and the language server normally spawns those plugin binaries to fetch schemas used for completion, hover, and validation inside action bodies. In untrusted workspaces the extension launches the server with PHOBOS_LSP_DISABLE_PLUGINS=1, which disables the subprocess-spawn path entirely. Syntax highlighting and built-in diagnostics stay available; plugin-specific action-body features are suppressed until you grant trust. Trust transitions restart the language server automatically.

The following settings are declared as restrictedConfigurations β€” VS Code ignores workspace-scoped overrides for them until trust is granted, so a hostile workspace can't point the extension at an attacker-controlled binary, host, or profile:

  • phobos.languageServer.path
  • phobos.languageServer.tcp.port
  • phobos.cliPath
  • phobos.profile
  • phobos.instance.host

Virtual workspaces (over SSH, Codespaces with a virtual file system, etc.) are unsupported β€” the language server requires a local filesystem and the extension declines to start in those contexts.

Development mode​

When working on phobos-language-server locally you can run it in TCP mode and have the extension connect to it instead of managing the subprocess itself.

1. Start the language server in TCP mode:

Start the language server on TCP port 7777
phobos-language-server --port 7777

2. Configure the extension to connect via TCP:

settings.json
{
"phobos.languageServer.tcp.port": 7777
}

3. Reload the VS Code window (Ctrl+Shift+P β†’ Developer: Reload Window).

The extension will now connect to the running process. You can restart the language server binary and reload the window as needed without touching your extension installation.

note

phobos.languageServer.path is ignored when phobos.languageServer.tcp.port is set. TCP mode is also refused in untrusted workspaces β€” grant trust first.

Viewing language server logs​

If the extension is not behaving as expected, open the Phobos output channel:

  1. Open the Output panel (Ctrl+Shift+U or View β†’ Output).
  2. Select Phobos from the dropdown in the top-right corner of the panel.

The channel shows the resolved binary path, connection status, and any errors reported by the language server. A second channel β€” Phobos CLI β€” carries output from extension-issued phobos … commands (plugin install, SSO login).

Frequently asked questions (FAQ)​

The extension prompted me to install the language server. Is that expected?​

Yes, for registry installs (VS Code Marketplace and Open VSX). Registry VSIXes ship without the language-server binary to keep them small and portable β€” the extension downloads it on first launch and installs it into the editor's global storage. You only see the prompt once; subsequent launches resolve the installed binary directly. If you prefer a bundled install (e.g. for an air-gapped machine), download a platform-specific VSIX from the GitLab releases page instead β€” those include the binary.

Why is syntax highlighting working but none of the other features are?​

The LSP features (diagnostics, hover, completion, formatting, go-to-definition) require phobos-language-server to be running. Check the Phobos output channel for errors. The most common causes are:

  • The first-launch install prompt was cancelled. Run Phobos: Install or Update Language Server from the palette to retry.
  • You installed a platform-specific VSIX for the wrong OS / architecture β€” the bundled binary won't run on a mismatched platform.
  • You built the extension from source β€” the binary is not bundled in that case.

How do I upgrade the language server without reinstalling the extension?​

Run Phobos: Install or Update Language Server from the palette. The extension downloads the latest release, verifies its SHA-256, and restarts the language client. Works for every install channel.

How do I enable format on save?​

Add the following to your settings.json:

{
"[phobos]": {
"editor.formatOnSave": true
}
}

The language server crashed. What do I do?​

The extension automatically restarts the language server up to three times within a five-minute window. If it exhausts that budget it stops restarting and shows an error notification. Check the Phobos output channel for the error, then either fix the underlying issue or reload the VS Code window (Ctrl+Shift+P β†’ Developer: Reload Window) to try again.

Can I use the extension without the language server?​

Yes. Set phobos.languageServer.enable to false to use only syntax highlighting. Diagnostics, hover, completion, formatting, and everything else will be unavailable.

My file is not recognized as a Phobos file. What's wrong?​

The extension claims three filename patterns by default:

  • Files named exactly pipeline.hcl or release_lifecycle.hcl.
  • Any file with the .pbvars extension.

Other .hcl files are not claimed unless you opt in via phobos.editor.associateAllHclFiles β€” see Configuration. The default is off so the extension doesn't fight Terraform / Nomad / Packer for ownership of .hcl in mixed-tool workspaces.

If your file matches one of the patterns above but isn't highlighted, check that the language mode shown in the VS Code status bar reads Phobos rather than HCL or Plain Text. You can click the language indicator in the status bar to change it manually for the current file. To make the change permanent for a specific filename pattern, use VS Code's files.associations setting:

settings.json
{
"files.associations": {
"my_pipeline.hcl": "phobos"
}
}

Can I use the extension in a forked editor like VSCodium, Code OSS, Cursor, or Kiro?​

Yes. Install from the Open VSX Registry (for VSCodium / Code OSS / Gitpod / Theia) or the VS Code Marketplace (for forks that support it, such as Cursor and Kiro). The runtime-install flow works the same way. If you're using an editor that doesn't support VS Code extensions, the Phobos Language Server can still power diagnostics, completion, and hover through any LSP-capable client β€” see the Language Server guide.