A command-line interface for the Fizzy API. See the official API docs at https://github.com/basecamp/fizzy/blob/main/docs/API.md.
fizzy-cli-demo-1.mp4
Download the latest release from GitHub Releases and add it to your PATH.
With Go
go install github.com/robzolkos/fizzy-cli/cmd/fizzy@latestFrom source
git clone https://github.com/robzolkos/fizzy-cli.git
cd fizzy-cli
go build -o fizzy ./cmd/fizzy
./fizzy --help-
Get your API token from your Fizzy profile under "Personal access tokens"
-
Configure the CLI:
fizzy auth login YOUR_TOKEN- List your accounts:
fizzy identity show- Set your default account (use the numeric slug without the leading slash):
# From identity show: "slug": "/897362094" β use 897362094
export FIZZY_ACCOUNT=897362094- (Optional) Set your default board:
export FIZZY_BOARD=BOARD_IDSelf-hosted domains:
If you're using a self-hosted domain instead of the default https://app.fizzy.do, specify it using one of these methods:
Option 1: Per-command flag
fizzy identity show --api-url=https://your_domainOption 2: Configuration file
Add to your ~/.config/fizzy/config.yaml:
token: your_token
account: your_account_id
api_url: https://your_domain
board: your_default_board_idfizzy <resource> <action> [options]
fizzy version| Option | Environment Variable | Description |
|---|---|---|
--token |
FIZZY_TOKEN |
API access token |
--account |
FIZZY_ACCOUNT |
Account slug (from fizzy identity show) |
--api-url |
FIZZY_API_URL |
API base URL (default: https://app.fizzy.do) |
--verbose |
Show request/response details |
# List all boards
fizzy board list
# Show a board
fizzy board show BOARD_ID
# Create a board
fizzy board create --name "Engineering"
# Update a board
fizzy board update BOARD_ID --name "New Name"
# Delete a board
fizzy board delete BOARD_ID# List cards (with optional filters)
fizzy card list
fizzy card list --board BOARD_ID
fizzy card list --tag TAG_ID
fizzy card list --status published
fizzy card list --assignee USER_ID
# Show a card
fizzy card show 42
# Create a card
fizzy card create --board BOARD_ID --title "Fix login bug"
fizzy card create --board BOARD_ID --title "New feature" --description "Details here"
fizzy card create --board BOARD_ID --title "Card" --tag-ids "TAG_ID1,TAG_ID2"
fizzy card create --board BOARD_ID --title "Card" --image /path/to/header.png
# Create with custom timestamp (for data imports)
fizzy card create --board BOARD_ID --title "Old card" --created-at "2020-01-15T10:30:00Z"
# Update a card
fizzy card update 42 --title "Updated title"
fizzy card update 42 --created-at "2019-01-01T00:00:00Z"
# Delete a card
fizzy card delete 42# Close/reopen
fizzy card close 42
fizzy card reopen 42
# Move to "Not Now"
fizzy card postpone 42
# Move into a column
fizzy card column 42 --column COLUMN_ID
# Send back to triage
fizzy card untriage 42
# Assign/unassign (toggles)
fizzy card assign 42 --user USER_ID
# Tag/untag (toggles, creates tag if needed)
fizzy card tag 42 --tag "bug"
# Watch/unwatch
fizzy card watch 42
fizzy card unwatch 42fizzy column list --board BOARD_ID
fizzy column show COLUMN_ID --board BOARD_ID
fizzy column create --board BOARD_ID --name "In Progress"
fizzy column update COLUMN_ID --board BOARD_ID --name "Done"
fizzy column delete COLUMN_ID --board BOARD_IDfizzy comment list --card 42
fizzy comment show COMMENT_ID --card 42
fizzy comment create --card 42 --body "Looks good!"
fizzy comment create --card 42 --body-file /path/to/comment.html
# Create with custom timestamp (for data imports)
fizzy comment create --card 42 --body "Old comment" --created-at "2020-01-15T10:30:00Z"
fizzy comment update COMMENT_ID --card 42 --body "Updated comment"
fizzy comment delete COMMENT_ID --card 42# Show a step
fizzy step show STEP_ID --card 42
# Create a step
fizzy step create --card 42 --content "Review PR"
fizzy step create --card 42 --content "Already done" --completed
# Update a step
fizzy step update STEP_ID --card 42 --completed
fizzy step update STEP_ID --card 42 --not-completed
fizzy step update STEP_ID --card 42 --content "New content"
# Delete a step
fizzy step delete STEP_ID --card 42# List reactions on a comment
fizzy reaction list --card 42 --comment COMMENT_ID
# Add a reaction (emoji, max 16 chars)
fizzy reaction create --card 42 --comment COMMENT_ID --content "π"
# Remove a reaction
fizzy reaction delete REACTION_ID --card 42 --comment COMMENT_IDfizzy user list
fizzy user show USER_IDfizzy tag listfizzy notification list
fizzy notification read NOTIFICATION_ID
fizzy notification unread NOTIFICATION_ID
fizzy notification read-allUpload files for use in rich text fields (card descriptions, comment bodies).
# Upload a file and get a signed_id
fizzy upload file /path/to/image.png
# Use the signed_id in a card description
fizzy card create --board BOARD_ID --title "Card" \
--description '<p>See image:</p><action-text-attachment sgid="SIGNED_ID"></action-text-attachment>'# Show your identity and all accessible accounts
fizzy identity showCommand results output JSON. (--help and --version output plain text.)
{
"success": true,
"data": { ... },
"meta": {
"timestamp": "2025-12-10T10:00:00Z"
}
}When creating resources, the CLI automatically follows the Location header to fetch the complete resource data:
{
"success": true,
"data": {
"id": "abc123",
"number": 42,
"title": "New Card",
"status": "published"
},
"location": "https://app.fizzy.do/account/cards/42",
"meta": {
"timestamp": "2025-12-10T10:00:00Z"
}
}Errors return a non-zero exit code and structured error info:
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Card not found",
"status": 404
}
}| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Invalid arguments |
| 3 | Authentication failure |
| 4 | Permission denied |
| 5 | Not found |
| 6 | Validation error |
| 7 | Network error |
The CLI looks for configuration in multiple locations:
Global config is stored in one of these locations:
~/.config/fizzy/config.yaml(preferred)~/.fizzy/config.yaml
token: fizzy_abc123...
account: 897362094
api_url: https://app.fizzy.do
board: 123456You can also create a .fizzy.yaml file in your project directory. The CLI walks up the directory tree to find it, so you can run commands from any subdirectory.
# .fizzy.yaml - project-specific settings
account: 123456789
api_url: https://self-hosted.example.com
board: 123456Local config values merge with global config:
- Values in local config override global config
- Empty values in local config do not override global values
- This allows you to keep your token in global config while overriding account per project
Example: Global config has your token, local config specifies which account to use for this project:
# ~/.config/fizzy/config.yaml (global)
token: fizzy_abc123...
# /path/to/project/.fizzy.yaml (local)
account: 123456789Configuration priority (highest to lowest):
- Command-line flags (
--token,--account,--api-url) - Environment variables (
FIZZY_TOKEN,FIZZY_ACCOUNT,FIZZY_API_URL,FIZZY_BOARD) - Local project config (
.fizzy.yamlin current or parent directories) - Global config (
~/.config/fizzy/config.yamlor~/.fizzy/config.yaml) - Defaults
List commands return paginated results. Use --page to fetch specific pages or --all to fetch everything:
fizzy card list --page 2
fizzy card list --allgo build -o bin/fizzy ./cmd/fizzyUnit tests (no API credentials required):
make test-unitE2E tests (requires live API credentials):
# Set required environment variables
export FIZZY_TEST_TOKEN=your-api-token
export FIZZY_TEST_ACCOUNT=your-account-slug
# Build and run e2e tests
make test-e2eRun a specific e2e test:
make test-run NAME=TestBoardCRUDMIT