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

Configuration

deps-lsp is configured entirely through LSP initializationOptions (and updated live via workspace/didChangeConfiguration) — there is no separate config file. The README shows the most commonly changed options inline; this page is the exhaustive reference for every section and option.

For the inlay hint icons and the hover/diagnostic/code lens text conventions those options control, see Conventions.

Configuration Reference

SectionOptionDefaultDescription
inlay_hintsenabledtrueShow inline version annotations next to each dependency
inlay_hintsup_to_date_text"✅"Text shown when the dependency is up to date
inlay_hintsneeds_update_text"❌ {}"Text shown when an update exists; {} is replaced with the latest version
cold_startenabledtrueLoad previously opened files from disk at startup so features work before the editor sends didOpen
cold_startrate_limit_ms100Minimum delay in milliseconds between cold-start registry fetches for the same URI
cacheenabledtrueWhether the HTTP entry-map cache is used at all; false fetches fresh on every request and never stores. Overridden to behave as true while network.offline is set
cachefetch_timeout_secs5Per-package fetch timeout (1-300 seconds)
cachemax_concurrent_fetches20Concurrent registry requests (1-100)
loading_indicatorenabledtrueShow loading feedback during fetches
loading_indicatorfallback_to_hintstrueShow loading in inlay hints if LSP progress unsupported
loading_indicatorloading_text"..."Text shown during loading (max 100 chars)
code_lensenabledtrueShow the “Update N outdated dependencies” code lens, and (GitHub Actions/GitLab CI, gated additionally by diagnostics.mutable_ref_pin_enabled) the bulk “Pin N {noun} to commit SHA” code lens
diagnosticsoutdated_severity"hint"Severity for the outdated-version diagnostic
diagnosticsunknown_severity"warning"Severity for an unresolvable/unknown package or version
diagnosticsyanked_severity"warning"Severity for the yanked-version diagnostic
diagnosticsunsatisfiable_severity"warning"Severity for the unsatisfiable-requirement diagnostic
diagnosticsdeprecated_severity"warning"Severity for the package-deprecation diagnostic
diagnosticsmutable_ref_pin_severity"hint"Severity for the mutable-ref-pin diagnostic (GitHub Actions/GitLab CI)
diagnosticssha_comment_mismatch_severity"warning"Severity for the SHA-comment-mismatch diagnostic (GitHub Actions or GitLab CI/CD SHA pin whose # tag comment is not that commit’s tag)
diagnosticsunknown_ref_severity"warning"Severity for the unknown-ref diagnostic (GitHub Actions or GitLab CI/CD tag pin whose ref is a full release no published tag matches); no on/off toggle
diagnosticsmutable_ref_pin_enabledtrueTurns the mutable-ref-pin diagnostic and its bulk code lens off entirely — unlike the other diagnostics, severity alone cannot silence it
diagnosticsvulnerabilities_enabledtrueWhether OSV.dev-backed vulnerability diagnostics run at all
freshnessenabledtrueFlag a “latest” version still inside its cooldown window
freshnesscooldown_secs259200Cooldown window in seconds (3 days), clamped to 0-30 days
registriesworkspace_registries"public_only"Which workspace-declared registry index hosts are ever fetched, across every ecosystem (Cargo’s .cargo/config.toml/[source], npm’s .npmrc, PyPI’s --index-url/Poetry/uv sources, Go’s $GOENV GOPROXY, NuGet’s NuGet.Config, Swift’s registries.json) — "public_only", "off", or "all"; see Cargo Custom/Private Registries, npm Custom/Private Registries, PyPI Custom/Private Indexes, Go GOPROXY/GOPRIVATE Support, NuGet Private/Custom Feeds, and Swift Package Registries.
registriesnuget_user_profile_sourcesfalseWhether a NuGet user-profile-tier NuGet.Config source with no repo-declared counterpart becomes a routing hop (AlternateRegistry-sourced — OSV/deps.dev/hover-trust suppressed for it), instead of only ever supplying credentials for a matching repo-declared source; see NuGet Private/Custom Feeds
registriesswift_keychain_credentials"disabled""enabled" also reads macOS Keychain credentials for user-declared Swift SE-0292 registries (may show a macOS access prompt; ignored by deps-cli); see Swift macOS Keychain credentials
registriesgitlab_instance_host""The self-hosted GitLab instance host that a project: include and a $CI_SERVER_FQDN-relative component: include resolve against, which never receives GITLAB_TOKEN (the token goes only to gitlab.com or the host in the GITLAB_TOKEN_HOST environment variable). Unset ("") means neither form is version-resolved; see GitLab CI/CD Self-Hosted Instances
networkofflinefalseBlock every outbound registry/OSV/GitHub request; already-cached data still serves, uncached dependencies show an offline marker
supply_chainenabledtrueShow the OpenSSF Scorecard/build-provenance hover line, backed by deps.dev requests; false disables the requests and the section entirely
license_policyallow[]SPDX identifiers a dependency’s license must include at least one of, when non-empty; produces a WARNING diagnostic otherwise. Invalid entries are dropped with a logged warning, not rejected. See License Policy Diagnostic
license_policydeny[]SPDX identifiers a dependency’s license must not include any of; produces an ERROR diagnostic when matched (wins over allow). Invalid entries are dropped with a logged warning, not rejected. See License Policy Diagnostic
typosquatenabledfalseWhether the typosquat-similarity diagnostic runs at all — opt-in, backed by deps.dev’s v3alpha GetSimilarlyNamedPackages/GetDependents endpoints
gossipenabledfalseWhether deps.dev GOSSIP signals (Dynamic Cooldown, low-usage) are fetched at all — opt-in, backed by deps.dev’s v3alpha GetFindingsBatch/GetFindings endpoints

Editor workspace settings and trust

Editors merge project-level settings into the initializationOptions and workspace/didChangeConfiguration payloads the server receives: Zed’s .zed/settings.json, VS Code’s .vscode/settings.json, Helix’s .helix/languages.toml, and coc.nvim’s .vim/coc-settings.json. The server cannot tell a repository-written value from a user-written one, so any registries.* or diagnostics.* field can be set by a repository you open. Credentials are therefore never bound to a settings value; they come from your process environment.

SettingWhat a repository can do with it
registries.gitlab_instance_hostRedirect GitLab host resolution (unauthenticated requests only). GITLAB_TOKEN is not sent to it unless you also export the same host as GITLAB_TOKEN_HOST
registries.workspace_registriesSet "all". Alone this reaches no private host: the private hosts and CIDR ranges in your DEPS_LSP_PRIVATE_REGISTRY_HOSTS environment variable are the effective control. Once you export that variable, any repository you open can send unauthenticated, blind GET requests to the listed hosts, on any port. Loopback, link-local, cloud-metadata, unspecified and reserved hosts are never reachable
registries.nuget_user_profile_sourcesAdd user-profile NuGet sources as routing hops; credentials stay bound to the URL declared in your own user-level NuGet.Config
registries.swift_keychain_credentialsTrigger a macOS Keychain access prompt; the credential goes only to registries declared in your user-level registries.json
diagnostics.vulnerabilities_enabled, network.offlineHide vulnerability findings or all registry data in the editor

Warning: If your editor lets a repository’s settings change the server’s environment or binary (for example Zed’s lsp.<id>.binary), that is already code execution under the editor’s own trust prompt, which this server cannot guard against.

Private registry allowlist

registries.workspace_registries = "all" allows public hosts plus the hosts listed in the DEPS_LSP_PRIVATE_REGISTRY_HOSTS environment variable (read by both deps-lsp and deps-cli; there is no settings or config-file field for it). It is a comma-separated list of CIDR ranges (10.0.0.0/8), bare IPs and exact lowercase host names (registry.corp.internal, punycode for non-ASCII), for example DEPS_LSP_PRIVATE_REGISTRY_HOSTS=10.20.0.0/16,registry.corp.internal.

  • The setting is repository-controllable, so the variable, not the setting, is the effective control. List registry hosts or narrow CIDRs only; never a broad range.
  • An allowlisted host is reachable on any port.
  • Prefixes shorter than /8 (IPv4) or /16 (IPv6), ports, paths, wildcards, brackets, zone ids and userinfo are rejected. Because of the /16 minimum, a unique-local (fc00::/7) range must be listed as a /48 or longer prefix (for example fd12:3456:789a::/48), not as fc00::/7.
  • A CIDR cannot name a host by its DNS name. A declared *.internal, *.local or single-label host (https://nexus/) is accepted when the list contains at least one CIDR, and then only connects if it resolves into a listed CIDR; list the host name itself to vouch for it regardless of the address it resolves to. One bad entry invalidates the whole variable (nothing is allowed) and the server warns once without echoing the value. Unset, empty, 0 and false mean no private host.
  • With "all" but no valid variable the server behaves like "public_only" and shows a warning once per change.
  • The GitHub Action needs the variable in the step’s env:.

When a registry host is blocked by the access policy, the hint that suggests workspace_registries = "all" and DEPS_LSP_PRIVATE_REGISTRY_HOSTS is not shown at "off" or for a host refused under every policy (loopback, link-local, cloud-metadata), where the allowlist cannot help.

Proxies and guarded registry traffic

Registry requests that the access policy guards (hosts declared by the workspace, pinned registries, and operator-owned sources such as the $GOENV GOPROXY, your user ~/.npmrc and your user-profile NuGet.Config) connect directly by default and bypass the system and HTTP(S)_PROXY proxy. The connect-time SSRF guard checks the address a host actually resolves to, and a proxy would hide that address from it. Public default registries (crates.io, npm, PyPI and so on) keep using your proxy.

If a system proxy is detected, the server says so once at startup: deps-lsp logs a warning and shows a window/showMessage warning, and deps-cli prints one line on stderr. To route guarded traffic through the proxy as well, set:

DEPS_LSP_WORKSPACE_REGISTRY_PROXY=proxy

Any other value, including unset, keeps the direct default. The variable is read from the environment only, never from settings, so a repository cannot change it. With it set, a proxy whose own host is localhost or a private name works on every tier.

Routing through a proxy is weaker than the direct default:

  • Weaker check. The server cannot see the address the proxy connects to. It resolves the target host itself and checks that answer against the policy first, but DNS can rebind between this local check and the proxy’s own lookup.
  • Local DNS is required. On a network whose local DNS cannot resolve external names, every guarded request fails at that check (fail closed), even though the proxy could have reached the host.
  • Same-host redirects only. Cross-host redirects are stopped, so a registry that redirects to a CDN host fails to resolve versions.

Blocked or unreachable guarded hosts fail after a 10 second connect timeout. In the GitHub Action, set the variable in the step’s env:.

GITLAB_TOKEN is sent only to gitlab.com, or to the single host named by the GITLAB_TOKEN_HOST environment variable when set (for example GITLAB_TOKEN_HOST=gitlab.mycorp.dev). An invalid GITLAB_TOKEN_HOST disables the token entirely. See GitLab CI/CD Self-Hosted Instances.

Full Example

{
  "inlay_hints": {
    "enabled": true,
    "up_to_date_text": "✅",
    "needs_update_text": "❌ {}"
  },
  "diagnostics": {
    "outdated_severity": "hint",
    "unknown_severity": "warning",
    "yanked_severity": "warning",
    "unsatisfiable_severity": "warning",
    "deprecated_severity": "warning",
    "mutable_ref_pin_severity": "hint",
    "sha_comment_mismatch_severity": "warning",
    "unknown_ref_severity": "warning",
    "mutable_ref_pin_enabled": true,
    "vulnerabilities_enabled": true
  },
  "freshness": {
    "enabled": true,
    "cooldown_secs": 259200
  },
  "cache": {
    "enabled": true,
    "fetch_timeout_secs": 5,
    "max_concurrent_fetches": 20
  },
  "loading_indicator": {
    "enabled": true,
    "fallback_to_hints": true,
    "loading_text": "..."
  },
  "cold_start": {
    "enabled": true,
    "rate_limit_ms": 100
  },
  "code_lens": {
    "enabled": true
  },
  "registries": {
    "workspace_registries": "public_only",
    "nuget_user_profile_sources": false,
    "gitlab_instance_host": "",
    "swift_keychain_credentials": "disabled"
  },
  "network": {
    "offline": false
  },
  "supply_chain": {
    "enabled": true
  },
  "license_policy": {
    "allow": [],
    "deny": []
  },
  "typosquat": {
    "enabled": false
  },
  "gossip": {
    "enabled": false
  }
}

Notes and Caveats

Note: diagnostics.outdated_severity, diagnostics.unknown_severity, diagnostics.unsatisfiable_severity, and diagnostics.yanked_severity are all honored end-to-end. The yanked diagnostic fires in two independent cases (never both at once for the same dependency): (1) the dependency’s in-use version — lock-file-resolved, or an exact pin such as requirements.txt’s ==1.2.3 — is itself reported as yanked/deprecated/retracted, supported for Cargo, npm, PyPI, Bundler, and Dart; or (2) the dependency’s declared version requirement (a range) is currently satisfiable only by yanked versions, even with no lock file at all. See Yanked Version Diagnostic for exact semantics and per-ecosystem coverage of each case (RubyGems cannot be detected by either mechanism, since its registry omits yanked versions from the list entirely rather than flagging them).

Note: diagnostics.deprecated_severity flags a dependency whose package — not a specific version — is reported as deprecated/abandoned (This package is deprecated: <reason>), with a matching hover section and, for Composer packages naming a successor, a “Replace with X” quick fix. Currently sourced from npm’s deprecated field and Composer’s abandoned field only. See Package Deprecation Diagnostics for the full ecosystem coverage table and how this differs from the yanked diagnostic above.

Note: diagnostics.mutable_ref_pin_severity flags a GitHub Actions or GitLab CI dependency pinned to a mutable ref (a tag, e.g. actions/checkout@v4, or a GitLab component: pinned via ~latest/a partial version) instead of a full commit SHA — a supply-chain hardening recommendation independent of the outdated-version check above (a dependency can be both up to date and mutable). Comes with a “Pin <name> to commit SHA” quick fix, and a bulk “Pin N {noun} to commit SHA” code lens batching every resolvable one in the document, when the commit SHA is already known (GitHub Actions rewrites the ref to <sha> # <tag>; GitLab CI rewrites to a bare <sha>). Set diagnostics.mutable_ref_pin_enabled to false to turn both the diagnostic and the bulk lens off entirely — unlike the other diagnostics above, severity alone cannot silence it. See Mutable-Ref-Pin Diagnostic and Bulk “Pin All to SHA” Code Lens for full details.

Note: The release-freshness signal applies uniformly across all ecosystems — there is no per-ecosystem override. Coverage depth varies with what each registry exposes (e.g. Deno’s jsr: specifiers get full coverage at no extra request cost; Swift, GitHub Actions, and Maven/Gradle have partial coverage since their APIs don’t expose per-version publish dates directly). See Swift/GitHub Actions Release-Freshness Coverage and Maven/Gradle Release-Freshness Coverage for per-ecosystem details.

Note: network.offline blocks every outbound request the server makes (registry, OSV vulnerability, and GitHub tags), across every ecosystem. Already-cached data keeps serving; an uncached dependency shows an offline marker in inlay hints, and hover appends a footer stating that version and vulnerability data were not checked. Toggling it via workspace/didChangeConfiguration takes effect immediately, with no editor restart. A change to diagnostics.* (for example vulnerabilities_enabled or a *_severity) republishes diagnostics for every open document, so clients that only receive publishDiagnostics (no workspace/diagnostic/refresh support) do not keep stale diagnostics.

Note: The supply-chain trust signal only appears for npm, Cargo, Go, Maven, PyPI, Bundler, and NuGet (Composer, Dart, and Swift have no deps.dev coverage) and only for a dependency with a concrete in-use version — a lock-file-resolved version, or an exact requirement pin. It shows the linked source repository’s OpenSSF Scorecard score and the resolved version’s SLSA/attestation provenance status; a Scorecard fetched via a package-self-reported (rather than attested) repository link is marked *(self-reported repo)*. Informational only — a low score never becomes a diagnostic. See Supply-Chain Trust Signal for the full details.

Note: license_policy diagnostics only fire for dependencies this feature already has license data for — Composer, Dart, Swift, Deno, and Gradle. This list is a snapshot, not a designed-in limit: any ecosystem whose registry client gains a license: field on its version type joins the diagnostic set automatically, with no further code changes required. Gradle’s Maven Central POM licenses are free text (e.g. "The Apache Software License, Version 2.0"), not SPDX identifiers, so they are normalized against a known-variant table before evaluation — the table covers the common Apache/MIT/BSD/GPL/LGPL/AGPL/EPL/MPL/CDDL/ISC families but is not exhaustive. A free-text license the table doesn’t recognize is never falsely flagged, but it is also not enforced — it is silently excluded from evaluation rather than guessed at, the same as a dependency with no license data at all. A dependency with no known license is never treated as a violation. allow/deny take exact, case-insensitive SPDX identifiers only — no AND/OR/WITH expression parsing. See License Policy Diagnostic for matching rules and precedence.

Tip: Increase fetch_timeout_secs for slower networks. The per-dependency timeout prevents slow packages from blocking others. Cold start support ensures LSP features work immediately when your IDE restores previously opened files.