View on GitHub

cat-task-manager

cat-task-manager

cat-task-manager

A TUI for managing small, daily recurring tasks. Keyboard operated. Written in Rust.

Background

Just as everyone has their own quirks, so too do task management apps for daily life.

In this modern era where “vibe coding” is possible, there’s no longer a need to conform your habits to a task management app; it’s faster to “vibe code” a task management app that fits your own habits.

That’s what I thought, so I “vibe coded” this. It’s not intended for use by others. I will frequently make breaking changes without prior notice. That said, I hope sharing this might provide some sort of hint or inspiration to someone.

※Note: Much of the following text was generated by AI and may be difficult to read, so I plan to revise it manually later.

Philosophy

This application is not a general-purpose TODO app. Rather than handling projects, deadlines, priorities, tags, search, or complex dependencies, it prioritizes seamlessly progressing through “today’s fixed sequence of tasks.”

Daily tasks won’t continue if their management becomes overly elaborate. What’s needed is to quickly see only the single task that needs attention, to record its start time, to move to the next task upon completion, and for the user’s required operations to be lightweight.

Therefore, cat-task-manager does not have features to encourage adding too many tasks. Tasks are not hierarchical. They don’t have parallel dependencies. They don’t have per-task notes or attributes. To maintain a daily flow, it strongly emphasizes progressing tasks sequentially.

Tasks and their current daily status are solely defined by tasks/*.md. Tasks are not written in the config. It does not maintain a separate status directory. Prioritizing the ability to frequently maintain tasks, adhering to the Easy To Change (ETC) principle, the user’s interaction is limited solely to the task description Markdown files.

- [ ] 朝のルーティン
- [ ] メール確認
- [ ] コードレビュー

With this format, there’s no need to duplicate tables or field names when adding tasks. The top-to-bottom order directly becomes the execution order, and if you want to change the order, you can simply move lines in a text editor.

Implementation Approach

Task definitions and their current state are consolidated in tasks/*.md. Regular non-empty lines serve as task definitions, and the state is read as JSON at the end of each task line. The end-of-line JSON is an area managed by the application.

- [x] 朝のルーティン {"date":"2026-05-19","state":"done","started_at":"2026-05-19T09:00:00+09:00","completed_at":"2026-05-19T09:05:00+09:00"}
- [ ] メール確認 {"date":"2026-05-19","state":"in_progress","started_at":"2026-05-19T09:12:00+09:00"}
- [ ] コードレビュー {"date":"2026-05-19","state":"not_started"}

This is a compromise to avoid duplicating state into separate files. Even if you correct a typo in a task name, the state won’t disappear as long as the end-of-line JSON for that line is preserved. If lines are added, deleted, or reordered, the state moves along with the same line. Tasks marked - [x] without end-of-line JSON will be normalized to include the detected time as both start and completion times in the end-of-line JSON. If the end-of-line JSON format is corrupted, it will be treated as an error upon startup or reload.

Statistics for past data are read from tasks/*.md files preserved in the Git history. On the statistics screen, the task list’s estimation displays the average of the most frequent band in a 5-minute histogram, after excluding outliers using the IQR method from past completion records for each task. If there’s a tie for the most frequent band, the median is displayed. The persistent state of task information is stored solely in tasks/*.md.

The screen is designed to allow focusing on the next task while also being able to view the overall list only when needed. Upon startup, it defaults to a single-line view, and v toggles between single-line, incomplete tasks, and full display. In the incomplete view, completed tasks are excluded, while the full display includes completed tasks. For completed tasks, the work time is shown based on start and completion times. Operations are only applicable to tasks that are not started, in progress, on hold, or deferred.

The states are kept minimal: Not Started, In Progress, Completed, On Hold, Deferred, and Timed Out. On Hold blocks the next task, while Deferred allows progressing to the next task without blocking. When a task is on hold in the single-line view of an individual tab, a status explanation is displayed for moving to other tabs. Once the date changes, any incomplete tasks are treated as “Timed Out” for that day’s record. This is not to complicate deadlines or scheduling, but a compromise to simply record that a task “wasn’t finished that day.”

Operations are primarily keyboard-driven. Starting and completing tasks use the same key, and holding (to another tab) and resuming also toggle with the same key. Deferring tasks is also toggled by key input. tasks/*.md can also be opened via key command and reloaded upon closing. It’s faster to rely on your usual editor than to build forms within the app, and it’s easier to review content in case of errors.

Configuration Format

config.toml only contains settings for editor candidates, keybindings, startup Git snapshot, and auto-start for free time. It does not contain tasks.

editors = ["fresh", "zed", "nvim", "code"]

[startup_git]
auto_commit_and_push = false

[auto_free_time]
enabled = false
idle_seconds = 60
active_hours = "09:00-17:00"

[keybindings]
j = "next"
down = "next"
k = "previous"
up = "previous"
enter = "advance"
space = "advance"
p = "hold"
d = "defer"
q = "quit"
e = "edit"
l = "next_tab"
right = "next_tab"
h = "previous_tab"
left = "previous_tab"
v = "toggle_view"
s = "stats"
"?" = "help"

Only when startup_git.auto_commit_and_push = true, %LOCALAPPDATA%\cat-task-manager will be Git committed and pushed once a day upon startup.

Only when auto_free_time.enabled = true, free time will automatically start if there are no ‘in progress’ tasks for idle_seconds within the active_hours period. The end time is not included in the period. Cross-day periods like 22:00-02:00 can also be specified.

The save location is consolidated under Windows’ AppData Local.

%LOCALAPPDATA%\cat-task-manager\config.toml
%LOCALAPPDATA%\cat-task-manager\tasks\tasks.md

tasks/*.md serves as the Single Source of Truth (SSoT) that both the user and the app read from and write to. config.toml contains settings for the operating environment.

Deliberate Choices

This app is designed not as a place to “manage tasks”, but as a place to “progress through a fixed daily routine.”

For flexible TODO management, search, tagging, and deadline management, rely on other tools. cat-task-manager starts the same way every day, progresses sequentially from top to bottom, and records unfinished tasks as part of that day’s outcome. Maintaining this simplicity is a top implementation priority.