Skip to main content

ToDos

Lightweight, project-scoped task tracking — accessible from the web UI, the Telegram bot, and the CLI. Useful for capturing follow-ups during meetings, filing CI failures as actionable items, or letting AI agents pick up work.

Each todo has a title, optional notes (up to 256 characters), a status, and an optional assignee.

Anatomy of a todo

Each todo has these fields:

FieldNotes
titleRequired. ≤ 200 characters.
notesOptional. ≤ 256 characters.
statusOne of in_progress, complete, cancelled. Defaults to in_progress.
assigneeOptional. Must be a project member (or the org owner).

Storage — markdown files in your project

Each todo is a markdown file at todos/<id>.md in the project's storage, with YAML frontmatter for the metadata and the markdown body for the notes. This means AI agents and other tools can read and write todos through the same file commands they'd use for any other project file — no separate API to learn.

---
id: 9f3e2c1d-3c4d-4a8e-b1f2-1234567890ab
title: Wire up the LED driver
status: in_progress
assigned_to: 7a1b2c3d-...
assigned_to_username: alice
created_by: 5c8d9e0f-...
created_by_username: bob
created_at: 2026-04-26T10:30:00Z
updated_at: 2026-04-26T11:00:00Z
---

Up to 256 characters of notes here.

Permissions

Access to todos is controlled by the project role permission system, scoped to the virtual /todos/* folder. A user's role must explicitly grant the permission to see / create / delete todos:

Role permission on /todos/*Allowed actions
readSee the ToDos card; list todos
writeCreate a todo; change status, title, assignee
deleteRemove a todo

The organization owner always has full access, regardless of role.

If a user has no role granting access to /todos/*, the ToDos card on the project page is hidden entirely.

In the web UI

The project page shows a ToDos card alongside Releases, Documents, etc.

  • Click + New to create a todo (title, notes, optional assignee).
  • Click the status pill to change status inline (yellow = in progress, green = complete, red = cancelled).
  • Click the assignee chip to reassign or unassign.
  • The trash icon deletes the todo.

From the Telegram bot

Once a Telegram group is linked to a project (see /configure), three commands are available:

  • /todos — list current todos with status icons
    Todos for myorg/myproject:

    1. ⏳ Wire up the LED driver — @alice
    2. ✅ Update README — @bob
    3. ❌ Investigate flaky CI — unassigned
  • /newtodo — start a multi-step wizard. The bot asks for the title, then notes (or /skip), then shows project members as inline buttons for the assignee picker.
  • /canceltodo — abort an in-progress /newtodo wizard.

Activity events are pushed to the linked group automatically:

  • 📝 created todo "..."
  • 🔁 updated todo "..." (in_progress → complete)
  • 🗑️ deleted todo "..."

From the CLI

The embedhub todos command group works against the same backend. See the CLI documentation for the full command reference.

embedhub todos list myorg/myproject
embedhub todos add myorg/myproject --title "ship v2" --assignee anuj
embedhub todos status myorg/myproject 9f3e2c1d done
embedhub todos rm myorg/myproject 9f3e2c1d --yes

For AI agents

An AI agent with the EmbedHub CLI installed can read and write todos with the same commands a human would. Two paths, depending on whether the agent wants structured JSON or raw markdown:

Structured JSON via the typed todos commands

embedhub todos list myorg/myproject --json
embedhub todos show myorg/myproject 9f3e2c1d --json
embedhub todos status myorg/myproject 9f3e2c1d done

Raw markdown via the files commands

embedhub list myorg/myproject --prefix todos/
embedhub pull myorg/myproject todos/9f3e2c1d.md

Either path respects the same /todos/* role permissions described above.

The file convention is todos/<id>.md where <id> matches the id in the YAML frontmatter. An agent that produces a new markdown file and embedhub pushes it under todos/ triggers the same todo.create activity event the web UI would, so Telegram notifications fire as expected.