basecamp

Interact with Basecamp via the Basecamp CLI. Full API coverage: projects, todos, cards, messages, files, schedule, check-ins, timeline, recordings, templates, webhooks, subscriptions, lineup, and campfire. Use for ANY Basecamp question or action.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "basecamp" with this command: npx skills add basecamp/skills/basecamp-skills-basecamp

/basecamp - Basecamp Workflow Command

Full CLI coverage: 130 endpoints across todos, cards, messages, files, schedule, check-ins, timeline, recordings, templates, webhooks, subscriptions, lineup, and campfire.

Agent Invariants

MUST follow these rules:

  1. Choose the right output mode--json when you need to parse data; --md when presenting results to a human (see Output Modes below)
  2. Parse URLs first with basecamp url parse "<url>" to extract IDs
  3. Comments are flat - reply to parent recording, not to comments
  4. Check context via .basecamp/config.json before assuming project
  5. Content fields accept Markdown — message body and comment content accept Markdown syntax; the CLI converts to HTML automatically. Use Markdown formatting (lists, bold, links, code blocks) for rich content. For todos, documents, and cards, content is sent as-is — use plain text or HTML directly.
  6. Project scope is mandatory for most commands — via --in <project> or .basecamp/config.json. Cross-project exceptions: basecamp reports assigned for assigned work, basecamp reports overdue for overdue todos, basecamp recordings <type> for browsing by type.

Output Modes

Choosing a mode:

GoalFlagFormat
Parse data, pipe to jq--jsonJSON envelope: {ok, data, summary, breadcrumbs, meta}
Show results to a user--md / -mGFM tables, task lists, structured Markdown
Automation / scripting--agentSuccess: raw JSON data (no envelope); errors: {ok:false,...} object; no interactive prompts

Always pass --json or --md explicitly — auto-detection depends on config and may not produce the format you expect. Use --md when composing reports, summarizing data, or displaying results inline. --agent is for headless integration scripts.

Other modes: --quiet (success: raw JSON, no envelope; errors: {ok:false,...}), --ids-only, --count, --stats (session statistics), --styled (force ANSI), -v / -vv (verbose/trace).

CLI Introspection

Navigate unfamiliar commands with --agent --help — returns structured JSON describing any command:

basecamp todos --agent --help
{"command":"todos","path":"basecamp todos","short":"...","long":"...","usage":"...","notes":["..."],
 "subcommands":[{"name":"sweep","short":"...","path":"basecamp todos sweep"}],
 "flags":[{"name":"assignee","type":"string","default":"","usage":"..."}],
 "inherited_flags":[{"name":"json","shorthand":"j","type":"bool","default":"false","usage":"..."}]}

Walk the tree: start at basecamp --agent --help for top-level commands, then drill into any subcommand. Commands include notes with domain-specific agent hints (e.g., "Cards do NOT support --assignee filtering").

Pagination

basecamp <cmd> --limit 50   # Cap results (default varies by resource)
basecamp <cmd> --all        # Fetch all (may be slow for large datasets)
basecamp <cmd> --page 1     # First page only, no auto-pagination

--all and --limit are mutually exclusive. --page cannot combine with either.

Smart Defaults

  • --assignee me resolves to current user
  • --due tomorrow / --due +3 / --due "next week" - natural date parsing
  • Project from .basecamp/config.json if --in not specified

Quick Reference

Note: Most queries require project scope (via --in <project> or .basecamp/config.json). Cross-project exceptions: basecamp reports assigned, basecamp reports overdue, basecamp recordings <type>.

TaskCommand
List projectsbasecamp projects list --json
My todos (in project)basecamp todos list --assignee me --in <project> --json
My todos (cross-project)basecamp reports assigned --json (defaults to "me")
All todos (cross-project)basecamp recordings todos --json (no assignee data — cannot filter by person)
Overdue todos (in project)basecamp todos list --overdue --in <project> --json
Overdue todos (cross-project)basecamp reports overdue --json
Assign todobasecamp assign <id> --to <person> --in <project> --json
Create todobasecamp todo "Task" --in <project> --list <list> --json
Create todolistbasecamp todolists create "Name" --in <project> --json
Complete todobasecamp done <id> --json
List cardsbasecamp cards list --in <project> --json
Create cardbasecamp card "Title" --in <project> --json
Move cardbasecamp cards move <id> --to <column> --in <project> --json
Post messagebasecamp message "Title" "Body" --in <project> --json
Post silentlybasecamp message "Title" "Body" --no-subscribe --in <project> --json
Post to campfirebasecamp campfire post "Message" --in <project> --json
Add commentbasecamp comment <recording_id> "Text" --in <project> --json
Searchbasecamp search "query" --json
Parse URLbasecamp url parse "<url>" --json
Download filebasecamp files download <id> --in <project>
Watch timelinebasecamp timeline --watch

URL Parsing

Always parse URLs before acting on them:

basecamp url parse "https://3.basecamp.com/2914079/buckets/41746046/messages/9478142982#__recording_9488783598" --json

Returns: account_id, project_id, type, recording_id, comment_id (from fragment).

URL patterns:

  • /buckets/27/messages/123 - Message 123 in project 27
  • /buckets/27/messages/123#__recording_456 - Comment 456 on message 123
  • /buckets/27/card_tables/cards/789 - Card 789
  • /buckets/27/card_tables/columns/456 - Column 456 (for creating cards)
  • /buckets/27/todos/101 - Todo 101
  • /buckets/27/uploads/202 - Upload/file 202
  • /buckets/27/documents/303 - Document 303
  • /buckets/27/schedule_entries/404 - Schedule entry 404

Replying to comments:

# Comments are flat - reply to the parent recording_id, not the comment_id
basecamp url parse "https://...messages/123#__recording_456" --json
# Returns recording_id: 123 (parent), comment_id: 456 (fragment) - comment on 123, not 456
basecamp comment 123 "Reply" --in <project>

Decision Trees

Finding Content

Need to find something?
├── Know the type + project? → basecamp <type> list --in <project> --json
│   (some groups have default list behavior; use --agent --help if unsure)
├── My assigned work? → basecamp reports assigned --json (defaults to "me")
├── Overdue across projects? → basecamp reports overdue --json
├── Browse by type cross-project? → basecamp recordings <type> --json
│   (types: todos, messages, documents, comments, cards, uploads)
│   Note: Defaults to active status; use --status archived for archived items
│   ⚠ No assignee data — cannot filter by person; use reports assigned instead
├── Full-text search? → basecamp search "query" --json
└── Have a URL? → basecamp url parse "<url>" --json

Modifying Content

Want to change something?
├── Have URL? → basecamp url parse "<url>" → use extracted IDs
├── Have ID? → basecamp <resource> update <id> --field value
├── Change status? → basecamp recordings trash|archive|restore <id>
└── Complete todo? → basecamp done <id>

Common Workflows

Link Code to Basecamp Todo

# Get commit info and comment on todo (use printf %q for safe quoting)
COMMIT=$(git rev-parse --short HEAD)
MSG=$(git log -1 --format=%s)
basecamp comment <todo_id> "Commit $COMMIT: $(printf '%s' "$MSG")" --in <project>

# Complete when done
basecamp done <todo_id>

Track PR in Basecamp

# Create todo for PR work
basecamp todo "Review PR #42" --in <project> --assignee me --due tomorrow

# When merged
basecamp done <todo_id>
basecamp campfire post "Merged PR #42" --in <project>

Bulk Process Overdue Todos

# Preview overdue todos
basecamp todos sweep --overdue --dry-run --in <project>

# Complete all with comment
basecamp todos sweep --overdue --complete --comment "Cleaning up" --in <project>

Move Card Through Workflow

# List columns to get IDs
basecamp cards columns --in <project> --json

# Move card to column
basecamp cards move <card_id> --to <column_id> --in <project>

Download File from Basecamp

basecamp files download <upload_id> --in <project> --out ./downloads

Resource Reference

Projects

basecamp projects list --json               # List all
basecamp projects show <id> --json          # Show details
basecamp projects create "Name" --json      # Create
basecamp projects update <id> --name "New"  # Update

Todos

basecamp todos list --in <project> --json               # List in project
basecamp todos list --assignee me --in <project>        # My todos
basecamp todos list --overdue --in <project>            # Overdue only
basecamp todos list --status completed --in <project>   # Completed
basecamp todos list --list <todolist_id> --in <project> # In specific list
basecamp todo "Task" --in <project> --list <list> --assignee me --due tomorrow
basecamp done <id> [id...]                              # Complete (multiple OK)
basecamp reopen <id>                                    # Uncomplete
basecamp assign <id> --to <person> --in <project>       # Assign (person: ID, email, or "me")
basecamp unassign <id> --from <person> --in <project>   # Remove assignee
basecamp todos position <id> --to 1                     # Move to top
basecamp todos sweep --overdue --complete --comment "Done" --in <project>

Flags: --assignee (todos only - not available on cards/messages), --status (completed/pending), --overdue, --list, --due, --limit, --all

Todolists

Todolists are containers for todos. Create a todolist before adding todos.

basecamp todolists list --in <project> --json              # List todolists
basecamp todolists show <id> --in <project>                # Show details
basecamp todolists create "Name" --in <project> --json     # Create
basecamp todolists create "Name" --description "Desc" --in <project>
basecamp todolists update <id> --name "New" --in <project> # Update

Cards (Kanban)

Note: Cards do NOT support --assignee filtering like todos. Fetch all cards and filter client-side if needed. If a project has multiple card tables, you must specify --card-table <id>. When you get an "Ambiguous card table" error, the hint shows available table IDs and names.

basecamp cards list --in <project> --json             # All cards
basecamp cards list --card-table <id> --in <project>  # Specific table (required if multiple)
basecamp cards list --column <id> --in <project>      # Cards in column
basecamp cards columns --in <project> --json          # List columns (needs --card-table if multiple)
basecamp cards show <id> --in <project>               # Card details
basecamp card "Title" "<p>Body</p>" --in <project> --column <id>
basecamp cards update <id> --title "New" --due tomorrow --assignee me
basecamp cards move <id> --to <column_id>             # Move to column (numeric ID)
basecamp cards move <id> --to "Done" --card-table <table_id>  # Move by name (needs table)

Identifying completed cards: Cards in Done columns have parent.type: "Kanban::DoneColumn" and completed: true. Use this to identify completed cards that haven't been archived.

Limitation: Basecamp does not track when cards are moved between columns. The updated_at field updates on any modification and cannot reliably indicate when a card was completed.

Card Steps (checklists):

basecamp cards steps <card_id> --in <project>     # List steps
basecamp cards step create "Step" --card <id> --in <project>
basecamp cards step complete <step_id> --in <project>
basecamp cards step uncomplete <step_id>

Column management:

basecamp cards column show <id> --in <project>
basecamp cards column create "Name" --in <project>
basecamp cards column update <id> --title "New"
basecamp cards column move <id> --position 2
basecamp cards column color <id> --color blue
basecamp cards column on-hold <id>                # Enable on-hold section
basecamp cards column watch <id>                  # Subscribe to column

Messages

basecamp messages list --in <project> --json  # List messages
basecamp messages show <id> --in <project>    # Show message
basecamp message "Title" "Body" --in <project>
basecamp messages update <id> --title "New" --body "Updated"
basecamp messages pin <id> --in <project>     # Pin to top
basecamp messages unpin <id>                  # Unpin

Flags: --draft (create as draft), --no-subscribe (silent, no notifications), --subscribe "people" (comma-separated names, emails, IDs, or "me"; mutually exclusive with --no-subscribe), --message-board <id> (if multiple boards)

basecamp message "Bot update" "Done" --no-subscribe --in <project>
basecamp message "FYI" "Note" --subscribe "Alice,bob@x.com" --in <project>

Comments

basecamp comments list <recording_id> --in <project> --json
basecamp comment <recording_id> "Text" --in <project>
basecamp comments update <id> "Updated" --in <project>

Files & Documents

basecamp files list --in <project> --json               # List all (folders, files, docs)
basecamp files list --vault <folder_id> --in <project>  # List folder contents
basecamp files show <id> --in <project>                 # Show item (auto-detects type)
basecamp files download <id> --in <project>             # Download file
basecamp files download <id> --out ./dir                # Download to specific dir
basecamp files folder create "Folder" --in <project>
basecamp files doc create "Doc" "Body" --in <project>
basecamp files doc create "Draft" --draft --in <project>
basecamp files doc create "Notes" "..." --no-subscribe --in <project>
basecamp files update <id> --title "New" --content "Updated"

Subcommands: folders, uploads, documents (each with pagination flags)

Schedule

basecamp schedule --in <project> --json           # Schedule info
basecamp schedule entries --in <project> --json   # List entries
basecamp schedule show <id> --in <project>        # Entry details
basecamp schedule show <id> --date 20240315       # Specific occurrence (recurring)
basecamp schedule create "Event" --starts-at "2024-03-15T09:00:00Z" --ends-at "2024-03-15T10:00:00Z" --in <project>
basecamp schedule create "Meeting" --all-day --notify --participants 1,2,3 --in <project>
basecamp schedule create "Sync" --starts-at "..." --ends-at "..." --no-subscribe --in <project>
basecamp schedule update <id> --summary "New title" --starts-at "..."
basecamp schedule settings --include-due --in <project>  # Include todos/cards due dates

Flags: --all-day, --notify, --participants <ids>, --no-subscribe, --subscribe "people" (mutually exclusive), --status (active/archived/trashed)

Check-ins

basecamp checkins --in <project> --json           # Questionnaire info
basecamp checkins questions --in <project>        # List questions
basecamp checkins question <id> --in <project>    # Question details
basecamp checkins answers <question_id> --in <project>  # List answers
basecamp checkins answer <id> --in <project>      # Answer details
basecamp checkins question create "What did you work on?" --in <project>
basecamp checkins question update <id> "New question" --frequency every_week
basecamp checkins answer create <question-id> "My answer" --in <project>
basecamp checkins answer update <id> "Updated" --in <project>

Schedule options: --frequency (every_day, every_week, every_other_week, every_month, on_certain_days), --days 1,2,3,4,5 (0=Sun), --time "5:00pm"

Timeline

basecamp timeline --json                          # Account-wide activity
basecamp timeline --in <project> --json           # Project activity
basecamp timeline me --json                       # Your activity
basecamp timeline --person <id> --json            # Person's activity
basecamp timeline --watch                         # Live monitoring (TUI)
basecamp timeline --watch --interval 60           # Poll every 60 seconds

Note: basecamp timeline (account-wide) works reliably. The --limit flag is not supported on timeline commands.

Recordings (Cross-project)

Use basecamp recordings <type> for cross-project type browsing. For assigned todos, prefer basecamp reports assigned — recordings do not include assignee data and cannot be filtered by person.

basecamp recordings todos --json                  # All todos across projects
basecamp recordings todos --all --json            # All todos (paginate through all)
basecamp recordings messages --in <project>       # Messages in project
basecamp recordings documents --status archived   # Archived docs
basecamp recordings cards --sort created_at --direction asc
basecamp recordings cards --status archived --all --json  # Include archived cards

Types: todos, messages, documents, comments, cards, uploads

Status filtering: By default, only active recordings are returned. Use --status archived or --status trashed to query other statuses. You may need separate queries to get complete data (e.g., active + archived).

Status management:

basecamp recordings trash <id> --in <project>     # Move to trash
basecamp recordings archive <id> --in <project>   # Archive
basecamp recordings restore <id> --in <project>   # Restore to active
basecamp recordings visibility <id> --visible --in <project>  # Show to clients
basecamp recordings visibility <id> --hidden      # Hide from clients

Templates

basecamp templates --json                         # List templates
basecamp templates show <id> --json               # Template details
basecamp templates create "Template Name"         # Create empty template
basecamp templates update <id> --name "New Name"
basecamp templates delete <id>                    # Trash template
basecamp templates construct <id> --name "New Project"  # Create project (async)
basecamp templates construction <template_id> <construction_id>  # Check status

Construct returns construction_id - poll until status="completed" to get project.

Webhooks

basecamp webhooks list --in <project> --json  # List webhooks
basecamp webhooks show <id> --in <project>    # Webhook details
basecamp webhooks create "https://..." --in <project>
basecamp webhooks create "https://..." --types "Todo,Comment" --in <project>
basecamp webhooks update <id> --active --in <project>
basecamp webhooks update <id> --inactive      # Disable
basecamp webhooks delete <id> --in <project>

Event types: Todo, Todolist, Message, Comment, Document, Upload, Vault, Schedule::Entry, Kanban::Card, Question, Question::Answer

Subscriptions

basecamp subscriptions <recording_id>              # Who's subscribed
basecamp subscriptions subscribe <id>              # Subscribe yourself
basecamp subscriptions unsubscribe <id>            # Unsubscribe
basecamp subscriptions add <id> --people 1,2,3     # Add people
basecamp subscriptions remove <id> --people 1,2,3  # Remove people

Lineup (Account-wide Markers)

basecamp lineup create "Milestone" "2024-03-15"   # Create marker
basecamp lineup create "Launch" tomorrow          # Natural date parsing
basecamp lineup update <id> "New Name" "+7"
basecamp lineup delete <id>

Note: Lineup markers are account-wide, not project-scoped.

Campfire

basecamp campfire --in <project> --json           # List campfires
basecamp campfire messages --in <project> --json  # List messages
basecamp campfire post "Hello!" --in <project>
basecamp campfire line <line_id> --in <project>   # Show line
basecamp campfire delete <line_id> --in <project> # Delete line

People

basecamp people list --json                          # All people in account
basecamp people list --project <project> --json    # People on project
basecamp me --json                                 # Current user
basecamp people show <id> --json                   # Person details
basecamp people add <id> --project <project>       # Add to project
basecamp people remove <id> --project <project>    # Remove from project

Search

basecamp search "query" --json                    # Full-text search
basecamp search "query" --sort updated_at --limit 20
basecamp search metadata --json                   # Available search scopes

Generic Show

basecamp show <type> <id> --in <project> --json   # Show any recording type
# Types: todo, todolist, message, comment, card, card-table, document (or omit <type> for generic lookup)

Configuration

The CLI uses two directory namespaces: basecamp for your Basecamp identity and project relationships, basecamp for tool-specific operational data.

~/.config/basecamp/           # Basecamp identity (DO NOT read credentials)
├── credentials.json          #   OAuth tokens — NEVER read or log
├── client.json               #   DCR client registration
└── config.json               #   Global preferences (account_id, base_url, format)

~/.cache/basecamp/            # Tool cache (ephemeral, auto-managed)
├── completion.json           #   Tab completion cache
└── resilience/               #   Circuit breaker state

.basecamp/                    # Per-repo config (committed to git)
└── config.json               #   Project defaults (project_id, account_id, todolist_id)

Per-repo config: .basecamp/config.json

{
  "project_id": "12345",
  "todolist_id": "67890"
}

Initialize:

basecamp config init
basecamp config set project_id <id>
basecamp config set todolist_id <id>

Config Trust:

Authority keys (base_url, default_profile, profiles) in local/repo configs are blocked until explicitly trusted. This prevents a cloned repo's config from redirecting OAuth tokens.

basecamp config trust                    # Trust nearest .basecamp/config.json
basecamp config trust /path/to/.basecamp/config.json  # Trust specific config file
basecamp config trust --list             # Show all trusted configs
basecamp config untrust                  # Revoke trust for nearest config
basecamp config untrust /path/to/.basecamp/config.json  # Revoke trust for specific path

Check context:

cat .basecamp/config.json 2>/dev/null || echo "No project configured"

Global config: ~/.config/basecamp/config.json (account_id, base_url, format preferences)

Error Handling

General diagnostics:

basecamp doctor --json                            # Check CLI health, auth, connectivity

Rate limiting (429): The CLI handles backoff automatically. If you see 429 errors, reduce request frequency.

Authentication errors:

basecamp auth status                              # Check auth
basecamp auth login                               # Re-authenticate
basecamp auth login --scope full                  # Full access (BC3 OAuth only)

Network errors / localhost URLs:

# Check for dev config
cat ~/.config/basecamp/config.json
# Should only contain: {"account_id": "<id>"}
# Remove base_url/api_url if pointing to localhost

Not found errors:

basecamp auth status                              # Verify auth working
cat ~/.config/basecamp/accounts.json              # Check available accounts

Required arguments are positional (not flags):

  • basecamp todo "Buy milk" (not --content)
  • basecamp card "New feature" (not --title)
  • basecamp message "Subject" "Body" (not --subject)
  • basecamp campfire post "Hello" (not --content)
  • basecamp comment <id> "Text" (not a flag)
  • basecamp webhooks create "https://..." --in <project> (not --url)
  • basecamp checkins answer create <question-id> "content" (not --question)

Missing argument errors (code: "usage"): When a required positional argument is missing, the CLI returns a structured error naming the specific argument. Use this for elicitation:

$ basecamp todo --json
{"ok": false, "error": "<content> required", "code": "usage",
 "hint": "Usage: basecamp todo <content>"}

$ basecamp comments create 123 --json
{"ok": false, "error": "<content> required", "code": "usage", ...}

The error field names the missing <arg> — use it to prompt the user for the specific value.

URL malformed (curl exit 3): Special characters in content. Use plain text or properly escaped HTML.

jq Patterns

Common data extraction patterns for the output envelope:

# Extract fields from data array
basecamp todos list --in <project> --json | jq '.data[] | select(.completed == false) | .title'
basecamp todos list --in <project> --json | jq '.data | length'
basecamp todos list --in <project> --json | jq '.data[] | {id, title, status}'

# Access envelope metadata
basecamp todos list --in <project> --json | jq '.breadcrumbs[0].cmd'
basecamp todos list --in <project> --json | jq '.meta.stats.requests'

Exit Codes

ExitMeaningFix
0OK
1Usage errorCheck basecamp <cmd> --help
2Not foundVerify ID/URL exists
3Auth errorbasecamp auth login
4ForbiddenCheck account/project permissions
5Rate limitWait and retry (resilience layer handles Retry-After automatically)
6Network errorCheck connectivity, basecamp doctor
7API errorRetry; if persistent, check basecamp doctor
8AmbiguousBe more specific (use ID instead of name)

Learn More

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

ralph-lisa-loop

No summary provided by upstream source.

Repository SourceNeeds Review
General

skill-crafting

No summary provided by upstream source.

Repository SourceNeeds Review
General

consult-outside-expert

No summary provided by upstream source.

Repository SourceNeeds Review
basecamp | V50.AI