A lightweight, transparent Mozilla SOPS integration for Neovim.
sops.nvim allows you to seamlessly open, edit, and save SOPS-encrypted files in Neovim. The encryption and decryption happen transparently in the background, ensuring your plaintext secrets never leak to disk in unencrypted files.
- 🔓 Transparent Decryption: Automatically detects if an opened file is SOPS-encrypted, decrypts it in-memory, and loads the plaintext content.
- 🔒 Transparent Encryption: Intercepts saving (
:w) and transparently re-encrypts the buffer contents before writing back to disk. - 📊 Statusline Integration: Exposes a helper function
require("sops").status()to display the encryption status (e.g.🔒SOPS) in your statusline.
- Neovim 0.10+ (uses the built-in
vim.systemAPI) - SOPS CLI tool installed and available in your
PATH. - A configured SOPS key provider (e.g., Age, PGP, AWS KMS, GCP KMS, HashiCorp Vault) configured on your system.
Install using your favorite package manager.
{
"RMTT/sops.nvim",
event = { "BufReadPre", "BufNewFile" },
opts = {
-- File pattern to trigger the SOPS check. Defaults to "*"
pattern = { "*.yaml", "*.json", "*.env", "*.ini" },
},
}use {
'RMTT/sops.nvim',
config = function()
require('sops').setup({
pattern = "*"
})
end
}The setup function accepts a configuration table:
require("sops").setup({
-- String or table specifying file patterns to check.
-- If a file matches and is recognized as SOPS-encrypted, the plugin intercepts it.
pattern = "*"
})sops.nvim provides the following user commands:
:Sops encrypt: Encrypt the current buffer's file and track it with SOPS. This is useful for encrypting a plaintext file for the first time.:Sops decrypt: Permanently decrypt the SOPS-encrypted file on disk, resetting the buffer type back to standard plaintext.
You can integrate the SOPS state into your statusline. The plugin provides:
require("sops").status(bufnr) -- returns "🔒SOPS" or ""Example with lualine.nvim
Add the following to your lualine configuration:
require('lualine').setup({
sections = {
lualine_x = {
{
function()
return require('sops').status()
end,
color = { fg = '#ff9e64' }, -- custom styling
},
'encoding',
'fileformat',
'filetype',
}
}
})- Detection: The plugin calls
sops filestatus <file>to verify if a file is actually encrypted with SOPS. If the file is not encrypted or not a SOPS file, the plugin does not interfere. - Buffer Options: On decryption, the buffer is set to
buftype=acwrite. This lets Neovim delegate write operations to our customBufWriteCmdhook where the encryption occurs. - Temporary Files: During save, a temporary file is created locally, populated with the plaintext buffer content, and used as the source for
sops edit <file>viaSOPS_EDITOR="cp <temp_file>". The temporary file is securely deleted immediately afterward.
If you use Nix, a development environment is provided:
# Enter the nix shell
nix develop
# Run the integration tests
nix develop --command nvim --headless -l tests/test_sops.luaThe Nix shell automatically wraps Neovim to load the local plugin, sets up sops and age binaries, and configures the environment with dummy test keys.