Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions .surface
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,16 @@ ARG basecamp subscriptions remove 01 [person_ids]
ARG basecamp subscriptions show 00 <id|url>
ARG basecamp subscriptions subscribe 00 <id|url>
ARG basecamp subscriptions unsubscribe 00 <id|url>
ARG basecamp subtasks complete 00 <id|url>
ARG basecamp subtasks create 00 <todo-or-card-id|url>
ARG basecamp subtasks create 01 <title>
ARG basecamp subtasks delete 00 <id|url>
ARG basecamp subtasks list 00 <todo-or-card-id|url>
ARG basecamp subtasks move 00 <id|url>
ARG basecamp subtasks show 00 <id|url>
ARG basecamp subtasks uncomplete 00 <id|url>
ARG basecamp subtasks update 00 <id|url>
ARG basecamp subtasks update 01 [title]
ARG basecamp templates construct 00 <template_id>
ARG basecamp templates construction 00 <template_id>
ARG basecamp templates construction 01 <construction_id>
Expand Down Expand Up @@ -1024,6 +1034,15 @@ CMD basecamp subscriptions remove
CMD basecamp subscriptions show
CMD basecamp subscriptions subscribe
CMD basecamp subscriptions unsubscribe
CMD basecamp subtasks
CMD basecamp subtasks complete
CMD basecamp subtasks create
CMD basecamp subtasks delete
CMD basecamp subtasks list
CMD basecamp subtasks move
CMD basecamp subtasks show
CMD basecamp subtasks uncomplete
CMD basecamp subtasks update
CMD basecamp templates
CMD basecamp templates construct
CMD basecamp templates construction
Expand Down Expand Up @@ -13919,6 +13938,208 @@ FLAG basecamp subscriptions unsubscribe --stats type=bool
FLAG basecamp subscriptions unsubscribe --styled type=bool
FLAG basecamp subscriptions unsubscribe --todolist type=string
FLAG basecamp subscriptions unsubscribe --verbose type=count
FLAG basecamp subtasks --account type=string
FLAG basecamp subtasks --agent type=bool
FLAG basecamp subtasks --cache-dir type=string
FLAG basecamp subtasks --count type=bool
FLAG basecamp subtasks --help type=bool
FLAG basecamp subtasks --hints type=bool
FLAG basecamp subtasks --ids-only type=bool
FLAG basecamp subtasks --in type=string
FLAG basecamp subtasks --jq type=string
FLAG basecamp subtasks --json type=bool
FLAG basecamp subtasks --markdown type=bool
FLAG basecamp subtasks --md type=bool
FLAG basecamp subtasks --no-hints type=bool
FLAG basecamp subtasks --no-stats type=bool
FLAG basecamp subtasks --profile type=string
FLAG basecamp subtasks --project type=string
FLAG basecamp subtasks --quiet type=bool
FLAG basecamp subtasks --stats type=bool
FLAG basecamp subtasks --styled type=bool
FLAG basecamp subtasks --todolist type=string
FLAG basecamp subtasks --verbose type=count
FLAG basecamp subtasks complete --account type=string
FLAG basecamp subtasks complete --agent type=bool
FLAG basecamp subtasks complete --cache-dir type=string
FLAG basecamp subtasks complete --count type=bool
FLAG basecamp subtasks complete --help type=bool
FLAG basecamp subtasks complete --hints type=bool
FLAG basecamp subtasks complete --ids-only type=bool
FLAG basecamp subtasks complete --in type=string
FLAG basecamp subtasks complete --jq type=string
FLAG basecamp subtasks complete --json type=bool
FLAG basecamp subtasks complete --markdown type=bool
FLAG basecamp subtasks complete --md type=bool
FLAG basecamp subtasks complete --no-hints type=bool
FLAG basecamp subtasks complete --no-stats type=bool
FLAG basecamp subtasks complete --profile type=string
FLAG basecamp subtasks complete --project type=string
FLAG basecamp subtasks complete --quiet type=bool
FLAG basecamp subtasks complete --stats type=bool
FLAG basecamp subtasks complete --styled type=bool
FLAG basecamp subtasks complete --todolist type=string
FLAG basecamp subtasks complete --verbose type=count
FLAG basecamp subtasks create --account type=string
FLAG basecamp subtasks create --agent type=bool
FLAG basecamp subtasks create --assignees type=string
FLAG basecamp subtasks create --cache-dir type=string
FLAG basecamp subtasks create --count type=bool
FLAG basecamp subtasks create --due type=string
FLAG basecamp subtasks create --help type=bool
FLAG basecamp subtasks create --hints type=bool
FLAG basecamp subtasks create --ids-only type=bool
FLAG basecamp subtasks create --in type=string
FLAG basecamp subtasks create --jq type=string
FLAG basecamp subtasks create --json type=bool
FLAG basecamp subtasks create --markdown type=bool
FLAG basecamp subtasks create --md type=bool
FLAG basecamp subtasks create --no-hints type=bool
FLAG basecamp subtasks create --no-stats type=bool
FLAG basecamp subtasks create --profile type=string
FLAG basecamp subtasks create --project type=string
FLAG basecamp subtasks create --quiet type=bool
FLAG basecamp subtasks create --stats type=bool
FLAG basecamp subtasks create --styled type=bool
FLAG basecamp subtasks create --todolist type=string
FLAG basecamp subtasks create --verbose type=count
FLAG basecamp subtasks delete --account type=string
FLAG basecamp subtasks delete --agent type=bool
FLAG basecamp subtasks delete --cache-dir type=string
FLAG basecamp subtasks delete --count type=bool
FLAG basecamp subtasks delete --force type=bool
FLAG basecamp subtasks delete --help type=bool
FLAG basecamp subtasks delete --hints type=bool
FLAG basecamp subtasks delete --ids-only type=bool
FLAG basecamp subtasks delete --in type=string
FLAG basecamp subtasks delete --jq type=string
FLAG basecamp subtasks delete --json type=bool
FLAG basecamp subtasks delete --markdown type=bool
FLAG basecamp subtasks delete --md type=bool
FLAG basecamp subtasks delete --no-hints type=bool
FLAG basecamp subtasks delete --no-stats type=bool
FLAG basecamp subtasks delete --profile type=string
FLAG basecamp subtasks delete --project type=string
FLAG basecamp subtasks delete --quiet type=bool
FLAG basecamp subtasks delete --stats type=bool
FLAG basecamp subtasks delete --styled type=bool
FLAG basecamp subtasks delete --todolist type=string
FLAG basecamp subtasks delete --verbose type=count
FLAG basecamp subtasks list --account type=string
FLAG basecamp subtasks list --agent type=bool
FLAG basecamp subtasks list --all type=bool
FLAG basecamp subtasks list --cache-dir type=string
FLAG basecamp subtasks list --count type=bool
FLAG basecamp subtasks list --help type=bool
FLAG basecamp subtasks list --hints type=bool
FLAG basecamp subtasks list --ids-only type=bool
FLAG basecamp subtasks list --in type=string
FLAG basecamp subtasks list --jq type=string
FLAG basecamp subtasks list --json type=bool
FLAG basecamp subtasks list --limit type=int
FLAG basecamp subtasks list --markdown type=bool
FLAG basecamp subtasks list --md type=bool
FLAG basecamp subtasks list --no-hints type=bool
FLAG basecamp subtasks list --no-stats type=bool
FLAG basecamp subtasks list --page type=int
FLAG basecamp subtasks list --profile type=string
FLAG basecamp subtasks list --project type=string
FLAG basecamp subtasks list --quiet type=bool
FLAG basecamp subtasks list --stats type=bool
FLAG basecamp subtasks list --styled type=bool
FLAG basecamp subtasks list --todolist type=string
FLAG basecamp subtasks list --verbose type=count
FLAG basecamp subtasks move --account type=string
FLAG basecamp subtasks move --agent type=bool
FLAG basecamp subtasks move --cache-dir type=string
FLAG basecamp subtasks move --count type=bool
FLAG basecamp subtasks move --help type=bool
FLAG basecamp subtasks move --hints type=bool
FLAG basecamp subtasks move --ids-only type=bool
FLAG basecamp subtasks move --in type=string
FLAG basecamp subtasks move --jq type=string
FLAG basecamp subtasks move --json type=bool
FLAG basecamp subtasks move --markdown type=bool
FLAG basecamp subtasks move --md type=bool
FLAG basecamp subtasks move --no-hints type=bool
FLAG basecamp subtasks move --no-stats type=bool
FLAG basecamp subtasks move --pos type=int
FLAG basecamp subtasks move --position type=int
FLAG basecamp subtasks move --profile type=string
FLAG basecamp subtasks move --project type=string
FLAG basecamp subtasks move --quiet type=bool
FLAG basecamp subtasks move --stats type=bool
FLAG basecamp subtasks move --styled type=bool
FLAG basecamp subtasks move --todolist type=string
FLAG basecamp subtasks move --verbose type=count
FLAG basecamp subtasks show --account type=string
FLAG basecamp subtasks show --agent type=bool
FLAG basecamp subtasks show --cache-dir type=string
FLAG basecamp subtasks show --count type=bool
FLAG basecamp subtasks show --help type=bool
FLAG basecamp subtasks show --hints type=bool
FLAG basecamp subtasks show --ids-only type=bool
FLAG basecamp subtasks show --in type=string
FLAG basecamp subtasks show --jq type=string
FLAG basecamp subtasks show --json type=bool
FLAG basecamp subtasks show --markdown type=bool
FLAG basecamp subtasks show --md type=bool
FLAG basecamp subtasks show --no-hints type=bool
FLAG basecamp subtasks show --no-stats type=bool
FLAG basecamp subtasks show --profile type=string
FLAG basecamp subtasks show --project type=string
FLAG basecamp subtasks show --quiet type=bool
FLAG basecamp subtasks show --stats type=bool
FLAG basecamp subtasks show --styled type=bool
FLAG basecamp subtasks show --todolist type=string
FLAG basecamp subtasks show --verbose type=count
FLAG basecamp subtasks uncomplete --account type=string
FLAG basecamp subtasks uncomplete --agent type=bool
FLAG basecamp subtasks uncomplete --cache-dir type=string
FLAG basecamp subtasks uncomplete --count type=bool
FLAG basecamp subtasks uncomplete --help type=bool
FLAG basecamp subtasks uncomplete --hints type=bool
FLAG basecamp subtasks uncomplete --ids-only type=bool
FLAG basecamp subtasks uncomplete --in type=string
FLAG basecamp subtasks uncomplete --jq type=string
FLAG basecamp subtasks uncomplete --json type=bool
FLAG basecamp subtasks uncomplete --markdown type=bool
FLAG basecamp subtasks uncomplete --md type=bool
FLAG basecamp subtasks uncomplete --no-hints type=bool
FLAG basecamp subtasks uncomplete --no-stats type=bool
FLAG basecamp subtasks uncomplete --profile type=string
FLAG basecamp subtasks uncomplete --project type=string
FLAG basecamp subtasks uncomplete --quiet type=bool
FLAG basecamp subtasks uncomplete --stats type=bool
FLAG basecamp subtasks uncomplete --styled type=bool
FLAG basecamp subtasks uncomplete --todolist type=string
FLAG basecamp subtasks uncomplete --verbose type=count
FLAG basecamp subtasks update --account type=string
FLAG basecamp subtasks update --agent type=bool
FLAG basecamp subtasks update --assignees type=string
FLAG basecamp subtasks update --cache-dir type=string
FLAG basecamp subtasks update --count type=bool
FLAG basecamp subtasks update --due type=string
FLAG basecamp subtasks update --help type=bool
FLAG basecamp subtasks update --hints type=bool
FLAG basecamp subtasks update --ids-only type=bool
FLAG basecamp subtasks update --in type=string
FLAG basecamp subtasks update --jq type=string
FLAG basecamp subtasks update --json type=bool
FLAG basecamp subtasks update --markdown type=bool
FLAG basecamp subtasks update --md type=bool
FLAG basecamp subtasks update --no-assignees type=bool
FLAG basecamp subtasks update --no-due type=bool
FLAG basecamp subtasks update --no-hints type=bool
FLAG basecamp subtasks update --no-stats type=bool
FLAG basecamp subtasks update --profile type=string
FLAG basecamp subtasks update --project type=string
FLAG basecamp subtasks update --quiet type=bool
FLAG basecamp subtasks update --stats type=bool
FLAG basecamp subtasks update --styled type=bool
FLAG basecamp subtasks update --title type=string
FLAG basecamp subtasks update --todolist type=string
FLAG basecamp subtasks update --verbose type=count
FLAG basecamp templates --account type=string
FLAG basecamp templates --agent type=bool
FLAG basecamp templates --cache-dir type=string
Expand Down Expand Up @@ -19206,6 +19427,15 @@ SUB basecamp subscriptions remove
SUB basecamp subscriptions show
SUB basecamp subscriptions subscribe
SUB basecamp subscriptions unsubscribe
SUB basecamp subtasks
SUB basecamp subtasks complete
SUB basecamp subtasks create
SUB basecamp subtasks delete
SUB basecamp subtasks list
SUB basecamp subtasks move
SUB basecamp subtasks show
SUB basecamp subtasks uncomplete
SUB basecamp subtasks update
SUB basecamp templates
SUB basecamp templates construct
SUB basecamp templates construction
Expand Down
18 changes: 12 additions & 6 deletions API-COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ Coverage of Basecamp 3 API endpoints. Source: [bc3-api/sections](https://github.

| Status | Sections | Endpoints |
|--------|----------|-----------|
| ✅ Implemented | 51 | 195 |
| ✅ Implemented | 52 | 203 |
| ⚠️ Blocked | 0 | 0 |
| ⏭️ Out of scope | 4 | 12 |
| **Total tracked** | **55** | **207** |
| **Total tracked** | **56** | **215** |

**195 of 195 tracked in-scope endpoints.** The client-admission endpoints
**203 of 203 tracked in-scope endpoints.** The eight subtask endpoints bc3
#12659 documented — the flat `/recordings/:id/subtasks.json` and
`/subtasks/:id` routes, modelled by basecamp/basecamp-sdk#883 — land as
`subtasks`. The client-admission endpoints
basecamp/bc3#13098 added — `PUT /projects/:id/people/client_users.json` and
`POST`/`DELETE /projects/:id/client_enablement.json` — land as `people clients`.
SDK v0.16.0 adds the three to-do
Expand Down Expand Up @@ -50,7 +53,9 @@ Out-of-scope sections are excluded from parity totals and scripts: chatbots (dif

**SDK version:** the pin in `go.mod`, with
`internal/version/sdk-provenance.json` authoritative for the exact commit. That
pin is basecamp-sdk v0.19.0, the release that ships the event-feed operations.
pin is basecamp-sdk `main` at 8216dd62c329 (a pseudo-version past v0.20.0), for the
Subtasks service basecamp/basecamp-sdk#883 adds ahead of a release — to be swapped
for the release that ships it. v0.19.0 shipped the event-feed operations.
The command surface below largely dates to the v0.12.0 bump, which added 20 exported
Go methods over 13 new backend operations; the extra seven wrapped endpoints
that already existed but were reachable only through the raw generated client,
Expand Down Expand Up @@ -187,7 +192,8 @@ cannot faithfully cover at least one endpoint for a reason outside the CLI. A
|---------|-----------|-------------|--------|-------|----------|-------|
| **Core** |
| projects | 9 | `projects` | ✅ | BC4 | - | list, show, create, update, delete |
| todos | 12 | `todos`, `todo`, `done`, `reopen` | ✅ | BC4 | - | list, show, create, update, complete, uncomplete, position (BC5: `steps` shown on `todos show`; edit via `cards step`). `todos create --loose` creates on the to-do set, outside any list |
| todos | 12 | `todos`, `todo`, `done`, `reopen` | ✅ | BC4 | - | list, show, create, update, complete, uncomplete, position (BC5: `steps` shown on `todos show`, plus `subtasks_count`/`subtasks_completed_count`/`subtasks_url`; edit via `subtasks`). `todos create --loose` creates on the to-do set, outside any list |
| subtasks | 8 | `subtasks` | ✅ | BC5 | - | list (`GET /recordings/:id/subtasks.json`, paginated), show, create (`POST` on the same list route), update (partial; `--no-due`/`--no-assignees` clear), complete/uncomplete (`POST`/`DELETE /subtasks/:id/completion.json`), move (`PUT /subtasks/:id/position.json`, 1-based), delete. Account-scoped flat routes (bc3#12659), so no `--in`. Parents are to-dos and cards only. Same `Kanban::Step` records as `card_table_steps` |
| todolists | 9 | `todolists` | ✅ | BC4 | - | list, show, create, update, position |
| todosets | 3 | `todosets` | ✅ | BC4 | - | Container for todolists, accessed via project dock (BC5: `todos_count`, `completed_loose_todos_count`, `todos_url`, `app_todos_url`) |
| todolist_groups | 8 | `todolistgroups` | ✅ | BC4 | - | list, show, create, update, position |
Expand All @@ -208,7 +214,7 @@ cannot faithfully cover at least one endpoint for a reason outside the CLI. A
| card_tables | 3 | `cards` | ✅ | BC4 | - | Accessed via project dock |
| card_table_cards | 9 | `cards` | ✅ | BC4 | - | list, show, create, update, move |
| card_table_columns | 11 | `cards columns` | ✅ | BC4 | - | list columns. SDK v0.12.0 added `Subscribe`/`Unsubscribe`; `cards column watch\|unwatch` already performs the same action through the generic recording-subscription endpoint and returns the resulting subscription details the specific endpoint does not, so the CLI keeps one spelling |
| card_table_steps | 4 | `cards steps` | ✅ | BC4 | - | Workflow steps on cards |
| card_table_steps | 4 | `cards steps` | ✅ | BC4 | - | Workflow steps on cards. The card-scoped aliases of `subtasks`, which bc3 keeps serving; `cards step move --position` is 1-based (the SDK refuses 0 since basecamp/basecamp-sdk#883) |
| card_table_wormholes | 3 | `cards wormholes` | ✅ | BC5 | - | list (via `wormholes[]` on card table), create, update, delete; `cards move --to-wormhole` teleports a card across projects (async, new id) |
| **Personal (My)** |
| my_bookmarks | 4 | `bookmarks` | ✅ | BC5 | - | list, check, add, remove. Private to the authenticated user; `add`/`remove` are idempotent, and `check` returns a bool reported in the payload rather than through the exit code. Bounded like the account-wide listings |
Expand Down
1 change: 1 addition & 0 deletions e2e/smoke/run_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ echo ""
echo "--- Level 1: Mutation tests (parallel, $jobs jobs) ---"
level1=(
"$SMOKE_DIR"/smoke_todos_write.bats
"$SMOKE_DIR"/smoke_subtasks.bats
"$SMOKE_DIR"/smoke_messages_write.bats
"$SMOKE_DIR"/smoke_files_write.bats
"$SMOKE_DIR"/smoke_cards_write.bats
Expand Down
Loading
Loading