
Markdown-native pomodoro timer for the LLM era
Every pomodoro app keeps your plan and your history inside its own database. You cannot diff it, you cannot paste it into a prompt, and when you stop using the app it is gone.
Pomodoro.md uses plain markdown as its interface instead. Your daily plan is a markdown timetable — in Obsidian, or any plain text file:
# Timetable
## Morning (09:00~12:00) 6p
- 1p Morning routine
- 3p #482 : Ship the onboarding redesign
- Review design feedback
- Implement the new welcome screen
- Write release notes
- 2p Reply to code reviews
It becomes a task list in Raycast. Pick a task, run pomodoros:

…and the log is written back into the same note:
### Pomodoro Log
- Morning routine
- [x] 09:02-09:27
- #482 : Ship the onboarding redesign
- [x] 09:32-09:57 Review design feedback
- [ ] 10:01-10:14
Plain markdown in, plain markdown out — readable for you, and for an LLM agent that plans your day or reviews it:
LLM plans your day → markdown → Pomodoro.md → markdown log → LLM reviews your day
Pick one in the extension preferences. Everything else works the same in both.
| Manual (default) | Daily Note | |
|---|---|---|
| Tasks come from | Typed into Raycast | A markdown timetable in your notes |
| Session log goes to | Nowhere — Manual mode keeps no log | Written into today's note as markdown |
| Setup needed | None | Point it at your notes folder |
| Good for | Using it as a plain pomodoro timer | Planning in Obsidian, or with an LLM |
Lists today's tasks — grouped by time block in Daily Note mode — and starts a pomodoro (25 minutes by default) on the one you pick. Subtasks are listed under their parent and can be started on their own, so the log records which part you actually worked on.
Type anything into the search bar to start it as an ad-hoc task (in Manual mode it is added to your list). Mark as Done ticks the task off; in Daily Note mode it writes [done] straight into the note.
If a pomodoro is already running, picking another task asks for confirmation and carries the remaining time over rather than restarting the clock.

Stops the current pomodoro, writes its log entry, and starts a break — remembering the task you were on. When the break ends, the task list opens with a one-key Resume action for that task, so you don't have to find it again.


Starts a pomodoro on a task name you configure once (e.g. Morning Routine) without opening any list. Anything already running is stopped and logged first.
Ends the current pomodoro or break. A stopped-early pomodoro is still logged, marked [ ] instead of [x]. A pomodoro that already ran its full length is recorded as completed, whichever command notices it first.
Keeps the remaining time in the menu bar while you work, with the current task name and actions to stop or switch tasks. Breaks count down the same way. When the time is up, it opens the task list with a Start Break / Resume prompt.


The default, and the one to use if you just want a pomodoro timer. Tasks live inside Raycast: type a name into Start Pomodoro to add one and start it, then Mark as Done or Remove Task from the action panel (⌘K). Nothing is written to your notes, so there is no setup — switch to Daily Note mode whenever you want the log in your notes.

Daily Note~/Obsidian/daily)YYYY-MM-DD.md, adjust Daily Note Filename (e.g. YYYYMM/YYYY-MM-DD.md for monthly subfolders)Only two lines matter:
## Block name — a time block, one heading level below the Timetable Header (# Timetable by default)- 2p Task title — a task, where 2p is how many pomodoros you plannedOptional extras:
(09:00~12:00) after the block name is shown next to it; a trailing 6p (planned total) is accepted and ignored - Subtask title — a subtask, indented with a tab or 2+ spaces[done] after Np (or after - on a subtask) marks it as already finishedBreak or Lunch by default) are skipped; the whole name must match, ignoring case, so add Lunch Break as its own keyword if you use that nameEach finished session appends one line under its task's bullet in the Pomodoro Log Header section. The section is created on first use — inside the Log Section Header section if it exists, otherwise at the end of the note. [x] is a completed pomodoro, [ ] one you stopped early, and a trailing label is the subtask that was running. Nothing else in the note is rewritten, so notes you keep in that section stay put.
| Preference | Default | Description |
|---|---|---|
| Task Mode | Manual | Manual keeps tasks in Raycast; Daily Note reads them from markdown |
| Daily Note Directory | — | Folder containing your daily notes |
| Daily Note Filename | YYYY-MM-DD.md | Path of today's note relative to the directory; YYYY, MM, DD are replaced |
| Pomodoro / Break Duration | 25 / 5 | Length in whole minutes |
| Timetable Header | # Timetable | Header that starts the timetable section |
| Log Section Header | ## Work Log | Section the pomodoro log is placed in |
| Pomodoro Log Header | ### Pomodoro Log | Header of the pomodoro log itself |
| Break Keywords | Break,Lunch | Comma-separated block names to skip; a block is skipped when its name equals a keyword, ignoring case |
| Quick Start Task Name | Morning Routine | Task started by the Quick Start command |
| Enable Logging | on | Write the pomodoro log to the daily note |
- 2p …), and subtasks must be indented with a tab or at least two spaces; a single space is not recognised.npm install
npm run dev # develop with hot reload
npm run lint # lint and format check
Commands in src/ sit on top of small modules: parser (markdown → tasks), timer (stored timer state + session log), session (start/stop transitions — every command settles an expired timer before acting), log-markdown (appends one entry to a note), and swappable task-source / log-writer backends for Manual vs Daily Note mode.
MIT
Stop the current pomodoro or break timer
Show current pomodoro status in the menu bar
Pick a task from your list and start a pomodoro
Start a break timer (stops the current pomodoro if running)
Start a pomodoro with the configured quick start task