Skip to content
Merged
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
26 changes: 26 additions & 0 deletions .surface
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,7 @@ CMD basecamp msgs trash
CMD basecamp msgs unpin
CMD basecamp msgs update
CMD basecamp notifications
CMD basecamp notifications bubbleups
CMD basecamp notifications list
CMD basecamp notifications read
CMD basecamp people
Expand Down Expand Up @@ -10395,6 +10396,28 @@ FLAG basecamp notifications --stats type=bool
FLAG basecamp notifications --styled type=bool
FLAG basecamp notifications --todolist type=string
FLAG basecamp notifications --verbose type=count
FLAG basecamp notifications bubbleups --account type=string
FLAG basecamp notifications bubbleups --agent type=bool
FLAG basecamp notifications bubbleups --cache-dir type=string
FLAG basecamp notifications bubbleups --count type=bool
FLAG basecamp notifications bubbleups --help type=bool
FLAG basecamp notifications bubbleups --hints type=bool
FLAG basecamp notifications bubbleups --ids-only type=bool
FLAG basecamp notifications bubbleups --in type=string
FLAG basecamp notifications bubbleups --jq type=string
FLAG basecamp notifications bubbleups --json type=bool
FLAG basecamp notifications bubbleups --markdown type=bool
FLAG basecamp notifications bubbleups --md type=bool
FLAG basecamp notifications bubbleups --no-hints type=bool
FLAG basecamp notifications bubbleups --no-stats type=bool
FLAG basecamp notifications bubbleups --page type=int32
FLAG basecamp notifications bubbleups --profile type=string
FLAG basecamp notifications bubbleups --project type=string
FLAG basecamp notifications bubbleups --quiet type=bool
FLAG basecamp notifications bubbleups --stats type=bool
FLAG basecamp notifications bubbleups --styled type=bool
FLAG basecamp notifications bubbleups --todolist type=string
FLAG basecamp notifications bubbleups --verbose type=count
FLAG basecamp notifications list --account type=string
FLAG basecamp notifications list --agent type=bool
FLAG basecamp notifications list --cache-dir type=string
Expand All @@ -10405,6 +10428,7 @@ FLAG basecamp notifications list --ids-only type=bool
FLAG basecamp notifications list --in type=string
FLAG basecamp notifications list --jq type=string
FLAG basecamp notifications list --json type=bool
FLAG basecamp notifications list --limit-bubble-ups type=bool
FLAG basecamp notifications list --markdown type=bool
FLAG basecamp notifications list --md type=bool
FLAG basecamp notifications list --no-hints type=bool
Expand Down Expand Up @@ -13935,6 +13959,7 @@ FLAG basecamp tools create --styled type=bool
FLAG basecamp tools create --todolist type=string
FLAG basecamp tools create --type type=string
FLAG basecamp tools create --verbose type=count
FLAG basecamp tools create --visible-to-clients type=bool
FLAG basecamp tools delete --account type=string
FLAG basecamp tools delete --agent type=bool
FLAG basecamp tools delete --cache-dir type=string
Expand Down Expand Up @@ -16812,6 +16837,7 @@ SUB basecamp msgs trash
SUB basecamp msgs unpin
SUB basecamp msgs update
SUB basecamp notifications
SUB basecamp notifications bubbleups
SUB basecamp notifications list
SUB basecamp notifications read
SUB basecamp people
Expand Down
13 changes: 7 additions & 6 deletions API-COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ Coverage of Basecamp 3 API endpoints. Source: [bc3-api/sections](https://github.

| Status | Sections | Endpoints |
|--------|----------|-----------|
| ✅ Implemented | 44 | 166 |
| ✅ Implemented | 45 | 167 |
| ⏭️ Out of scope | 4 | 12 |
| **Total tracked** | **48** | **178** |
| **Total tracked** | **49** | **179** |

**100% coverage of tracked in-scope API** (166/166 endpoints). This is not a
**100% coverage of tracked in-scope API** (167/167 endpoints). This is not a
complete bc-api parity figure; the other five BC5 sections introduced by
bc-api#410 remain untracked and outside this coverage matrix.

Out-of-scope sections are excluded from parity totals and scripts: chatbots (different auth), legacy Clientside (deprecated)

> Note: the per-row `Endpoints` column in the Coverage by Section table sums higher than the Summary totals above. The discrepancy predates the BC5 baseline; the row count (48 sections) is authoritative for the `Since` column. Reconciling endpoint counts is pre-existing maintenance, tracked separately.

**SDK version:** v0.8.1-0.20260725044648-3d4ec395922cadds the `Wormholes` service (`Create`/`Update`/`Delete`) and decodes `CardTable.Wormholes` (`card_table_wormholes`, basecamp/basecamp-sdk#397), consumed by `cards wormholes` and `cards move --to-wormhole`; also carries `Todolists.Reposition` (`PUT /todosets/todolists/{id}/position.json`, basecamp/basecamp-sdk#398) behind `todolists position`, create-time `visible_to_clients` support behind `todolists create --visible-to-clients`, `Campfires.UpdateLine` (`PUT /chats/{c}/lines/{l}`, basecamp/basecamp-sdk#295) behind `chat update`, and the BC5 `Tools.Create` create-by-type reshape. API date 2026-07-24.
**SDK version:** v0.9.1-0.20260727173625-bb363c847b92reshapes `MessageTypes` to the bucket-scoped categories API (`/buckets/{id}/categories…`, basecamp/basecamp-sdk#393), consumed by the now project-scoped `messagetypes` commands; adds the Bubble Ups successor surface (`MyNotifications.BubbleUps` via `GET /my/readings/bubble_ups.json` + `GetWithOptions`/`WithLimitBubbleUps`, basecamp/basecamp-sdk#426) behind `notifications bubbleups` and `notifications list --limit-bubble-ups`; adds create-time `visible_to_clients` on `Tools.Create` (basecamp/basecamp-sdk#419) behind `tools create --visible-to-clients`; and carries model-only Door fields on Recording (basecamp/basecamp-sdk#431) and activity-timeline event fields (basecamp/basecamp-sdk#424) that flow through `--json`. API date 2026-07-26.

## Coverage by Section

Expand All @@ -32,18 +32,19 @@ The **Since** column tags each row with the Basecamp version that introduced its
| 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 |
| dock_tools | 7 | `tools` | ✅ | BC4 | - | Dock tool management: show, update, trash, enable, disable, reposition. `create` is BC5-only (create-by-type: `POST /buckets/{id}/dock/tools.json`), replacing the removed clone call |
| dock_tools | 7 | `tools` | ✅ | BC4 | - | Dock tool management: show, update, trash, enable, disable, reposition. `create` is BC5-only (create-by-type: `POST /buckets/{id}/dock/tools.json`), replacing the removed clone call; create-time `visible_to_clients` behind `tools create --visible-to-clients` (chat/kanban only) |
| **Hill Charts** |
| hill_charts | 2 | `hillcharts` | ✅ | BC4 | - | show, track/untrack todolists |
| gauges | 7 | `gauges` | ✅ | BC4 | - | list, needles, needle, create, update, delete, enable/disable |
| **Communication** |
| messages | 10 | `messages`, `message` | ✅ | BC4 | - | list, show, create, update, publish, pin, unpin. Create supports `--subscribe`/`--no-subscribe` and `--draft`. Publish promotes drafts to active |
| message_boards | 3 | `messageboards` | ✅ | BC4 | - | Container, accessed via project dock |
| message_types | 5 | `messagetypes` | ✅ | BC4 | - | list, show, create, update, delete |
| message_types | 5 | `messagetypes` | ✅ | BC4 | - | list, show, create, update, delete. Bucket-scoped (`/buckets/{id}/categories…`); commands are project-scoped via `--in`/`--project` |
| campfires | 14 | `chat` | ✅ | BC4 | - | list, messages, post, line show/update/delete. @mentions in content |
| comments | 8 | `comment`, `comments` | ✅ | BC4 | - | list, show, create, update. @mentions in content |
| boosts | 6 | `boost`, `react` | ✅ | BC4 | - | list (recording + event), show, create (recording + event), delete |
| notifications | 2 | `notifications` | ✅ | BC4 | - | list, mark as read (BC5: `bubble_ups`/`scheduled_bubble_ups` sections; `memories` is BC4-only) |
| bubble_ups | 1 | `notifications bubbleups` | ✅ | BC5 | - | Dedicated Bubble Ups list (`GET /my/readings/bubble_ups.json`, paginated) plus the `limit_bubble_ups` variant behind `notifications list --limit-bubble-ups` |
| **Cards (Kanban)** |
| card_tables | 3 | `cards` | ✅ | BC4 | - | Accessed via project dock |
| card_table_cards | 9 | `cards` | ✅ | BC4 | - | list, show, create, update, move |
Expand Down
24 changes: 24 additions & 0 deletions e2e/messagetypes.bats
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@ load test_helper
}


# Missing project errors

@test "messagetypes list without project shows error" {
create_credentials
create_global_config '{"account_id": 99999}'

run basecamp messagetypes list
assert_failure
assert_output_contains "project"
}


# Flag parsing errors

@test "messagetypes --project without value shows error" {
create_credentials
create_global_config '{}'

run basecamp messagetypes list --project
assert_failure
assert_output_contains "--project requires a value"
}


# Missing context errors

@test "messagetypes show without id shows error" {
Expand Down
5 changes: 4 additions & 1 deletion e2e/smoke/.qa-allowlist
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Format: <test name> # <reason> — <owner>

# Message types — account-wide feature, no create command in scope
# Message types — per-project categories, no create command in scope
test_messagetypes_list_returns_message_types # not_found on some servers — smoke
test_messagetypes_show_returns_message_type_detail # depends on messagetypes list — smoke

Expand Down Expand Up @@ -39,3 +39,6 @@ test_cards_wormholes_create_needs_a_destination_table_on_another_board # no seco
test_cards_wormholes_update_needs_an_existing_wormhole_and_destination # depends on wormhole create — smoke
test_cards_wormholes_delete_needs_an_existing_wormhole # depends on wormhole create — smoke
test_cards_move_to_wormhole_needs_a_linked_wormhole_and_is_destructive # needs linked wormhole + destructive async — smoke

# Bubble Ups — BC5-added endpoint, may not exist on all QA environments
test_notifications_bubbleups_lists_bubble_ups # endpoint not available on some servers — smoke
6 changes: 3 additions & 3 deletions e2e/smoke/smoke_communication.bats
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ setup_file() {
ensure_project || return 1
}

# --- Message types (account-wide) ---
# --- Message types (per-project) ---

@test "messagetypes list returns message types" {
run_smoke basecamp messagetypes list --json
run_smoke basecamp messagetypes list -p "$QA_PROJECT" --json
# Message types may not exist on all environments
[[ "$status" -ne 0 ]] && mark_unverifiable "Message types not available"
assert_json_value '.ok' 'true'
Expand All @@ -27,7 +27,7 @@ setup_file() {
mt_id=$(<"$id_file")
[[ -n "$mt_id" ]] || mark_unverifiable "Messagetype ID is empty"

run_smoke basecamp messagetypes show "$mt_id" --json
run_smoke basecamp messagetypes show "$mt_id" -p "$QA_PROJECT" --json
assert_success
assert_json_value '.ok' 'true'
assert_json_not_null '.data.id'
Expand Down
7 changes: 7 additions & 0 deletions e2e/smoke/smoke_notifications.bats
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ setup_file() {
assert_failure
assert_output_contains "not found"
}

@test "notifications bubbleups lists bubble ups" {
run_smoke basecamp notifications bubbleups --json
# Bubble Ups are a BC5-added endpoint; may not exist on all QA environments
[[ "$status" -ne 0 ]] && mark_unverifiable "Bubble Ups endpoint not available"
assert_json_value '.ok' 'true'
}
11 changes: 11 additions & 0 deletions e2e/tools.bats
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,14 @@ load test_helper
assert_success
assert_output_contains "basecamp tools <command>"
}

# Create validation

@test "tools create --visible-to-clients without --type shows usage error" {
create_credentials
create_global_config '{"account_id": 99999}'

run basecamp tools create --visible-to-clients
assert_failure
assert_output_contains "--type is required"
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
charm.land/bubbles/v2 v2.1.1
charm.land/bubbletea/v2 v2.0.8
charm.land/lipgloss/v2 v2.0.5
github.com/basecamp/basecamp-sdk/go v0.8.1-0.20260725044648-3d4ec395922c
github.com/basecamp/basecamp-sdk/go v0.9.1-0.20260727173625-bb363c847b92
github.com/basecamp/cli v0.2.1
github.com/charmbracelet/bubbles v1.0.0
github.com/charmbracelet/glamour v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ
github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/basecamp/basecamp-sdk/go v0.8.1-0.20260725044648-3d4ec395922c h1:fZX/ctMBCzahWf5NEO+//W0/xeyHp2Yljyvr06xAprE=
github.com/basecamp/basecamp-sdk/go v0.8.1-0.20260725044648-3d4ec395922c/go.mod h1:SvHmG8I8jnB/3p8+Kqxs5NLPpvWssh8KUvr39bzRsl0=
github.com/basecamp/basecamp-sdk/go v0.9.1-0.20260727173625-bb363c847b92 h1:4gQJTR8e5kBvXHDHLvef+Q00XY7KzWTxnQSLWMSPcyA=
github.com/basecamp/basecamp-sdk/go v0.9.1-0.20260727173625-bb363c847b92/go.mod h1:r83ralDQ0q9vbAby5qQ5x9hgCgUdJLDLHYpiU6jaFjE=
github.com/basecamp/cli v0.2.1 h1:8GyehPVtsTXla0oOPu4QgXRjwwzJ99prlByvyi+0HRQ=
github.com/basecamp/cli v0.2.1/go.mod h1:p8tt/DatJ2LAzWO6N6tNfV8x3gF5T3IxDTo+U8FfWPo=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func CommandCategories() []CommandCategory {
{Name: "attachments", Category: "communication", Description: "List and download attachments", Actions: []string{"list", "download"}},
{Name: "comments", Category: "communication", Description: "Manage comments", Actions: []string{"create", "list", "show", "update", "trash", "archive", "restore"}},
{Name: "boost", Category: "communication", Description: "Manage boosts (reactions)", Actions: []string{"list", "show", "create", "delete"}},
{Name: "notifications", Category: "communication", Description: "View and manage notifications", Actions: []string{"list", "read"}},
{Name: "notifications", Category: "communication", Description: "View and manage notifications", Actions: []string{"list", "read", "bubbleups"}},
},
},
{
Expand Down
Loading
Loading