I Have 27 Half-Built Projects. Now I Can Search All Their Backlogs With One Command.
I counted. Twenty-seven projects in my dev folder. Some are actively shipping. Some haven’t been touched in months. A few are just scaffolds from a burst of late-night inspiration that didn’t survive the morning.
None of them had a backlog. Not a real one. A few had TODOs buried in code comments. One had a detailed feature list in a markdown file. The rest had nothing — just git histories and vibes.
The problem isn’t tracking tasks within a project. That’s easy. The problem is answering “what should I work on next?” when you have 27 projects competing for the same weeknight.
The Obvious Fix Doesn’t Work
A single central backlog breaks down fast. At three projects, it’s fine. At twenty-seven, you’re scrolling through a wall of tasks with no connection to the code they belong to. Context lives in the project directory, not in a master list.
Per-project backlogs are better — the tasks live next to the code. But then you lose the cross-project view. You can’t ask “which projects have unfinished API work?” without opening every folder.
Per-Project Kanban Boards + Semantic Search
Here’s what actually works: give every project its own Kanban board, then point a search engine at all of them.
Each project gets a BACKLOG.md that’s an Obsidian Kanban board:
---
kanban-plugin: basic
---
## Next
- [ ] Complete initial build beyond scaffold [added::2026-02-26]
## In Progress
## In Review
## Backlog
- [ ] Twilio integration [added::2026-02-26]
- [ ] SMS notification system [added::2026-02-26]
## Done
## Cancelled
Drag cards around in Obsidian. It’s markdown underneath — any tool can read it.
The boards live in each project directory. Symlinks connect them into my Obsidian vault so I can see and edit all 24 boards without leaving the app.
For the cross-project view, I use two tools:
QMD indexes every markdown file across all 27 projects — backlogs, READMEs, design docs, everything. It runs BM25 keyword search, vector similarity search, and LLM reranking, all locally. No API calls, no cloud.
$ qmd query "which projects need video processing work" -c dev
video-pipeline/docs/plans/2026-02-24-video-translation-pipeline.md Score: 38%
Dataview gives me a dashboard inside Obsidian — task lists filtered by column, a project health table, and a live bar chart showing how many tasks sit in each stage across all 24 projects.
The chart is a DataviewJS block that queries every backlog, counts tasks per column, and feeds the numbers to the Obsidian Charts plugin:
const pages = dv.pages('"work/dev-projects"')
.where(p => p.file.name !== "Dashboard");
const columns = ["Next", "In Progress", "In Review", "Backlog", "Done", "Cancelled"];
const counts = columns.map(col =>
pages.flatMap(p => p.file.tasks)
.where(t => t.section?.subpath === col && !t.completed).length
);
window.renderChart({
type: "bar",
data: { labels: columns, datasets: [{ data: counts }] }
}, this.container);
Fifteen lines. Updates live when you drag a card. No build step, no database, no API.
The Auto-Cancel Trick
Every task gets an addedDate date stamp. A Python script runs daily at 6am via launchd. If a backlog item is older than six months and still sitting in the Backlog column, it gets moved to Cancelled automatically.
if TODAY - added > timedelta(days=180):
# Move to Cancelled with a timestamp
cancel_line = f"- [ ] {task} [added::{added_str}] [cancelled::{TODAY}]"
No guilt. No ceremony. If something sat in the backlog for six months, I’m not doing it. The auto-cancel script just makes that honest.
The QMD reindex runs five minutes later, so the search index always reflects reality.
The Setup
Five pieces, about an hour to wire up:
- Template — an empty Kanban board with six columns (Next, In Progress, In Review, Backlog, Done, Cancelled)
- Per-project boards — copy the template into each project, seed with known tasks
- Symlinks — a shell script links each
BACKLOG.mdinto the Obsidian vault - QMD collection —
qmd collection add ~/dev --name dev --mask "**/*.md" && qmd embedindexes 163 files across all projects - Daily automation — two launchd plists: auto-cancel stale items at 6am, reindex at 6:05am
Total new code: one Python script (50 lines), two shell scripts, two launchd plists.
Same Pattern, Different Problem
If you read the previous posts in this series, this might feel familiar. We use the same Kanban-board-plus-watcher pattern to route our LLM agents to different models and to dispatch tasks to AI agents. Obsidian boards as the interface, small scripts as the glue, markdown as the source of truth.
The backlog system doesn’t even need a watcher. QMD indexes on a schedule. Dataview queries live. The Kanban boards are the state.
The best project management system is the one you already have open. For us, that’s still Obsidian.