Skip to content

zcag/odak

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

odak

The world's fastest todo app.

A personal todo service backed by a plain Markdown file. Every action — toggle, edit, add, delete — reflects instantly in the UI with no perceived latency. Changes to the file from any text editor propagate to all open clients in ~200ms via WebSocket. No database, no sync delay, no cloud.

Comes with a REST API, a real-time web UI, and a terminal interface — all reading from and writing to a single .md file.

## Focus
- [ ] ship the thing [t:work] [d:2026-05-25]
    - [ ] write tests
- [x] design review

## Inbox
- [ ] [!] call the doctor

Web UI


Installation

go install github.com/zcag/odak@latest

Installs the full binary — CLI, TUI, and REST server with embedded web UI. Point the client at a running server via env vars or ~/.config/odak/client:

# env vars
export ODAK_ENDPOINT=http://your-server:8761
export ODAK_TOKEN=your-api-key

# or config file (~/.config/odak/client)
endpoint=http://your-server:8761
token=your-api-key

Build from source

git clone https://github.com/zcag/odak
cd odak
make build        # local binary → ~/.local/bin/odak
make deploy       # cross-compile + push to server via rsync + systemd restart

Server

odak --server \
  --file ~/todos.md \
  --api-key secret \
  --user admin \
  --password secret \
  --port 8761 \
  --ui              # serve the web UI at /

Or via environment variables:

export ODAK_FILE=~/todos.md
export ODAK_API_KEY=secret
export ODAK_USER=admin
export ODAK_PASSWORD=secret
odak --server --ui

A systemd user service template is included at deploy/odak.service.template.


Web UI

Access at http://your-server:8761. Changes sync in real time via WebSocket — editing the Markdown file directly also reflects instantly in all open browsers.

Sections — items are grouped into named sections (Focus, Today, Next, Backlog, Someday, Recurring, Inbox). Sections collapse in the sidebar and in the main view.

Themes — 8 dark themes (Void, Carbon, Smoke, Midnight, Nord, Catppuccin, Gruvbox, Dracula) and 8 light themes. Hover the sun/moon icon to pick.

Keyboard shortcuts

Key Action
j / focus next item
k / focus previous item
x toggle done
e edit text
d delete
n / / focus add bar
w toggle #work filter
p toggle #personal filter
r refresh
? keyboard shortcut overlay
Esc clear focus / close

Drag and drop — reorder items within a section or drag to a different section header to move them.

Sub-items — child items are shown indented under their parent, collapsed by default. Click the indicator to expand.


Terminal UI

odak           # launch TUI (auto-detected when stdout is a TTY)
odak tui       # explicit

Navigate sections with arrow keys, toggle done with x, edit with e, hide completed with h.

Terminal UI


CLI

odak list [section]                          # list todos
odak list --tag work                         # filter by tag
odak add "review PR" --section Next          # add item
odak add "! urgent thing #work d:2026-05-25" # with flags inline
odak done <id>                               # toggle done
odak rm <id>                                 # delete
odak move <id> Today                         # move to section
odak show <id>                               # show details

File format

Standard Markdown task lists, grouped by ## headings. Extra metadata lives in inline tags:

## Focus
- [ ] [!] urgent item
- [ ] [t:work] [t:personal] tagged item
- [ ] [d:2026-05-25] item with deadline
- [ ] [w:2026-06-01] item with trigger/wait date
- [ ] parent item
    - [ ] child item (indented with 4 spaces or tab)
- [x] completed item

The file is the source of truth — edit it directly and all clients update within ~200ms.


MCP Server

Use odak as a tool inside Claude Code or any MCP-compatible AI client.

The MCP server is served by odak --server itself over the Streamable HTTP transport at /mcp, behind the same bearer API key as the REST API — there is no separate process to launch.

Register it with Claude Code (user scope — available in every project):

claude mcp add --transport http odak http://<host>:<port>/mcp \
  --header "Authorization: Bearer <api-key>"

For other MCP clients, point them at the HTTP endpoint with the bearer header:

{
  "mcpServers": {
    "odak": {
      "type": "http",
      "url": "http://<host>:<port>/mcp",
      "headers": { "Authorization": "Bearer <api-key>" }
    }
  }
}

Available tools:

Tool Description
list_todos List items, optionally filtered by section, tag, or parent_id
get_todo Get a single item by id
add_todo Add item with optional section, tags, urgent, deadline, trigger, parent_id
edit_todo Update any field of an existing item
toggle_done Toggle done state by id
delete_todo Delete item by id
move_todo Move item to a different section
reorder_todos Reorder items within a section by providing ordered ids
list_sections List sections with item counts
get_raw Get the raw Markdown content of the file
put_raw Overwrite the entire file with raw Markdown

OAuth (hosted connectors)

To connect odak from a hosted client that can't carry a static header — the Claude.ai / ChatGPT "Connect" flow — point /mcp at a WorkOS AuthKit authorization server. With it configured, /mcp accepts either the static API key (CLI/TUI/local clients) or a valid AuthKit-issued JWT, and serves the RFC 9728 Protected Resource Metadata at /.well-known/oauth-protected-resource so hosts can discover the auth server.

Env-only, all unset ⇒ OAuth off (/mcp stays API-key-only):

export ODAK_OAUTH_ISSUER=https://your-app.authkit.app   # AuthKit domain; JWKS at {issuer}/oauth2/jwks
export ODAK_MCP_RESOURCE=https://odak.example.com/mcp    # this endpoint's public URL = the OAuth audience
export ODAK_OAUTH_ALLOWED_EMAIL=you@example.com          # optional email-claim allowlist (single-user gate)
export ODAK_OAUTH_ALLOWED_SUB=user_123                   # optional sub-claim allowlist (single-user gate)

Tokens are validated against the JWKS, enforcing issuer, audience (== ODAK_MCP_RESOURCE, RFC 8707 replay defense), signature, and the optional allowlist — a token passes if its sub or email claim is listed (which claim an AuthKit access token carries varies, so set whichever you can confirm; a rejected token's sub/email is logged so you can pin it).


Raw API

All endpoints require Authorization: Bearer <api-key>.

GET    /todos              list items (?section=, ?tag=, ?parent_id=)
POST   /todos              create item
GET    /todos/:id          get item
PATCH  /todos/:id          update item
DELETE /todos/:id          delete item
PATCH  /todos/:id/done     toggle done
POST   /todos/:id/move     move to section
POST   /todos/reorder      reorder within section
GET    /sections           list sections with counts
GET    /raw                raw markdown
PUT    /raw                overwrite markdown
GET    /ws                 WebSocket (?token=)

About

World's fastest todo app. Server + WebUI/TUI/CLI all backed from an human-readable md file.

Resources

Stars

21 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors