Manage Markdown tasks in Neovim similar to Obsidian | Telescope to List Completed and Pending Tasks
Are you an Obsidian user and miss the way to manage tasks in Obsidian and would like to have something similar in Neovim? You don't need a dedicated plugin, I created a few keymaps for this and I'll share them below
Manage Markdown tasks in Neovim similar to Obsidian | Telescope to List Completed and Pending Tasks
Table of contents
- YouTube video
- Pre-requisites
- If you like my content, and want to support me
- Discord server
- Follow me on social media
- All links in the video description
- How do you manage your passwords?
- How I managed tasks in obsidian?
- How I manage tasks in Neovim
- List pending tasks
- List completed tasks
- Why did I switch from Obsidian to Neovim?
- Keymap to create a task
- Configure keymaps
- Start your 14 day FREE trial
YouTube video
Pre-requisites
Do you want to test this but not spend time configuring it?
- My entire
neobean
setup is in my github repo, so you can grab it from there - I have a video in which I show you how to download and setup my
neobean
config, but also other neovim distributions, so I highly recommend you check it out:
- If you don’t want to watch the video above, and you already have your own neovim config, and want to quickly get started and follow along in this tutorial
- Run the
git clone
commands below to clone my dotfiles in your .config directory and we will run my config below
1
2
mkdir -p ~/.config
git clone git@github.com:linkarzu/dotfiles-latest ~/.config/linkarzu/dotfiles-latest
- Open the newly downloaded
neobean
config with:
1
NVIM_APPNAME=linkarzu/dotfiles-latest/neovim/neobean nvim
- You can create an alias in your
.bashrc
or.zshrc
file to run my config
1
alias neobean='NVIM_APPNAME=linkarzu/dotfiles-latest/neovim/neobean nvim'
- Then to run this config, just run
neobean
- You still need some
requirements
to view images in neovim, for that watch this video:
- If you don’t even have neovim yet, of course you will need to install it first, so if you’re just getting started, I have a video for you:
If you like my content, and want to support me
- I create and edit my videos in an M1 mac mini, and it’s starting to stay behind in the editing side of things, tends to slow me down a bit, I’d like to upgrade the machine I use for all my videos to a
mac mini
with these specs:- Apple M4 Pro chip with 14‑core CPU, 20‑core GPU, 16-core Neural Engine
- 24GB unified memory
- 1TB SSD storage
- 10 Gigabit Ethernet
- If you want to help me reach my goal, you can donate here
Discord server
- My discord server is now open to the public, feel free to join and hang out with others
- join the discord server in this link
Follow me on social media
- Twitter (or “X”)
- TikTok
- GitHub
- Threads
- OnlyFans 🍆
- YouTube (subscribe MF, subscribe)
- Ko-Fi
All links in the video description
- The following links will be in the YouTube video description:
- Each one of the videos shown
- A link to this blogpost
How do you manage your passwords?
- I’ve tried many different password managers in the past, I’ve switched from
LastPass
toDashlane
and finally ended up in1password
- You want to find out why? More info in my article:
How I managed tasks in obsidian?
- In obsidian I used to manage tasks as you see on the image below, notice that when I mark a task as done it shows me the date and time in which it was completed
- I wanted the same in Neovim, so I created a few keymaps that allow me to mange tasks
How I used to manage tasks in Obsidian
How I manage tasks in Neovim
- This is the end result in Neovim, notice that when I mark a task as done, it moves it to the
Completed Tasks
section - Also notice that the date and time are added to the completed tasks, that’s configurable and you can modify it to your liking
- Also notice that I add the
done:
tag at the beginning of a completed task, I use this tag when searching for completed or incomplete tasks
How I mark tasks as done in Neovim
- In the video I demo how I complete tasks by pressing
alt+x
and how they are automatically moved to theCompleted Tasks
section - In the video I also demonstrate how I use the app you see on the right hand side, where I keep my daily tasks, it’s called skitty-notes
- It’s basically a sticky notes app, but the main reason I came up with it, is that it allows me to use vim motions to edit text
- It’s basically my neovim configuration (modified a bit) running inside kitty
- I have a full tutorial on how to set it up, you can find it here:
How I untoggle tasks
- Sometimes you need to untoggle a finished task, I mean, mark it again as not done, so if you go to the
Completed Tasks
section, and you pressalt+x
in one of the tasks, it’s going to replace the label - Notice in the image below that the first 2 tasks in that section show as untoggled, notice the date was automatically removed
- You can toggle them as completed again, and the new date and time will be added
List pending tasks
- A lot of the times, you want to see all the pending tasks, not only in a single file, but in the current working directory in which you opened Neovim
- So I created the keymap
leader+tt
- Notice in the image below, I have some tasks that are not completed in my blogpost
List of uncompleted tasks in the current working directory
- I’ll show you how I configured this keymap below
List completed tasks
- For this I created another keymap,
leader+tc
as seen on the image below
List of completed tasks in the current working directory
- I’ll show you how I configured this keymap below
Why did I switch from Obsidian to Neovim?
- I have a video in which I cover this in detail, if you want to learn more about that you can find it here:
Keymap to create a task
- I create tasks with
Alt+l
- So if I’m on a blank line and press that, it will add
- [ ]
at the beginning of the line, which is basically a task - I also use the plugin: bullets-vim/bullets.vim
- This plugin is used to create a task on the line below if I hit “enter” at the end of a task
- I also use this plugin to create bulletpoints across all my different files
- If you would like to learn about my markdown setup in detail, I would highly recommend you to check my markdown workflow video, the 2025 version:
Configure keymaps
Alt+x to toggle tasks
- This can be found in my keymaps.lua file which is in my dotfiles, link here: config/keymaps.lua
- There you’ll be able to find the most up to date version of this keymap, as of Feb 11th 2025 the keymaps tarts here (If you don’t understand where the keymap starts and ends, watch the video):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- If there is no `untoggled` or `done` label on an item, mark it as done
-- and move it to the "## completed tasks" markdown heading in the same file, if
-- the heading does not exist, it will be created, if it exists, items will be
-- appended to it at the top lamw25wmal
--
-- If an item is moved to that heading, it will be added the `done` label
vim.keymap.set("n", "<M-x>", function()
-- Customizable variables
-- NOTE: Customize the completion label
local label_done = "done:"
-- NOTE: Customize the timestamp format
local timestamp = os.date("%y%m%d-%H%M")
-- local timestamp = os.date("%y%m%d")
-- NOTE: Customize the heading and its level
local tasks_heading = "## Completed tasks"
-- Save the view to preserve folds
vim.cmd("mkview")
.
.
.
.
- Notice above I left some notes on the things that you can customize for the keymap
- The configuration for this keymap is quite long, so go and get it directly from my dotfiles also, while you’re there:
- ⭐⭐⭐⭐ Remember to star my dotfiles ⭐⭐⭐⭐
Alt+l to create task
- This is the keymap I’m used when I’m on a blank line and I need to create a new tasks, so that I don’t have to manually type
- [ ]
- This one is shorter (that’s what she said), so you can see it below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- Crate task or checkbox lamw25wmal
-- These are marked with <leader>x using bullets.vim
-- I used <C-l> before, but that is used for pane navigation
vim.keymap.set({ "n", "i" }, "<M-l>", function()
-- Get the current line and cursor position
local line = vim.api.nvim_get_current_line()
local cursor = vim.api.nvim_win_get_cursor(0)
-- Check if the line starts with a bullet or "- ", and remove it
local updated_line = line:gsub("^%s*[-*]%s*", "", 1)
-- Update the line
vim.api.nvim_set_current_line(updated_line)
-- Move the cursor back to its original position
vim.api.nvim_win_set_cursor(0, { cursor[1], #updated_line })
-- Insert the checkbox
vim.api.nvim_put({ "- [ ] " }, "c", true, true)
end, { desc = "[P]Toggle checkbox" })
Leader+tt and leader+tc to list incomplete and completed tasks
- I used telescope when I recorded this video, but I recently switched over to the Snacks Picker by Folke, in the video I demo the telescope keymaps, here’s the code for
Leader+tt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- Iterate through incomplete tasks in telescope
-- You can confirm in your terminal lamw25wmal with:
-- rg "^\s*-\s\[ \]" test-markdown.md
vim.keymap.set("n", "<leader>tt", function()
require("telescope.builtin").grep_string(require("telescope.themes").get_ivy({
prompt_title = "Incomplete Tasks",
-- search = "- \\[ \\]", -- Fixed search term for tasks
-- search = "^- \\[ \\]", -- Ensure "- [ ]" is at the beginning of the line
search = "^\\s*- \\[ \\]", -- also match blank spaces at the beginning
search_dirs = { vim.fn.getcwd() }, -- Restrict search to the current working directory
use_regex = true, -- Enable regex for the search term
initial_mode = "normal", -- Start in normal mode
layout_config = {
preview_width = 0.5, -- Adjust preview width
},
additional_args = function()
return { "--no-ignore" } -- Include files ignored by .gitignore
end,
}))
end, { desc = "[P]Search for incomplete tasks" })
- The same thing for the
leader+tc
keymaps, here’s the code below, but keep in mind that I don’t use this anymore, as I migrated from telescope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- Iterate through completed tasks in telescope lamw25wmal
vim.keymap.set("n", "<leader>tc", function()
require("telescope.builtin").grep_string(require("telescope.themes").get_ivy({
prompt_title = "Completed Tasks",
-- search = [[- \[x\] `done:]], -- Regex to match the text "`- [x] `done:"
-- search = "^- \\[x\\] `done:", -- Matches lines starting with "- [x] `done:"
search = "^\\s*- \\[x\\] `done:", -- also match blank spaces at the beginning
search_dirs = { vim.fn.getcwd() }, -- Restrict search to the current working directory
use_regex = true, -- Enable regex for the search term
initial_mode = "normal", -- Start in normal mode
layout_config = {
preview_width = 0.5, -- Adjust preview width
},
additional_args = function()
return { "--no-ignore" } -- Include files ignored by .gitignore
end,
}))
end, { desc = "[P]Search for completed tasks" })
- If you want to understand how I migrated away from Telescope to Snacks picker and also why I did it, I have a video:
Start your 14 day FREE trial
This post is licensed under CC BY 4.0 by the author.