SkillAgentSearch skills...

Dotmd.nvim

๐Ÿ““ Organize. Navigate. Create. Markdown. Keep all your notes, todos, and journals inside Neovim without ever leaving the editor.

Install / Use

/learn @y3owk1n/Dotmd.nvim
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

๐Ÿ““ dotmd.nvim

Organize. Navigate. Create. Markdown. Keep all your notes, todos, and journals inside Neovim without ever leaving the editor.

<!-- panvimdoc-ignore-start -->

https://github.com/user-attachments/assets/509f19d9-4172-4708-ad48-6a31735e6a6b

๐Ÿค” Why dotmd.nvim?

"I just want to write Markdown files... fast."

As a Neovim user, we spent most of our time in the editor. Yet everytime when we need to:

  • Jot a quick thought
  • Write a note
  • Create a daily journal
  • Track todos

...we end up reaching for external underused but overpowered apps or fighting complex plugins.

dotmd.nvim fixes this with:

  • โšก Zero context-switching - Manage everything in Neovim
  • ๐ŸŽฏ Dead-simple workflow - No databases, no proprietary formats, just Markdown that we loved
  • ๐Ÿ”‹ Batteries included - Smart templates, navigation, and cross-device sync ready (It's just Markdown files and folders)
<!-- panvimdoc-ignore-end -->

โœจ Features

  • ๐Ÿš€ Zero Context-Switching: Stay in Neovim.
  • ๐Ÿ—‚ Effortless Organization: Auto-created directories for notes, todos, journals, plus an inbox file.
  • ๐ŸŽฉ Smart File Creation: Use adaptive templates.
  • โช Todo Time Machine: Automatically roll over unfinished tasks.
  • ๐Ÿงญ Rapid Navigation: Jump between entries with ease.
  • ๐Ÿ” Universal Search: Fuzzy-match files with Telescope, fzf-lua, snacks.nvim, or mini.pick.
  • โš™๏ธ Complete Customizability: Tweak directories, templates, split directions, and more.
<!-- panvimdoc-ignore-start -->

๐Ÿ“• Contents

<!-- panvimdoc-ignore-end -->

๐Ÿ“ฆ Installation

Using lazy.nvim:

-- dotmd.lua
return {
 "y3owk1n/dotmd.nvim",
 version = "*", -- remove this if you want to use the `main` branch
 opts = {
  -- your configuration comes here
  -- or leave it empty to use the default settings
  -- refer to the configuration section below
 }
}

If you are using other package managers you need to call setup:

require("dotmd").setup({
  -- your configuration
})

Requirements

  • Neovim 0.9+ with Lua support
  • The following CLI tools must be available in your $PATH:
    • find: for listing files across note directories
    • grep: for searching files across note directories
  • (Optional but recommended) One of the following picker for better picking files and grepping:

โš™๏ธ Configuration

[!important] Make sure to run :checkhealth dotmd if something isn't working properly.

dotmd.nvim is highly configurable. And the default configurations are as below.

Default Options

---@alias DotMd.Split "vertical" | "horizontal" | "float" | "none" Split direction
---@alias DotMd.PickerType "telescope" | "fzf" | "snacks" | "mini" Picker type

---@class DotMd.Config
---@field root_dir? string Root directory of dotmd, default is `~/dotmd`
---@field default_split? DotMd.Split Split direction for new or existing files, default is `none`
---@field picker? DotMd.PickerType Picker type, default is `nil`
---@field rollover_todo? DotMd.Config.RolloverTodo
---@field dir_names? DotMd.Config.DirNames
---@field templates? Dotmd.Config.Templates

---@class DotMd.Config.RolloverTodo
---@field enabled? boolean Rollover the nearest previous unchecked todos to today's date, default is `false`
---@field headings? string[] H2 Headings to search for in your todos template to rollover, default is { "Tasks" }

---@class DotMd.Config.DirNames
---@field notes? string Directory name for notes, default is "notes"
---@field todos? string Todo directory name, default is "todos"
---@field journals? string Journal directory name, default is "journals"

---@class Dotmd.Config.Templates
---@field notes? fun(name: string): string[]
---@field todos? fun(date: string): string[]
---@field journals? fun(date: string): string[]
---@field inbox? fun(date: string): string[]
{
 root_dir = "~/dotmd",
 default_split = "none",
 rollover_todo = {
  enabled = false,
  heading = { "Tasks" },
 },
 picker = nil,
 dir_names = {
  notes = "notes",
  todos = "todos",
  journals = "journals",
 },
 templates = {
  notes = function(title)
   return {
    "---",
    "title: " .. title,
    "created: " .. os.date("%Y-%m-%d %H:%M"),
    "---",
    "",
    "# " .. title,
    "",
   }
  end,
  todos = function(date)
   return {
    "---",
    "type: todo",
    "date: " .. date,
    "---",
    "",
    "# Todo for " .. date,
    "",
    "## Tasks",
    "",
   }
  end,
  journals = function(date)
   return {
    "---",
    "type: journal",
    "date: " .. date,
    "---",
    "",
    "# Journal Entry for " .. date,
    "",
    "## Highlights",
    "",
    "## Thoughts",
    "",
    "## Tasks",
    "",
   }
  end,
  inbox = function()
   return {
    "---",
    "type: inbox",
    "---",
    "",
    "# Inbox",
    "",
    "## Quick Notes",
    "",
    "## Tasks",
    "",
    "## References",
    "",
   }
  end,
 },
}

๐Ÿš€ Quick Start

See the example below for how to configure dotmd.nvim.

{
 "y3owk1n/dotmd.nvim",
 cmd = {
  "DotMdCreateNote",
  "DotMdCreateTodoToday",
  "DotMdCreateJournal",
  "DotMdInbox",
  "DotMdNavigate",
  "DotMdPick",
  "DotMdOpen",
 },
 event = "VeryLazy",
 ---@type DotMd.Config
 opts = {
  root_dir = "~/dotmd" -- set it to your desired directory or remain at it is
  default_split = "float" -- or "vertical" or "horizontal" or "none" based on your preference
  rollover_todo = {
   enabled = true, -- enable rollover
  },
  picker = "snacks" -- or "fzf" or "telescope" or "mini" based on your preference
 },
 keys = {
  {
   "<leader>nc",
   function()
    require("dotmd").create_note()
   end,
   desc = "[DotMd] Create new note",
  },
  {
   "<leader>nt",
   function()
    require("dotmd").create_todo_today()
   end,
   desc = "[DotMd] Create todo for today",
  },
  {
   "<leader>ni",
   function()
    require("dotmd").inbox()
   end,
   desc = "[DotMd] Inbox",
  },
  {
   "<leader>nj",
   function()
    require("dotmd").create_journal()
   end,
   desc = "[DotMd] Create journal",
  },
  {
   "<leader>np",
   function()
    require("dotmd").navigate("previous")
   end,
   desc = "[DotMd] Navigate to previous todo",
  },
  {
   "<leader>nn",
   function()
    require("dotmd").navigate("next")
   end,
   desc = "[DotMd] Navigate to next todo",
  },
  {
   "<leader>no",
   function()
    require("dotmd").open({
     pluralise_query = true, -- recommended
    })
   end,
   desc = "[DotMd] Open",
  },
  {
   "<leader>sna",
   function()
    require("dotmd").pick()
   end,
   desc = "[DotMd] Everything",
  },
  {
   "<leader>snA",
   function()
    require("dotmd").pick({
     grep = true,
    })
   end,
   desc = "[DotMd] Search everything grep",
  },
  {
   "<leader>snn",
   function()
    require("dotmd").pick({
     type = "notes",
    })
   end,
   desc = "[DotMd] Search notes",
  },
  {
   "<leader>snN",
   function()
    require("dotmd").pick({
     type = "notes",
     grep = true,
    })
   end,
   desc = "[DotMd] Search notes grep",
  },
  {
   "<leader>snt",
   function()
    require("dotmd").pick({
     type = "todos",
    })
   end,
   desc = "[DotMd] Search todos",
  },
  {
   "<leader>snT",
   function()
    require("dotmd").pick({
     type = "todos",
     grep = true,
    })
   end,
   desc = "[DotMd] Search todos grep",
  },
  {
   "<leader>snj",
   function()
    require("dotmd").pick({
     type = "journals",
    })
   end,
   desc = "[DotMd] Search journal",
  },
  {
   "<leader>snJ",
   function()
    require("dotmd").pick({
     type = "journals",
     grep = true,
    })
   end,
   desc = "[DotMd] Search journal grep",
  },
 },
},

๐Ÿ“ฆ How It Works

dotmd.nvim organizes your Markdown files as follows:

dotmd/
โ”œโ”€โ”€ inbox.md         # Brain dump file
โ”œโ”€โ”€ notes/           # Organized Markdown notes
โ”œโ”€โ”€ todos/           # Date-based todo files (with rollover support)
โ””โ”€โ”€ journals/        # Date-based journal entries

Note Creation

When you create a new note, dotmd.nvim:

  1. Prompts for select/create a subdirectory or use the base directory.
  2. Prompts for a file name or path. (See Input patterns)
  3. Generates a file path inside the configured notes folder.
  4. Optionally applies a notes template.
  5. Opens the file in a vertical/horizontal split or current window.

Input patterns

  • If the file name is not a path, it will be transformed and used as a file name and title.
    • Input: Amazing Idea
    • Output path: amazing-idea.md
    • Output h1 heading: # Amazing Idea
  • If the file name is a path, it will be used as a file path and the title will be transformed from the file name.
    • Input: amazing-idea.md
    • Output path: amazing-idea.md
    • Output h1 heading: # Amazing Idea
  • Support also nested directories during file creation (e.g. project/idea.md)
    • Input: project/idea.md
    • Output path: project/idea.md
    • Output h1 heading: # Idea
  • Weird enough, something like this will work too
    • project/Amazing Idea -> project/amazing-idea.md
    • project/amazing-idea -> project/amazing-idea.md

Todo Files

When you create a new todo file, dotmd.nvim:

  1. Checks if today's todo file exists (e.g. todos/2025-04-09.md).
  2. If the file doesn't exist, prompt for create confirmation.
  3. If confirm, rolls over unfinished - [ ] tasks from the previous file from the nearest previous todo file (if any and enabled).
  4. Applies the todo template.
  5. Opens the file for

Related Skills

View on GitHub
GitHub Stars25
CategoryDevelopment
Updated1mo ago
Forks0

Languages

Lua

Security Score

95/100

Audited on Feb 18, 2026

No findings