TaskLoops
approvedby Sahand
Collects tagged task lines from across your vault into a sidebar inbox, sorts them with the GTD method, and flags projects that have stalled. - This plugin has not been manually reviewed by Obsidian staff.
TaskLoops
An Obsidian plugin that collects #task lines from anywhere in your vault into
a sidebar inbox, walks them through the GTD clarify flow, and marks each line
*(Handled)* once you've sorted it.
An open loop is anything you've committed to that isn't closed yet. TaskLoops finds them, helps you file them, and tells you when a project has quietly stalled.
What it writes to your notes
Two things, both of which you trigger deliberately:
*(Handled)*appended to the end of a task's own line, once you sort it. Turn off Mark lines when sorted and this stops entirely.- The sentence of a task you explicitly edit, and only that — see Editing a task.
- A new
- … #taskline appended to your capture note, and only when you use quick capture. That note is named in settings, defaults toTaskLoops Inbox.md, and is created on first use. Capture only ever appends to the end of that one file.
Beyond those, nothing. It never touches frontmatter or note properties, never adds tags, never reorders or moves lines, never deletes anything, and never edits a line you have not personally sorted or edited. If you never press the capture button, the capture note is never created.
All state — bucket, context, delegate, date, project links, done — lives in the
plugin's own data.json, never in your notes.
Three layouts
One row of controls at the top of the panel:
- GTD — the bucket lists. The button names the list on screen; clicking it opens the picker for the other buckets, each with its count. What used to be a rail of nine tabs is now one button, so the panel stays quiet.
- Board — a Kanban board, one column per bucket, cards dragged between them. Columns fill the panel height, so the empty space under the last card is a drop target too.
- Calendar — day, week or month, with the tasks themselves shown rather than summarised.
A sidebar is narrow for a board, so the columns scroll horizontally. For the full width, run Open in a main tab from the command palette — it is the same view over the same data, just with room.
The clarify flow
Standard GTD, one question at a time:
- Is it actionable? No leads to Trash, Someday/Maybe or Reference.
- Under two minutes? Yes means do it now; it is filed as done immediately.
- What kind of thing is it? Next action (pick a context), Project (multi-step), Delegate (name the person), or Schedule (pick a date).
You can back out of any step, and re-file anything later from the ⋯ menu.
Capture
The + button in the panel header opens a capture row. Type, press Enter, and the line is appended to your capture note and appears in the Inbox unsorted — the row stays open so a burst of thoughts costs one keystroke each. Escape closes it. There is also a Capture a task to the inbox command you can bind to a hotkey.
The first time you capture anything, you are asked which folder captures should
live in, and TaskLoops Inbox.md is created there. Dismissing that prompt is a
valid answer — it puts the note at the vault root. You are only asked once; the
capture row shows the destination underneath it, and clicking it moves the
capture note somewhere else at any time.
Projects
The projects list stays a list of outcomes, not a place to keep steps. The plugin tracks one thing about a project: which actions belong to it, so it can tell you when a project has nothing open against it. A project showing no next action has stalled, which is the single failure mode the weekly review exists to catch. Those projects sort to the top and put a dot on the Projects tab.
Actions get attached to a project three ways:
- Indentation. A
#taskline indented under a project's#taskline is its action. Blank lines are transparent; any non-blank line at column zero ends the block, so an outline further down the note won't attach itself to something unrelated. This is read-only inference — nothing is written. - During clarify. If you have projects and the task isn't already attached, the last step of the flow offers them. Indented tasks skip this step, because the answer is already known.
- Afterwards, via
⋯→ Part of project….
Expanding a project shows its actions one level deep. There is no nesting beyond that, and a project can't belong to another project — choosing Standalone pins a task as unattached even if it sits under a project in the outline.
A project whose only children are unclarified inbox items still counts as stalled. That is deliberate: an uncaptured thought is not something you can act on.
Editing a task
Double-click a task's text in the panel to rewrite it, or use ⋯ → Edit text.
Enter saves, Escape cancels, Shift+Enter adds a line break.
This is the one place the plugin rewrites something you wrote, so it is careful
about it: only the sentence changes. The line's indentation, bullet, checkbox,
blockquote or heading markers, the tag exactly as you wrote it — #task/work
stays #task/work — any block id, and the handled marker are all preserved.
Before writing, the line is re-located by its exact previous text, so an edit
made in the note meanwhile cannot cause the wrong line to be rewritten.
Renaming changes a task's identity, since identity is derived from its text. The record is moved across explicitly, so its bucket, context, date and project links all survive.
The context, waiting-on and date chips under each task are clickable: one click
changes any of them. Empty ones appear on hover as + context and + date, and
on touch they live on the ⋯ menu instead.
Changing an attribute never re-files a task. A context, a date and a person
are orthogonal to the filing decision — a delegated task can have a context, a
next action can have a date — so setting one leaves the task exactly where it
is. Buckets change only through the clarify flow, the ⋯ menu, or a drag, all
of which are explicit. Attributes also survive a re-file; returning a task to
the Inbox is the one reset, since that means it is unclarified again.
Priority
Each task has a priority slot: P1 high, P2 medium, P3 low, or none.
Click the chip, or use ⋯ → Priority. P1 and P2 also colour the card's left
edge, so urgency reads without reading the chip, and priority tints the dots on
the calendar.
Priority is a sort key, applied after any manual order you set and before how recently a task was filed. Tasks without one sort last, so nothing reshuffles until you start using it.
Dragging
Everything files by dragging, in every layout:
- Onto a bucket. Start dragging and a strip of bucket targets appears along the bottom. It only exists while you drag, which is what lets the tab rail collapse into one button without losing drag-to-file.
- Between board columns. The obvious one.
- Onto a calendar day, which sets that date — rescheduling without opening a picker.
- Onto another task, which sets a manual order. The line across the card shows where it will land. Ordering lives in the plugin's data, so the order of lines in your notes is never touched.
- Onto a project card, which files the task under that project.
Dropping onto Scheduled asks for a date and Waiting asks for a name, because those buckets are meaningless without them; every other target files immediately.
Dragging is mouse-only — it uses HTML5 drag events, which touch screens don't
fire. Every drag action is also on the ⋯ menu, which is the path to use on a
phone.
Calendar
Three scales, switched with the Day / Week / Month buttons. The heading steps back and forward by whichever scale you are on, and clicking it jumps to today.
- Day — one day, its tasks in full.
- Week — seven day panels, stacked in a sidebar and fanned into columns once the panel is wide enough.
- Month — a grid where each day carries a count badge, tinted by the highest priority on it, followed by every dated day of that month with its tasks. The grid tells you where things are; the list underneath tells you what they are.
Every day shown is a drop target, at every scale, so rescheduling is a drag. Each day also has a + to create a task already dated to it. Undated tasks are listed at the bottom so there is always something to drag onto the calendar.
Dates
Every task row has a date chip. Click it to set, change or clear the date —
there are Today / Tomorrow / In a week shortcuts plus a picker. The same is on
the ⋯ menu. Setting a date records the date and nothing more — it does not
move the task to Scheduled. Use the clarify flow, the ⋯ menu or a drag onto
the Scheduled tab for that, all of which ask for the date too.
How lines are found
Tag positions come from Obsidian's own metadata cache, not a text search, so
fenced code blocks, inline code and YAML frontmatter are excluded automatically.
#task/work and other child tags count. A line holding nothing but the tag is
ignored. Bullets, checkboxes, ordered lists, blockquotes, headings and block ids
are stripped from the display text but left untouched in the note.
Identity and edit safety
A task is identified by a hash of its note path, its cleaned text, and its index among identical lines in that file. Two consequences worth knowing:
- Editing a sorted line's wording gives it a new identity. When exactly one record in a note is orphaned and exactly one marked line there has no record, that is unambiguously a rewording, and the record moves across intact — so a reworded project keeps the actions pointing at it. Project links survive this because they reference an internal id, not the line's text. If the match is ambiguous, the line falls back to Next, where it stays visible rather than silently vanishing.
- Deleting a task line drops its record. This only happens after a full, successful vault scan, so a partial view can never prune anything.
Before writing a marker the plugin re-locates the line by its exact prior text. If the line moved and the text is still unique, it follows it; if it cannot identify the line unambiguously, it writes nothing and tells you.
Renaming or moving a note carries its filed tasks along with it.
Layout
The panel sizes itself against its own width, not the window's, using a CSS container query — a desktop sidebar is often narrower than a phone screen, so viewport media queries would tune the wrong thing. Below about 290px the tab labels drop and the rail becomes icons and counts.
Touch devices get larger targets and lose nothing to hover: the ⋯ button is
always visible rather than fading in, and the hover-only "add a date" chip is
hidden outright, since its actions live on the ⋯ menu anyway. Verified with no
horizontal overflow down to a 260px panel.
Installing
From Obsidian — open Settings → Community plugins → Browse, search for TaskLoops, install and enable. This is the easiest route and gets you updates automatically. Plugin page
Requires Obsidian 1.7.2 or later, on desktop and mobile.
From a release — download main.js, manifest.json and styles.css from
the releases page into
<vault>/.obsidian/plugins/taskloops/, then enable it under
Settings → Community plugins.
From source — clone this repo, then:
npm install
OBSIDIAN_VAULT="/path/to/your/vault" npm run deploy
To avoid repeating the path, write it once into a .vault-path file, which is
gitignored:
echo "/path/to/your/vault" > .vault-path
npm run deploy
deploy builds and copies only the three files Obsidian loads. It never touches
data.json, so your sorting survives a redeploy.
Development
npm install
npm run dev # watch build
npm run build # typecheck + minified build
npm test # 79 tests over the scanner
npm run deploy # build, then copy into a vault
Source layout:
src/
├── main.ts plugin lifecycle, state, reconciliation, filing actions
├── scanner.ts finding tagged lines, identity, the one write path
├── view.ts sidebar: tabs, lists, cards, projects, drag and drop
├── wizard.ts the GTD clarify flow
├── modals.ts folder, project, task and date pickers
├── settings.ts settings pane
├── types.ts buckets, stored shapes, defaults
├── dates.ts calendar-day helpers
└── text.ts string helpers
scripts/ build tooling: deploy, version bump
test/ node test suite over scanner.ts
main.js is built to the repository root, because that is where Obsidian loads
it from and where the release workflow picks it up. styles.css and
manifest.json stay at the root for the same reason — they ship verbatim rather
than being compiled.
The tests cover the risky parts: which lines count as tasks, how identity is derived, how indentation implies a parent, and that marking a line is idempotent and reversible without disturbing its indent, bullet or checkbox.
Releasing
Obsidian resolves a release by its git tag, which must be the bare version
number with no v prefix, and expects main.js, manifest.json and
styles.css attached individually as assets.
npm version patch
git push && git push --tags
npm version bumps package.json, then version-bump.mjs writes the same
version into manifest.json and adds a row to versions.json. The .npmrc
sets tag-version-prefix="", which is what stops npm creating a v0.1.1 style
tag — Obsidian would not resolve that.
Pushing the tag runs .github/workflows/release.yml, which installs, tests,
builds, verifies the tag matches manifest.json, attests build provenance, and
opens a draft release with main.js, manifest.json and styles.css
attached individually. Review it and publish when ready.
versions.json maps each plugin version to the minimum Obsidian version it
needs, so older Obsidian installs resolve to a release they can actually run.
Support
If TaskLoops is useful to you, you can buy me a coffee. Entirely optional — the plugin is free and always will be.
License
MIT © Sahand Poursadeghi Khiavi
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.