Stable agent-facing interface. Every platform binary is dual-mode: any argument at launch routes to the CLI (the GUI toolkit is never initialized); no arguments opens the GUI. Command output and exit codes are identical across platforms — enforced by golden-output tests in CI.
taskly <subcommand> [options] [--json] [--db PATH] [--quiet]
--jsonmachine-readable output (stdout only; errors as JSON on stderr)--db PATHoverrides DB resolution--quiet/-qminimal output (usually just the id)- DB resolution:
--db→ configlast-db-path→~/.taskly/tasks.db; unopenable → error, exit 4. - Response-file expansion is disabled (
@10ammust never read a file).
| Code | Meaning | Triggers |
|---|---|---|
| 0 | success (including rm of an already-missing id) |
|
| 1 | generic error | unknown exceptions; install/uninstall failures |
| 2 | validation failure | bad --view / --status / --color; unparseable --due; text/name too long or empty |
| 3 | not found | --list name miss; add with no lists; update/done/undone unknown id |
| 4 | database error | cannot open; SQLite error |
Error JSON on stderr, 2-space indented, always:
{"ok": false, "error": "<message>", "exitCode": <code>}
Success JSON on stdout, 2-space indented, null fields omitted
(WhenWritingNull), fixed field order.
{ "id": 1, "listId": 1, "listName": "工作", "text": "买牛奶", "completed": false,
"dueDate": "2026-09-16", "dueTime": "10:00", "notes": null, "createdAt": "..." }
{ "id": 1, "name": "工作", "icon": "📋", "color": -4104388, "pendingCount": 3 }Human-readable (non---json) task row: %5d [x| ] text 🗓 dueDate[ dueTime];
empty result prints (no tasks) (suppressed when --quiet).
List row: %5d icon name (pendingCount).
Default: all incomplete.
--list ID|NAME— numeric → id; otherwise case-sensitive exact name match; miss → exit 3 withList not found by name: "<list>". Takes precedence over--viewwhen both given.--view today|planned|scheduled|all|completed(case-insensitive;scheduled=planned; defaultall; anything else → exit 2).--status all|incomplete|open|pending|completed|done(defaultincomplete;allandcompletedboth map to "include completed, completed sinks to bottom"; default/others → incomplete only).--limit N(default 1000).completedview alwayscompleted = 1, no ORDER BY.- Sorting: today
id DESC; planneddue_date ASC; all/listid DESC(completed ASC first when included).
All lists with pendingCount (COUNT(*) WHERE list_id=? AND completed=0).
--list ID|NAME(default: first list; none exists → exit 3,No lists exist yet. Create one withtaskly mklistfirst.)--due EXPR(below),--time HH:mm(explicit--timeoverrides a time carried by--due),--notes "...".createdAt= local ISO-8601 round-trip now. Text validation → exit 2.- Output: task JSON / human row / quiet → id.
Read-modify-write; unspecified fields unchanged. --text --due --clear-due --time --clear-time --list --notes --clear-notes.
--due overwrites dueTime only when the expression carries a time (a pure
date keeps the existing time); --clear-due clears the date only. Unknown
id → exit 3. Outputs the updated task.
Idempotent completed=1/0 (affected rows == 0 → exit 3). --json prints
the task; --json --quiet prints {"ok":true,"id":N,"completed":bool}.
--json prints {"ok":true,"id":N,"deleted":bool} regardless of --quiet;
exit 0 either way. Non-json: Deleted task N / Task N did not exist.
text LIKE '%kw%' — task text only, completed included, unsorted,
--limit default 100. Empty keyword → empty array.
--icon <emoji> --color #RRGGBB|AARRGGBB|<int>. Name validation → exit 2.
Color parsing: plain int → as-is; #RRGGBB → 0xFF000000|RGB; 8-digit hex
→ as-is; anything else → exit 2. Null icon/color get defaults (📋 / Crail).
Output: list JSON / list row / quiet → id.
Cascade-delete tasks then the list; output like rm (Deleted list N (and its tasks)); exit 0 either way.
- macOS/Linux: shell wrapper
#!/bin/sh\nexec "<exe>" "$@"at~/.local/bin/taskly(chmod +x); if~/.local/binis not on PATH, append an idempotent# Added by Tasklyblock to~/.zshrc(macOS) /~/.bashrc(Linux) and report NeedsShellRestart. - Windows: copy self to
%LOCALAPPDATA%\Programs\Taskly\taskly.exe, writetaskly.cmdshim, add the dir toHKCU\Environment\Path(idempotent, REG_EXPAND_SZ) and broadcastWM_SETTINGCHANGE. - Uninstall removes the artifacts; when nothing is installed, print
taskly command was not installed (nothing to remove).to stderr and exit 1.
Pre-map bare words (case-insensitive): today → +0d, tomorrow/tmw →
+1d, tonight → @20:00.
Then DateParser:
- Relative
+N{m|h|d|w|M}— regex^(\d*)([mhdwM])$, digits optional (default 1), case-sensitive (mminutes,Mmonth = 30 days), from now. @time:now|H|H:MM|Ham|Hpm|H:MMam|H:MMpm(am/pm any case; 12am→0, pm<12→+12; hour 0–23, min 0–59). Optional trailing modifier:tomorrow/tmw, orsun..sat= next such weekday (if today or past → next week). No modifier + time already past → tomorrow.- Absolute:
yyyy-MM-dd,yyyy/MM/dd,MM/dd/yyyy,dd/MM/yyyy(tried in this order), year in [1900, 2100]; normalized toyyyy-MM-dd. - Relative results are full
yyyy-MM-dd HH:mm:ss; absolute areyyyy-MM-dd.
Pure-date intent (today/tomorrow/tmw, +Nd/+Nw/+NM, a 10-char absolute
result) clears dueTime; +Nm/+Nh/@… keep it.
Unparseable → exit 2:
Cannot parse date/time: "<due>". Supported: +10m, +2h, +1d, +1w, @10am, @10:30pm, today, tomorrow, yyyy-MM-dd