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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ help:
@echo " BASECAMP_TEST_PROJECT_ID Project ID to test against"
@echo " BASECAMP_TEST_BOARD_ID Board ID for card tests"
@echo " BASECAMP_TEST_CARD_ID Card ID for detail/move tests"
@echo " BASECAMP_TEST_TODOLIST_ID Todolist ID for todo tests"
@echo ""
@echo "Example:"
@echo " export BASECAMP_TEST_PROJECT_ID=12345678"
@echo " export BASECAMP_TEST_BOARD_ID=87654321"
@echo " export BASECAMP_TEST_CARD_ID=44444444"
@echo " export BASECAMP_TEST_TODOLIST_ID=99999999"
@echo " make test-e2e"

build:
Expand Down
285 changes: 284 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,25 @@ A command-line interface for Basecamp written in Go with zero external dependenc

## Installation

### Homebrew

```bash
brew install rzolkos/tap/basecamp
```

### AUR (Arch Linux)

```bash
yay -S basecamp-cli
```

### Go

```bash
go install github.com/rzolkos/basecamp-cli/cmd/basecamp@latest
```

Or build from source:
### Build from source

```bash
make build
Expand All @@ -26,13 +40,18 @@ Configuration files (XDG Base Directory):

## Usage

### Card Tables

```bash
# List all projects
basecamp projects

# List card tables in a project
basecamp boards <project_id>

# List columns in a board
basecamp columns <project_id> <board_id>

# List cards in a board
basecamp cards <project_id> <board_id>

Expand All @@ -45,10 +64,274 @@ basecamp card <project_id> <card_id>
# View card with comments
basecamp card <project_id> <card_id> --comments

# Create a card
basecamp card-create <project_id> <board_id> --column <column_id> --title "Card title"

# Update a card
basecamp card-update <project_id> <card_id> --title "New title" --content "Description"

# Move a card to a different column
basecamp move <project_id> <board_id> <card_id> --to "Done"
```

### Card Steps

```bash
# Steps are shown when viewing a card
basecamp card <project_id> <card_id>

# Create a step on a card
basecamp step-create <project_id> <card_id> --title "Step description"

# Create a step with due date and assignees
basecamp step-create <project_id> <card_id> --title "Task" --due 2026-02-01 --assignees "123,456"

# Update a step
basecamp step-update <project_id> <step_id> --title "Updated title"

# Complete a step
basecamp step-complete <project_id> <step_id>

# Uncomplete a step
basecamp step-uncomplete <project_id> <step_id>

# Reposition a step (0-indexed)
basecamp step-reposition <project_id> <card_id> <step_id> --position 0
```

### Todos

```bash
# List todo lists in a project
basecamp todolists <project_id>

# List todos in a todo list
basecamp todos <project_id> <todolist_id>

# List completed todos
basecamp todos <project_id> <todolist_id> --completed

# View a todo
basecamp todo <project_id> <todo_id>

# Create a todo
basecamp todo-create <project_id> <todolist_id> --content "Task description"

# Complete a todo
basecamp todo-complete <project_id> <todo_id>

# Uncomplete a todo
basecamp todo-uncomplete <project_id> <todo_id>

# Reposition a todo within its list (1-indexed)
basecamp todo-reposition <project_id> <todo_id> --position 1
```

### Todo Groups

```bash
# List groups within a todolist
basecamp todolist-groups <project_id> <todolist_id>

# View a group
basecamp todolist-group <project_id> <group_id>

# Create a group within a todolist
basecamp todolist-group-create <project_id> <todolist_id> --name "Group Name"

# Create a group with color
basecamp todolist-group-create <project_id> <todolist_id> --name "Group Name" --color green
```

### Messages

```bash
# List messages in a project
basecamp messages <project_id>

# View a message
basecamp message <project_id> <message_id>

# View a message with comments
basecamp message <project_id> <message_id> --comments

# Create a message
basecamp message-create <project_id> --subject "Subject" --content "Body"
```

### Comments

```bash
# Add a comment to any recording (card, message, todo, etc.)
basecamp comment-add <project_id> <recording_id> --content "Comment text"
```

### Documents

```bash
# List documents in a project
basecamp docs <project_id>

# View a document
basecamp doc <project_id> <doc_id>

# View a document with comments
basecamp doc <project_id> <doc_id> --comments

# Create a document
basecamp doc-create <project_id> --title "Title" --content "Content"
```

### Schedule

```bash
# List schedule entries
basecamp schedule <project_id>

# View an event
basecamp event <project_id> <entry_id>

# View an event with comments
basecamp event <project_id> <entry_id> --comments

# Create an event
basecamp event-create <project_id> --summary "Meeting" --starts-at "2026-02-01T10:00:00Z" --ends-at "2026-02-01T11:00:00Z"

# Create an all-day event
basecamp event-create <project_id> --summary "Holiday" --starts-at "2026-02-01" --ends-at "2026-02-01" --all-day
```

### Campfire

```bash
# List campfire messages
basecamp campfire <project_id>

# Post to campfire
basecamp campfire-post <project_id> --content "Hello team!"
```

### Search

```bash
# Search across all projects
basecamp search "query"

# Search with type filter
basecamp search "query" --type Todo

# Search within a project
basecamp search "query" --project <project_id>
```

### People

```bash
# List all people
basecamp people

# View a person's details
basecamp person <person_id>

# List pingable people
basecamp people-pingable

# List people on a project
basecamp people-project <project_id>

# View your own profile
basecamp my-profile

# Update project access (grant/revoke people)
basecamp project-access <project_id> --grant "123,456" --revoke "789"
```

### Automatic Check-ins (Questions)

```bash
# Get questionnaire info for a project
basecamp questionnaire <project_id>

# List check-in questions
basecamp questions <project_id>

# View a question
basecamp question <project_id> <question_id>

# View a question with comments
basecamp question <project_id> <question_id> --comments

# List answers to a question
basecamp question-answers <project_id> <question_id>

# View an answer
basecamp question-answer <project_id> <answer_id>

# View an answer with comments
basecamp question-answer <project_id> <answer_id> --comments
```

### Uploads

```bash
# Upload a file (returns attachable_sgid for use in other API calls)
basecamp upload /path/to/file.pdf

# List uploads in a vault (get vault_id from 'docs' command)
basecamp uploads <project_id> <vault_id>

# View an upload
basecamp upload-view <project_id> <upload_id>

# View an upload with comments
basecamp upload-view <project_id> <upload_id> --comments
```

### Recordings Management

```bash
# Archive any recording (todo, message, card, etc.)
basecamp archive <project_id> <recording_id>

# Unarchive a recording (set back to active)
basecamp unarchive <project_id> <recording_id>

# Trash a recording
basecamp trash <project_id> <recording_id>
```

### Message Types

```bash
# List message types (categories)
basecamp message-types <project_id>

# View a message type
basecamp message-type <project_id> <type_id>

# Create a message type
basecamp message-type-create <project_id> --name "Announcement" --icon "📢"

# Update a message type
basecamp message-type-update <project_id> <type_id> --name "Update" --icon "✅"

# Delete a message type
basecamp message-type-delete <project_id> <type_id>
```

### Activity Events

```bash
# List all events (across all projects)
basecamp events

# List events for a project
basecamp events-project <project_id>

# List events for a specific recording
basecamp events-recording <project_id> <recording_id>
```

## Project-specific config

Create `.basecamp.yml` in your project directory to set a default project_id:
Expand Down
6 changes: 6 additions & 0 deletions e2e/harness/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type Harness struct {
// CardID is a test card ID for read operations
CardID string

// TodolistID is a test todolist ID
TodolistID string

// t is the testing context
t *testing.T
}
Expand Down Expand Up @@ -57,6 +60,7 @@ type Config struct {
ProjectID string
BoardID string
CardID string
TodolistID string
}

// Exit codes
Expand Down Expand Up @@ -84,6 +88,7 @@ func LoadConfig() *Config {
ProjectID: os.Getenv("BASECAMP_TEST_PROJECT_ID"),
BoardID: os.Getenv("BASECAMP_TEST_BOARD_ID"),
CardID: os.Getenv("BASECAMP_TEST_CARD_ID"),
TodolistID: os.Getenv("BASECAMP_TEST_TODOLIST_ID"),
}
}

Expand All @@ -109,6 +114,7 @@ func New(t *testing.T) *Harness {
ProjectID: cfg.ProjectID,
BoardID: cfg.BoardID,
CardID: cfg.CardID,
TodolistID: cfg.TodolistID,
t: t,
}
}
Expand Down
Loading
Loading