tuiboard

June 6, 2026 · View on GitHub

A terminal kanban board on plain markdown files, with three optional panels you switch on or off: a Today/Tomorrow planner across all your boards, a 24-hour agenda with a read-only Google / Microsoft 365 calendar overlay, and a live view of your Claude Code sessions. Run it as a pure kanban, or any mix of the four. The board is always on; the rest is opt-in (see Zones).

Built with OpenTUI + SolidJS on Bun. Cross-platform (Linux, macOS, Windows). No vendor lock-in: boards are CommonMark with the Obsidian Tasks-plugin emoji vocabulary, so they open and edit fine in any markdown editor.

tuiboard — kanban board, Today/Tomorrow panel, 24h agenda with calendar overlay, and live Claude Code agents in one terminal dashboard

Install

Requires Bun ≥ 1.2 — tuiboard runs on the Bun runtime (it's not a Node CLI). OpenTUI ships its own native renderer binaries; Bun picks the right one for your platform automatically. Pick whichever install fits:

Global, straight from GitHub (no npm needed) — run tuiboard from anywhere:

bun install -g github:NazzarenoGiannelli/tuiboard
tuiboard

Global, from npm:

bun install -g tuiboard      # or run once, no install: bunx tuiboard

From source (for hacking on it):

git clone https://github.com/NazzarenoGiannelli/tuiboard.git
cd tuiboard
bun install
bun run dev          # or: bun link  → then `tuiboard` globally, live-linked

Quick start

Starting fresh — no Obsidian, no special folders required:

  1. Install Bun (bun.sh), then bun install -g tuiboard.
  2. Make one or more board files. A board is a plain .md file: every ## heading is a column, every - [ ] line is a task. The simplest board:
    ## To Do
    - [ ] My first task
    
    ## In Progress
    
    ## Done
    
    Create one file per tab you want (e.g. Work.md, Personal.md). Columns named exactly Done and Archive are treated specially (hidden from the board view but used by the done-stats and the archive action).
  3. Point tuiboard at them. Create ~/.config/tuiboard/config.yaml (found from any directory) with absolute paths:
    boards:
      - path: /home/you/notes/Work.md
        name: Work
      - path: /home/you/notes/Personal.md
        name: Personal
    
    Or skip the config entirely and just run tuiboard inside a folder that already contains .md files with - [ ] tasks — it auto-discovers them.
  4. Run it: tuiboard (or the short alias tb).

The Agent view needs zero setup. tuiboard reads your local Claude Code sessions from ~/.claude/ automatically, so the live agent strip fills in as soon as you've used Claude Code — nothing to connect or configure. (Tools that don't write to ~/.claude, like Codex, won't show up there.)

See Configure for assignees, the done/archive column names, and the optional custom "open session in your terminal" command.

Let an AI agent set it up for you

Paste this into Claude Code (or Codex / Cursor) from any directory — it interviews you and wires everything up:

I just installed `tuiboard` (a terminal kanban dashboard:
https://github.com/NazzarenoGiannelli/tuiboard). Set it up for me from scratch:

1. Ask me: (a) which directory should hold my board markdown files,
   (b) how many boards/tabs I want and their names (e.g. Work, Personal),
   (c) any assignee names I use.
2. Create one markdown file per board in that directory. Each file: a few `##`
   column headings — default `## To Do`, `## In Progress`, `## Done` — and no
   tasks yet. Always include a `## Done` column (tuiboard treats columns named
   `Done` and `Archive` specially and hides them from the board view).
3. Create a global config at `~/.config/tuiboard/config.yaml` (resolve the real
   home path) with a `boards:` list pointing at those files by ABSOLUTE path,
   plus `assignees: [...]`, `done_column: Done`, `archive_column: Archive`.
4. Ask me which zones I want besides the kanban board: the Today/Tomorrow
   planner, the 24h agenda, and the live Claude Code agents view. For any I
   don't want, add a `zones:` block setting it to `off` (e.g. someone who
   doesn't use Claude Code would set `agents: off`). If I want them all, omit
   the block. Do NOT configure the agents view beyond on/off — it reads
   `~/.claude` automatically when enabled.
5. Ask me whether I want to overlay my Google Calendar or Microsoft 365 events
   on the Agenda (skip this if I turned the agenda off). If yes, tell me to run
   `tuiboard calendar-setup google` (or `microsoft`) — it interviews me, opens
   the browser, and prints the exact `calendars:` YAML block to add. Don't try
   to do the OAuth yourself. If no, skip it (it's optional and can be added later).
6. Show me the final config, then tell me to run `tuiboard`, and how to add a
   board later (create a new `.md` and append it to the `boards:` list).

Confirm the directory and file names with me before writing any files.

Configure

Copy .tuiboard/config.example.yaml to a config location and edit the boards: list to point at your markdown files. tuiboard resolves the config in this order (first hit wins):

  1. $TUIBOARD_CONFIG — explicit path to a config file.
  2. Project-local.tuiboard/config.yaml, walking up from the cwd. Drop a .tuiboard/ folder at a project/vault root and it's used whenever you launch from inside that tree.
  3. Global~/.config/tuiboard/config.yaml (or ~/.tuiboard/config.yaml). Use absolute board paths here and tuiboard shows your boards from any directory — the usual setup for a single-vault user.
  4. Fallback — scan the cwd for any .md file containing - [ ] tasks.
boards:
  - path: ./Work.md
    name: Work
  - path: ./Personal.md
    name: Personal

assignees: [Alice, Bob]
done_column: Done
archive_column: Archive

# Optional: override Enter in the Agents zone. argv array, {cwd}/{sessionId}
# substituted, run directly (no shell — element 0 must be a real binary/abs
# path, NOT a shell builtin or Windows App Execution Alias). Defaults to
# opening a WezTerm tab with `claude --resume <id>`. For a custom layout:
# resume_command: ["nu", "C:/Users/you/.config/tuiboard/code-resume.nu", "{cwd}", "{sessionId}"]

Zones

tuiboard is four zones — board (kanban), planner (Today/Tomorrow across all boards), agenda (24h timeline + calendar overlay), and agents (live Claude Code sessions). Only want some of them? The board is always on; the other three are yours to configure:

zones:
  planner: on      # Today/Tomorrow panel          (toggle at runtime with F1)
  agenda: on       # 24h agenda + calendars        (F2)
  agents: off      # live Claude Code view         (F3)

Each zone takes one of:

ValueBehavior
onEnabled and shown at launch (the default).
offDisabled entirely — never rendered, skipped by Shift-Tab, its F-key is inert, and its background work never starts (no calendar fetch, no ~/.claude reads).
hiddenEnabled but collapsed at launch — reveal it any time with its F-key.

true/false work as aliases for on/off. So a pure kanban is just agenda: off and agents: off; kanban + calendar is agents: off. The difference between off and the F-key hide: off means the feature never runs at all — handy if you don't use Claude Code and don't want tuiboard reading ~/.claude.

Calendars (Agenda overlay)

The Agenda zone (the 24h timeline) can overlay events from Google Calendar and Microsoft 365 alongside your time-blocked tasks — timed events render as colored 📅 blocks on the grid, and all-day events ride in a chip strip at the top (like Google Calendar's all-day band). The day's real shape is visible at a glance. Each calendar keeps its own color. Events are cached 30 min on disk and refreshed every 5 min. Bring your own credentials — there's nothing to sign up for and nothing leaves your machine. (Reading is the default; opt into creating/editing events below.)

Connect a calendar with the built-in setup command:

tuiboard calendar-setup google      # opens your browser (read-only scope)
tuiboard calendar-setup microsoft   # device-code flow, no redirect

Microsoft needs an Azure app registration (Public client, Calendars.Read delegated) whose client ID goes in ~/.config/tuiboard/azure_config.json — running calendar-setup microsoft with no config writes a template that walks you through it.

Google: one-time OAuth client setup

There's no hosted tuiboard app — you create your own free OAuth client in your own Google Cloud project, so nothing is shared and your data never passes through anyone else's servers. It takes about five minutes, once:

  1. Go to the Google Cloud Console and create a project (or pick an existing one) from the project dropdown.
  2. APIs & Services → Library → search "Google Calendar API"Enable.
  3. APIs & Services → OAuth consent screen: if prompted, choose External, give the app a name and your email, and save. You don't need to publish it or submit for verification — as the project owner you're automatically a test user of your own app, which is all tuiboard needs. (Add your Google address under Test users if it asks.)
  4. APIs & Services → Credentials → Create credentials → OAuth client ID. Application type: Desktop app. Create.
  5. Download JSON on the client you just made, and save it as ~/.config/tuiboard/google_credentials.json.
  6. Run tuiboard calendar-setup google (add --write to also create/edit/delete — see below). Your browser opens; approve the access. You'll briefly see an "unverified app" notice — that's expected for your own personal client; click Advanced → go to (your app) to continue. The token is saved and the command prints the YAML block to paste into your config.

The calendar-setup command prints these exact steps too if it doesn't find the credentials file.

After connecting, the command prints the exact YAML to paste into your config:

calendars:
  google:
    enabled: true
    token: ~/.config/tuiboard/google_token.json
  microsoft:
    enabled: true
    config: ~/.config/tuiboard/azure_config.json
    token_cache: ~/.config/tuiboard/ms_token.json

Paths support ~ and resolve against the config dir if relative. A missing, expired, or unconfigured calendar never breaks the board — it just shows no events. Set either provider's enabled: false (or drop the block) to turn it off; add a color: to override the fallback block color.

Creating, editing & deleting events (Google, opt-in)

Reading is the default. To also create, edit, and delete Google Calendar events from the Agenda, re-authorize with the write scope:

tuiboard calendar-setup google --write

Create — in the Agenda zone, press n (or click an empty time slot) to open the new-event modal: type a title, press Enter, pick the target calendar with j/k, Enter to create. Only calendars you can write to (owner/writer) show in the picker. Append tokens to the title to set the time and date:

Standup 9:00-9:30            # today (or the viewed day), 09:00–09:30
Lunch m 12-13                # tomorrow (m), 12:00–13:00
Review 2026-06-10 15-16      # that date, 15:00–16:00
Call +3 16:00-16:30          # in 3 days · lun = next Monday also works
Holiday 2026-12-25 allday    # an all-day event (no time)

The date defaults to whichever day the Agenda is showing; an explicit date token (t / m / +N / weekday / YYYY-MM-DD — the same t/m = today/tomorrow as the board keys) overrides it. The time is taken from the clicked slot, or HH:MM-HH:MM. Add allday (or all-day) anywhere in the title to create an all-day event instead — it lands in the top chip strip.

Edit / deleteclick an existing event in the Agenda to select it (only events on writable calendars can be selected; read-only ones just say so). Then:

  • e (or Enter) opens the edit modal, prefilled with the title and time — change the title, time, and/or date (same Title [date] HH:MM-HH:MM syntax) and Enter to save. A date token moves the event to another day.
  • d deletes it (with a confirm).
  • Esc deselects.

Edits stay on the same calendar (moving an event between calendars isn't supported). Every change appears in the Agenda right away and on Google Calendar.

Set the calendar new events default to with default_calendar (a calendar id; unset → your primary). You can still override per-event in the modal:

calendars:
  google:
    enabled: true
    token: ~/.config/tuiboard/google_token.json
    default_calendar: you@example.com   # optional; default target for new events

The write scope is opt-in: without --write, tuiboard stays read-only and the n shortcut / slot-click / event-selection do nothing. Microsoft event write isn't supported yet (read-only).

Markdown board format

tuiboard reads and writes plain CommonMark with the Obsidian Tasks-plugin emoji vocabulary. Any markdown editor renders these files sensibly; the Obsidian Kanban plugin renders them as a kanban; we render them as a TUI.

Minimal example

---
kanban-plugin: board
---

## Today

- [ ] Fix auth flow @nazza ⏳ 2026-05-27 ⌚ 09:00-10:30 #pr-followup
- [x] Review PR #412 ✅ 2026-05-26

## In Progress

- [ ] Migrate timeline to OpenTUI @nazza

## Done

The kanban-plugin: board frontmatter is optional — it's only there so the file also renders as a board in Obsidian's Kanban plugin. tuiboard itself needs just the ## column headings and - [ ] task lines.

Metadata vocabulary

SymbolMeaningNotes
## HeadingColumn nameOne column per H2 heading
- [ ] / - [x]Task (open / done)Standard markdown task list
@nameAssigneeConfigurable list in config.yaml
#tagTagAny hashtag; passed through verbatim
⏳ YYYY-MM-DDScheduled dateTasks-plugin convention
📅 YYYY-MM-DDDue dateTasks-plugin convention
🛫 YYYY-MM-DDStart dateTasks-plugin convention
✅ YYYY-MM-DDDone dateTasks-plugin convention
⌚ HH:MM-HH:MMTime blocktuiboard-specific (Tasks plugin has no time-of-day)
🔺 ⏫ 🔼 🔽 ⏬PriorityTasks-plugin convention

Anything else stays in the task text untouched on write-back. Roundtrip is byte-for-byte preserving when a task hasn't been edited; structured fields are rebuilt only after an in-app mutation.

Layouts

Launch tuiboard with no flag for the default dashboard (every enabled zone).

FlagViewUse case
(none)Dashboard — every enabled zoneDefault; your configured layout
--view=boardKanban + planner panel onlyFocus mode, or a single WezTerm pane
--view=timelineTimeline fullscreenWall-mounted "what's now"
--view=agentsAgent view fullscreenCross-machine session monitor

The dashboard auto-collapses optional zones on narrow terminals:

Terminal widthDefault zones visible
≥ 150 colsplanner + board + timeline + agents
120–149planner + board + agents
100–119planner + board
< 100board only

F1 / F2 / F3 toggles override the auto-collapse for the current session (until the next terminal resize).

Keyboard

KeyAction
h j k l / arrowsMove cursor inside the active zone
TabCycle to next board
1..9Jump to board N
vToggle Today/Tomorrow planner panel focus
Shift-TabCycle active zone (planner → board → timeline → agents)
F1 / F2 / F3Toggle visibility of Planner / Timeline / Agents zones
zZoom active zone to full screen
rRefresh everything — reload boards from disk, rescan agents, force-refetch the agenda calendar (bypasses the 30-min cache)

Agenda (timeline zone)

KeyAction
[ / ]Previous / next day — shows that day's tasks and calendar events (works from any zone)
\Jump back to today
cArm mode: click a task, then click a slot to schedule (works from any zone)
j / kWhile armed: nudge the block ±15 min
+ / -While armed: resize the block's end ±15 min

Task actions (work in board, planner, AND timeline zones)

KeyAction
EnterToggle done
oOpen detail view
eEdit task text
sSchedule date modal
tSet scheduled = today
mSet scheduled = tomorrow
.Schedule now — time block at the next 15-min slot
bSet time block modal
pCycle priority (none → 🔺 → ⏫ → 🔼 → 🔽 → ⏬ → none)
aSet assignee
cToggle calendar arm mode — then click a task, click a timeline slot, repeat
Shift-CCopy task to clipboard (markdown line — paste as context for Claude Code)
dDelete task (with confirm)
Shift-XArchive task → moves to Archive column

Multi-select

KeyAction
SpaceMark / unmark task — task actions then apply to ALL marked
EscClear marks (when no modal is open)

Board-only / bulk / global

KeyAction
nNew task in current column (quick-add syntax)
Shift-TReset ALL overdue tasks (any board) to today
Ctrl-ZUndo last mutation
?Help modal with the full reference
q · Ctrl-CQuit

Status

See CHANGELOG.md for the full release history.

  • v0.8 — write to Google Calendar from the Agenda: create, edit, and delete events (opt-in), set their date and time in the modal, plus all-day events in the top strip, consistent t/m date shortcuts, and a boot splash.
  • v0.7 — configurable zones: turn the planner, agenda, or agents view off (or start it collapsed) via the zones: config, so tuiboard can be a pure kanban, kanban + calendar, or any mix.
  • v0.6 — adds the Agenda calendar overlay (Google + Microsoft 365, read-only, BYO credentials), day-navigation ([ / ] / \) to page tasks and events across days, and a manual full-refresh key (r).
  • v0.5 — daily-driver ready. Kanban + planner + timeline + agents all functional, multi-select, undo, atomic file roundtrip, mouse click, responsive layout. Tested on Windows with WezTerm; Linux/macOS should work via the same OpenTUI binaries (untested).

Contributing

Contributions are welcome — bugs, docs, fixes, features, or just trying it on a platform I haven't tested. See CONTRIBUTING.md for setup, the project layout, and the checks to run, and the good first issues for a place to start.

License

MIT — see LICENSE.