Skip to content
vic

evanphx/jjsigns.nvim

Neovim gutter support for jj

evanphx/jjsigns.nvim.json
{
"createdAt": "2025-08-27T20:49:02Z",
"defaultBranch": "main",
"description": "Neovim gutter support for jj",
"fullName": "evanphx/jjsigns.nvim",
"homepage": null,
"language": "Lua",
"name": "jjsigns.nvim",
"pushedAt": "2025-08-27T20:55:27Z",
"stargazersCount": 12,
"topics": [],
"updatedAt": "2025-11-18T21:07:10Z",
"url": "https://github.com/evanphx/jjsigns.nvim"
}

A Neovim plugin that shows Jujutsu (jj) diff information in the gutter, similar to how gitsigns.nvim works for Git.

  • Gutter Signs: Shows , , , ~ signs in the sign column for added, changed, and deleted lines (same as gitsigns)
  • Line Highlighting: Optional highlighting of modified lines
  • Number Column: Optional highlighting of line numbers for modified lines
  • Real-time Updates: Updates signs as you type (with debouncing for performance)
  • Auto-attach: Automatically attaches to files in JJ repositories
  • Customizable: Configurable signs, colors, and behavior
{
'your-username/jjsigns.nvim',
config = function()
require('jjsigns').setup()
end
}
use {
'your-username/jjsigns.nvim',
config = function()
require('jjsigns').setup()
end
}
require('jjsigns').setup({
enabled = true,
attach = {
auto = true, -- Auto-attach to JJ repository files
},
signs = {
add = { text = '', numhl = 'JjSignsAddNr', linehl = 'JjSignsAddLn' },
change = { text = '', numhl = 'JjSignsChangeNr', linehl = 'JjSignsChangeLn' },
delete = { text = '', numhl = 'JjSignsDeleteNr', linehl = 'JjSignsDeleteLn' },
topdelete = { text = '', numhl = 'JjSignsDeleteNr', linehl = 'JjSignsDeleteLn' },
changedelete = { text = '~', numhl = 'JjSignsChangeNr', linehl = 'JjSignsChangeLn' },
},
sign_priority = 6,
signcolumn = true, -- Toggle with `:JjSigns toggle_signs`
numhl = false, -- Toggle with `:JjSigns toggle_numhl`
linehl = false, -- Toggle with `:JjSigns toggle_linehl`
-- JJ specific options
base = '@-', -- Base revision to compare against (default: parent revision)
-- Performance options
update_debounce = 100, -- Debounce time for updates in milliseconds
})
  • :JjSigns setup - Setup/reinitialize the plugin
  • :JjSigns toggle - Toggle the plugin on/off
  • :JjSigns enable - Enable the plugin
  • :JjSigns disable - Disable the plugin

The plugin defines the following highlight groups:

  • JjSignsAdd - Added lines sign
  • JjSignsChange - Changed lines sign
  • JjSignsDelete - Deleted lines sign
  • JjSignsTopdelete - Top deleted lines sign
  • JjSignsChangedelete - Changed+deleted lines sign
  • JjSignsAddNr - Added lines number
  • JjSignsChangeNr - Changed lines number
  • JjSignsDeleteNr - Deleted lines number
  • JjSignsTopdeletNr - Top deleted lines number
  • JjSignsChangedeletefNr - Changed+deleted lines number
  • JjSignsAddLn - Added lines background
  • JjSignsChangeLn - Changed lines background
  • JjSignsDeleteLn - Deleted lines background
  • JjSignsTopdeleteLn - Top deleted lines background
  • JjSignsChangedeleteLn - Changed+deleted lines background

By default, these link to the corresponding GitSigns* highlight groups if available, providing consistent styling with gitsigns.nvim.

  1. The plugin automatically detects JJ repositories when you open files
  2. For tracked files, it runs jj diff to compare the working copy with the parent revision (@-)
  3. It parses the diff output to identify added, changed, and deleted lines
  4. Signs are placed in the gutter using Neovim’s extmarks API
  5. Signs are updated in real-time as you edit files, with debouncing for performance

The plugin compares your working copy files against the base revision (default @-, the parent revision). This is equivalent to running:

Terminal window
jj diff --git --context=0 -r @-..@ -- path/to/file

You can change the base revision in the configuration if you want to compare against a different revision.

  • Uses debouncing (100ms by default) to avoid excessive updates while typing
  • Only processes files that are tracked in the JJ repository
  • Automatically detaches from buffers when they’re unloaded
  • Minimal memory footprint by storing only essential state
  1. Ensure jj is in your PATH: :!jj version
  2. Check if you’re in a JJ repository: :!jj status
  3. Verify the file is tracked: :!jj file list path/to/file
  4. Check if the plugin is enabled: :JjSigns toggle
  • Increase update_debounce in the configuration
  • Disable linehl or numhl if not needed

Contributions are welcome! Please feel free to submit issues and pull requests.

The codebase uses StyLua for formatting. To format the code:

Terminal window
# Install stylua (if not already installed)
cargo install stylua
# Format all Lua files
stylua --config-path stylua.toml lua/ plugin/ *.lua

MIT License - see LICENSE file for details.