v1.31.0
Added
-
taskr mints sync tokens, and says when yours is guessable.
taskr serve --new-tokengenerates one from the system CSPRNG, stores it and
prints it;ctrl+gon the Settings server-token row does the same. Every
other protection around the token — constant-time comparison,0600on
sync.json, never logged — was downstream of a secret you invented at a
prompt, which made a short one the likeliest realistic compromise of a sync
setup.taskr doctor, Settings andtaskr servenow warn when the
configured token is short or looks like a word. The Settings server-token
row goes further and refuses one outright, since that token is taskr's own
choice andctrl+gis one keystroke away; the client token,taskr serveand
TASKR_SYNC_TOKENonly warn, because the first has to match whatever the
other end already uses and the last two may come from a secret manager or a
unit file written a year ago. taskr refuses only where it can offer the
alternative in the same breath. -
The updater only follows GitHub. The download URL arrives inside the
release API's JSON, so it is data rather than a constant; it is now confined
togithub.comandgithubusercontent.comover TLS, checked on the initial
request and on every redirect — a pre-flight check alone would have been
walked past by a 302. -
Release builds are reproducible (
-trimpath,CGO_ENABLED=0, the Go
version pinned ingo.mod), so a tag can be rebuilt and compared against
SHA256SUMSby anyone.SECURITY.mdnow states plainly what that checksum
proves — that your download matches what the workflow published — and what it
does not: that the publisher was honest. Signing that binds a release to the
workflow identity would close that gap and is not implemented yet. -
j/kmove the cursor, everywhere↑/↓do: the task lists, the detail
pane, the drill-ins, the board, the calendar, settings, and scrolling the help
overlay. They are aliases resolved at dispatch rather than per-switch cases,
so a context that answers an arrow answers them too — and a key you rebind
ontojorkstill wins over the alias. -
The score reads as a percentage of the current field. The raw score is
unbounded upward — Age alone adds 0.2/day forever — so "24.4" in the Score
column asked to be calibrated against a scale nobody had published, and read
as an arbitrary number. Everywhere the score is shown (the Tasks column,
the detail pane, the Settings preview,taskr top,taskr show) it is now a
percentage, where 100% is the highest-scoring pending task right now. The
points survive where the arithmetic is being explained — thewoverlay and
taskr why— and those state what 100% currently costs in points, so the
mark moving when you finish the top task is visible rather than mysterious.
taskr top --jsonkeepsscoreand gainspercent. -
/filters the Board. The columns were already a projection of the same
filtered lists the Tasks tab shows, but there was no way to set the filter
from the Board.#tag,@projectand free text now narrow every column at
once, with the same chip in the status line as everywhere else. -
wexplains a task's rank, andtaskr why <ref>prints the same answer.
The sequencing score decided the order and showed you one number for it, so a
list that reordered itself was something to argue with rather than follow.
The overlay breaks the score into its five factors with the multiplication
each bias applied and the reason behind each reading ("3 days overdue",
"project @house saw activity in the last 48h", "nothing here was touched in
the last 48h"), states the margin to the tasks directly above and below, and
— the part no breakdown could answer — forecasts the moments the ranking
moves with no edit from you: the deadline ramp stepping at midnight and
momentum expiring 48h after the last signal, each with the score and the
position it lands on. -
The parser now speaks the interface's language. Danish and German
translated everything you read and nothing you type: a fully Danish
screen still wanteddue:friday p:high, and the help advertised those
English tokens under Danish headings. With the language set, the quick-add
and search grammars accept that language's words as well —frist:imorgen,
p:høj,størrelse:lille,forfalden,fällig:freitag,p:hoch,
überfällig— including weekday names, taken from the same tables the
calendar prints. The spellings are read out of the translation table the
interface renders from, so the help, the input hints and the parser cannot
disagree. English keeps working in every language, and only input is
localized: stored data and the sync format stay English, so installs in
different languages sync unchanged. (The CLI stays English on both sides.) -
TASKR_NO_WATCH=1turns off live reload. The filesystem watcher is the
only thing taskr does continuously against the OS, so it is the first thing
to remove when input feels laggy — at the cost of not noticing another
shell'staskr adduntil the next reload. -
TASKR_TRACE=1writes a per-frame latency log to~/.taskr/trace.log:
wall clock, gap since the last frame,UpdateandViewtimes, GC cycles,
and the message, plus a percentile summary on quit. Off unless asked for. -
taskr doctornow diagnoses the installation: version, platform, data
directory, database size and SQLite integrity, schema version, settings and
keybinding problems, sync configuration and last sync, and the resolved
editor. It is the output to paste into a bug report, it never prints a sync
token,--jsonmakes it machine-readable, and it exits non-zero when
something is actually broken. -
A version on the sync wire. Client and server now agree on a protocol
version and refuse a payload they might misread, with a message naming which
side to upgrade. Clients from before this change keep working unchanged. -
Fuzz tests for the quick-add, search, due-date and time-entry parsers,
with a bounded CI job that keeps mutating. -
Arch Linux and Windows packages.
yay -S taskr-binon Arch (with shell
completions and the man page installed), and
scoop install https://github.com/Iliorn/taskr/releases/latest/download/taskr.json
on Windows. Both manifests are generated by the release workflow from the
binaries it just built, so their checksums cannot drift from the release. -
German UI (
"language": "de", or cycle it in Settings). All 482 UI
strings plus the month and weekday tables. The no-wrap guard that used to
check Danish now sweeps every language, so a future one inherits it. -
A security policy (
SECURITY.md) with a private reporting channel, and
an explicit scope — the sync server, the sync client, self-update and token
handling are in; plain HTTP without a tunnel is documented behaviour. -
Command palette (
ctrl+k): find any action by name, with the key that
performs it and the tab it runs on. An action from another tab switches there
first. -
Quick-add completion: typing
#or@offers your existing tags and
projects, most recently used first;tabinserts the highlighted one. -
Tags tab is workable:
enterdrills into a tag's tasks, where the
row-level keys (d,t,p,T,r,x,enter) act on the task under
the cursor.astarts a new task already carrying the tag;fshows the
tag's tasks on the Tasks tab as a filter. The Projects drill gained the same
keys, andxon a project row — long advertised in the help — now clears the
project off its tasks. -
Dsets a due date straight from the task list — the detail pane's
prompt and parser, on the row under the cursor. Rescheduling used to mean
opening the task, walking to the field and pressing enter. -
Board columns are editable in Settings (comma-separated). Renaming a
column carries its cards over. -
Searchable help:
/filters the shortcut overlay by key, description or
section. The overlay also documents the quick-add and search token grammars. -
shift+tabsteps back through the tabs; the digit shortcuts now work in
the detail pane too. -
Shell completions and a man page:
taskr completion bash|zsh|fishand
taskr man. Task refs complete from the live store. -
Custom keybindings:
"keys": {"done": "D"}in~/.taskr/settings.json
rebinds any single-key action. The old key is freed, and the hints, help
overlay and palette all show the new one. -
linux/arm64 release binary (
taskr-linux-arm64) and aSHA256SUMSfile
on each release.go install github.com/Iliorn/taskr@latestis documented.
Changed
-
Files follow platform conventions instead of one dot-directory. A new
install puts config in$XDG_CONFIG_HOME/taskr, the database in
$XDG_DATA_HOME/taskr, undo/sync state and logs in$XDG_STATE_HOME/taskr
and the editor scratch file in$XDG_CACHE_HOME/taskr—%APPDATA%/
%LOCALAPPDATA%on Windows,~/Library/Application Supporton macOS, and an
explicitly exportedXDG_*variable wins everywhere. An existing
~/.taskrkeeps being used exactly as before: nothing moves, nothing is
migrated.TASKR_HOMEputs everything back in one directory, and
taskr doctorprints what it resolved. -
Search matches notes, not just the title. Titles stay fuzzy; notes are
matched as a plain substring, since a subsequence match over a whole note
would hit almost anything. -
taskr doctorwas renamed totaskr suggestfor its old job — proposing
dependency links from note refs and related titles. Every other tool means
"diagnose my installation" bydoctor, and the shell completions already
described it that way. If you scriptedtaskr doctor --list, it is now
taskr suggest --list. -
A build without an injected version now reports a real one.
go install github.com/Iliorn/taskr@latestused to call itselfdev
forever, which also made the update check announce a new release on every
single run. It now reports the module version, and a local build reports
dev+<commit>. -
Self-update no longer needs the GitHub CLI. It reads the release API over
plain HTTP, so the update button works on a stock install. Rate-limit and
"no releases" failures now say what happened. -
The Danish translation is complete. About a third of the interface was
still English on a Danish install — the whole sync and server half of
Settings, the stats labels, the sort names, most of the help reference, and
the Sequencer pane, which never went through the translation layer at all. A
missing translation now fails the build instead of quietly rendering English. -
Roughly twice as fast at scale. At 2000 tasks a cache refresh went from
11.1 ms to 5.8 ms and a search keystroke from 7.5 ms to 3.4 ms, with about a
third of the allocations gone.
Removed
- Learnings. A second free-text list beside notes and comments, with its own
table, its own sync fold and its own CLI command, but never a tab of its own.
Migration 011 appends every learning to its task's notes under a
## Learningsheading and drops the table, so nothing you wrote is lost —
andtaskr searchnow matches notes, which is where the recall
taskr learningsused to provide now comes from.taskr learningsprints
where the text went instead of silently opening the TUI.
Fixed
-
Windows input latency. A keystroke after a pause waited up to 16 ms to be
noticed: Bubble Tea reads the Windows console by polling it with a 16 ms
sleep between attempts, and a burst of keys spins the loop instead of
sleeping — the first key felt late, the rest did not. taskr now opens
CONIN$as its own file, which selects a blocking read of the console's
escape-sequence stream and returns the moment a key arrives.
TASKR_WIN_CONSOLE_INPUT=1restores the old reader; the Windows build polls
the console size four times a second, since resize events only came with it. -
The first frame is rendered before the program starts. Building every
derived cache and filling the string-builder pool used to happen on the first
keystroke of a session. -
The renderer now paints at 120 FPS instead of 60. Bubble Tea repaints on
a ticker, so the frame rate is also the worst case between pressing a key and
seeing it: ~17 ms became ~8 ms. Frames are line-diffed, so the extra ticks
cost nothing when nothing changed. -
A stutter on the first keystroke, and again after a pause. A filesystem
event on our own database write made the app reload and rebuild its whole
task set — about 15 ms at 2000 tasks, on the event loop, landing on whatever
key you pressed next. A reload that carries no new task versions is now
recognised and skipped (~1 ms), and the startup write no longer comes back as
an external change at all. -
A stale "plain http" sync warning no longer sticks. Moving the sync URL
from a publichttp://host to a Tailscale address orhttps://left the
earlier warning on screen, still claiming the token travelled unencrypted. A
security notice that outlives the condition it describes is worse than none. -
Config files are replaced atomically. settings.json, sync.json,
sync-state.json, serve-state.json, the undo stack and task notes were written
by truncating the old file first, so a crash or a full disk mid-write left a
truncated file behind. A failed write now leaves the previous contents
intact. -
Crash on small terminals. Width budgets went negative and the render
panicked; every shared width helper clamps now. The Calendar and the
drilled-in Projects view fall back to a single column instead of emitting
lines wider than the window. -
The cursor could point past the end of a list — after an undo, a delete
confirmed from a modal, or a tab switch — leaving nothing selected, so the
next keystroke silently did nothing. -
go teston Windows wrote to the developer's real~/.taskr: the test
isolation setHOME, which Windows does not use. -
The help overlay advertised keys that did nothing (
1–8for seven tabs,
jump/page keys on tabs with no list) and hid--each,--editand
--deletefromtaskr subtask --helpandtaskr comment --help. -
The README's fuzzy-search example (
grcry) never actually matched. -
An undone deletion could delete itself again on the next sync. The
restore was stamped from the clock, which on Windows ticks about every 15 ms
— often the same instant as the deletion two keystrokes earlier. A tie is
resolved by content hash, so the tombstone could win. A deletion now carries
the moment it happened, and the restore is ordered strictly after it. -
The editor was resolved from scratch every time it was launched, statting
every entry onPATH(times everyPATHEXTextension on Windows) before
opening the file.
Security
- Self-update now verifies what it downloads. Every release publishes a
SHA256SUMSfile; until now the update button ignored it and installed the
binary unchecked. The download is hashed as it is written and compared
against the published checksum, and anything that cannot be verified — no
SHA256SUMS, no entry for this platform, a mismatch — installs nothing and
says why. This is an integrity check, not a signature.
Full changelog: https://github.com/Iliorn/taskr/blob/v1.31.0/CHANGELOG.md