Home
Softono
camouflage.nvim

camouflage.nvim

Open source MIT Lua
46
Stars
0
Forks
0
Issues
0
Watchers
1 month
Last Commit

About camouflage.nvim

Mask sensitive values in config files during screen sharing. Supports .env, JSON, YAML, TOML, XML, Terraform/HCL, Dockerfile, and more. Zero file modification - uses Neovim extmarks.

Platforms

Web Self-hosted Docker

Languages

Lua

Links

camouflage.nvim

Hide sensitive values in configuration files during screen sharing.

A Neovim plugin that visually masks secrets in .env, .json, .yaml, .toml, .properties, .netrc, .xml, .http, Terraform/HCL (.tf, .tfvars, .hcl), and Dockerfile files using extmarks - without modifying the actual file content.

Version CI Neovim License Ask DeepWiki

Demo

camouflage.nvim demo

Features

  • Multi-format support: .env, .json, .yaml, .yml, .toml, .properties, .ini, .conf, .sh, .netrc, .xml, .http, .tf, .tfvars, .hcl, Dockerfile, Containerfile
  • Nested key support: Handles database.connection.password in JSON/YAML/XML
  • All value types: Masks strings, numbers, and booleans
  • Multiple styles: stars, dotted, text, scramble
  • Reveal & Yank: Temporarily reveal or copy masked values
  • Follow Cursor Mode: Auto-reveal current line as you navigate
  • Have I Been Pwned: Check passwords against breach database (Neovim 0.10+)
  • JWT Expiry Hints: Decode exp claim and show "expires in 2h" badges
  • Hot Reload: Config changes apply immediately
  • Event System: Hooks for extending functionality
  • TreeSitter Support: Enhanced parsing for JSON/YAML/TOML/XML/HTTP/HCL/Dockerfile
  • Telescope/Snacks Integration: Mask values in preview buffers
  • Zero file modification: All masking is purely visual
  • Extensible: Register custom parsers for unsupported formats via a public API

Security Model

camouflage hides sensitive values visually, by drawing over them with virtual text. It does not change the file, and it does not encrypt or remove anything.

It protects against casual exposure of secrets on screen: shoulder-surfing, screen sharing, pair programming, screenshots, and demos.

It does not protect against anything that reads the buffer or file contents directly, because the real text is still there underneath the mask:

  • search results and grep tools, including Telescope live_grep result lines (only the preview buffer is masked, not the matched result rows)
  • LSP servers, completion sources, and AI assistants
  • :%print, :substitute previews, :w/:saveas, and yanking with yy/"+y
  • the +/* clipboard registers (use :CamouflageYank, which copies the real value deliberately with a confirm prompt and timed auto-clear)

For per-repo .camouflage.yaml files, masking config is applied as data only (no code execution). If you don't trust the repositories you open, set project_config.secure = true to gate the file behind Neovim's vim.secure/:trust mechanism.

The scramble style is cosmetic, not protective: the mask is a shuffle of the real characters, so it leaks the value's length and character set.

Installation

lazy.nvim

{
  'zeybek/camouflage.nvim',
  event = 'VeryLazy',
  opts = {},
  keys = {
    { '<leader>ct', '<cmd>CamouflageToggle<cr>', desc = 'Toggle Camouflage' },
    { '<leader>cr', '<cmd>CamouflageReveal<cr>', desc = 'Reveal Line' },
    { '<leader>cy', '<cmd>CamouflageYank<cr>', desc = 'Yank Value' },
    { '<leader>cf', '<cmd>CamouflageFollowCursor<cr>', desc = 'Follow Cursor' },
  },
}
Other package managers

packer.nvim

use {
  'zeybek/camouflage.nvim',
  config = function()
    require('camouflage').setup()
  end
}

vim-plug

Plug 'zeybek/camouflage.nvim'

" In your init.lua or after/plugin/camouflage.lua:
lua require('camouflage').setup()

mini.deps

local add = MiniDeps.add
add({
  source = 'zeybek/camouflage.nvim',
})
require('camouflage').setup()

Manual Installation

git clone https://github.com/zeybek/camouflage.nvim.git \
  ~/.local/share/nvim/site/pack/plugins/start/camouflage.nvim

Then add to your init.lua:

require('camouflage').setup()

Configuration

The plugin works with zero configuration. Here's a quick overview of common options:

require('camouflage').setup({
  enabled = true,
  auto_enable = true,
  style = 'stars',           -- 'text' | 'dotted' | 'stars' | 'scramble'
  mask_char = '*',
  debounce_ms = 150,
  max_lines = 5000,

  reveal = {
    follow_cursor = false,   -- Auto-reveal current line
  },

  yank = {
    confirm = true,          -- Require confirmation before copying
    auto_clear_seconds = 30, -- Auto-clear clipboard
  },

  integrations = {
    telescope = true,
    cmp = { disable_in_masked = true },
  },
})

Full configuration reference on the wiki.

Commands

Command Description
:CamouflageToggle Toggle camouflage on/off
:CamouflageReveal Reveal masked values on current line
:CamouflageYank Copy unmasked value at cursor to clipboard
:CamouflageFollowCursor Toggle follow cursor mode
:CamouflageStatus Show status and masked count
:CamouflageRefresh Refresh decorations
:CamouflagePwnedCheck Check if value under cursor is pwned
:CamouflagePwnedCheckBuffer Check all values in buffer
:CamouflageExpiryToggle Toggle JWT expiry check on/off
:CamouflageInit Create .camouflage.yaml in project root
:CamouflageParsers List registered parsers (debug)

Full commands list on the wiki.

Supported File Formats

Format Extensions Nested Keys
Environment .env, .env.*, .envrc, .sh No
JSON .json Yes
YAML .yaml, .yml Yes
TOML .toml Yes (sections)
Properties .properties, .ini, .conf, credentials Yes (sections)
Netrc .netrc, _netrc No
XML .xml Yes
HTTP .http No
HCL / Terraform .tf, .tfvars, .hcl Yes
Dockerfile Dockerfile, Containerfile, *.dockerfile No

For unsupported formats, you can define custom patterns.

Documentation

For detailed documentation, visit the Wiki:

You can also use :help camouflage within Neovim.

Also Available

License

MIT License - see LICENSE for details.