Release Notes
Added
- The web UI edits the title and the description of a task in place. The
description is a markdown editor with a live preview: the markdown shows where
the caret is, and the rest shows as it renders. / inserts a block, @ or
[[ inserts a reference to a task, and e on a task page starts the edit.
The text saves when you leave it, and a draft that did not save comes back on
the next visit.
PUT /api/projects/{project}/tasks/{id}/text writes the title and the
description of a task. It takes the text the edit started from and merges the
edit with what other writers changed since. Where both changed the same lines,
a conflict block keeps both versions.
- The web UI shows the author of each task in the task list and on the task
page. The author is the person who wrote the revision that created the task,
and the task page also shows the agent. A task list row and the task detail
in the API have an author with a name, an email, and an agent.
- Canary builds. Each push to
main replaces the prerelease canary with a
new build of the CLI and the daemon, versioned <next patch>-canary.<run>.
openplan update --canary installs it. openplan update goes back to the
newest stable release, also when that release is older.
- Docs: markdown pages that live with the tasks, in
docs/<name>.md of the
same git ref or local directory. A doc has a title, a body, and an optional
parent doc. openplan doc creates, lists, prints, edits, nests, renames, and
deletes them. The web UI has a docs page across projects (g d) and a page
for each doc. [[name]] links to a doc and [[OPP-42]] to a task, from a
task or a doc. Renaming a doc moves every link to it and the docs nested
under it. Deleting a doc moves the docs nested under it up to its parent. openplan migrate brings the docs in .plan/docs/ along with the
tasks.
- A file names every other file by its path, relative to its own directory:
[[../docs/storage.md]] from a task, [[../tasks/00042-ship-login.md]] from
a doc, and parent: ./architecture.md in a doc. A write turns a key or a doc
name into that path, and the API and the CLI show the key or the name again.
openplan lint reports a reference that a file spells in another way.
- The doc page edits the title and the body in place with the editor of the
task page. PUT /api/projects/{project}/docs/{name}/text merges the edit
with what other writers changed since. A new title renames the doc. The [[
menu of the editor offers docs as well as tasks.
- A doc page shows its parent in the header, its nested docs and its history
in a side column, and the person who created it, as a task page does. "Add
doc" nests an existing doc or writes a new one, as "Add subtask" does for
tasks. A revision of a doc opens as that revision left it. The activity view
shows each doc change with its title and a link to the doc.
- Sync merges a doc as it merges a task: the parent by field, and the body by
line. When two people change the parent or the same lines differently, the
doc keeps both versions, and the published version is in force until
someone picks. openplan doc get warns about conflicts, openplan doc list
marks them, and openplan lint reports them. When sync gives a task a new
number because another task took its number first, the links to it in your
docs follow it.
openplan lint checks docs too: Mermaid diagrams, references to a task or a
doc that does not exist, and parent cycles. openplan url prints the page of
a doc.
GET /api/events takes the cursor of the last event a client saw in the
query too (?last_event_id=<id>), because a new EventSource cannot set the
Last-Event-ID header. The web UI uses it to resume after a reconnect.
- In the status menu of the web UI, one letter key sets a status and closes the
menu: b backlog, t todo, p in progress, r in review, d done, and
c cancelled. The menu shows the letter next to each status.
- The sync state of a project (
GET /api/projects/{project}/sync, and sync
in the project list) has a syncing flag. The daemon sends a sync_changed
event when a sync starts and another when it ends. The web UI spins the sync
icon while a sync runs.
mermaid fenced code blocks in a task body render as diagrams in the web UI.
The daemon draws them (POST /api/diagram) with its own layout engine: a
subset of flowchart, sequenceDiagram, and erDiagram. A block that does
not parse shows the message and marks the line.
openplan lint reports a mermaid block that does not parse, in a task body
or in a comment, with its line and column in the task file. The daemon and
the web UI show it as a task problem (diagram).
- The daemon updates itself. It checks for a new release 5 minutes after it
starts and then every hour. A canary build follows the canary release, and
any other build follows the newest stable release. The daemon downloads and
verifies the release, waits until no agent session runs, replaces its
executable, and starts again on it in the same process, with the same pid and
port. A request to start an agent session after that stop gets 503. The
daemon does not update a binary that a package manager owns, a build in a
directory with a CACHEDIR.TAG (cargo's target/), or a daemon that the
desktop app runs.
openplan update --auto on|off turns the updates of the daemon on or off.
The default is on. The setting and the result of the last check are in
OPENPLAN_HOME/update.json, and openplan server ping prints them.
- The web UI reloads the page when the daemon runs a new version after a
reconnect, so the tab gets the new web app. When the page holds an open
dialog or typed text, it shows "New version" with a Reload button instead.
openplan url <key>... prints the address of each task page in the web UI.
The openplan skill tells the agent to write each task key in a reply as a
link to that page.
- In the activity view and in the history of a task, a change line opens a
card with the diff of the change when the pointer is on the line or when
the line has the keyboard focus.
GET /api/projects/{project}/revisions/{revision}/diff?path=<path> gives
the unified diff of one document against the first parent of the
revision. The diff stops at 400 lines, and a binary document has no diff.
Changed
TaskDetail and revision snapshots carry description in place of body:
the text without the # title line, with task references as keys.
openplan get --json shows the same.
- The
daemon_stopping event has a reason: stop or update. On update,
the web UI shows "Updating" and connects again at once.
openplan update refuses a binary in a directory with a CACHEDIR.TAG, such
as a cargo build or cargo run build in target/.
- A release carries only the CLI and the daemon for now. It carries no desktop
app. The app workflow runs only when you start it by hand.
openplan update skips OpenPlan.app when the release carries no app
bundle. The app keeps its version. It failed before.
- The history reads what each revision changed from the task files, not from
the commit message. openplan history and the web UI show the same result
for every revision, also for a revision that plain git or an import wrote.
Examples: OPP-114: status → in_review, description, a new title, tags
added or removed, new comments, a task that a sync moved to a new number, and
a renamed tag or doc. The history API gives each entry a summary (one line for each
document), tasks (the changed fields of each task), and tags. openplan
writes its commit messages from the same description, so git log openplan/tasks agrees with openplan history.
- One
openplan agent skill replaces the task-management, task-comments,
and task-management-merge skills. openplan setup-skills removes the three
old skills, and openplan lint --skills reports an old skill that stays.
- The agent skill teaches openplan only, and does not set a code workflow. At a
merge, it settles the task status and lets the repository's own process do
the merge. It does not require a worktree, a squash merge, or gh, and it
does not delete the branch or sync main.
- The daemon reads only the tasks that changed. Before, each write read every
task file two times. On 1,500 tasks a write takes 5 ms instead of 33 ms, and
the history of one task takes 10 ms instead of 231 ms.
- A local
.plan/ project reads a file only when its size, times, or inode
changed, and keeps large documents, such as images, out of memory until a
reader asks for them.
- The web UI refreshes each read once for a burst of changes, such as a sync
that brings in many tasks. A key press on a big board renders only the rows
that change.
- The CLI help shows the permitted values of
--status on create and list,
and of --color on tag create. Shell completion offers them too.
- The sync popover of the web UI shows one line for each project: the name,
the time of the last successful sync, and "Sync now". A warning icon marks a
failed sync, and its tooltip gives the error. The header button and "Sync
now" use the same icon and the same state color.
- Each relative time in the web UI updates while it is on screen. Below one
minute, it counts in steps of ten seconds: "just now", "10 seconds ago",
"20 seconds ago", and so on.
- The flow page shows an SVG that the daemon draws (
GET /api/flow/drawing)
for the size of the page. It asks for a new drawing after a resize. A
two-finger scroll or the wheel pans a diagram, and a pinch or Ctrl with the
wheel zooms it. A click on a card opens its task without a reload.
- The web app is smaller: its assets are 2.3 MB instead of 12 MB.
Removed
POST /api/projects/{project}/tasks/{id}/resolve. To settle a conflict
block, replace it in the description and write the text with
PUT /api/projects/{project}/tasks/{id}/text.
d2 fenced code blocks no longer render as diagrams. They show as code. Use
mermaid.
GET /api/flow. GET /api/flow/drawing takes the same query.
Fixed
- A Mermaid self-loop (
a -->|text| a) shows its label beside the loop. Two
loops on one node no longer share one path. A loop on the last node of a row
stays inside its subgraph and inside the drawing.
openplan lint reports a link between a node and a subgraph that holds it,
and a link from a subgraph to itself. The diagram drew such a link through
its own node and dropped its label.
- Two or more commands that open a new local project at the same time now all
work. Before, a command could fail with "database is locked". A command could
also delete a file of the project from the disk, such as .plan/config.toml,
when another command recorded that file at the same time.
- An open task page did not show a change to a task around it, such as a new
subtask from the CLI or from a sync, until a reload. A task page and a doc
page now read again after each change to a task or a doc in their project.
- Enter in a search box, such as "Add subtask" or "Change parent", right after
typing picked an option for the text before the last keys. It now picks the
first option for the text in the box.
- A project named
flow had no board, because the flow page has that
address. A new project does not take the name api, docs, or flow: it
takes docs-2, for example. A rename to one of these names is refused.
Install openplan 0.0.4
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/sukovanej/openplan/releases/download/v0.0.4/openplan-installer.sh | sh
Download openplan 0.0.4