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
| Section | Option | Default | Description |
|---|---|---|---|
inlay_hints | enabled | true | Show inline version annotations next to each dependency |
inlay_hints | up_to_date_text | "✅" | Text shown when the dependency is up to date |
inlay_hints | needs_update_text | "❌ {}" | Text shown when an update exists; {} is replaced with the latest version |
cold_start | enabled | true | Load previously opened files from disk at startup so features work before the editor sends didOpen |
cold_start | rate_limit_ms | 100 | Minimum delay in milliseconds between cold-start registry fetches for the same URI |
cache | enabled | true | Whether 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 |
cache | fetch_timeout_secs | 5 | Per-package fetch timeout (1-300 seconds) |
cache | max_concurrent_fetches | 20 | Concurrent registry requests (1-100) |
loading_indicator | enabled | true | Show loading feedback during fetches |
loading_indicator | fallback_to_hints | true | Show loading in inlay hints if LSP progress unsupported |
loading_indicator | loading_text | "..." | Text shown during loading (max 100 chars) |
code_lens | enabled | true | Show 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 |
diagnostics | outdated_severity | "hint" | Severity for the outdated-version diagnostic |
diagnostics | unknown_severity | "warning" | Severity for an unresolvable/unknown package or version |
diagnostics | yanked_severity | "warning" | Severity for the yanked-version diagnostic |
diagnostics | unsatisfiable_severity | "warning" | Severity for the unsatisfiable-requirement diagnostic |
diagnostics | deprecated_severity | "warning" | Severity for the package-deprecation diagnostic |
diagnostics | mutable_ref_pin_severity | "hint" | Severity for the mutable-ref-pin diagnostic (GitHub Actions/GitLab CI) |
diagnostics | sha_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) |
diagnostics | unknown_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 |
diagnostics | mutable_ref_pin_enabled | true | Turns the mutable-ref-pin diagnostic and its bulk code lens off entirely — unlike the other diagnostics, severity alone cannot silence it |
diagnostics | vulnerabilities_enabled | true | Whether OSV.dev-backed vulnerability diagnostics run at all |
freshness | enabled | true | Flag a “latest” version still inside its cooldown window |
freshness | cooldown_secs | 259200 | Cooldown window in seconds (3 days), clamped to 0-30 days |
registries | workspace_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. |
registries | nuget_user_profile_sources | false | Whether 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 |
registries | swift_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 |
registries | gitlab_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 |
network | offline | false | Block every outbound registry/OSV/GitHub request; already-cached data still serves, uncached dependencies show an offline marker |
supply_chain | enabled | true | Show the OpenSSF Scorecard/build-provenance hover line, backed by deps.dev requests; false disables the requests and the section entirely |
license_policy | allow | [] | 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_policy | deny | [] | 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 |
typosquat | enabled | false | Whether the typosquat-similarity diagnostic runs at all — opt-in, backed by deps.dev’s v3alpha GetSimilarlyNamedPackages/GetDependents endpoints |
gossip | enabled | false | Whether 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.
| Setting | What a repository can do with it |
|---|---|
registries.gitlab_instance_host | Redirect 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_registries | Set "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_sources | Add user-profile NuGet sources as routing hops; credentials stay bound to the URL declared in your own user-level NuGet.Config |
registries.swift_keychain_credentials | Trigger a macOS Keychain access prompt; the credential goes only to registries declared in your user-level registries.json |
diagnostics.vulnerabilities_enabled, network.offline | Hide 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/16minimum, a unique-local (fc00::/7) range must be listed as a/48or longer prefix (for examplefd12:3456:789a::/48), not asfc00::/7. - A CIDR cannot name a host by its DNS name. A declared
*.internal,*.localor 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,0andfalsemean 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, anddiagnostics.yanked_severityare 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 asrequirements.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_severityflags 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’sdeprecatedfield and Composer’sabandonedfield 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_severityflags a GitHub Actions or GitLab CI dependency pinned to a mutable ref (a tag, e.g.actions/checkout@v4, or a GitLabcomponent: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>). Setdiagnostics.mutable_ref_pin_enabledtofalseto 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.offlineblocks 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 viaworkspace/didChangeConfigurationtakes effect immediately, with no editor restart. A change todiagnostics.*(for examplevulnerabilities_enabledor a*_severity) republishes diagnostics for every open document, so clients that only receivepublishDiagnostics(noworkspace/diagnostic/refreshsupport) 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_policydiagnostics 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 alicense: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/denytake exact, case-insensitive SPDX identifiers only — noAND/OR/WITHexpression parsing. See License Policy Diagnostic for matching rules and precedence.
Tip: Increase
fetch_timeout_secsfor 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.