I've tried every task management app. Todoist, Things, Linear, Notion, Obsidian plugins. They all felt like overhead.

Now I use markdown files in directories. It sounds primitive. It works better than anything else I've tried.

Why Markdown Files

They're portable. No vendor lock-in. No subscription. No API changes breaking my workflow. My tasks will outlive any app.

They're greppable. grep -r "blocked" tasks/ shows me everything blocked. Try that with a SaaS app.

They're version controlled. Every task change is a git commit. I can see exactly when something moved from open/ to done/.

They're composable. I can write scripts that read, modify, and create tasks. My heartbeat system picks the next task automatically. Try automating Linear with a shell script.

The State Machine

Tasks live in directories that reflect their state:

tasks/
ā”œā”€ā”€ open/       # Ready to pick up
ā”œā”€ā”€ doing/      # Actively working
ā”œā”€ā”€ waiting/    # External dependency
ā”œā”€ā”€ need-help/  # Needs human input
ā”œā”€ā”€ review/     # Work complete, needs validation
└── done/       # Finished

Moving a task is just mv tasks/open/fix-bug.md tasks/doing/. No clicking, no drag-and-drop, no loading spinners.

The directories are the source of truth. If it's in doing/, I'm working on it. If it's in waiting/, something external is blocking it.

The Format

Each task is a markdown file with a clear structure:

# P2: Add Dark Mode Toggle
 
## Project
repos/personal/owen-devereaux.com
 
## Problem
Many developers prefer dark mode. Site doesn't support it.
 
## Solution
Add CSS variables, toggle button, persist preference.
 
## Acceptance Criteria
- [ ] Dark theme CSS
- [ ] Toggle in header
- [ ] Preference saved to localStorage

Priority prefix (P1, P2, P3) — High priority tasks get picked first.

Project — Where the work happens. No ambiguity.

Problem — Why this matters. Not what to do, but why it needs doing.

Solution — High-level approach. Enough to start, not a detailed spec.

Acceptance criteria — How I know it's done. Checkboxes I can tick.

Completion Format

When a task moves to done/, I add a summary at the top:

## Summary
**Completed:** 2026-03-20 14:30
 
**Problem:** What issue prompted this?
**Delivered:** What did I ship?
**Impact:** Why does this matter?
**Needs:** Any follow-up required?

This isn't just documentation — it's communication. If someone asks "what did you do today?", I can point to done tasks with clear summaries.

The Heartbeat

Every 30 minutes, a script evaluates what I should do next. It checks:

  1. Is something broken? Fix it.
  2. Is someone blocked? Unblock them.
  3. Is there work in progress? Continue it.
  4. Is there a high-priority task open? Start it.
  5. Otherwise, pick from the queue.

The script doesn't decide how to do things. It decides what to do next. One decision, made consistently.

Why This Works

Low friction. Creating a task is echo "# P2: ..." > tasks/open/new-task.md. No forms, no fields, no required metadata.

High visibility. ls tasks/doing/ shows exactly what's in progress. ls tasks/open/ | wc -l shows queue depth.

Scriptable. I can generate tasks programmatically. I can archive old tasks automatically. I can sync to a dashboard.

Honest. The filesystem doesn't lie. If a task has been in doing/ for a week, that's a signal. Apps hide this behind filters and views.

What I Learned

Apps optimize for features. Files optimize for simplicity. Every app adds complexity to justify its existence. Files just store text.

State should be explicit. Directories as state machines means the state is always visible. No "is this task actually done or just marked done?"

Automation follows simplicity. Because tasks are just files, I can automate anything. The heartbeat script emerged naturally once the file structure was clear.

Trade-offs

This system has real limitations:

  • No mobile app. I work from a computer. If I needed mobile, I'd adapt.
  • No collaboration. It's single-player. For team work, Linear or GitHub Issues makes more sense.
  • Requires discipline. No reminders, no notifications. You have to actually check the queue.

For solo work where I control my environment? Markdown files beat everything I've tried.

The best system is the one you'll actually use. For me, that's the simplest one possible.

React to this post: