docs: add design sketch
This commit is contained in:
494
docs/design_sketch.adoc
Normal file
494
docs/design_sketch.adoc
Normal file
@ -0,0 +1,494 @@
|
|||||||
|
= lopa: v1 Design Sketch
|
||||||
|
Bertalan Z. Péter <bertalan.peter@bp99.eu>
|
||||||
|
:toc: left
|
||||||
|
:toclevels: 2
|
||||||
|
:sectnums:
|
||||||
|
:sectanchors:
|
||||||
|
:icons: font
|
||||||
|
:source-highlighter: rouge
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
This is a design sketch, not a specification.
|
||||||
|
It exists to pin down v1 scope, data model, file format, and CLI surface before implementation begins.
|
||||||
|
It is expected to evolve during and after v1 use.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
== 💡 Purpose and Motivation
|
||||||
|
|
||||||
|
`lopa` is a single-user CLI tool that aims to do *two* things well: task management and day planning.
|
||||||
|
It was built to scratch a specific itch: existing tools (eg todo.txt, TaskWarrior, SuperProductivity) each solve part of this problem but none solve all of it well for the author.
|
||||||
|
|
||||||
|
.Key motivations, in order
|
||||||
|
. Efficient **CLI**-first interaction (TaskWarrior does this well)
|
||||||
|
. *Day scheduling:* assigning tasks to concrete time slots on a given day (SuperProductivity does this reasonably well; TaskWarrior does not)
|
||||||
|
. **Plaintext**-first storage, so tasks can be viewed and edited on any device with a text editor, without a dedicated client (neither motivating tool does this)
|
||||||
|
. *Simple* by default: no urgency calculation, no forced project hierarchy
|
||||||
|
. *Nothing is deleted:* tasks are permanent records; if you want to get a task out of your view, close it with the appropriate reason
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
It should be emphasized that besides pure task management, _day scheduling_ is also a key feature of `lopa`.
|
||||||
|
Doing this type of scheduling well was a strong factor when I decided to develop _yet another_ task manager.
|
||||||
|
In my view, none of the existing perform adequately in this regard (SuperProductivity comes closest).
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
== 🚧 Scope
|
||||||
|
|
||||||
|
.In scope for v1
|
||||||
|
* Fundamentals
|
||||||
|
** Create and edit tasks
|
||||||
|
** Close tasks (as done or with a different reason: ‘wontfix’, invalid, duplicate)
|
||||||
|
** Reopen closed tasks
|
||||||
|
* Metadata
|
||||||
|
** Tag tasks (tags subsume the notion of ‘project’, at least for now)
|
||||||
|
** Add freeform notes to tasks
|
||||||
|
* Scheduling
|
||||||
|
** Create and edit day plans: ordered lists of tasks planned for a specific date with optional start times and durations
|
||||||
|
** Reorder tasks manually within day plans and the backlog
|
||||||
|
* Views
|
||||||
|
** Today’s plan (default)
|
||||||
|
** Other day’s plans
|
||||||
|
** Backlog
|
||||||
|
** Filtered task lists (including closed task archive)
|
||||||
|
|
||||||
|
.Out of scope for v1
|
||||||
|
* Bulk maintenance operations (including task deletion; to deal with the ever-growing task list)
|
||||||
|
* Priorities
|
||||||
|
* Subtasks
|
||||||
|
* Blocking relationships between tasks
|
||||||
|
* Recurring tasks
|
||||||
|
* Undo (git on the task directory serves this role)
|
||||||
|
* Sync protocol (external file-sync tools handle this)
|
||||||
|
* Long-running daemon
|
||||||
|
* REPL, TUI, alternative frontends
|
||||||
|
* Urgency calculation
|
||||||
|
* Other date fields on tasks (e.g. due dates). Distinct from day plan scheduling: day plans express intent to work on a specific date; a due date would express a deadline
|
||||||
|
* Notifications and reminders
|
||||||
|
* Natural-language date parsing
|
||||||
|
* Time tracking (start/stop timers)
|
||||||
|
* Calendar integration
|
||||||
|
* Import from other tools
|
||||||
|
* Plugins
|
||||||
|
|
||||||
|
.Explicit non-goals
|
||||||
|
* *Not* a multiuser system
|
||||||
|
* *Not* a networked system
|
||||||
|
* *Not* a GUI-focused application.
|
||||||
|
The primary interface is the CLI.
|
||||||
|
Additional frontends (potentially including a first-party GUI) may consume the same core library in future versions.
|
||||||
|
* *Not* a collaboration tool
|
||||||
|
|
||||||
|
|
||||||
|
== 🧠 Design Principles
|
||||||
|
|
||||||
|
. *Plaintext first.*
|
||||||
|
The task database must be readable and editable with any text editor on any device.
|
||||||
|
The tool is a convenience layer, not a gatekeeper.
|
||||||
|
Anybody must be able to develop their own alternative tooling over the same task database.
|
||||||
|
. *Tasks are permanent records.*
|
||||||
|
`lopa` does not delete tasks.
|
||||||
|
A task created has either an `open` state or some type of _closed_ state (`done`, `wontfix`, `invalid`, `duplicate` in v1).
|
||||||
|
. *Tasks and plans are separate artefacts.*
|
||||||
|
A task describes work that exists; a day plan describes intent for a specific date.
|
||||||
|
. *One thing per file.*
|
||||||
|
Editing one task or one plan must not require rewriting the whole database.
|
||||||
|
This also makes file-level sync tools (Syncthing, git, rsync) work correctly out of the box.
|
||||||
|
. *Boring, standard formats.*
|
||||||
|
Prefer widely-parsed formats over custom syntax.
|
||||||
|
Others should be able to write their own processors without implementing our parser.
|
||||||
|
. *Small, composable commands.*
|
||||||
|
Each subcommand does one thing.
|
||||||
|
Complex operations compose from simple ones.
|
||||||
|
. *Core logic as a library.*
|
||||||
|
The CLI is one frontend among possible others.
|
||||||
|
Task and plan operations live in a library package; the CLI is a thin shell over it.
|
||||||
|
The library is designed to serve the CLI’s actual needs – abstractions are not added in anticipation of hypothetical future consumers.
|
||||||
|
. *Defer complexity.*
|
||||||
|
Features earn their place through real use, not through anticipation.
|
||||||
|
. *Design for the daemon we might build, but do not build it.*
|
||||||
|
Keep business logic separable from CLI plumbing so a future daemon or alternate frontend does not require a rewrite.
|
||||||
|
|
||||||
|
|
||||||
|
== 💽 Data Model
|
||||||
|
|
||||||
|
We have two artefact types: *tasks* and *day plans.*
|
||||||
|
Tasks describe work to be done and day plans describe your intent to do certain tasks on a specific date.
|
||||||
|
Day plans reference tasks by their IDs.
|
||||||
|
|
||||||
|
=== The task
|
||||||
|
|
||||||
|
A task has the following fields in v1:
|
||||||
|
|
||||||
|
[cols="2,1,1,4",options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Type | Required | Notes
|
||||||
|
|
||||||
|
| `id`
|
||||||
|
| string
|
||||||
|
| yes
|
||||||
|
| Short generated identifier, 5-character base32.
|
||||||
|
Short enough to type, long enough to avoid collisions at expected scale.
|
||||||
|
|
||||||
|
| `title`
|
||||||
|
| string
|
||||||
|
| yes
|
||||||
|
| One-line summary of the task.
|
||||||
|
|
||||||
|
| `status`
|
||||||
|
| enum
|
||||||
|
| yes
|
||||||
|
| One of `open`, `done`, `wontfix`, `invalid`, or `duplicate`.
|
||||||
|
Defaults to `open` on creation and `done` when closed without any specific reason.
|
||||||
|
|
||||||
|
| `created`
|
||||||
|
| datetime (ISO 8601)
|
||||||
|
| yes
|
||||||
|
| Auto-set on creation.
|
||||||
|
|
||||||
|
| `tags`
|
||||||
|
| list of strings
|
||||||
|
| no
|
||||||
|
| Free-form labels.
|
||||||
|
Also used to model what other tools call ‘projects.’
|
||||||
|
|
||||||
|
| `order`
|
||||||
|
| integer
|
||||||
|
| no
|
||||||
|
| Manual ordering within the backlog.
|
||||||
|
Higher values sort higher.
|
||||||
|
|
||||||
|
| `notes`
|
||||||
|
| string (multiline)
|
||||||
|
| no
|
||||||
|
| Freeform text attached to the task.
|
||||||
|
Stored as a multiline TOML string.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
=== The day plan
|
||||||
|
|
||||||
|
A day plan has the following fields in v1:
|
||||||
|
|
||||||
|
[cols="2,1,1,4",options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Type | Required | Notes
|
||||||
|
|
||||||
|
| `date`
|
||||||
|
| date (ISO 8601)
|
||||||
|
| yes
|
||||||
|
| The date this plan covers.
|
||||||
|
Matches the filename; stored in-file for self-containment.
|
||||||
|
|
||||||
|
| `entries`
|
||||||
|
| array of tables
|
||||||
|
| no
|
||||||
|
| Ordered list of planned entries.
|
||||||
|
Empty array is valid (a plan can exist without content).
|
||||||
|
Ordering is by array position in the file; reordering means editing the array.
|
||||||
|
|===
|
||||||
|
|
||||||
|
Each entry within `entries` has:
|
||||||
|
|
||||||
|
[cols="2,1,1,4",options="header"]
|
||||||
|
|===
|
||||||
|
| Field | Type | Required | Notes
|
||||||
|
|
||||||
|
| `task`
|
||||||
|
| string
|
||||||
|
| yes
|
||||||
|
| ID of a task file.
|
||||||
|
|
||||||
|
| `start`
|
||||||
|
| time (HH:MM)
|
||||||
|
| no
|
||||||
|
| Start time within the plan’s date.
|
||||||
|
Absence means ‘on the list, no specific slot.’
|
||||||
|
|
||||||
|
| `duration`
|
||||||
|
| integer (minutes)
|
||||||
|
| no
|
||||||
|
| Expected duration.
|
||||||
|
Required when `start` is set; ignored when `start` is absent.
|
||||||
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
== 🤯 Design Notes
|
||||||
|
|
||||||
|
=== Tasks vs Day Plans
|
||||||
|
|
||||||
|
In `lopa`, tasks are timeless artefacts.
|
||||||
|
Day plans form a mechanism to schedule a task to a specific time.
|
||||||
|
|
||||||
|
.Consequences
|
||||||
|
* Initially, a special ‘today’ feature was considered that would be used at the start of a day to add a set of tasks that are planned for today.
|
||||||
|
However, since more long-term scheduling was also desired, this would mean managing two schedules in parallel.
|
||||||
|
It could be done but would be convoluted.
|
||||||
|
Instead, the simple, sane, and logical choice was to not treat ‘today’ differently than other dates.
|
||||||
|
Tasks for ‘today’ are those that are scheduled for today’s date in a day plan.
|
||||||
|
* Historical plans are preserved; for example, `plans/2026-03-15.toml` is a record of what the user intended to do on that day and remains readable indefinitely.
|
||||||
|
|
||||||
|
|
||||||
|
=== Task Lifecycle
|
||||||
|
|
||||||
|
It is a rather unorthodox choice, but in `lopa`, tasks live forever and are never meant to be deleted.
|
||||||
|
If deletion were possible, we would have to think about what to do when a task is deleted that was referenced in a day plan but that becomes a non-issue.
|
||||||
|
|
||||||
|
The state change of a task never implies any change to the day plans.
|
||||||
|
For example, even if a task is marked `done`, it remains in the day plans it was added to.
|
||||||
|
In practice, the default `lopa view` and `lopa ls` output hides closed tasks; passing `--all` shows them.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
Unlike tasks, day plans *can* be deleted.
|
||||||
|
These plans represent intent and can be reasonably discarded.
|
||||||
|
Of course, deleting a plan does not affect the tasks that were referenced in that plan in any way.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
=== IDs
|
||||||
|
|
||||||
|
* Generated at task creation.
|
||||||
|
* 5-character base32 (alphabet: `abcdefghijkmnpqrstuvwxyz23456789`, omitting visually ambiguous characters such as `l` and `o`).
|
||||||
|
* Case-insensitive on input, canonicalized to lowercase on write.
|
||||||
|
* If collision, retry.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
Because tasks are never deleted, the ID space accumulates over time.
|
||||||
|
For power users, this _might_ become an issue after prolonged use.
|
||||||
|
The future plan to handle this problem is a supported mechanism for wiping the ‘archive,’ possibly after an export.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
== 🗄️ File Format
|
||||||
|
|
||||||
|
=== One file per artefact
|
||||||
|
|
||||||
|
Each task lives in its own file named `<id>.toml`.
|
||||||
|
Each day plan lives in its own file named `<date>.toml`.
|
||||||
|
|
||||||
|
.Rationale
|
||||||
|
* Editing one task or plan rewrites only that file.
|
||||||
|
Sync tools handle per-file merges cleanly.
|
||||||
|
Concurrent edits on different devices only conflict when the same file is edited on both.
|
||||||
|
* `git diff` on the data directory shows exactly what changed.
|
||||||
|
* `grep`, `find`, etc work across the directory without any custom tooling.
|
||||||
|
* On a phone with a text editor, opening one task means opening one file, not scrolling through thousands of lines.
|
||||||
|
* This pattern is well-precedented (Maildir for email, Jekyll/Hugo for static sites, Obsidian for notes).
|
||||||
|
|
||||||
|
=== File structure
|
||||||
|
|
||||||
|
Each task file is a valid TOML document.
|
||||||
|
|
||||||
|
.Example task file (eg `4a2fk.toml`)
|
||||||
|
[source,toml]
|
||||||
|
----
|
||||||
|
id = "4a2fk"
|
||||||
|
title = "Write project spec"
|
||||||
|
status = "open"
|
||||||
|
created = 2026-07-02T09:15:00Z
|
||||||
|
tags = ["work", "writing"]
|
||||||
|
order = 100
|
||||||
|
notes = """
|
||||||
|
Freeform notes go here.
|
||||||
|
|
||||||
|
Multiple paragraphs are fine. Markdown, code blocks, whatever the user
|
||||||
|
wants. The tool treats this string as opaque.
|
||||||
|
"""
|
||||||
|
----
|
||||||
|
|
||||||
|
Each day plan file is also a valid TOML document.
|
||||||
|
Entries are represented as an array of tables.
|
||||||
|
|
||||||
|
.Example day plan file (eg `2026-07-13.toml`)
|
||||||
|
[source,toml]
|
||||||
|
----
|
||||||
|
date = 2026-07-13
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
task = "4a2fk"
|
||||||
|
start = "11:00"
|
||||||
|
duration = 90
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
task = "7b3cm"
|
||||||
|
start = "13:00"
|
||||||
|
duration = 10
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
task = "9k4mp"
|
||||||
|
# no start time – planned for the day but no fixed slot
|
||||||
|
----
|
||||||
|
|
||||||
|
The order of entries in the file is the display order.
|
||||||
|
Reordering means moving the `[[entries]]` blocks up or down in the file.
|
||||||
|
|
||||||
|
.Rationale for TOML over alternatives
|
||||||
|
* *JSON*: 👎 hostile to hand-editing (no comments, quoted keys, trailing-comma paranoia).
|
||||||
|
* *YAML*: 👎 whitespace-significant editing on a phone is error-prone.
|
||||||
|
* *TOML*: 👍 unambiguous, comments allowed, native date/time types, wide parser support in every serious language.
|
||||||
|
* *Custom format*: would require documenting and maintaining a parser, and would raise the barrier for third-party tooling.
|
||||||
|
|
||||||
|
|
||||||
|
== 📁 Directory Layout
|
||||||
|
|
||||||
|
.Default layout under XDG base directories
|
||||||
|
----
|
||||||
|
$XDG_DATA_HOME/lopa/ (default: ~/.local/share/lopa/)
|
||||||
|
tasks/
|
||||||
|
4a2fk.toml
|
||||||
|
7b3cm.toml
|
||||||
|
...
|
||||||
|
plans/
|
||||||
|
2026-07-13.toml
|
||||||
|
2026-07-14.toml
|
||||||
|
...
|
||||||
|
archive/
|
||||||
|
9k4mp.toml
|
||||||
|
...
|
||||||
|
|
||||||
|
$XDG_CONFIG_HOME/lopa/ (default: ~/.config/lopa/)
|
||||||
|
config.toml
|
||||||
|
----
|
||||||
|
|
||||||
|
.Design decisions
|
||||||
|
* Three flat directories: `tasks/` for open tasks, `plans/` for day plans, `archive/` for closed tasks.
|
||||||
|
* Plan files are named by the date they cover (`YYYY-MM-DD.toml`).
|
||||||
|
* Tasks whose `status` is not `open` (i.e. `done`, `wontfix`, `invalid`, or `duplicate`) move to `archive/` via rename.
|
||||||
|
Rationale: keeps the active `tasks/` directory focused on live work, cleaner git diffs for daily activity.
|
||||||
|
* Reopening a closed task moves it back to `tasks/`.
|
||||||
|
* Plan files are never archived – they accumulate as a permanent journal of intent.
|
||||||
|
* No index file. The directory listings are the index.
|
||||||
|
A cache can be added later without changing the on-disk format.
|
||||||
|
|
||||||
|
|
||||||
|
== ⌨️ CLI Surface
|
||||||
|
|
||||||
|
=== Command shape
|
||||||
|
|
||||||
|
Subcommand style.
|
||||||
|
Every mutating command takes a task ID.
|
||||||
|
|
||||||
|
.Command surface for v1
|
||||||
|
[cols="2,3",options="header"]
|
||||||
|
|===
|
||||||
|
| Command | Effect
|
||||||
|
|
||||||
|
| `lopa`
|
||||||
|
| Default view: today’s scheduled tasks.
|
||||||
|
|
||||||
|
| `lopa add "title" [flags]`
|
||||||
|
| Create a task.
|
||||||
|
Flags: `--tag`, `--plan <when>`, `--note`.
|
||||||
|
|
||||||
|
| `lopa ls [filters]`
|
||||||
|
| List tasks.
|
||||||
|
Filters: `--today`, `--tag <t>`, `--status <s>`, `--planned`, `--unplanned`, `--planned-on <d>`, `--all` (include closed).
|
||||||
|
Composable.
|
||||||
|
|
||||||
|
| `lopa show <id>`
|
||||||
|
| Show full detail of one task, including notes and referencing day plans.
|
||||||
|
|
||||||
|
| `lopa edit <id>`
|
||||||
|
| Open the raw task file in `$EDITOR`.
|
||||||
|
Re-parsed and validated on save.
|
||||||
|
|
||||||
|
| `lopa close <id> [reason]`
|
||||||
|
| Close a task, optionally with a specific reason (`done` is the default).
|
||||||
|
|
||||||
|
| `lopa reopen <id>`
|
||||||
|
| Reopen a closed task.
|
||||||
|
|
||||||
|
| `lopa view [when]`
|
||||||
|
| Show the day plan for `<when>` (an ISO 8601 date) or today by default.
|
||||||
|
Closed tasks are hidden unless `--all` is passed.
|
||||||
|
|
||||||
|
| `lopa plan <id> [when]`
|
||||||
|
| Add a task to a day plan (today by default).
|
||||||
|
|
||||||
|
| `lopa unplan <id> [when]`
|
||||||
|
| Remove a task from a day plan (today by default).
|
||||||
|
An `--all` flag requests removal from all day plans.
|
||||||
|
|
||||||
|
| `lopa edit-plan [when]`
|
||||||
|
| Open the raw plan in `$EDITOR` for today or the specified date.
|
||||||
|
|
||||||
|
| `lopa mv <id> <where> [--on <date>\|--backlog]`
|
||||||
|
| Reorder a task using anchored positioning.
|
||||||
|
`<where>` is one of: `top`, `bottom`, `before <other_id>`, `after <other_id>`.
|
||||||
|
By default, operates on today’s plan.
|
||||||
|
`--on <date>` targets a specific day’s plan.
|
||||||
|
`--backlog` adjusts the task’s `order` field to fit the specified position.
|
||||||
|
|
||||||
|
| `lopa tag <id> +foo -bar`
|
||||||
|
| Add or remove tags.
|
||||||
|
|===
|
||||||
|
|
||||||
|
=== Date arguments
|
||||||
|
|
||||||
|
In v1, all date arguments to CLI commands must be in ISO 8601 (`YYYY-MM-DD`) format.
|
||||||
|
Human-readable date grammars (`today`, `tomorrow`, `next mon`) are deferred to a later version.
|
||||||
|
Commands that accept a date default to today’s date when the argument is omitted.
|
||||||
|
|
||||||
|
=== Output
|
||||||
|
|
||||||
|
* Default output is human-readable, formatted for terminal width.
|
||||||
|
* `--json` flag on `ls`, `show`, and `view` produces machine-readable output.
|
||||||
|
This is the first seed of the future protocol/API, but is a byproduct of the CLI, not a separate design effort.
|
||||||
|
|
||||||
|
=== Design notes on the command surface
|
||||||
|
|
||||||
|
* *Verbs, not `set field=value`.*
|
||||||
|
`lopa close`, `lopa plan`, `lopa tag` express intent more clearly than something like `lopa set 4a2fk status=done`.
|
||||||
|
* *`lopa edit` as escape hatch.*
|
||||||
|
Anything the flags do not cover can be done by editing the file directly.
|
||||||
|
This lowers the bar for the tool itself: it does not need to support every possible mutation as a flag.
|
||||||
|
* *`lopa add` accepts common fields at creation.*
|
||||||
|
Avoids the add-then-edit friction for the common case.
|
||||||
|
|
||||||
|
|
||||||
|
== 🛠️ Implementation Notes
|
||||||
|
|
||||||
|
These are guidance for implementation, not final decisions.
|
||||||
|
|
||||||
|
* *Language*: Go, provisionally.
|
||||||
|
Rationale: fast to write, good stdlib for filesystem and encoding work, single static binary, easy cross-compilation for future device targets, mature TOML libraries.
|
||||||
|
* *Dependencies*: minimize.
|
||||||
|
Curated libraries allowed where they replace significant plumbing (TOML parsing, CLI arg parsing).
|
||||||
|
Zero deps is not a goal.
|
||||||
|
* *Architecture*: the core lives in a library package (task and plan CRUD, filtering, scheduling logic).
|
||||||
|
The CLI is a thin frontend over this library.
|
||||||
|
This keeps the door open to a first-party GUI, a daemon, a REPL, a TUI, or any other frontend without rewriting core logic.
|
||||||
|
Design the library API to serve the CLI’s needs; do not speculatively add abstractions for consumers that do not yet exist.
|
||||||
|
* *No daemon in v1.*
|
||||||
|
Each invocation opens the data directory, does its work, and exits.
|
||||||
|
|
||||||
|
|
||||||
|
== ❓ Open Questions
|
||||||
|
|
||||||
|
Questions to resolve before or during implementation:
|
||||||
|
|
||||||
|
* Whether closing a task should also remove its references from *future* plan files.
|
||||||
|
The current proposal is to leave them.
|
||||||
|
* How `--json` output represents null/unset optional fields.
|
||||||
|
* Whether to include a `--dry-run` flag on mutating commands.
|
||||||
|
* How `lopa mv --backlog` computes `order` values when inserting between existing tasks (renumber vs. fractional gaps vs. large-integer gap policy). Implementation detail, but affects long-term stability of manual ordering.
|
||||||
|
|
||||||
|
|
||||||
|
== ✅ What v1 "Done" Looks Like
|
||||||
|
|
||||||
|
.v1 is done when the author can
|
||||||
|
. Add tasks with tags from the CLI.
|
||||||
|
. Create day plans and add tasks to them with or without specific time slots.
|
||||||
|
. Put the same task on multiple day plans.
|
||||||
|
. See the day’s plan and other days’ plans with a single command.
|
||||||
|
. Reorder tasks manually within a plan and within the backlog.
|
||||||
|
. Edit any field of any task, and any plan file, directly in `$EDITOR`.
|
||||||
|
. Close tasks with a reason.
|
||||||
|
. Sync the whole data directory across machines with Syncthing and have it _Just Work™._
|
||||||
|
. Use the tool daily for at least two weeks without reaching for another tried-and-tested tool.
|
||||||
|
|
||||||
|
The last item is the real acceptance test.
|
||||||
Reference in New Issue
Block a user