ADR-0001: Design Principle¶
Status¶
Accepted
Context¶
td has two audiences: humans at terminals and AI agents delegating
through the command tree. Without a shared principle, individual
commands drift toward whichever audience the author has in mind that
day. We saw this in PR #241, where CRUD commands followed the API's
shape (project-edit, section-delete) instead of user intent, and
produced the redesign called for in issue #250. The decision: establish
a single principle every command is measured against, so drift is
visible and correctable before it ships.
Decision¶
Surface the context users need to be successful, nothing more.
Every command, error message, and output is measured against this. The CLI should feel like a tool built for the person using it, not a wrapper around an API.
Four sub-principles apply this rule:
1. Accept what the user means, not what the system needs¶
The common case should be flag-free. If a command has one obvious argument, accept it positionally. Flags exist for disambiguation and advanced use.
td sections Blog # obvious intent: scope to project
td completed Work # same pattern
td ls -p Work --sort due # flags only for the less common case
2. Show what's useful, not what the API returns¶
Rich and Plain output modes are for humans. Raw IDs belong in JSON output for scripting, not in tables.
- Tables show row numbers, names, and dates, not opaque IDs
- Empty states explain what to do next, not just "no results"
- Success messages confirm what happened in human terms
3. Help the user recover when things go wrong¶
Every error answers three questions: what happened, why, what to do next.
- Ambiguous input triggers a picker instead of an error
- Missing arguments launch interactive mode instead of printing usage
- Suggestions are specific: "Run
td projectsto see available names"
4. Progressive disclosure¶
The simple case is simple. Power features exist but are not in the way.
Consequences¶
Positive. New commands have a concrete measuring stick: "does this conform to ADR-0001?" is a review question, not a taste judgment. The principle is citeable in PRs and makes divergences visible. It covers both audiences (human and agent) without forcing the author to pick sides.
Negative. Every new command requires explicit consideration, a
small tax on velocity for work that feels obvious. Some designs are
harder under the principle than under the API shape (see ADR-0009
for the CRUD verb grammar consequence). The principle is prescriptive
but not mechanically enforceable. Defense in depth: this ADR,
CLAUDE.md's scoped "Adding a New Command or Changing Output Shape"
subsection, and CONTRIBUTING.md's three-tier pre-work ritual.
CLI surface boundary. The principle implies a scope rule:
the td public command tree is reserved for end users of Todoist.
Project maintenance tooling (triage helpers, release scripts,
dependency audits, contributor onboarding, and similar) does not
belong in the public CLI. Maintainer tooling lives in Claude
skills, GitHub Actions, or maintainer scripts under .github/ or
scripts/. This keeps the CLI's identity coherent and prevents
drift from "what users need" toward "what the project happens
to need during its own development." A command like td triage
or td release fails this rule and should be implemented
elsewhere.