Sync issues from Beads (git-backed CLI issue tracker) to Fizzy (Kanban board) via REST API.
Let AI agents visualize their work on a Kanban board.
📖 Complete Setup Guide | 🏗️ Architecture Overview
This is my first open-source project—feedback, suggestions, and help are very welcome.
- One-way sync from Beads to Fizzy
- Self-healing sync — automatically detects and corrects Fizzy drift
- Automatic column creation for active states (default: Doing, Blocked)
- Smart status mapping using Fizzy's built-in columns:
open→ Maybe? (Fizzy's built-in inbox/backlog)in_progress→ Doing (custom column)blocked→ Blocked (custom column)closed→ Done (Fizzy's built-in)
- Priority and issue type as tags (P0-P4, bug, feature, task, epic, chore)
- Change detection via checksums (only syncs modified issues)
- State persistence (tracks which Beads issues map to which Fizzy cards)
- Python 3.11+
- uv (handles dependencies automatically)
- A Beads project (
.beads/directory) - A Fizzy instance with API access
- Log into your Fizzy account
- Go to Settings > API Tokens (or navigate to
/settings/tokens) - Click Create Token
- Copy the generated token (it won't be shown again)
Store the token securely:
export FIZZY_API_TOKEN="your-token-here"git clone https://github.com/hugo-alves/bizzy.git
cd bizzy
# Optional: install deps for local dev
uv sync
# From your Beads project directory:
uv run bizzy wizardThat’s it — the wizard sets up config, board, and your first sync.
# Navigate to your Beads project
cd /path/to/your/project
# Run the interactive setup wizard
uv run bizzy wizardThe wizard guides you through the entire setup process interactively.
# Navigate to your Beads project
cd /path/to/your/project
# Initialize config
uv run bizzy init
# Set your API token (see above)
export FIZZY_API_TOKEN="your-token-here"
# Test connection
uv run bizzy auth
# Set up board with correct columns
uv run bizzy setup --new-board "My Project"
# Update .fizzy-sync.yml with the board ID shown
# Sync issues
uv run bizzy sync
# Or run in watch mode (recommended)
uv run bizzy watchThe init command creates .fizzy-sync.yml in the current directory:
# Fizzy API connection
fizzy:
base_url: https://fizzy.example.com
account_slug: "YOUR_ACCOUNT_SLUG"
api_token: ${FIZZY_API_TOKEN} # Use environment variable
# Target board
board:
id: "your-board-id"
# Status -> Column mapping (only active work states need custom columns)
# "open" stays in Maybe? (Fizzy's built-in inbox = backlog)
# "closed" goes to Done (Fizzy's built-in)
columns:
in_progress: Doing
blocked: Blocked
# Sync options
sync:
auto_triage: true # Move cards to columns automatically
auto_create_columns: true # Create missing columns
include_closed: false # Skip closed issues by default
priority_as_tag: true # Add P0-P4 tags
type_as_tag: true # Add bug/feature/task tags
self_healing_interval: 300 # Seconds between self-healing checks (0 to disable)
# Beads source
beads:
path: "." # Path to repo with .beads/Create a new .fizzy-sync.yml configuration file.
uv run bizzy init
uv run bizzy init --force # Overwrite existing configTest the API connection and display account info.
uv run bizzy authSet up a Fizzy board for Beads sync. Creates the custom columns (Doing, Blocked) needed for active work states. Fizzy's built-in Maybe? and Done columns handle open and closed issues.
# Create a new board (recommended for fresh start)
uv run bizzy setup --new-board "My Project"
# Reset existing board columns (removes duplicates)
uv run bizzy setup --reset --force
# Just add missing columns (non-destructive)
uv run bizzy setupNote: When creating a new board, update .fizzy-sync.yml with the board ID shown in the output.
Show sync status (Beads issue count, synced count, pending changes).
uv run bizzy statusSync issues from Beads to Fizzy.
# Sync all open issues
uv run bizzy sync
# Sync a specific issue
uv run bizzy sync --issue bizzy-123
# Include closed issues
uv run bizzy sync --include-closed
# Preview changes without syncing
uv run bizzy sync --dry-runRecommended for continuous sync. Watches the beads database and automatically syncs when changes are detected.
# Start watching (runs until Ctrl+C)
uv run bizzy watch
# Verbose mode - show all sync output
uv run bizzy watch -vThis is the best way to keep Fizzy in sync with Beads:
- Runs initial sync on startup
- Monitors
.beads/beads.dbfor changes - Auto-syncs within seconds of any beads operation
- Self-healing checks to correct Fizzy drift (every 5 minutes by default)
- No manual intervention needed
# Custom heal interval (in seconds)
uv run bizzy watch --heal-interval 600
# Disable self-healing
uv run bizzy watch --heal-interval 0| Beads Status | Fizzy Location | Type |
|---|---|---|
open |
Maybe? | Built-in (inbox/backlog) |
in_progress |
Doing | Custom column (Lime) |
blocked |
Blocked | Custom column (Pink) |
closed |
Done | Built-in |
Note: Fizzy has built-in columns (Not Now, Maybe?, Done) that cannot be removed. We use Maybe? as the backlog and Done for closed issues, so we only create 2 custom columns: Doing and Blocked.
Blocked status from dependencies: Issues with blocks dependencies are automatically shown as blocked when their blocker is open, and return to Maybe? when the blocker is closed. This is derived from Beads' blocked_issues_cache table.
- Priority:
P0,P1,P2,P3,P4 - Issue Type:
bug,feature,task,epic,chore - Labels: Any custom labels from Beads
Note: Tags are additive. Bizzy adds missing tags but does not remove existing tags.
Each Fizzy card includes a marker in its description to link back to the Beads issue:
Issue description here.
[beads:bizzy-123]
Fizzy is a visibility tool, not the source of truth. Beads is the authoritative source for all issue data. The self-healing feature ensures Fizzy always reflects the true state in Beads, even when cards are manually modified in Fizzy.
- Drift Detection — Periodically compares each synced Fizzy card against the corresponding Beads issue
- Auto-Correction — When drift is detected (wrong column, outdated title/description, missing tags), the card is automatically updated to match Beads
- Non-Destructive — Only updates cards that have drifted; cards already in sync are untouched
| Drift Type | Example | Correction |
|---|---|---|
| Column mismatch | Card moved manually in Fizzy | Moved back to correct column based on Beads status |
| Title changed | Card renamed in Fizzy | Title restored from Beads |
| Description edited | Notes added in Fizzy | Description restored (with [beads:id] marker) |
| Tags modified | Priority tag removed | Tags restored from Beads priority/type/labels |
# In .fizzy-sync.yml
sync:
self_healing_interval: 300 # Check every 5 minutes (default)Or via command line:
# Custom interval
uv run bizzy watch --heal-interval 600 # Every 10 minutes
# Disable self-healing
uv run bizzy watch --heal-interval 0- Fizzy is for visibility — Drag cards around to explore, but changes don't stick
- Beads is the source of truth — All real changes happen via
bdcommands - No surprises — The board always reflects actual issue state
- Team-friendly — Multiple people can view Fizzy without corrupting data
Tip: If you need to change an issue's status, use
bd start,bd block, orbd closein the terminal. The change will sync to Fizzy automatically.
Sync state is stored in .beads/.fizzy-sync-state.json:
{
"synced_issues": {
"bizzy-123": {
"card_number": 42,
"checksum": "abc123...",
"synced_at": "2026-01-05T10:30:00"
}
},
"last_sync": "2026-01-05T10:30:00"
}This file tracks:
- Which Beads issues have been synced
- The corresponding Fizzy card number
- A checksum to detect changes
alias bizzy="uv run bizzy"
bizzy syncAdd to .git/hooks/post-commit:
#!/bin/bash
export FIZZY_API_TOKEN="your-token"
uv run bizzy sync --quietRun bizzy init to create the config file.
Set the FIZZY_API_TOKEN environment variable:
export FIZZY_API_TOKEN="your-token-here"Make sure you're in a directory with a .beads/ folder, or run bd init to initialize Beads.
Check that the columns exist in Fizzy. If auto_create_columns: true, they should be created automatically.
Use bizzy setup --reset --force to clean up and recreate the standard Beads columns.
# Install dev dependencies and run tests
uv run --with pytest --with pytest-httpx pytest tests/ -v
# Or with the dev dependencies from pyproject.toml
uv sync --extra dev
uv run pytest tests/ -vfizzy-beads-sync/
fizzy_sync.py # Main script (runnable with uv run)
pyproject.toml # Package configuration
tests/ # Test suite
test_mapper.py # Tests for data mapping
test_config.py # Tests for configuration
test_client.py # Tests for API client
MIT