Add --due to cards create
Fixes #876.
What
basecamp cards create takes -d, --due, with the same help text and parsing as cards update --due:
basecamp cards create "Launch review" --due "next friday" --in myproject
basecamp cards create "Daily card" -d 2026-07-04 --in myproject
The date goes into the create request (CreateCardRequest.DueOn), so the card is made with its date in one POST.
Parsing lives in one helper, parseDueDate in internal/commands/helpers.go: dateparse.Parse, then a YYYY-MM-DD check, and on failure the existing usage error Invalid due date: "<value>". cards create, cards update and todos update all call it. The last two had identical inline copies of this check, so their behavior is unchanged.
On cards create the date is checked with the other flag-only checks, before a - body drains stdin and before any request. A whitespace-only --due " " is rejected rather than creating a card with no date.
Why
Today a dated card takes two calls (cards create, then cards update <id> --due). If the second fails, the card is left without a date, which is what the scheduled job in #876 runs into. The API already accepts due_on on card create.
Testing
internal/commands/cards_test.go: the single create POST carriesdue_onfor--due 2026-07-04,-d 2026-07-04and--due tomorrow, and has nodue_onkey without the flag.not-a-dateand" "return a usage error with zero HTTP requests. Each test fails if the feature is removed, if the raw value is passed through unchecked, or if the check moves after the network calls.stdin_integration_test.go/stdin_ordering_test.go: a bad--dueis rejected before stdin is read;parseDueDateis registered as a pre-read check.- Ran the built binary against local bc3 (master
c329da98a81) and read each card back from the API:--due 2026-07-04storeddue_on: "2026-07-04",-d tomorrowstored tomorrow's date, and--due not-a-date/--due " "exited 1 with a usage error and created no card. -
bin/cipasses (includesmake check).
Summary by cubic
Adds -d, --due to basecamp cards create so a card is created with its date in one POST instead of two calls. Previously a dated card required cards create followed by cards update <id> --due; a failure in the second call left the card without a date, which is what #876 runs into.
The due date is parsed exactly like cards update --due: natural language or YYYY-MM-DD, with anything that doesn't resolve rejected as a usage error before any request is sent or stdin is read. The check moves into a shared parseDueDate helper used by cards create, cards update, and todos update; the latter two had identical inline copies, so their behavior is unchanged.