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.
Install
Section titled “Install”npx tasuku --help # run without installingnpm i -g tasuku # or install globallyRequires Node ≥ 20. Distributed via npm (ADR-005).
Authentication
Section titled “Authentication”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.
tasuku auth login # opens the browser, captures the redirect, stores the tokentasuku auth status # show the signed-in identity (alias: tasuku whoami)tasuku auth logout # revoke the token and clear local credentialsauth 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.
Lists & tasks
Section titled “Lists & tasks”tasuku list lstasuku list create "Groceries"tasuku list rename Groceries "Shopping" # by name or by IDtasuku list rm <list> --yes
tasuku task ls "Shopping"tasuku task add "Shopping" "Buy milk"tasuku task done "Shopping" "Buy milk" # --undo to reopentasuku task rename "Shopping" <task> "Buy oat milk"tasuku task rm "Shopping" <task> --yesA <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 │ │└──────────────────────────────────────┴───────────┴────────┘Scripting
Section titled “Scripting”--json— machine-readable output ({ ok, data }/{ ok, error }); data on stdout, diagnostics on stderr.- Stable, documented exit codes:
0ok ·2usage ·3auth-required ·4not-found/forbidden ·5validation ·6network ·7version-skew ·8ambiguous-ref. - Honours
NO_COLOR; supports-q/--quietand-v/--verbose. Fully non-interactive (destructive commands need--yes), so it runs cleanly in CI.
Environment
Section titled “Environment”| Variable | Purpose |
|---|---|
TASUKU_API_URL | API origin (default the production Worker; or --api) |
TASUKU_TOKEN | Pre-obtained bearer token for CI (skips the browser flow; read-only, not persisted) |
TASUKU_OAUTH_CLIENT_ID | Public OAuth client id (or --client-id) |
TASUKU_OAUTH_ISSUER | Clerk Frontend API URL / OAuth issuer (or --issuer) |
TASUKU_OAUTH_SCOPE | OAuth scope (default openid profile email) |
TASUKU_CREDENTIAL_STORE | Set to file to force the encrypted-file store and bypass the OS keychain |
NO_COLOR | Disable colour |
Design & governance
Section titled “Design & governance”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.