Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Workspace trust

Helix has several features that can execute arbitrary code:

  • Language servers (LSP)
  • Debug adapters (DAP)
  • Local workspace configuration (.helix/config.toml, .helix/languages.toml)
  • Git integration (filters and other commands in a repository’s .git/config)

To protect against malicious projects (a checked-out PR, a freshly cloned repository, etc.) Helix gates these behind explicit per-workspace trust. By default language servers start automatically (their binaries come from $PATH, not from the workspace) and debug adapters may be launched, but loading .helix/config.toml or .helix/languages.toml and trusting a repository’s .git/config requires opting in. Note that debug adapters are never started automatically — you launch them yourself — but the same trust level still gates whether they may run. The model is intentionally similar to direnv: you run :workspace-trust once per workspace and Helix remembers across sessions.

Granting trust

When Helix opens a file inside a workspace it has never seen before, a modal trust prompt asks:

  • Trust — allow the workspace permanently.
  • Never — exclude the workspace; never prompt again.

<Esc> (or any other dismissal) caches “untrusted for this session” so the prompt doesn’t re-fire for every file you open in the workspace. The next time you start Helix in that workspace, it’ll prompt again.

A small [⚠] indicator appears in the bottom-right of the editor (next to the macro-recording [@]) whenever the workspace is in restricted mode and running :workspace-trust would change observable behavior — i.e. when there’s a local config to load or an LSP that would start.

You can also run :workspace-trust / :workspace-untrust / :workspace-exclude directly from the typed command prompt.

Revoking trust

Run :workspace-untrust to revoke a workspace’s trust grant. The next time you open a file in that workspace, you’re back to the untrusted hint.

Detecting changes after trust was granted

When you trust a workspace, Helix records a hash of every file under .helix/. If those files change afterwards (a malicious checkout, an inadvertent rebase, etc.) Helix detects the mismatch on the next open and reports the workspace as stale:

Workspace `.helix/` config changed since `:workspace-trust`. Local config
not loaded. Run `:workspace-trust` to re-allow.

In the stale state, language servers continue to run (they use the globally-configured binaries on $PATH, which are unchanged), but .helix/config.toml and .helix/languages.toml are not loaded. Run :workspace-trust again to re-pin the new hash.

Storage

Trust grants live in data_dir()/workspace_trust/, one small file per workspace. The filename is the SHA-256 of the workspace’s absolute path; the contents look like:

path = /home/user/proj1
hash = sha256:abc123...
excluded = false
  • Linux, macOS: ~/.local/share/helix/workspace_trust/
  • Windows: %AppData%\Roaming\helix\workspace_trust\

The one-file-per-workspace shape is safe under multiple concurrent Helix instances — different workspaces never write the same file.

Configuration

Settings live under [editor.workspace-trust]:

KeyValuesDefaultEffect
level"none", "servers", "insecure""servers"What is auto-trusted in every workspace. See below.
prompttrue, falsetrueWhether to surface the modal popup. The [⚠] indicator is shown regardless.
trustedlist of glob patterns[]Workspaces matching a pattern are trusted without a grant. Discouraged; see below.

Default: trust servers, prompt before loading workspace config.

[editor.workspace-trust]
level = "servers"
prompt = true

Language servers start automatically in every workspace — their binaries come from $PATH and are not workspace-controlled — and debug adapters you launch are allowed to run. The modal only appears when opening a file in a workspace whose .helix/config.toml or .helix/languages.toml would unlock something. Trust everything else with one keystroke per workspace, deny with another.

Maximum security: never prompt, trust each workspace by hand.

[editor.workspace-trust]
level = "none"
prompt = false

Nothing trusts implicitly: language servers, debug adapters, local config, and git Trust::Full are all off until you run :workspace-trust. The popup never appears; the [⚠] indicator in the bottom-right is your only signal that the current workspace is restricted. Suited to users who would rather grant trust as a deliberate action than dismiss a dialog.

Warning

level = "insecure" is highly discouraged. It implicitly trusts every workspace you open, which defeats the protection entirely: a checked-out PR with a malicious .helix/config.toml would get its configuration loaded and any language server it defines launched, with no prompt and no indicator. Only set this if you accept full responsibility for what’s in every project directory you cd into.

Trusting workspaces by path (discouraged)

If you keep all your repositories under a predictable layout, you can trust them in bulk with glob patterns instead of granting each workspace individually:

[editor.workspace-trust]
trusted = [
  "~/src/github.com/me/*",
  "~/work/repos/*",
]

A workspace whose path matches a pattern is trusted for everything, just as if you had run :workspace-trust in it. ~ and environment variables are expanded.

Warning

This is weaker than an explicit grant and is discouraged. It skips the .helix/ change detection entirely (a malicious checkout under a matched directory is never flagged as stale), and it trusts any repository that later lands under a matching path — including one you clone into ~/src/github.com/me/ from an untrusted source. Prefer granting trust per workspace; reach for this only if the prompts are genuinely disruptive to your workflow. An explicit :workspace-exclude still overrides a matching pattern.

Git trust

Workspace trust also gates how Helix opens git repositories. Untrusted workspaces are opened in gix’s Trust::Reduced mode; trusted workspaces use Trust::Full.

Under Trust::Reduced, gix still runs the full filter pipeline (so built-in conversions like core.autocrlf keep working) but ignores configuration coming from the untrusted, repository-local .git/config. That means filter.*.clean / filter.*.smudge drivers and similar keys that would otherwise execute external programs are dropped until you trust the workspace.

Helix forces this trust level explicitly rather than letting gix infer it from .git directory ownership — a malicious .git/config in a directory you happen to own is still treated as untrusted until you run :workspace-trust.