Minimal Node.js + TypeScript CLI scaffold for Todoist REST API workflows.
- List / add / complete tasks
- List projects and saved filters
- Run tasks through a Todoist filter query
- Interactive three-pane TUI (
tdcli tui): projects & filters | tasks | detail - Token config via env var, user config file (
tdcli config set-token), or local.env --jsonoutput on most read commands
src/
app/ App orchestration and command routing
cli/ Argument parsing helpers
commands/ Command handlers
config/ Environment and configuration loading
todoist/ Minimal Todoist REST client wrapper
tui/ Interactive three-pane terminal UI (readline raw-mode)
types/ Shared API types
utils/ Task sorting and output helpers
- Node.js 20+ (tested with Node 22)
- A Todoist API token
cd /home/steve/projects/tdcli
cp .env.example .env
# edit .env and set TODOIST_API_TOKEN
npm install
npm run buildAfter npm run build, register the command so you can type tdcli from any directory instead of node dist/cli.js.
Creates a symlink from your global Node path to this source folder. Rebuilding updates the command automatically — no reinstall needed.
cd /home/steve/projects/tdcli
npm linkVerify:
which tdcli
tdcli helpTo remove later:
npm unlink -g tdcliInstalls a snapshot of the current build into your global node_modules. You must re-run this after every npm run build to pick up changes.
cd /home/steve/projects/tdcli
npm install -g .To remove later:
npm uninstall -g tdclitdcli: command not found— your global npmbindirectory is not onPATH. Find it withnpm prefix -g(append/binon macOS/Linux, use that folder directly on Windows) and add it to your shell profile (~/.bashrc,~/.zshrc, etc.).EACCESpermission error on Linux/macOS — avoidsudo. Instead configure a user-owned global prefix once:npm config set prefix ~/.npm-globalthen add~/.npm-global/bintoPATH.- Command runs stale code — Option B requires re-running
npm install -g .after each build. Use Option A to avoid this.
# List tasks (after global install)
tdcli tasks list
# Or without installing globally
node dist/cli.js tasks list
# List tasks with a Todoist filter query
node dist/cli.js tasks list --filter "today | overdue"
# Add a task
node dist/cli.js tasks add --content "Buy milk" --due "tomorrow at 9am" --priority 4
# Complete a task
node dist/cli.js tasks complete --id 1234567890
# List projects
node dist/cli.js projects list
# List saved filters
node dist/cli.js filters list
# Run tasks through a filter
node dist/cli.js filters tasks --filter "@work & today"
# Token config (stored in user config file)
node dist/cli.js config set-token --token <TODOIST_TOKEN>
node dist/cli.js config status
node dist/cli.js config path
node dist/cli.js config test
node dist/cli.js config clear-token
# Launch interactive TUI
node dist/cli.js tui↑/↓orj/k— moveTab/h/l/[/]— switch paneEnter/r— refresha— add task (types inline;Entersubmit,Esccancel) — goes to current project or Inbox if filter selectedc/x— complete taskd— delete task (confirm withy)p— cycle priority (P1→P2→P3→P4→P1)t/T— due today / tomorroww/W— due next Monday / next Saturdayq— quit
- The CLI uses Node's built-in
fetch, so no HTTP client dependency was added. - Argument parsing is intentionally lightweight to keep the dependency footprint tiny.
- TUI:
src/tui/index.tsimplements a live three-pane UI overreadlineraw-mode keypress events, wired viatdcli tuiinsrc/app/app.ts. No Ink/Blessed dependency. - Todoist filter queries use Todoist's own filter syntax.
- Token precedence:
TODOIST_API_TOKENenv var → local.envin cwd →~/.env-todoist(override path withTDCLI_ENV_FILE) → user config file (config set-token). ~/.env-todoistis the recommended spot when runningtdclias a globally installed command from arbitrary directories.
- Interactive auth/setup flow
- Priority color coding (P1–P4) in TUI — matching Todoist web colors
- Richer table formatting / colors in list commands
- Project lookup by name instead of only ID
- Task update / delete support