Simon Späti349 downloadsScans the active file for TODO, FIXME, BUG, NOTE, and WARN tags and lists them in a sidebar panel.
A sidebar panel, inspired by todo-comments.nvim, that lists the things you want to come back to: TODO-style keywords, list callouts and open checkbox tasks. It shows the current note by default, or the whole vault, and jumps to the line when you click an entry. It does nothing while the panel is closed and never changes a note unless you press a check button.

[!NOTE] Why the name "Trouble"? It comes originally from trouble.nvim as I thought the TODO capabilities in Neovim come from there. But it is actually todo-comments.nvim that finds the keywords and feeds them into trouble.nvim. I just kept the name as it's kind of true to the tags/flags/keywords still.
| Source | Syntax | Example |
|---|---|---|
| Keywords | Upper case keyword, with or without # |
TODO: call bank, #FIXME, (TODO), ## TODO's |
| List callouts | List item starting with a configured character | - ? question, - ! important, - = idea |
| Tasks | Markdown checkbox | - [ ] buy milk |
todo, TODOS and MYTODO do not match.TODO, FIXME, BUG, NOTE, WARN, IDEA, TK.> [!NOTE] and frontmatter are skipped. Code blocks are scanned.~~strikethrough~~ and a checked task ([x]) count as done and are hidden unless "Show done" is on.folder/note); hover a file header or a row location to see the full path.TODO into ~~TODO~~ or [ ] into [x]. On a done row (with "Show done" on) an undo button restores it, including keywords inside a wider ~~struck span~~. Callouts have no done state. If the line changed since the last scan, a notice appears and nothing is edited.With the Vimrc Support plugin you can bind the commands to motions in .obsidian.vimrc, for example ]t and [t. Mapping } and { works too but replaces the paragraph motions.
exmap next_item obcommand trouble-tags:next-item
exmap prev_item obcommand trouble-tags:previous-item
nmap ]t :next_item<CR>
nmap [t :prev_item<CR>
| Setting | Default | What it does |
|---|---|---|
| Keywords | TODO, FIXME, BUG, NOTE, WARN, IDEA, TK |
Comma separated keywords, matched in upper case. |
| Keyword match | Hashtag and bare | Also "Hashtag only" and "Bare only". |
| Callout characters | & ? ! ~ @ $ % = |
Space separated characters. "Import from List Callouts" copies them from the List Callouts plugin. |
| Show done items | Off | Include completed tasks and struck-through keywords. |
| Status bar count | Off | Shows the number of open items of the current note in the status bar. Click it to toggle the panel. Shows – while the panel is closed. Not available on mobile. |
| Icon | List todo | Icon of the ribbon button and the panel tab. |
| Excluded folders | Empty | One folder path per line, skipped when building the vault index. |
| Vault sort | Modified | Whole-vault file order: Modified, Created or Name. Set from the panel header. |
| Note sort | Line | Row order of the note view: Line or Label. Set from the panel header. |
| Rebuild index | Discards the index and rebuilds it right away if the panel shows the whole vault; otherwise the Build index button appears. | |
| Clear index | Deletes the cached index. |
Changing keywords, match mode, callout characters or excluded folders discards the vault index. The panel then offers "Build index" again; it never rebuilds by itself.
index.json in the plugin folder, not in your notes. It is a disposable cache: delete it any time (or use "Clear index") and build it again.The plugin lists the vault's markdown files only when you build or refresh the index, and reads them through Obsidian's own Vault API. Nothing leaves the vault and no note is written to by scanning.
Settings, Community plugins, Browse, search for "Trouble Tags", install and enable.
Manually: build or download main.js, manifest.json and styles.css, put them in <vault>/.obsidian/plugins/trouble-tags/ (copy or symlink this folder), then enable the plugin in Settings, Community plugins.
npm install
npm run dev # watch and rebuild main.js
npm run build # type-check and bundle
npm test # unit tests (node --test)
npm run lint (or make lint) runs ESLint with the official Obsidian rules.
Releasing: make bump VERSION=x.y.z updates package.json, manifest.json and versions.json, rebuilds and commits. make release runs the tests and lint, tags the version from manifest.json and pushes. The Release workflow in .github/workflows/release.yml then builds main.js from source, attaches GitHub artifact attestations to main.js, manifest.json and styles.css, and publishes the release. make release VERSION=x.y.z does both.
For manual testing, node scripts/make-test-notes.mjs writes fixture notes (all matching forms plus 300 generated notes) into a throwaway vault at ~/git/obsidian/trouble-tags-testvault. It only creates or overwrites its own files.
Also check out my other plugin: Obsidian Open Specific File