kubectl (optional) - for fetching CRD schemas from your Kubernetes cluster:TSInstall yaml)Install the plugin with your preferred package manager:
{
"mosheavni/yaml-companion.nvim",
opts = {
-- Add any options here, or leave empty to use the default settings
-- lspconfig = {
-- settings = { ... }
-- },
},
config = function(_, opts)
local cfg = require("yaml-companion").setup(opts)
vim.lsp.config("yamlls", cfg)
vim.lsp.enable("yamlls")
end,
}
yaml-companion comes with the following defaults (pass these to opts):
{
-- Shared cache directory for all cached data (datree catalog, cluster CRD schemas)
cache_dir = nil, -- Override location (default: stdpath("data")/yaml-companion.nvim/)
-- Built in file matchers
builtin_matchers = {
-- Detects Kubernetes files based on content
kubernetes = { enabled = true },
cloud_init = { enabled = true }
},
-- Additional schemas available in the picker
schemas = {
--{
--name = "Kubernetes 1.32.1",
--uri = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.32.1-standalone-strict/all.json",
--},
},
-- Key navigation features
keys = {
enabled = true, -- Enable key navigation features (creates :YamlKeys command)
include_values = false, -- Show values in quickfix entries
max_value_length = 50, -- Truncate long values in display
},
-- Modeline features
modeline = {
auto_add = {
on_attach = false, -- Auto-add modelines when yamlls attaches
on_save = false, -- Auto-add modelines before saving
},
overwrite_existing = false, -- Whether to overwrite existing modelines
validate_urls = false, -- Check if schema URL exists (slower)
notify = true, -- Show notifications when modelines are added
},
-- Datree CRD catalog settings
datree = {
cache_ttl = 3600, -- Cache TTL in seconds (0 = never expire, -1 = disable)
raw_content_base = "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/",
},
-- Cluster CRD features
cluster_crds = {
enabled = true, -- Enable cluster CRD features
fallback = false, -- Auto-fallback to cluster when Datree doesn't have schema
-- Auto-apply cluster CRD schema on buffer attach (cache-first). false | "modeline" | "lsp"
auto_apply = false,
cache_ttl = 86400, -- Cache expiration in seconds (default: 24h, 0 = never expire)
},
-- Customize which API groups are considered "core" (skipped by CRD detection)
core_api_groups = {
[""] = true,
["apps"] = true,
["batch"] = true,
["networking.k8s.io"] = true,
-- ... add or remove as needed
},
-- Pass any additional options that will be merged in the final LSP config
lspconfig = {
flags = {
debounce_text_changes = 150,
},
settings = {
redhat = { telemetry = { enabled = false } },
yaml = {
validate = true,
format = { enable = true },
hover = true,
schemaStore = {
enable = true,
url = "https://www.schemastore.org/api/json/catalog.json",
},
schemaDownload = { enable = true },
schemas = {},
trace = { server = "debug" },
},
},
},
}
All commands and their Lua equivalents are listed in Commands and Lua API.
Schemas are auto-detected and applied, resolved from these sources in order:
schemas tableAuto-detection: Kubernetes manifests are detected via kind:/apiVersion: fields (core resources map to the appropriate Kubernetes schema); cloud-config files via the #cloud-config header. Disable either matcher with builtin_matchers.<name>.enabled = false.
Manual selection: open_ui_select() opens a vim.ui.select picker of all available schemas (works with any picker, e.g. dressing.nvim).
Progress notifications: Applying a schema sends an LSP $/progress notification, integrating with UIs like fidget.nvim.
Statusline:
local function get_schema()
local schema = require("yaml-companion").get_buf_schema(0)
if schema.result[1].name == "none" then
return ""
end
return schema.result[1].name
end
Navigate YAML keys using treesitter (:TSInstall yaml).
:YamlKeys — populate the quickfix list with every key's dotted path (.spec.containers[0].image).get_key_at_cursor() — returns { key, value, human, line, col } for the cursor position.Example keymap (copy the key path under the cursor):
vim.keymap.set("n", "<leader>yk", function()
local info = require("yaml-companion").get_key_at_cursor()
if info then
vim.fn.setreg("+", info.key)
end
end, { desc = "Copy YAML key path" })
Modelines are YAML comments that pin a schema and persist in the file:
# yaml-language-server: $schema=https://example.com/schema.json
:YamlBrowseDatreeSchemas [modeline|lsp] — browse the datreeio/CRDs-catalog and apply a schema. Without an argument you're prompted to add it as a modeline (persisted) or set it as the LSP schema (session only).:YamlAddCRDModelines — detect non-core CRDs in the buffer (by kind:/apiVersion:) and add Datree modelines. Core resources are skipped (handled by the kubernetes matcher).require("yaml-companion").add_crd_modelines(0, { dry_run = true }) -- preview
require("yaml-companion").add_crd_modelines(0, { overwrite = true }) -- overwrite existing
Add modelines automatically:
modeline = { auto_add = { on_attach = true, on_save = true } }
For CRDs not in the Datree catalog (custom/internal), fetch schemas directly from your cluster via kubectl — which must be installed, configured for cluster access, and the CRDs installed.
cluster_crds = { enabled = true }
:YamlFetchClusterCRD — detect CRDs in the buffer, fetch their OpenAPI schema via kubectl get crd, cache it, and add a modeline.:YamlBrowseClusterCRDs [modeline|lsp] — browse all cluster CRDs and apply one (same prompt as Datree).Auto-fallback to the cluster when Datree lacks a schema:
cluster_crds = { enabled = true, fallback = true },
modeline = { auto_add = { on_attach = true } },
[!NOTE] With
fallback = true,modeline.validate_urlsis forced totrue. Explicitly settingvalidate_urls = falsealongsidefallback = trueerrors at startup.
Auto-apply on attach: set cluster_crds.auto_apply to apply a cluster CRD schema automatically when yamlls attaches — the first non-core CRD is detected, resolved from the cache (or fetched on a miss, cached per kubectl context), and applied. Stays silent if kubectl is unavailable or no CRD is found.
cluster_crds = { enabled = true, auto_apply = "lsp" }, -- "lsp" (session only) or "modeline" (persisted)
[!IMPORTANT]
auto_applyis cache/cluster-first and takes precedence over the Datree-basedmodeline.auto_add.on_attach, which is skipped on attach when it's set. Leaveauto_apply = falseto use Datree-first modelines.
Caches live in ~/.local/share/nvim/yaml-companion.nvim/ — crd-cache/<context>/<crd>.json for cluster CRD schemas and datree-catalog.json for the Datree index. Override with cache_dir.
TTLs (seconds): datree.cache_ttl (default 3600; 0 = never, -1 = disable) and cluster_crds.cache_ttl (default 86400; 0 = never).
Clear by deleting the directory:
rm -rf ~/.local/share/nvim/yaml-companion.nvim/
| Command | Description |
|---|---|
:YamlKeys |
Open quickfix with all YAML keys in the buffer |
:YamlBrowseDatreeSchemas [action] |
Browse Datree CRD catalog. Optional: modeline or lsp to skip action prompt |
:YamlAddCRDModelines |
Detect CRDs in buffer and add schema modelines |
:YamlFetchClusterCRD |
Fetch CRD schema from Kubernetes cluster for current buffer |
:YamlBrowseClusterCRDs [action] |
Browse all CRDs in your cluster. Optional: modeline or lsp to skip action prompt |
All public functions are available via require("yaml-companion"):
| Function | Description |
|---|---|
setup(opts) |
Initialize the plugin with configuration options |
get_buf_schema(bufnr) |
Get the current schema for a buffer |
set_buf_schema(bufnr, schema) |
Set the schema for a buffer |
open_ui_select() |
Open schema picker (all available schemas) |
open_datree_crd_select(action?) |
Browse Datree catalog. If action is nil, prompts user; if "modeline" or "lsp", applies directly |
open_cluster_crd_select(action?) |
Browse CRDs from cluster. If action is nil, prompts user; if "modeline" or "lsp", applies directly |
fetch_cluster_crd(bufnr) |
Fetch CRD schema from cluster for buffer |
add_crd_modelines(bufnr, opts) |
Auto-detect CRDs and add modelines |
get_modeline(bufnr) |
Get modeline info from a buffer |
get_keys_quickfix(bufnr, opts) |
Get all YAML keys in quickfix format |
get_key_at_cursor() |
Get key info at current cursor position |
load_matcher(name) |
Load a custom matcher |
Run :checkhealth yaml-companion to verify your setup:
This repository was originally forked from someone-stole-my-name/yaml-companion.nvim. It has since been unforked and is now maintained independently. The original commit history has been preserved.