A fast, keyboard-driven terminal UI for todo.txt.
A fast, keyboard-driven terminal UI for todo.txt. Vim-style bindings, atomic writes, instant external-edit detection, and five hand-tuned themes — all in a single static binary.
brew install tuxedoFor a more in-depth walkthrough, please watch this video by @IogaMaster.
tuxedo for the interactive UI, or tuxedo <command> for a todo.txt-cli-compatible command line (add, ls, do, pri, archive, …) — scriptable, with --json output and $TODO_DIR / $TODO_FILE / $DONE_FILE support.Pay rent monthly on the first, show 3 days before due, project home — and tuxedo rewrites it to canonical todo.txt for you to review and save. Local, offline, no AI service.s for a QR pointing at a tiny PWA on your machine's LAN — type tasks from your phone and they appear in the list. Captures land in a sibling inbox.txt first, so any tool that can append a line (shell, iOS Shortcuts, cron) is also a capture source.j / k to move, dd to delete, gg / G to jump, u to undo (50 levels), chord prompts (gg, dd, fp, fc) with a 600 ms window.: or Ctrl-P opens a fuzzy palette over every action — type a few letters, hit Enter. Same matcher as / search, ranked so start-of-label hits beat word-boundary hits beat mid-word hits.A moves completed tasks to done.txt next to your file, atomically.+project or @context, sort by priority / due / file order, and bulk-complete or bulk-delete in visual mode./-search with fs, then recall it any time by cycling saved filters with ff. Stored as plain filter.<name> lines in the config — hand-editable like everything else.T and D. Choices persist across runs and hot-reload when you edit config.toml externally.| Empty state • cell-bowtie mark and quick-start when the file has no tasks | |
| List • list of todos, optionally grouped | |
| Archive • completed tasks grouped by completion date | |
Filter sidebar active • fp cycles projects with j/k, fc cycles contexts; saved searches list under a SAVED heading with live match counts |
|
Command palette • : or Ctrl-P opens a fuzzy palette over every action |
|
Help • ? opens the full keybindings overlay |
The screenshots in the table above are checked-in SVGs. Regenerate them with:
mise run screenshotsThe hero GIF at the top is recorded with vhs from docs/demo.tape. Regenerate it with:
mise run demoT opens a picker over five built-in themes, including Terminal, which respects your terminal palette.
| Muted Slate (default) | Dawn |
|---|---|
| Nord | Matrix |
Beyond the built-ins, tuxedo loads any *.toml file you drop in
${XDG_CONFIG_HOME:-$HOME/.config}/tuxedo/themes/. Each one joins the T
picker in sorted filename order. Ready-made themes live in
docs/themes/ — copy one in and press T:
mkdir -p ~/.config/tuxedo/themes
curl -o ~/.config/tuxedo/themes/gruvbox-dark-soft.toml \
https://raw.githubusercontent.com/webstonehq/tuxedo/main/docs/themes/gruvbox-dark-soft.tomlA theme file is one key = value per line. name is the label shown in the
picker; every other field is a color value. All fields are required: a file
missing one, carrying an unparseable color, or whose name collides with
another theme is skipped with a warning at startup.
Color values accept two forms:
#rrggbb — a solid hex color (case-insensitive).reset or transparent — inherits the terminal emulator's own background
color. Useful for bg, panel, and statusbar when you want your
terminal's opacity, blur, or wallpaper to show through while keeping a
custom text palette. Both keywords are case-insensitive and behave
identically (same effect as the built-in Terminal theme).| Field | Colors |
|---|---|
name |
label shown in the T picker (the only non-color field) |
bg |
window background |
panel |
filter and detail panel background |
border |
panel and modal borders |
fg |
primary text |
dim |
secondary / muted text |
accent |
logo, headings, hints, and selection markers |
cursor |
current row, and the highlighted row in the T picker |
selection |
set to the same value as selected |
statusbar |
status bar background |
status_fg |
status bar text |
mode_fg / mode_bg |
mode chip text / background |
pri_a pri_b pri_c pri_d |
priorities A through D |
pri_other |
priorities E through Z |
project |
+project tags |
context |
@context tags |
due |
due: date |
overdue |
past-due date |
today |
date due today |
done |
completed tasks |
selected |
selected-row background (visual mode) and the active filter |
matched |
search-match highlight |
brew install tuxedoDownload the archive for your platform from the latest release and put tuxedo on your PATH.
Targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin, x86_64-pc-windows-msvc. Each archive ships with a .sha256 checksum.
cargo install --git https://github.com/webstonehq/tuxedoOr clone and build:
git clone https://github.com/webstonehq/tuxedo
cd tuxedo
cargo build --release
./target/release/tuxedo [FILE]Requires the Rust 2024 edition (recent stable toolchain).
tuxedo is two things in one binary: an interactive TUI, and a one-shot
command line. With no subcommand it launches the TUI; with a recognized
subcommand it runs the command line and exits.
tuxedo [FILE] # launch the TUI on FILE (created if missing)
tuxedo # TUI on the default file (see resolution below)
tuxedo --sample # open the bundled sample file in the temp dir
tuxedo <command> # run a one-shot CLI command — see "Command-line interface"
tuxedo update # print upgrade instructions for your install
tuxedo --help
tuxedo --versionWhen a newer release is available, the status bar shows ↑ <version> (tuxedo update) next to the version. The check runs in the background, is cached at
$XDG_CACHE_HOME/tuxedo/latest_version.json for 24 h, and fails silently
when offline. Set TUXEDO_NO_UPDATE_CHECK=1 to disable.
Both the TUI and the CLI resolve the todo file the same way, in order:
FILE argument (TUI only).$TODO_FILE, if set.$TODO_DIR/todo.txt, if $TODO_DIR is set../todo.txt in the current directory, if it exists.c to create
./todo.txt here, or s to open a sample todo.txt in the system temp
directory so you can poke around without committing to a path. (The
one-shot CLI is non-interactive and uses the sample directly.)The archive file is $DONE_FILE if set, otherwise a sibling done.txt next
to the todo file. The file (and any missing parent directories) is created on
first use. These are the same TODO_DIR / TODO_FILE / DONE_FILE variables
todo.txt-cli uses, so an existing todo.cfg works as-is:
export TODO_DIR="$HOME/Documents/todo"
export TODO_FILE="$TODO_DIR/todo.txt"
export DONE_FILE="$TODO_DIR/done.txt"Edits are persisted on every change via atomic write (write .tmp, rename).
If the file changes on disk (another editor, a sync client, a script), tuxedo notices on the next keypress, or within ~250 ms while idle, and reloads. The keystroke that triggered the reload is consumed — press it again to act on the fresh state — and the status bar flashes a notice.
Pressing A appends every completed task to a sibling done.txt and
removes them from the working file (atomically: done.txt is written
before the originals are dropped). a toggles the archive view so you
can browse, un-archive, or permanently delete past tasks.
When the first argument is a recognized subcommand, tuxedo runs a one-shot command instead of launching the TUI. The surface mirrors todo.txt-cli — same commands, aliases, task numbering, and output — so it's a drop-in for scripts and aliases.
tuxedo add "Pay rent +home @bank due:2026-07-01" # or: tuxedo a "..."
tuxedo ls @bank # filter by context
tuxedo do 3 # mark task 3 complete
tuxedo pri 3 A # set priority
tuxedo archive # move done tasks to done.txt
tuxedo ls --json | jq . # machine-readable output| Command | Aliases | Arguments | Description |
|---|---|---|---|
add |
a |
TEXT... |
Add a task (natural-language dates supported, same as the n prompt). |
append |
app |
N TEXT... |
Append text to task N. |
prepend |
prep |
N TEXT... |
Prepend text to task N. |
replace |
N TEXT... |
Replace task N entirely. |
|
pri |
p |
N PRIORITY |
Set priority A–Z on task N. |
depri |
dp |
N... |
Remove priority from the given tasks. |
do |
done, complete |
N... |
Mark tasks complete (recurring tasks spawn their next instance). |
del |
rm |
N [TERM] |
Delete task N, or remove just TERM from it. Prompts unless -f. |
archive |
Move completed tasks to the done file. | ||
list |
ls |
[TERM...] |
List tasks. TERM is +project, @context, or free text. |
listall |
lsa |
[TERM...] |
List the todo file and the done file. |
listpri |
lsp |
[PRIORITY] |
List prioritized tasks (optionally a single priority). |
listproj |
lsprj |
List all +projects. |
|
listcon |
lsc |
List all @contexts. |
Task numbers are 1-based line numbers in the file, exactly as printed by
list — stable regardless of how the list is filtered or sorted. list
sorts by the full line (case-insensitive) and prints a TODO: X of Y tasks shown footer, matching todo.txt-cli.
Options:
-f, --force — skip confirmation prompts (e.g. for del).--json — emit machine-readable JSON instead of text. list-style commands
print an array of task objects; mutating commands print a result object.
No prompts or footers are written in this mode.Global flags may appear before the subcommand (tuxedo -f del 3).
Differences from todo.txt-cli: do marks a task complete but does not
auto-archive it — completed tasks stay in the file until you
No open issues yet, or sync has not completed.