Skip to content

Active development — do not use in production yet. Build-in-public project. First stable release: v1.0.0. Expect breaking changes, missing features and rough edges before then.

kandown
116 releases

Changelog

2026-08-13

v0.50.0· Named Files

Added

  • Task files are now named after what they are. A new task lands in tasks/t293_fix_login_button.md instead of tasks/t293.md, so a git diff --stat, a pull request file list, your editor tabs and a grep -rl all read as English. Three words, lowercase ASCII, taken from the title; accents are flattened, a leading [CATEGORY] tag is ignored, and a title that yields nothing printable (emoji-only, CJK, Cyrillic) keeps the bare <id>.md rather than inventing a placeholder.

    The id is still the only identifier. It lives in the id: frontmatter, so depends_on, [[t232]] links, deep links and branch names cannot be broken by a rename, and both filename forms keep working forever, side by side in the same folder. Every reader, the CLI, the TUI, the daemon and the web app, resolves an id through one shared pure module (src/lib/task-filename.ts) rather than rebuilding a path from the id.

    The slug is frozen at creation: editing a title never touches the filesystem. Bringing older tasks in line is an explicit kandown reslug <id>, or kandown reslug --all, with --dry-run to preview and git mv under the hood so history follows the rename. kandown work mentions the leftovers and asks the agent to offer the rename, never to perform it unprompted.

Fixed

  • The per-daemon API auth token declared as M5 in daemon.ts:42 is finally wired end to end. The daemon now mints a 32-byte random token at boot, stores it next to the port in .kandown/daemon.json, injects it into the served HTML as window.__KANDOWN_TOKEN__, and refuses every API request that does not carry the matching X-Kandown-Token header (or ?token= query parameter for EventSource). GET /api/daemon stays open without a token because it is the liveness check. The CORS Access-Control-Allow-Origin stops being a wildcard: every response now echoes the daemon's own http://127.0.0.1:<port> origin, so a foreign page can no longer read or rewrite tasks/*.md with a plain fetch. The vite dev server is exempt by design (localhost only, dev tree only) and the choice is documented in vite.config.ts.