Skip to content

Command-Line Interface (CLI)

tasuku is the user-facing product CLI (constitution §7.15, spec 028 / S14). It is a thin, first-class client of the same HTTP API the web app uses — it holds no business logic and has no direct database access; everything goes through the versioned /v1 API and the single Clerk auth boundary. Persona: Eddy (power user, P3); objective O-09.

Terminal window
npx tasuku --help # run without installing
npm i -g tasuku # or install globally

Requires Node ≥ 20. Distributed via npm (ADR-005).

The CLI signs in with the OAuth 2.0 Authorization Code flow + PKCE and a loopback redirect (http://127.0.0.1/callback), with Clerk as the identity provider (ADR-004). It presents the resulting bearer token to the API, which verifies it at the same boundary as a web session (ADR-014) — identity always comes from the verified token, never from client input.

Terminal window
tasuku auth login # opens the browser, captures the redirect, stores the token
tasuku auth status # show the signed-in identity (alias: tasuku whoami)
tasuku auth logout # revoke the token and clear local credentials

auth status renders the identity as a table:

┌──────────────────────────────────┬───────┬─────────────┐
│ Email │ Name │ Token store │
├──────────────────────────────────┼───────┼─────────────┤
│ you@example.com │ You │ keychain │
└──────────────────────────────────┴───────┴─────────────┘

The token is stored in the OS keychain where available, otherwise in an encrypted, 0600 fallback file under $XDG_CONFIG_HOME/tasuku (with a warning — weaker than the keychain). Tokens are never printed or logged. On logout the token is revoked server-side and removed locally.

Terminal window
tasuku list ls
tasuku list create "Groceries"
tasuku list rename Groceries "Shopping" # by name or by ID
tasuku list rm <list> --yes
tasuku task ls "Shopping"
tasuku task add "Shopping" "Buy milk"
tasuku task done "Shopping" "Buy milk" # --undo to reopen
tasuku task rename "Shopping" <task> "Buy oat milk"
tasuku task rm "Shopping" <task> --yes

A <list>/<task> reference is the ID shown by ls (and in --json), or an unambiguous name. An ambiguous name errors (exit 8) rather than guessing.

Results render as bordered, headed tables:

┌──────────────────────────────────────┬───────────┬────────┐
│ ID │ Title │ Shared │
├──────────────────────────────────────┼───────────┼────────┤
│ a1b2c3d4-e5f6-4789-8abc-def012345678 │ Groceries │ │
└──────────────────────────────────────┴───────────┴────────┘
  • --json — machine-readable output ({ ok, data } / { ok, error }); data on stdout, diagnostics on stderr.
  • Stable, documented exit codes: 0 ok · 2 usage · 3 auth-required · 4 not-found/forbidden · 5 validation · 6 network · 7 version-skew · 8 ambiguous-ref.
  • Honours NO_COLOR; supports -q/--quiet and -v/--verbose. Fully non-interactive (destructive commands need --yes), so it runs cleanly in CI.
VariablePurpose
TASUKU_API_URLAPI origin (default the production Worker; or --api)
TASUKU_TOKENPre-obtained bearer token for CI (skips the browser flow; read-only, not persisted)
TASUKU_OAUTH_CLIENT_IDPublic OAuth client id (or --client-id)
TASUKU_OAUTH_ISSUERClerk Frontend API URL / OAuth issuer (or --issuer)
TASUKU_OAUTH_SCOPEOAuth scope (default openid profile email)
TASUKU_CREDENTIAL_STORESet to file to force the encrypted-file store and bypass the OS keychain
NO_COLORDisable colour

The CLI’s architecture is fixed by three decisions (see Design Decisions):

  • ADR-004 — auth via OAuth 2.0 Authorization Code + PKCE, loopback callback, Clerk as IdP.
  • ADR-005 — implemented in TypeScript, distributed via npm.
  • ADR-014 — JWT access tokens + short TTL + refresh-revoke on logout; the shared auth boundary accepts both session and OAuth tokens.

It targets a declared API version and degrades gracefully on version skew. Operational configuration and deployment are covered in Operations & Configuration.