# Basecamp Assistant

> Basecamp 4 assistant with a complete Python API client. Fulfill user requests by writing and executing Python code against BasecampClient. Use when users want to interact with Basecamp: managing projects, to-dos, messages, documents, schedules, card tables (Kanban), campfire chat, people, webhooks, templates, or any other Basecamp 4 feature. Triggers on: any mention of Basecamp, project management tasks referencing Basecamp data, or requests to read/write/update Basecamp resources.

- Skill: `nikhilbhansali/basecamp-assistant` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add nikhilbhansali/basecamp-assistant`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nikhilbhansali/basecamp-assistant/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: nikhilbhansali (https://skillmd.com/u/nikhilbhansali)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nikhilbhansali/basecamp-assistant

---


# Basecamp 4 Assistant

Fulfill Basecamp requests by writing and executing Python code against `BasecampClient`.

## Workflow

1. Locate config and client files
2. Initialize the client
3. Resolve project/resource names to IDs
4. Execute the request
5. Print clear output summarizing what was done or found

## Step 1: Locate Files

Find `basecamp_config.json` — check in order:
1. `basecamp_config.json` (cwd)
2. `basecamp_docs/basecamp_config.json`
3. Ask the user

Find `basecamp_client.py` — check in order:
1. Same directory as config
2. `basecamp_client.py` (cwd)
3. `basecamp_docs/basecamp_client.py`
4. Ask the user

## Step 2: Initialize

```python
import sys, os, json

config_path = "<resolved_config_path>"
client_dir  = os.path.dirname(os.path.abspath("<resolved_client_path>"))

if client_dir not in sys.path:
    sys.path.insert(0, client_dir)

from basecamp_client import create_client_from_config

bc = create_client_from_config(config_path)
```

## Step 3: Resolve Names to IDs

Users refer to projects by name. Always resolve:

```python
projects = bc.get_projects()
project = next((p for p in projects if p["name"].lower() == "some name".lower()), None)
if not project:
    # Try partial match
    project = next((p for p in projects if "some name".lower() in p["name"].lower()), None)
project_id = project["id"]
```

Most tools require a dock-resolved tool ID. Use cached helpers:

```python
todoset_id    = bc.get_todoset_id(project_id)
board_id      = bc.get_message_board_id(project_id)
vault_id      = bc.get_vault_id(project_id)
schedule_id   = bc.get_schedule_id(project_id)
chat_id       = bc.get_chat_id(project_id)
```

### Card tables (Kanban boards)

A project can have **multiple** card tables. Always list them all:

```python
boards = bc.get_card_table_ids(project_id)
# [{"id": 123, "title": "Sprint Board", ...}, ...]
```

If one board -> use `boards[0]["id"]`. If multiple -> match by title or show the user a list.

Finding a to-do list by name:

```python
todoset_id = bc.get_todoset_id(project_id)
lists = bc.get_todolists(project_id, todoset_id)
target = next(l for l in lists if l["name"].lower() == "list name".lower())
```

## Key Behaviors

- **Pagination**: All `get_*` list methods auto-paginate via Link headers. They return the complete list.
- **Rich text**: Message bodies, to-do descriptions, document content, and comments accept HTML (`<strong>`, `<em>`, `<a href>`, `<ul>/<li>`, `<br>`).
- **Token refresh**: The client auto-refreshes expired tokens on HTTP 401 and persists to config.
- **Rate limits**: The client auto-retries on HTTP 429 with Retry-After.
- **update_todo WARNING**: Omitting an optional param CLEARs its value. Always pass all fields you want to keep.
- **Multiple card tables**: Always use `bc.get_card_table_ids(project_id)` to discover all boards.
- **Error handling**: Never swallow errors. If an API call raises an exception, let it propagate and show the user the full error (HTTP status, message, traceback). Do not catch exceptions just to print a friendly message — the user needs the real error to diagnose issues. Only catch exceptions when you need to branch on the result (e.g., checking if a resource exists before creating it).

## Status & Completion

### To-do status vs completion

To-dos have **two independent axes** — don't confuse them:

- **`status`** param = recording lifecycle: `active` (default) / `archived` / `trashed`
- **`completed`** param = whether the task is done: `None` (default = incomplete only) / `True` / `False`

| User wants | Call |
|---|---|
| Pending to-dos | `bc.get_todos(pid, lid)` (default — active + incomplete) |
| Completed to-dos | `bc.get_todos(pid, lid, completed=True)` |
| All to-dos regardless | Fetch twice: default + `completed=True`, combine results |

**Important**: when the user says "show me my to-dos" or "what's on my list", the default (incomplete only) is correct. Only fetch completed to-dos when the user explicitly asks for them (e.g. "show completed", "what did I finish").

Each to-do dict has:
- `completed` (bool) — whether it's done
- `completion` (object) — who completed it and when (null if not completed)

### Card status (Kanban)

Cards have **NO `completed` boolean**. A card's status is determined by the **column type** it sits in:

| Column `type` | Meaning |
|---|---|
| `Kanban::Triage` | Intake / unsorted |
| `Kanban::Column` | In-progress (normal column) |
| `Kanban::NotNowColumn` | Parked / deferred |
| `Kanban::DoneColumn` | Done |

To check if a card is done, check the column it's in:

```python
table = bc.get_card_table(project_id, card_table_id)
for col in table["lists"]:
    is_done = col["type"] == "Kanban::DoneColumn"
    cards = bc.get_cards(project_id, col["id"])
    for card in cards:
        print(f"{card['title']} — {'done' if is_done else col['title']}")
```

When listing "active" or "pending" cards, skip columns where `type == "Kanban::DoneColumn"`. When listing "completed" cards, only show cards from `DoneColumn`.

## API Reference

For the complete method listing with signatures, see [references/api_reference.md](references/api_reference.md).

Key categories: Projects, To-dos (sets/lists/groups/items), Messages (boards/types/comments), Documents & Vaults, Uploads & Attachments, Schedules & Entries, Campfires & Chatbots, Card Tables (columns/cards/steps), People & Access, Questionnaires & Answers, Question Reminders, Recordings, Search, Reports, Timeline, Boosts, Timesheets, Subscriptions, Events, Webhooks, Templates, Tools (Dock Management), Client Features, Inboxes, Lineup Markers.

