๐Ÿ“ fusen.nvim

July 19, 2026 ยท View on GitHub

A sticky notes plugin for Neovim with git branch awareness. Place sticky notes (fusen - ไป˜็ฎ‹ in Japanese) in your code and keep them organized across different git branches.

Neovim Lua License Tests

https://github.com/user-attachments/assets/4ebcb70b-0be8-4668-8a65-2eb5c950aec4

Handing sticky notes to your AI assistant
Adding/Editing an annotation
Viewing annotation
Listing marks in Telescope

โœจ Features

  • ๐Ÿค– AI-friendly yank - Hand all your sticky notes to AI assistants (Claude Code, Copilot CLI, etc.) in one keystroke
  • ๐Ÿ“ Simple sticky notes - Clean and minimalist sticky note system
  • ๐ŸŒณ Git branch awareness - Sticky notes are stored per git branch
  • ๐Ÿ’พ Persistent storage - Your sticky notes are saved between sessions
  • ๐Ÿ“ Annotations - Add descriptive text to your sticky notes
  • ๐ŸŽˆ Float window display - Show annotations in floating windows on cursor hover
  • ๐Ÿ” Telescope integration - Search and navigate through all your sticky notes
  • โšก Fast navigation - Jump between sticky notes quickly
  • ๐Ÿ“‹ Quickfix list support - View all sticky notes in the current project in a quickfix list

๐Ÿ“ฆ Installation

Using lazy.nvim

{
  "walkersumida/fusen.nvim",
  version = "*",
  event = "VimEnter",
  opts = {},
}

For custom save file location:

{
  "walkersumida/fusen.nvim",
  version = "*",
  event = "VimEnter",
  opts = {
    save_file = vim.fn.expand("$HOME") .. "/my_fusen_marks.json",
  }
}

Using packer.nvim

use {
  "walkersumida/fusen.nvim",
  config = function()
    require("fusen").setup()  -- Add options here if needed
  end
}

Note: Configuration examples below use lazy.nvim's opts syntax. For packer.nvim, pass the same options to setup().

Using vim-plug

Plug 'walkersumida/fusen.nvim'

Then add to your init.lua:

require("fusen").setup()  -- Add options here if needed

Note: Configuration examples below use lazy.nvim's opts syntax. For vim-plug, pass the same options to setup().

โš™๏ธ Configuration

Default Configuration

-- Using lazy.nvim
{
  "walkersumida/fusen.nvim",
  opts = {
    -- Storage location
    save_file = vim.fn.expand("$HOME") .. "/fusen_marks.json",

    -- Mark appearance
    mark = {
      icon = "๐Ÿ“",
      hl_group = "FusenMark",
    },

    -- Key mappings
    keymaps = {
      add_mark = "me",        -- Add/edit sticky note
      clear_mark = "mc",      -- Clear mark at current line
      toggle_mark = "mt",     -- Toggle mark at current line
      clear_buffer = "mC",    -- Clear all marks in buffer
      clear_all = "mD",       -- Clear ALL marks (deletes entire JSON content)
      next_mark = "mn",       -- Jump to next mark
      prev_mark = "mp",       -- Jump to previous mark
      list_marks = "ml",      -- Show marks in quickfix
      yank_line = "my",       -- Yank mark at cursor line to clipboard
      yank_buffer = "mY",     -- Yank marks in current buffer to clipboard
      yank_all = "mA",        -- Yank all marks in project to clipboard
    },

    -- Yank to clipboard settings
    yank = {
      -- Template for each mark. Placeholders: {path} {file} {line} {annotation}
      template = '- @{path}:L{line} - "{annotation}"',
      -- Used instead when the mark has no annotation
      template_no_annotation = "- @{path}:L{line}",
    },

    -- Toggle mark settings
    toggle_mark = {
      skip_confirm = false,   -- Skip confirmation when removing mark via toggle
    },

    -- Telescope integration settings
    telescope = {
      keymaps = {
        delete_mark_insert = "<C-d>",  -- Delete mark in insert mode
        delete_mark_normal = "<C-d>",  -- Delete mark in normal mode
      },
    },

    -- Sign column priority
    sign_priority = 10,

    -- Annotation display settings
    annotation_display = {
      mode = "float", -- "eol", "float", "both", "none"
      spacing = 2,    -- Number of spaces before annotation in eol mode

      -- Float window settings
      float = {
        delay = 100,
        border = "rounded",
        max_width = 50,
        max_height = 10,
      },
    },

    -- Exclude specific filetypes from keymaps
    exclude_filetypes = {
      -- "neo-tree",     -- Example: neo-tree
      -- "NvimTree",     -- Example: nvim-tree
      -- "nerdtree",     -- Example: NERDTree
    },

    -- Plugin enabled state
    enabled = true,
  }
}

Annotation Display Modes

The annotation_display.mode option controls how annotations are displayed:

  • "eol": Shows annotations at the end of the line (traditional mode)
  • "float": Shows annotations in a floating window when cursor hovers over a marked line
  • "both": Shows both end-of-line text and floating window
  • "none": Hides annotations (marks only)

Float Window Settings

-- Using lazy.nvim
{
  "walkersumida/fusen.nvim",
  opts = {
    annotation_display = {
      mode = "float",
      float = {
        delay = 300,         -- Show after 300ms (default: 100ms)
        border = "single",   -- Border style: "single", "double", "rounded", etc.
        max_width = 60,      -- Maximum width (default: 50)
        max_height = 15,     -- Maximum height (default: 10)
      }
    }
  }
}
  • delay: Time in milliseconds to wait after cursor stops before showing the float window
  • border: Border style for the float window
  • max_width / max_height: Maximum dimensions for the float window

๐ŸŽฎ Usage

Key Mappings

All default mappings start with m prefix for consistency:

KeyDescription
meAdd or edit sticky note with annotation
mcClear sticky note at current line
mtToggle mark at current line (add/remove)
mCClear all sticky notes in current buffer
mDClear ALL sticky notes (deletes entire JSON content)
mnJump to next sticky note
mpJump to previous sticky note
mlList all sticky notes in current project in quickfix
myYank sticky note at cursor line to clipboard
mYYank sticky notes in current buffer to clipboard
mAYank all sticky notes in project to clipboard

Commands

CommandDescription
:FusenAddMarkAdd or edit sticky note with annotation
:FusenClearMarkClear sticky note at current line
:FusenToggleMarkToggle mark at current line (add/remove)
:FusenClearBufferClear all marks in current buffer
:FusenClearAllClear ALL marks (deletes entire JSON content)
:FusenNextJump to next mark
:FusenPrevJump to previous mark
:FusenListShow all marks in current project in quickfix list
:FusenYank [line|buffer|all]Yank marks to clipboard (default: line)
:FusenRefreshRefresh all marks display
:FusenSaveManually save marks
:FusenLoadManually load marks
:FusenInfoShow info about mark at current line
:FusenBranchShow current git branch info
:FusenOpenSaveFileOpen save file for debugging/editing
:FusenEnableEnable Fusen plugin (show marks and annotations)
:FusenDisableDisable Fusen plugin (hide all marks and annotations)
:FusenToggleToggle Fusen on/off

Yank to Clipboard

Copy your sticky notes to the system clipboard (+ register) and paste them anywhere โ€” AI chats, issues, code review comments, etc.

Note: This requires a clipboard provider (see :help clipboard). macOS works out of the box; on Linux install xclip, xsel or wl-clipboard. Without a provider, a warning is shown and nothing is copied.

:FusenYank          " Mark at cursor line (same as `my`)
:FusenYank buffer   " Marks in current buffer (same as `mY`)
:FusenYank all      " All marks in project (same as `mA`)

Each mark is formatted with a customizable template:

-- Using lazy.nvim
{
  "walkersumida/fusen.nvim",
  opts = {
    yank = {
      template = '- @{path}:L{line} - "{annotation}"',
      template_no_annotation = "- @{path}:L{line}",
    },
  }
}

Available placeholders:

PlaceholderDescription
{path}File path relative to the current working directory
{file}Absolute file path
{line}Line number
{annotation}Sticky note text

With the default template, the copied text looks like:

- @lua/fusen/init.lua:L42 - "TODO: refactor this function"
- @lua/fusen/ui.lua:L15 - "This layout breaks on narrow windows"

Telescope Integration

If you have telescope.nvim installed:

-- Search through all sticky notes
:Telescope fusen marks

-- Set up a keybinding (example)
vim.keymap.set("n", "<leader>fm", ":Telescope fusen marks<CR>", { desc = "Find fusen marks" })

-- In Telescope window:
-- <CR> - Jump to mark
-- <C-d> - Delete mark (customizable, see configuration)

-- Custom key mappings for Telescope (using lazy.nvim)
{
  "walkersumida/fusen.nvim",
  opts = {
    telescope = {
      keymaps = {
        delete_mark_insert = "<C-x>",  -- Custom key for insert mode
        delete_mark_normal = "dd",     -- Custom key for normal mode
      },
    },
  }
}

๐ŸŒณ Git Branch Awareness

One of the unique features of fusen.nvim is its git branch awareness. When you switch git branches, your sticky notes automatically switch too!

# On main branch
git checkout main
# Your main branch sticky notes are loaded

# Switch to feature branch
git checkout feature/new-feature
# Your feature branch sticky notes are loaded

# Sticky notes are stored separately for each branch

This is especially useful when:

  • Working on multiple features simultaneously
  • Reviewing different versions of code
  • Keeping TODO items branch-specific
  • Maintaining separate documentation notes per branch

๐ŸŽจ Customization

Float Window Display

Configure how annotations appear in floating windows:

-- Using lazy.nvim
{
  "walkersumida/fusen.nvim",
  opts = {
    annotation_display = {
      mode = "float",  -- Use floating windows
      float = {
        delay = 300,         -- Show after 300ms
        border = "single",   -- Border style
        max_width = 60,      -- Maximum width
        max_height = 15,     -- Maximum height
      }
    }
  }
}

Custom Highlighting

You can customize the appearance of marks by changing the highlight group:

-- Using lazy.nvim
{
  "walkersumida/fusen.nvim",
  opts = {
    mark = {
      icon = "๐Ÿ“",
      hl_group = "MyCustomHighlight",  -- Custom highlight group
    },
  },
  config = function(_, opts)
    require("fusen").setup(opts)
    -- Define your custom highlight group
    vim.api.nvim_set_hl(0, "MyCustomHighlight", {
      fg = "#ff6b6b",      -- Red foreground
      bg = "#1e1e1e",      -- Dark background
      bold = true,         -- Bold text
    })
  end,
}

The hl_group setting controls the color and style of:

  • Mark icons in the sign column
  • Annotation text display
  • Mark icons in Telescope search results

By default, it uses the "Special" highlight group which typically appears in a distinct color in most colorschemes.

Custom Key Mappings

-- Set your own mappings
vim.keymap.set("n", "<leader>m", require("fusen").add_mark)
vim.keymap.set("n", "<leader>mc", require("fusen").clear_mark)
-- etc...

โญ Show your support

Give a โญ๏ธ if this project helped you! Thank you!