github pixari/OpenTodo v0.10.0
OpenTodo v0.10.0

latest release: v0.10.1
3 hours ago

OpenTodo 0.10.0 is a calmer app with room for more people. The interface was redrawn: one quiet task row, a new mark and sidebar, softer colours, motion that marks a completed task, and a phone layout with swipe actions and a task sheet. Workspaces and groups keep work and home apart and share a project with a team in one step. Automation rules let a task change itself, notes and comments share one editor with tables, images, mentions and reactions, and a task page hands one task to someone without an account. Tasks can have a location on a map, your account can live as a Markdown vault for Obsidian, the importer reads six more apps, and the owner can give the server its own name and logo. An early Android app is in the repository, not yet in the stores.

Upgrade notes

  • Six migrations, no mandatory environment variables. Replace the image or the binary and restart; migrations 0040 to 0045 (relay devices, task pages, projects kept away from AI assistants, automation rules, profiles, workspaces) run on start. There are no down-migrations, so back up first. New optional settings: OPENTODO_MAPS, OPENTODO_MAPS_TILES_URL and OPENTODO_MAPS_GEOCODER_URL (maps), OPENTODO_STT_URL and OPENTODO_STT_KEY_FILE (dictation through your own speech service), and OPENTODO_AUTOMATIONS (automation rules). Upgrade the server before the devices, as for every release.
  • Sample tasks and the start guide's checklist add two additive sync fields (sample on tasks, start_checklist in the user's preferences); older servers refuse them as unknown fields and the devices keep their values, older apps show sample tasks as ordinary tasks. No migration.
  • Workspaces add one migration (0045_workspaces: workspaces, workspace_members, workspace_invites, groups, group_members, project_grants) and a column project_members.via, added at startup together with one default workspace per account; every existing member becomes a direct grant. No new variable. Back up first, as for every release. An older server ignores the new tables and column, but devices from this version write workspace_id, which an older server refuses, so downgrade the server only together with the web app.
  • Reactions and mentions in notes are new sync fields (reactions.<account id> on comments, note_mentions on tasks); both stay plaintext with end-to-end encryption. Upgrade the server before the devices: an older server refuses the new fields. No migration.
  • Quick add reads numeric dates in your date format only (breaking). The device-level choice "Numeric dates like 12/11" under Settings → Capture is gone: 12/11 is read day-month or month-day as your date format in Settings → General → Date and time says, and with System or ISO as your language says. A device that had fixed the other order reads such dates differently now; the stored choice is ignored and removed. (Quick add)
  • Profiles add one migration (user_profiles, email_changes); pictures are stored under <data>/avatars and are part of backups.
  • Calendar alarms become reminders. Display alarms set in a CalDAV calendar app turn into OpenTodo reminders the next time the app saves the task, and OpenTodo reminders now appear in calendar apps as alarms. Nothing is converted in bulk; alarms the reminder model cannot express (sound, email, repeating) stay the app's own data.
  • Task pages add one migration (task_pages, task_page_replies, task_page_actions) and two additive comment fields (guest_name, page_id); older apps ignore them. Publishing is refused on a demo instance.
  • Maps are on by default. Task locations show OpenStreetMap maps and search addresses through your server, which fetches from OpenFreeMap (tiles) and Photon (search) with no account data. Set OPENTODO_MAPS=off, or switch off Settings → Server → Maps, to keep the server from making those requests. Tiles are cached under <data>/cache/maps (at most 200 MB, not backed up). (Maps)

Added

  • Your own name and logo. Settings → Server → Branding lets the owner name the server (up to 40 characters) and upload a square logo: the name replaces "OpenTodo" in the browser tab, the installed app's name, the sign-in screen and the sidebar, and the logo becomes the favicon, the touch icon, the installed app's icons and the sidebar mark, rendered by the server in every size from one PNG or JPEG. The sign-in screen then reads "Powered by OpenTodo". Routes GET/PUT /api/v1/settings/branding, PUT/DELETE /api/v1/settings/branding/logo and the public /branding/logo-<size>.png; auth/status carries branding; changes are recorded as settings.changed. (Branding, #234)

  • Profile pictures from your sign-in provider. With the owner's new switch Use profile pictures from … in Settings → People → Single sign-on (off by default), the picture your OpenID Connect provider names becomes your profile picture when you sign in or link the provider: cropped to a square, scaled to 256×256 and re-encoded, so no metadata is kept. A picture you upload yourself is never replaced, one you remove is not fetched again, and a picture that cannot be fetched changes nothing. Uploading a picture was already there, in Settings → Account → Profile. (Single sign-on, #233)

  • An interface audit for contributors. make ux-audit opens every screen and the main overlays of the app at 360, 768 and 1280 px, light and dark, in English and German, and writes a contact sheet with the findings ranked: overflow, target size, focus rings, cut-off text, overlapping controls, layout shift, movement under reduced motion, the interface budget and how fast the Inbox shows from the local copy with the server stopped. CI runs it on every code change and uploads the report. A screen inventory keeps the router, the layout check and the workbench in step, and the workbench's accessibility gate now also checks the focus ring on the core screens. The rarely used screens are in the workbench too (sign-in and the other signed-out screens, the invitations, display mode, the public list, Import, Help, the capture screen, a location's page, the About settings and the project and voice dialogs), each with a visual baseline in both themes at phone and desktop width.

  • Completing a task feels like it. The check fills and pops, the title is struck through and the row folds away while the rows below move up, all within 400 ms; the completion is saved at once, so c on three tasks in a row never waits and the cursor moves on. A repeating task stays and rolls to its next date. Undo during the moment keeps the row in place. Rescheduling, dragging, bulk actions and Undo slide the rows that stay to their new places (up to 40 rows; changes from other devices never move the list). Dialogs fade and scale in from 640 px and leave faster, the phone sheet and the task panel slide, toasts slide up, and menus fade in and close at once. Phones and tablets tick on completion and on a long-press lift, with a Haptic feedback switch in Settings → Appearance that follows your account. With the system's reduced-motion setting only colour and opacity fade; nothing moves or scales.

  • Profile: your picture, name and email. Settings → Account opens with a Profile card. Change your name, add a picture (crop it in a circle with the mouse, touch or the keyboard; the browser turns it into a 256×256 JPEG and the server re-encodes it so no location or other metadata is kept), or change your sign-in email: with outgoing email a link to the new address confirms it and the old address gets a notice, without it the change applies at once after you confirm your password. Pictures show wherever initials did (account menu, comments, assignees, members, history) for people who share a project with you. Accounts that sign in only through single sign-on keep the provider's email. Routes GET/PATCH /api/v1/me/profile, POST/DELETE /api/v1/me/email, POST /api/v1/me/email/confirm, PUT/DELETE /api/v1/me/avatar, GET /api/v1/users/{id}/avatar; audit events account.name_changed, account.email_change_requested, account.email_changed, account.avatar_changed, never with a name, address or picture. The cropper (react-easy-crop 6.2.3, MIT) is a lazy chunk of 7.75 KB gzipped. (API)

  • Dictation through your own speech service. The owner can connect a speech-to-text service that speaks the OpenAI-compatible /v1/audio/transcriptions request, such as Speaches or whisper.cpp, in Settings → Server → Speech to text or with OPENTODO_STT_URL, OPENTODO_STT_MODEL and OPENTODO_STT_KEY_FILE (none required). People then choose This server's speech service in Settings → Capture → Voice capture, after a statement naming the service's host: each phrase is recorded in the browser, sent once through your server and returned as text, and neither keeps the audio or the text. 5 MB and 60 seconds a phrase, 30 a minute per person, requests only to the configured host. (Speech to text)

  • Moments and onboarding. The start guide offers Start with three sample tasks instead of the "Show me around" project: three tasks marked Sample that show the panel, a time with an estimate and a subtask, never counted in Statistics, the Loop pulse or the weekly digest, and removed in one tap with Undo (the panel's notice, the Inbox's menu or the checklist). The guide ends on Your first day (add a task, plan today, get it on another device), which Start guide · n of 3 done under More reopens until it is done or hidden. Closing the day ends on Done for today: the time, the day's figures and your line for tomorrow, with no streak or score. Ctrl/⌘+K opens one command bar with Search, Add, Commands and Ask (when the assistant is on), switched with +, > and ?; Search always ends with Add "…" as a task (Ctrl+Enter), and q opens Add mode on screens without a quick add. Quick add tints what it recognised in the line itself, five new line illustrations fill the empty Today, Upcoming, project and Trash, and the undo toast pauses while hovered or focused, puts Undo first and never covers the focused element. (Your first task, Search)

  • Workspaces and groups. Keep work and home apart: each workspace has its own projects, labels, filters and people, and the sidebar's header is now the workspace switcher, with Inbox and Today counts per workspace and a dot when another one has updates (one workspace reads OpenTodo · Personal, as before). Switching is per device; links, notifications and search results from another workspace switch for you. Settings → Workspaces manages members (by email), roles, groups and single-use invite links (/invite/w/…, sent by email when outgoing mail is set up); in a workspace you created, a project is shared only with its members and groups, and sharing with a group gives everyone in it one role, kept up to date as the group changes. Move to workspace… on a project re-matches its labels by name with Undo. Additive workspace_id on projects, labels, views and project-less tasks; the directory reaches devices in every sync (three queries). Routes under /api/v1/workspaces and /api/v1/projects/{id}/grants, workspaces in the export and the own-format import, one Inbox calendar per workspace over CalDAV (names prefixed outside the default workspace), workspace_id in webhook payloads, list_workspaces and a workspace argument for AI assistants (MCP and the assistant), and ot workspaces, --workspace/OPENTODO_WORKSPACE and ot project move in the CLI. Limits: 20 workspaces per account, 200 members and 50 groups per workspace, 100 people per group, lower per tenant in host mode. End-to-end encrypted accounts can create workspaces and move things, but not add members, groups or links yet. (Workspaces)

  • An Android app. mobile/android is a small Kotlin app that opens your own server in a full-screen web view and adds what the installed web app cannot do on Android: reminders scheduled on the phone with exact alarms and no push service (refreshed hourly in the background, with Snooze 10 min and Dismiss that act like the web notifications), the share menu for links, text, photos and files (also on phones without Google Play services), a Today widget and a quick-add widget, and fingerprint or face unlock of an end-to-end encrypted account (the key is kept by Android's keystore and never leaves the phone). The first-run screen checks the address and says why it can't connect; plain http:// works only on your own network. The web app talks to it through an optional, versioned bridge (window.opentodoShell, only on your server's origin): Settings → Notifications reads Notifications through the app, Settings → About names the app and warns when it is too old, and nothing changes in a browser, where web push stays as it is. AndroidX only, no trackers, release APK about 1 MB; make android builds and tests it, a new CI job runs on changes under mobile/ and signs the APK and AAB on tags once the signing secrets exist. Not in the stores yet. The web bundle grows by about 4 KB gzipped. (The Android app)

  • Assistants plan with the app's own words. MCP, ot and the assistant in the app can now set a task's deadline, start date, Someday, This Evening, what it waits for and its location: create_tasks and update_tasks take deadline, start, evening, blocked_by and location, task results carry them with a derived blocked, list_tasks gains the someday and anytime views and a blocked filter (and two resources), and the agent REST routes accept the same fields, so PATCH {"start": "someday"} with an agent token works (#198). ot add/ot edit gain --deadline, --start, --evening, --blocked-by and --location; ot list gains --someday, --anytime, --blocked and a BY column. GET /api/v1/places lists saved locations. The assistant's instructions and the Plan my week, Weekly review and Triage skills use the new fields, and its review describes them. (AI assistants (MCP), CLI)

  • Keep a project away from AI assistants. The owner or an admin of a project can switch on Keep away from AI assistants in the share dialog or the command palette: no member's assistant (MCP, ot with an agent token, the assistant in the app) sees the project, its sub-projects or their tasks, and writes to them fail as not found. The app, sync, CalDAV, feeds and the export are unaffected. Routes GET/PUT /api/v1/projects/{id}/agent-access, agent_excluded_projects in GET /api/v1/me, audit event project.agent_access; one migration (project_agent_exclusions); no new dependency. (Sharing, API)

  • Browser extension 0.6: a popup and Quick save. The toolbar button and Alt+Shift+O open a small popup with one quick-add line from the page, a project and a label picker, and the page as the origin. In the new Quick save mode, with a full-access API token kept on that device only, Save creates the task at once and previews the line as chips in your account's language; the default Capture screen mode opens the capture screen as before and sends nothing itself. "Add to OpenTodo" now works on links and images, and a message open in Gmail or Outlook on the web becomes a task with its subject, its sender and a Gmail/Outlook origin (origin: gmail). Two packages, one for Chromium and one for Firefox (now 128 or later). New route POST /api/v1/quick-add/parse answers how a line reads without saving anything. See Capturing pages.

  • Automation rules. More → Rules lets a task change itself: when the label waiting is added, move it to Waiting, every Sunday at 18:00, give overdue tasks tomorrow's date, when a task is due, notify me. A rule has a trigger (created, completed, reopened, a label added or removed, assigned to me, moved, due, overdue, or a schedule), optional conditions (project with sub-projects, labels, priority, date, deadline, assignee, blocked and more, with a live count of matching tasks) and actions (priority, date, start, deadline, assignee, labels, project and section, complete or reopen, a comment, an in-app notification, a delivery to one webhook as the new rule.fired event). Rules sync as a new rule entity, are saved offline and run on the server for their author only, never for imports or a teammate's edits; each run is one batch per task with device rule:<id>, shown as Rule (name) in the task's history and undone like any change. Limits: 60 runs a minute and 2,000 a day per account, 500 tasks a run, 50 rules; a rule that keeps hitting the limit is paused with a notification, rules that trigger each other stop after three in a row, and Pause all rules pauses yours. A rule's History lists its last 100 runs. Encrypted accounts can use every action except the comment. The owner can turn automations off in Settings → Server → Automations or with OPENTODO_AUTOMATIONS=off; a demo never runs them. Also ot rules list|enable|disable|runs, the read-only MCP resource opentodo://rules, rules in the export, and Make an automation rule on saved filters and board columns. One migration (rule_events, rule_runs, rule_state, user_rules_paused). (Automation rules)

  • One editor for notes and comments, with tables, quotes, code, images and mentions. Type / in the notes or a comment for a menu of everything the editor inserts: headings, lists, a table (Tab moves between cells; up to 10 columns and 100 rows), a quote, a code block, a link, an image, today's date or a mention. Paste a screenshot into the notes or a comment and it becomes an attachment shown in place (decrypted on your device with end-to-end encryption). @ mentions a member in a task's notes, who is notified once. On a checklist line, Ctrl+Shift+Enter makes it a subtask linked from the note (Ctrl+Z takes it back), and GitHub, GitLab, Jira and Linear issue links read as chips. On a phone a row of formatting buttons sits above the text while you write. Comments stay Markdown: the API, the CLI and email see pipe tables and ![…](attachment:…), and a comment saved unchanged stays byte for byte the same.

  • Reactions on comments. Thumbs up, heart, check, eyes, party popper or question under any comment, offline too, with who reacted on hover; PUT /api/v1/comments/{id}/reactions sets yours from a script, and comments in the API and the export carry reactions and my_reactions.

  • Estimates and reminders over CalDAV. A task's duration estimate travels as ESTIMATED-DURATION, and reminders and calendar alarms are the same thing seen from two sides: reminders are served as VALARMs with a stable UID, and a display alarm added, changed or removed in a calendar app adds, changes or removes the reminder. A calendar app that never shows alarms cannot delete reminders by accident. (Calendar apps)

  • A Markdown vault for Obsidian and plain text. ot vault init ~/Notes/Tasks writes your account as a folder of Markdown files, one per project (Inbox.md, Home.md, sub-projects in a folder next to the folder note Work/Work.md), each task a checklist line in the Obsidian Tasks format: 📅 do-on date, 🛫 start, 🔁 repeat rule (when done for after completion), 🔺 ⏫ 🔼 priority, #tags as labels, ⛔ blockers, 🆔 the task id, and Dataview fields such as [deadline:: ] and [estimate:: 45m]. ot vault sync (or ot vault watch, which follows the server's live channel and the files) keeps it in two-way sync: tick a line, add one, nest it, move it under a ## section, rename or move a file, and every device sees the change, which history credits to "a Markdown vault". The vault is an ordinary sync device with a three-way merge per field: a field changed on both sides keeps the app's value and puts the file's line in <file>.conflict.md, a removed line trashes its task unless the app changed it, a deleted file is written again, and prose, other headings and text such as ⏳ stay where you wrote them. --dry-run plans without writing, --read-only pulls without sending, ot vault status works offline. Limits: 1 MB and 5,000 task lines per file, 20,000 tasks, 64 KB per note, checked before anything is written or sent. On an end-to-end encrypted account the vault needs ot encryption unlock, decrypts and encrypts on your machine so the server sees only ciphertext, and says once that the folder holds your tasks in plain text. CLI only: the server binary is unchanged and ot grows by about 380 KB. (Markdown vault)

  • Switch from six more apps. The importer reads Google Tasks (Takeout's Tasks.json), Trello (a board's JSON, or a ZIP of boards), Asana (a project's CSV), Microsoft To Do, Apple Reminders and Any.do, detected from the file like the others. Microsoft To Do and Apple Reminders have no export, so their guides give a short PowerShell script (Microsoft Graph, read-only) and a Shortcut that write one JSON file; Apple Reminders can also sync over CalDAV. Any.do's file comes from its data request and is undocumented, so it may change. Lists become projects (the default list goes to your Inbox), Trello boards open as boards, checklists and steps become subtasks, and every task keeps its origin. Trello custom fields and Asana's extra columns become custom fields of the project (numbers, checkboxes, dates, choices or text), and Linear estimates now become a number field "Estimate" instead of being dropped; the preview counts new fields, and undo removes the ones the import created. A switch guide per app under Help. No new dependency; the Windows time zone table (generated from CLDR) adds about 8 KB to the binary. (Import formats)

  • Task pages: hand one task to someone without an account. Publish task page… in the task panel's menu turns a task into a calm page at a private, unindexed link: its title, dates, description, checklist, links, map and conversation. Choose whether guests can read, reply, or reply and tick (subtasks, and the task itself, which they can reopen within a day); add a label, an expiry and the map. Guests type a name once; their replies arrive as comments by "Marco (guest)", history names them, and you get a notification. Published in the panel's header shows the page's status, a new link or Revoke. End-to-end encrypted tasks can be published too: your device encrypts the page with a key only the link carries after #, which the server never receives, and imports the guests' encrypted replies. The page is its own small document with no account, no cookie and no third-party request. (Task pages)

  • Task locations. A task can say where it happens: search an address, type coordinates, pick a point on the map or use your current position, from the task panel's Where line. A small map and Open in maps (your phone's maps app, or openstreetmap.org) show it. Save for reuse keeps a location under a name; Locations in the sidebar's More lists them with their open tasks and a map, and a task linked to one follows it when you rename or move it. Locations sync as one additive task.location value and a new place entity, work offline (except the address search), are in the export, and are encrypted for end-to-end encrypted accounts. Each user can turn maps off in Settings → General → Maps. The map code (MapLibre GL, about 280 KB gzipped plus its worker) loads only where a map is shown; the main bundle grows by about 2 KB. (Locations)

  • Cloud AI connectors on an encrypted account, through your own device. Turn on Settings → Integrations → AI assistants → Answer AI connectors here on an unlocked device, and a connector such as Claude.ai can read and write your encrypted tasks while that device is online: the server sends it, sealed for that device only, the values each call needs, and the device decrypts or encrypts them with a key that never leaves it. The server never stores, logs or audits what it relays, but the text a connector asks for passes through its memory, and Settings says so. The device decrypts at most 5,000 values an hour and 20,000 a day, lists recent requests without their text, shows a key in the sidebar while it answers, can ask before every change (Confirm changes first), and stops when you lock it or sign out. Off by default, refused on the demo. New audit events relay.enabled and relay.disabled; one migration (relay_devices); no new dependency. (AI assistants (MCP))

  • Reopen the day. Closed the day too early? Until your day ends, Reopen the day next to Day closed (or at the top of the Close the day screen) puts the carried-over tasks back where they were and clears the close, on any of your devices, offline too; the line for tomorrow is kept, a task you moved again by hand after closing stays where you put it and is named, and Undo takes the reopen back. The carry-over is recorded in an additive synced field, review.carry_over (task ids, fields and dates, never content). (Rhythms)

  • Drop a task on the sidebar. From any list or board, drag a task onto a project or Inbox to move it there, or onto a label to add that label; ticked tasks go along as one change with Undo, and projects you can only view don't accept drops. (Change several tasks at once)

  • Hundreds of icons, with search. A project's Icon… opens a picker with 411 icons in 16 categories instead of 24: type to search by name, keyword or category (category names in your language), use the arrows and Enter, or pick No icon for the coloured dot. The icons load the first time you open the picker and then work offline; an icon set on a newer device shows as the dot until this one updates. The app's main bundle grows by about 0.2 KB gzipped, and the catalogue is its own chunk of about 34 KB gzipped. (Projects)

  • Section colour and icon. A section's menu has Colour… and Icon…: the icon, in the section's colour, or a small dot of its colour appears before its name in the list and on the board. New sections have neither, and No section never does. They sync as two additive fields, section.color and section.icon, are not encrypted content (so encrypted accounts can use them), travel in the export, and are accepted by /api/v1/sections, which refuses an icon outside the catalogue or a colour that is not #rrggbb with 400 invalid_input. (Sections and boards, API)

  • A template library in the app. From a template… (and New project from a template in the command palette) now opens on ten curated templates: trip planning, moving house, household chores, home maintenance, meal planning, a new job, a product launch, a study plan, a weekly review and a Getting Things Done setup. Search them by title, label or task, read what each one is for and preview every section and task with when it falls ("day 3", "week 2") before anything is created; ↓, Enter and Esc work throughout. The library works offline, is in Italian as well as English, and reuses labels you already have by name. Upload a file… in the same dialog keeps taking template files. (Project templates)

  • Templates are contributed on GitHub. The library lives in templates/, one folder per template in a short hand-written YAML format with optional translations, checked in CI (fields, declared labels, icons, size limits, no personal data) and started by a test on a fixed day. templates/README.md has the format and the bar; templates are shared under CC BY 4.0. The site bundle carries the same library (templates/index.json, one file per template, a templates fact) for the website. The library is a separate chunk of about 12 KB gzipped, loaded when the dialog opens; no new dependency.

  • Assistants can arrange projects and sections. Over MCP an assistant can now recolour a project, give it an icon, rename it, move it under another project or reorder it (update_project), pin it to Favourites (set_favourite), and create, rename, restyle and reorder sections (create_sections, update_sections, reorder_sections). list_icons searches the icon catalogue the app offers, and every icon is checked against it. Archiving and deleting stay out of reach; the owner's and your switches, the limits and the audit apply as before. Creates take an optional id you choose. (AI assistants)

  • A local assistant for encrypted accounts. ot encryption unlock unwraps your account key with your encryption passphrase (or recovery key) on your computer and stores it owner-only; ot mcp --decrypt then lets an assistant such as Claude Desktop read and write your encrypted tasks, decrypting and encrypting on your machine while the server keeps receiving only ciphertext. The assistant's AI provider does receive the plaintext, and the bridge says so when it starts. Remote assistants of an encrypted account can now change colours, icons, order and Favourites; text still needs ciphertext. (AI assistants, Command-line client)

Changed

  • Overdue is now Earlier, and pages have a rhythm. Today's first group is Earlier: a quiet label with only each task's date in red, and two actions always in its header, Move all to today and Reschedule…, which change the whole group in one batch with Undo (also in the palette as Move earlier tasks to today and Reschedule earlier tasks…). With more than five tasks it starts folded on a device that never opened it. The word "overdue" leaves the interface, the Daily check, the display, the weekly review, Close the day and the weekly digest ("Still open from earlier"); the filter keyword overdue is unchanged. Dates climb a ladder: later dates muted, tomorrow in the text colour, today in the accent, an earlier day in red. Page titles are larger, with the date and totals (or a project's members, a label's count) on a soft line under them. Group headers are small labels, uppercase for the groups the app makes and in your own case for sections and projects. Pages without a layout switch are centred in wide windows and slide to the new centre when the task panel docks; a project keeps one frame for list, board and timeline, and its list now uses the width.

  • The app on a phone. Two rows sit above your tasks: the top bar and quick add. A list's buttons (Process, Ask, the duration filter) moved into the top bar, and Select tasks, Display mode and a project's layout and Share into its ⋯ menu. The Inbox's "planned without a project" count is the bar's subtitle. Swipe a task right to complete it, left to schedule it (Today, Tomorrow, Next week, a day you pick, or Someday); the same two actions start the task's menu, and a one-time hint shows the gesture. Press and hold a task to select it; Done in the selection bar hides the checkboxes. A task opens as a sheet over its list, with a handle you drag down to close it. Menus and pickers close the same way. While you scroll down, the bottom bar shrinks to icons and the + slides away. The list keeps room for the + under its last task, and the Undo toast sits above both. More opens a wider drawer with what the bottom bar doesn't have, in larger rows. (Work from the list, Bulk actions)

  • A new mark, and a quieter sidebar. OpenTodo has its own mark, an open loop that closes into a tick, beside the name at the top of the sidebar and on the sign-in, setup, reset, invitation and email screens. The app icon, the favicon, the Apple touch icon and a new maskable icon for Android home screens use it too; installed apps pick it up on their next load, with no reinstall. The browser extension's icons follow in its version 0.6.1. In the sidebar, rows rest in a quieter tone and brighten under the pointer, the current place is set in a stronger tone with its icon in your accent, and a group's All, Find and + appear while the pointer or keyboard focus is on its heading (always on a touch screen). On a computer, More is a heading that opens its menu, with no icon; the review-due dot is now on Review (inside More, or among the primary destinations in Open Loops first) and the unread count on Updates, never on More. While you track time, the elapsed time, the task and Stop sit in a pill in the sidebar's bottom row instead of a line of their own. On a computer the sidebar column has a faint tint of your accent colour (none in high contrast).

  • Settings, tidied. Cards carry an icon before their title (also in Settings search). Every Learn more points like a link and opens Help. Card buttons lose their trailing "…". How you work has a Start guide row that says whether you finished it and opens the guide over the Inbox. Recent activity groups by day, folds repeated sign-ins from one browser into "Signed in ×4", shows ten lines and Show all, and names failed or unusual events in the warning tone. The audit log is a compact list with filter chips, Export in the header and its retention and address settings in a separate Audit settings card. Date and time shows one Sample box. The issue connection editor is three steps with More options. API tokens are rows with scope badges and a create dialog that describes each scope. The Assistant card has a status line and "For everyone on this server" and "For you" groups. AI assistants is three numbered steps with ready-made configuration for Claude Desktop, Claude Code and other clients.

  • One quiet task row. When a list has timed tasks, their times stand in a column before the titles (a deadline's countdown where there is no time), so a day reads like a schedule; the column's width follows your 12- or 24-hour format. The line under a title is one run of muted text (date, repeat, deadline, start, estimate or 35m / 1h, blocked, streak, field values) with dots between items, labels are small chips with their colour (two, then "+n") and the only pills of a row, and the project moves to the end of the row next to the counts. With a mouse on a wide screen, hovering a row or tabbing into it shows Schedule, Priority and More; touch screens keep the long-press menu. Board cards, Plan, the review screens and Close the day use the same language. (Work from the list)

  • The Rows choice is gone. Settings → Appearance no longer offers Calm or Detailed rows: there is one row. The stored row_detail preference is kept in sync and in exports but no longer read; the task panel and the wide layout's field columns show what Detailed rows used to.

  • Filled calendar blocks, neutral events, board columns, settings tiers, statistics tiles. Calendar blocks, Month and Plan rows and timeline bars are filled in their project's colour, dimmed before today, with a red edge when a timeline task is past its deadline; events from other calendars are neutral with a calendar dot, and a day shows three all-day events then +N. Board columns sit on their own surface, cards lift on hover and a dashed space shows where a dragged card lands. Each Settings page keeps one card for its main setting and draws the rest as flat sections, and the statistics tiles show their figure larger above flat panels.

  • Calmer colours and sharper headings. The neutrals are a less blue slate, and the dark theme's canvas is lifted off near-black so cards, panels and menus separate by lightness. Headings are weight 600 with slightly tighter tracking, a new 28 px display step sets the clocks, and Inter's optical sizing is on, so large text uses its Display cut; the font file grows from 54 to 84 KB (one file, cached). Times, counts and durations use tabular figures so they line up. Every colour token is now written in OKLCH and accent themes declare three values from which the rest derive; quieter text uses a lower tone instead of transparency, which the design lint now enforces. (Design system)

  • Calmer rows. Hovering a row gives it a faint neutral tint and nothing else; the selected row is marked by a thinner bar and a lighter tint, and hovering it adds nothing.

  • Sub-projects read as children. The sidebar indents each level by 16 px, joins a project's open sub-projects to it with a thin guide line, leaves a little space between rows and after an expanded project's subtree, and shows a sub-project's full path as its tooltip.

  • The Inbox holds only what still needs a decision. A task is in the Inbox while it has no project and no plan: a due date, a start date or Someday now takes it out, even without a project, and clearing the date brings it back. A deadline alone doesn't. The same rule applies to the Inbox list and count, Process the Inbox, the Daily check and weekly review, the Loop pulse, ot inbox and the MCP inbox view, today_summary and opentodo://views/inbox. Nothing is written to your tasks: the rule reads their fields, so it works offline and every device agrees. The Inbox header says how many planned tasks have no project and opens them in Filter (no project); a deferred task without a project or due date is listed in Upcoming on its start day; quick add in the Inbox says where a dated task went ("Added to Friday", with Open); and project pickers call the choice No project. (Today and Upcoming)

  • Schedule from Process the Inbox like from the panel. s opens the Do on editor's choices, worded field and calendar in your date format, and for a task with a deadline, On the deadline, 1 day, 3 days, 1 week, 2 weeks or 1 month before on 1–6, leaving out choices already past. Decided tasks stay counted, so "4 of 17" doesn't jump. (Process the Inbox)

  • Inbox zero has a picture. The empty Inbox and the end of Process the Inbox show a calm line drawing above "Inbox zero: every task has a place.", the first of a set of illustrations drawn only with the theme's colours, in light and dark.

  • One page frame. Every page uses the same frame, at most 80 rem wide: the title and the header's actions stay in the same place when you switch a project between list, board and timeline or go to Labels, Trash or Filter, and lists start at the frame's left edge instead of being centred. Wide boards and timelines scroll sideways inside the frame. (Interface guide)

  • Statistics is a dashboard. Pick this week, this month, this quarter, this year or last week; every figure is compared with the same days of the previous period ("+12 % vs last month"), in words and an arrow. Four tiles (done, on time, streak, tracked against estimates) lead to panels that each answer one question: am I keeping up (completed and created as two lines), where does my time go (tracked time, or completions, per project), a year of done tasks (53 weeks of shaded days), when do I get things done (weekday by hour), how good are my estimates, and what keeps slipping (open tasks whose due date was pushed back three times in 90 days, from this device's history). Every chart has Show as table and can be explored with the arrow keys. The 4- and 12-week periods are gone; a device that last showed one opens on this week. Still computed on your device, with nothing sent anywhere; the charts are drawn by the app, with no chart library. (Statistics)

Fixed

  • Opening a task no longer moves the list. Pages now start at the left edge of the content column, so the task panel opens into the space beside the list and the list stays where it is; before, a page re-centred and slid up to 208 px left when the panel opened. The panel is also 30 rem wide from 1440 px again, as intended (it had stayed 26 rem). (Interface guide)
  • Completing a repeating task in Thunderbird completes it in OpenTodo. Thunderbird's task list completes one occurrence of a repeating task as a separate entry next to the series, which was ignored; completing the current occurrence now records it in Completed and moves the task to its next date, as completing it in OpenTodo does. Thunderbird and todoman are now verified against a real server (Calendar apps).
  • Focus rings show where they were missing, and cut text can be read whole. Keyboard focus now shows the ring on the calendar grid, the Month and Plan day cells, the statistics charts, the timeline, a row's label chips, the workspace and archived-project rows, the task panel's title and Add subtask field, and the sidebar's resize edge. A project name, page title, Trash title, member line or day header that is cut off shows its whole text in a tooltip on hover or keyboard focus. With a mouse, the completion circle, the chevrons, the selection boxes and the sidebar's group actions have 24 px targets, and a row's Schedule, Priority and More no longer cover its title. Lists, project pages and Statistics no longer jump as they load; on a phone the project's line under the title is plain text, and Share in the project menu opens members and public links. The issue connection editor says in the dialog why Test is off until the connection is saved.
  • More screens no longer jump while they load. The Plan, Projects and Updates show their placeholder rows until your tasks are read, instead of an empty page that fills in; the sidebar no longer opens its project tree and then folds it; and a settings page shows its cards together once each has its first answer from the server (at most 0.6 seconds). Nothing moves under reduced motion, now checked on every menu, dialog, sheet and drag.
  • Apple Reminders and Calendar can add the CalDAV account. macOS and iOS ended account setup with "Unable to verify account name or password" because the /.well-known/caldav redirect named a relative address and the host root answered their probes with a bare 405. The redirect now carries the server's full address (OPENTODO_BASE_URL, or the address the client used), a PROPFIND on the root or on /principals/… is redirected to /dav/, and an OPTIONS on the root reports the DAV capabilities. (Calendar apps, #249)
  • Tasks scheduled in Mitra stay scheduled, and moving them adds no deadline. A task with a due time is now served with DTSTART equal to DUE, so clients that schedule by start show it as scheduled; and when such a client moves the task and sends the old DUE back unchanged, the task moves instead of gaining a deadline. Equal start and due echoed back are no longer kept as client data. (Scheduled times and estimates, #248)
  • Files attached from a phone whose clock runs ahead now finish uploading. The server's "uploaded" mark lost to the phone's own timestamp and was dropped while the upload still answered success, so every device showed "still uploading from another device" for good. The mark now always wins, and an upload that could not be recorded answers an error so the phone retries. (#246)
  • Empty dashboard panels and an empty Plan panel say what would be there ("No tasks match this panel.", "Every task of these days is placed.") instead of "Nothing here.", and the Ask button and the Calendars toggles show their name in the app's tooltip instead of the browser's.
  • ot vault watch no longer misses a save made during a sync. A file saved while the watch was syncing counted as already synced, and with the live channel up it waited for the next change in the app; it is now synced on the next check. (Markdown vault)
  • Scheduling clients no longer erase dates over CalDAV. A calendar app that writes a start and a duration without a due date (Mitra, issue #196) cleared the task's due date and deadline; it now sets the due date from the start and keeps the deadline and the repeat rule. A VTODO without a due date never clears a deadline, and equal start and due keep it too. (Scheduled times and estimates)
  • A click selects a task in the Plan. Clicking a task in the Plan selected it and cleared the selection in the same moment, so the arrow keys moved nothing; the arrows now move the clicked task.
  • Task rows line up on phones. On touch screens the circle sat about half a line above the title; it is centred on the title's first line again, keeping the 44 px tap areas. The layout check now fails when they drift apart.
  • "Inbox" means the Inbox. A dated task without a project no longer carries an "Inbox" chip on its row; the task panel says "No project".
  • Subtasks leave the Inbox with their parent. A subtask without a project or date of its own stayed in the Inbox after its parent was scheduled or moved to a project; it now follows the parent, in the app, the count, ot inbox and the MCP tools.
  • Scheduling shows your date and time formats. Process the Inbox and Focus showed a due time as 15:00 even with the 12-hour clock, and a time-zone-fixed due in its own zone; they now follow your formats and your zone. The date field's hint now gives an example in your date order instead of 22/10.

Install

  • Docker: docker run -d -p 8080:8080 -v opentodo:/data ghcr.io/pixari/opentodo:0.10.0
  • Binary: download opentodo-<os>-<arch> below, then run it (data goes to ./data).
  • Command-line client: ot-<os>-<arch>. Browser extension: opentodo-browser-extension-chrome.zip and opentodo-browser-extension-firefox.zip.

Verify downloads with sha256sum -c SHA256SUMS. Self-hosting guides: docs/self-hosting.

Don't miss a new OpenTodo release

NewReleases is sending notifications on new releases.