Python SDK and CLI for the Kanboard JSON-RPC API
Project description
kanboard-cli
A Python SDK and CLI for the Kanboard JSON-RPC API — complete coverage of all 158 API methods, a plugin system for custom workflows, and a first-class developer experience.
Documentation: CLI Reference • SDK Guide • Configuration • Workflows • Contributing
Overview
kanboard-cli provides two complementary interfaces for Kanboard:
kanboard(SDK) — An importable Python library (import kanboard) with typed models, structured exceptions, and resource-based access to the full Kanboard API.kanboard(CLI) — A Click-based command-line tool with rich table output, JSON/CSV/quiet modes, named configuration profiles, and a plugin system for user-defined workflows.
Both are distributed as a single kanboard-cli package installable from PyPI.
Key Features
- Complete API coverage — All 158 Kanboard JSON-RPC methods across 24 resource categories
- Typed Python SDK — Dataclass models, structured exceptions, and IDE-friendly type hints
- Powerful CLI — Subcommand groups for every resource, four output formats, shell completions
- Multiple output formats —
table(rich/colored),json,csv,quiet(IDs only) - Named profiles — Manage multiple Kanboard instances (production, dev, staging) via TOML config
- Layered configuration — Config file → environment variables → CLI flags
- Workflow plugins — Drop
.pyfiles into~/.config/kanboard/workflows/to add custom CLI commands - Context manager support —
KanboardClientworks withwithstatements for clean resource management - Cross-project orchestration — Portfolio management, cross-project milestones, dependency analysis, and critical-path computation with dual-backend support (local JSON file or server-side plugin API)
Cross-Project Orchestration
kanboard-cli ships a dual-backend orchestration layer that treats multiple Kanboard projects as a unified portfolio, with two interchangeable persistence backends.
What it enables
| Capability | Description |
|---|---|
| Portfolio management | Group multiple projects into a named portfolio; stored locally or via the plugin |
| Cross-project milestones | Define milestones that span tasks from multiple projects; track percent-complete and at-risk status |
| Dependency analysis | Discover cross-project blocks/is blocked by relationships; detect blocked and blocking tasks |
| Critical path | Compute the longest dependency chain (topological sort) across all portfolio tasks |
| Metadata sync | Push portfolio and milestone membership into Kanboard project/task metadata using the kanboard_cli: key prefix |
| Backend migration | Move data between local and remote backends with portfolio migrate |
Backends
kanboard-cli supports two interchangeable backends for portfolio and milestone storage:
| Local (default) | Remote (plugin) | |
|---|---|---|
| Flag | --portfolio-backend local |
--portfolio-backend remote |
| Storage | ~/.config/kanboard/portfolios.json on your machine |
Server-side database tables in Kanboard (via plugin) |
| Plugin required | No — works with any Kanboard instance | Yes — kanboard-plugin-portfolio-management |
| Shared with other users | No — data is machine-local only | Yes — all users with server access see the same portfolios |
| Offline operation | Yes — reads/writes local file | No — requires a live Kanboard connection |
| Performance | N+1 API calls for task aggregation | Single server-side query (faster for large portfolios) |
| Kanboard web UI integration | No | Yes — portfolio dashboards, Gantt timeline, dependency graphs |
| Referential integrity | None — stale task/project IDs possible | Enforced by server-side foreign keys |
When to use Local: solo use, no plugin, offline-capable, quick setup — portfolio definitions live only on your machine and are invisible to other Kanboard users.
When to use Remote: team environments, shared visibility, large portfolios (performance), or when you want Kanboard's web UI to show portfolio dashboards and dependency graphs.
The backend is selected via --portfolio-backend flag, KANBOARD_PORTFOLIO_BACKEND env var, or portfolio_backend in your TOML profile (see Configuration — Portfolio Backend Selection). Switching backends at any time is safe — use portfolio migrate to copy data across.
Quick example
# Create a portfolio grouping two projects
kanboard portfolio create "Platform Launch" --description "Q3 release"
kanboard portfolio add-project "Platform Launch" 1
kanboard portfolio add-project "Platform Launch" 2
# Create a milestone spanning both projects
kanboard milestone create "Platform Launch" "Beta Release" --target-date 2026-06-30
kanboard milestone add-task "Platform Launch" "Beta Release" 42
kanboard milestone add-task "Platform Launch" "Beta Release" 99 --critical
# Check progress and risks
kanboard milestone progress "Platform Launch"
kanboard portfolio show "Platform Launch"
# Visualise cross-project dependencies
kanboard portfolio dependencies "Platform Launch"
kanboard portfolio blocked "Platform Launch"
kanboard portfolio critical-path "Platform Launch"
SDK example
from kanboard import KanboardClient
from kanboard.orchestration import PortfolioManager, DependencyAnalyzer, LocalPortfolioStore
with KanboardClient(url=URL, token=TOKEN) as kb:
store = LocalPortfolioStore()
manager = PortfolioManager(kb, store)
analyzer = DependencyAnalyzer(kb)
# Aggregate tasks across all portfolio projects
tasks = manager.get_portfolio_tasks("Platform Launch")
# Find blocked cross-project tasks
edges = analyzer.get_dependency_edges(tasks, cross_project_only=True)
blocked = analyzer.get_blocked_tasks(tasks)
# Compute critical path
critical = analyzer.get_critical_path(tasks)
Backend migration
# Check current backend config and data counts
kanboard portfolio migrate status
# Preview migration without writing
kanboard portfolio migrate local-to-remote --all --dry-run
# Migrate all local portfolios to the remote plugin
kanboard portfolio migrate local-to-remote --all
# Pull all remote portfolios to local
kanboard portfolio migrate remote-to-local --all
# Compare local and remote state
kanboard portfolio migrate diff --all
SDK backend selection
from kanboard import KanboardClient, create_backend
from kanboard.orchestration import PortfolioManager
with KanboardClient(url=URL, token=TOKEN) as kb:
# Local backend (default — no plugin required)
local_backend = create_backend("local")
manager = PortfolioManager(kb, local_backend)
# Remote backend (plugin required)
remote_backend = create_backend("remote", client=kb)
remote_manager = PortfolioManager(kb, remote_backend)
# Both managers expose the same API
tasks = manager.get_portfolio_tasks("Platform Launch")
tasks = remote_manager.get_portfolio_tasks("Platform Launch")
Server-side visualization (optional)
For in-browser Kanboard UI features — including interactive dependency graphs, multi-project Gantt timelines, portfolio dashboards, and board-level blocking indicators — see the companion Kanboard Portfolio plugin.
The CLI's portfolio and milestone commands work independently of the plugin (using the local JSON backend by default), but the plugin provides both the visual layer within Kanboard's web interface and the remote backend for the CLI and SDK.
See docs/sdk-guide.md#cross-project-orchestration and docs/cli-reference.md#portfolio for full reference documentation.
Prerequisites
- Python 3.11+ (required for
tomllib, modern typing features) - A running Kanboard instance with API access enabled
- API token from Kanboard Settings → API
Installation
From PyPI
pip install kanboard-cli
From source (development)
git clone https://github.com/geekmuse/kanboard-cli.git
cd kanboard-cli
pip install -e ".[dev]"
Quick Start
1. Configure your connection
Create ~/.config/kanboard/config.toml:
[profiles.default]
url = "https://kanboard.example.com/jsonrpc.php"
token = "your-api-token-here"
[settings]
default_profile = "default"
output_format = "table"
Or use environment variables:
export KANBOARD_URL="https://kanboard.example.com/jsonrpc.php"
export KANBOARD_TOKEN="your-api-token-here"
2. Use the CLI
# List all projects
kanboard project list
# Create a task
kanboard task create 1 "Fix login bug" --color red --priority 3
# Get task details as JSON
kanboard task get 42 --output json
# Search tasks
kanboard task search 1 "status:open assignee:me"
# View the board
kanboard board show 1
# List overdue tasks across all projects
kanboard task overdue
3. Use the SDK
from kanboard import KanboardClient
with KanboardClient(url="https://kanboard.example.com/jsonrpc.php",
token="your-api-token") as kb:
# Create a project
project_id = kb.projects.create_project(name="My Project")
# Create a task
task_id = kb.tasks.create_task(
title="Implement feature X",
project_id=project_id,
color_id="green",
priority=2,
)
# Get all active tasks
tasks = kb.tasks.get_all_tasks(project_id, status_id=1)
for task in tasks:
print(f"#{task.id} [{task.color_id}] {task.title}")
# Work with columns, swimlanes, comments, tags, and more
columns = kb.columns.get_columns(project_id)
kb.comments.create_comment(task_id=task_id, user_id=1, content="Started work")
kb.tags.set_task_tags(project_id, task_id, ["backend", "urgent"])
For the full SDK guide including all resource examples, exception handling, and batch usage, see docs/sdk-guide.md.
Configuration
Config File
Location: ~/.config/kanboard/config.toml
[profiles.default]
url = "https://kanboard.example.com/jsonrpc.php"
token = "your-api-token-here"
portfolio_backend = "local" # or "remote" if plugin is installed
[profiles.dev]
url = "http://localhost:8080/jsonrpc.php"
token = "dev-token"
[settings]
default_profile = "default"
output_format = "table" # table | json | csv | quiet
Environment Variables
| Variable | Overrides |
|---|---|
KANBOARD_URL |
profiles.<active>.url |
KANBOARD_TOKEN |
profiles.<active>.token |
KANBOARD_PROFILE |
settings.default_profile |
KANBOARD_OUTPUT_FORMAT |
profiles.<active>.output_format |
KANBOARD_AUTH_MODE |
profiles.<active>.auth_mode |
KANBOARD_USERNAME |
profiles.<active>.username |
KANBOARD_PASSWORD |
profiles.<active>.password |
KANBOARD_PORTFOLIO_BACKEND |
profiles.<active>.portfolio_backend |
CLI Flags
| Flag | Purpose |
|---|---|
--url URL |
Kanboard JSON-RPC endpoint |
--token TOKEN |
API token |
--profile NAME |
Config profile to use |
--output FORMAT |
Output format: table, json, csv, quiet |
--auth-mode MODE |
Auth mode: app (API token) or user (username/password) |
--portfolio-backend BACKEND |
Portfolio storage: local (JSON file) or remote (plugin API) |
--verbose |
Enable debug logging |
Resolution order: config file → environment variables → CLI flags (highest priority)
CLI Reference
Every Kanboard resource has a corresponding command group:
| Command Group | Description |
|---|---|
kanboard task |
Tasks: list, get, create, update, close, open, remove, search, move |
kanboard project |
Projects: list, get, create, update, remove, enable, disable, activity |
kanboard board |
Board view for a project |
kanboard column |
Column management |
kanboard swimlane |
Swimlane management |
kanboard comment |
Task comments |
kanboard category |
Project categories |
kanboard tag |
Tags (global and per-project) |
kanboard subtask |
Subtask management |
kanboard timer |
Subtask time tracking |
kanboard user |
User administration |
kanboard me |
Current user dashboard and activity |
kanboard link |
Link type definitions |
kanboard task-link |
Internal task-to-task links |
kanboard external-link |
External task links |
kanboard group |
Group management and membership |
kanboard action |
Automatic action configuration |
kanboard project-file |
Project file attachments |
kanboard task-file |
Task file attachments |
kanboard project-meta |
Project key-value metadata |
kanboard task-meta |
Task key-value metadata |
kanboard project-access |
Project permissions (users/groups) |
kanboard app |
Application info (version, colors, roles) |
kanboard config |
Configuration management |
kanboard workflow |
List discovered workflow plugins |
kanboard completion |
Shell completion (bash/zsh/fish) |
kanboard portfolio |
Portfolio management + dependency analysis (cross-project orchestration) |
kanboard milestone |
Cross-project milestone tracking |
Use kanboard <command> --help for detailed usage of any command.
For the full command reference, see docs/cli-reference.md.
Output Formats
All list/get commands support four output formats via --output / -o:
# Rich colored table (default)
kanboard task list 1
# JSON (for scripting and piping)
kanboard task list 1 -o json
# CSV (for spreadsheets and data tools)
kanboard task list 1 -o csv
# Quiet / ID-only (for shell pipelines)
kanboard task list 1 -o quiet | xargs -I{} kanboard task close {}
Workflows (Plugin System)
kanboard-cli supports user-defined workflow plugins for custom automation.
Creating a workflow
- Create a Python file in
~/.config/kanboard/workflows/:
# ~/.config/kanboard/workflows/my_workflow.py
import click
from kanboard_cli.workflows.base import BaseWorkflow
class MyWorkflow(BaseWorkflow):
@property
def name(self) -> str:
return "my-workflow"
@property
def description(self) -> str:
return "My custom automation workflow"
def register_commands(self, cli: click.Group) -> None:
@cli.command("my-workflow")
@click.pass_context
def run(ctx):
"""Run my custom workflow."""
client = ctx.obj["client"]
# Use the full SDK here
tasks = client.tasks.get_all_tasks(project_id=1, status_id=1)
click.echo(f"Found {len(tasks)} active tasks")
- Optionally add config in
~/.config/kanboard/config.toml:
[workflows.my-workflow]
target_project = 1
- The workflow is automatically discovered on next CLI invocation:
kanboard workflow list # See discovered workflows
kanboard my-workflow # Run your workflow
See docs/plan/05-milestone-3-extended.md (Tasks 40–41) for full architecture details.
Project Structure
kanboard-cli/
├── src/
│ ├── kanboard/ # SDK package (import kanboard)
│ │ ├── __init__.py # Public API surface
│ │ ├── client.py # JSON-RPC transport layer
│ │ ├── config.py # Layered configuration resolution (incl. portfolio_backend)
│ │ ├── exceptions.py # Typed exception hierarchy
│ │ ├── models.py # Dataclass response models + plugin models
│ │ ├── resources/ # 26 modules, one per API category
│ │ │ ├── portfolios.py # PortfoliosResource — plugin API (18 methods)
│ │ │ ├── milestones.py # MilestonesResource — plugin API (10 methods)
│ │ │ └── [24 core modules]
│ │ └── orchestration/ # Cross-project orchestration (opt-in)
│ │ ├── __init__.py # Exports: PortfolioManager, DependencyAnalyzer, LocalPortfolioStore,
│ │ │ # PortfolioBackend, RemotePortfolioBackend, create_backend
│ │ ├── portfolio.py # PortfolioManager — multi-project aggregation
│ │ ├── dependencies.py # DependencyAnalyzer — graph traversal, critical path
│ │ ├── store.py # LocalPortfolioStore — JSON persistence
│ │ └── backend.py # PortfolioBackend Protocol, RemotePortfolioBackend, create_backend()
│ └── kanboard_cli/ # CLI package
│ ├── main.py # Click app root, global options (incl. --portfolio-backend)
│ ├── formatters.py # Table / JSON / CSV / quiet renderers
│ ├── renderers.py # ASCII dependency graph, progress bar renderers
│ ├── workflow_loader.py # Plugin discovery and loading
│ ├── commands/ # One module per CLI command group
│ │ ├── portfolio.py # Portfolio CRUD + dependency analysis + migrate subgroup
│ │ └── milestone.py # Cross-project milestone management
│ └── workflows/
│ └── base.py # BaseWorkflow ABC
├── tests/
│ ├── unit/ # Mocked httpx tests
│ │ ├── resources/ # One test file per resource module
│ │ └── orchestration/ # Orchestration unit tests (incl. test_backend.py)
│ ├── integration/ # Docker-based lifecycle tests (incl. test_plugin_backend.py)
│ ├── security/ # Security fuzzing (API fuzz + Hypothesis property tests)
│ └── cli/ # CliRunner output tests
├── docs/
│ ├── plan/ # Architecture and build plan
│ ├── design/ # Design documents and research
│ └── tasks/ # Per-task implementation notes
├── docker/
│ └── Dockerfile.kanboard-plugin-test # Kanboard image with portfolio plugin pre-installed
├── docker-compose.test.yml
├── pyproject.toml
├── Makefile
├── LICENSE
└── CHANGELOG.md
Development
Setup
git clone https://github.com/geekmuse/kanboard-cli.git
cd kanboard-cli
pip install -e ".[dev]"
Common Commands
make install # Install in editable mode with dev dependencies
make lint # Run ruff linter
make test # Run unit and CLI tests
make test-integration # Run integration tests (requires Docker)
make coverage # Run tests with coverage report
Testing
- Unit tests — Mocked
httpxviapytest-httpx; covers all SDK resource methods and exception paths - CLI tests — Click
CliRunner-based; verifies output across all four formats - Integration tests — Docker-based (
docker-compose.test.yml) with a live Kanboard instance; full CRUD lifecycle for every resource - Security fuzzing — See Security Testing below
Security Testing
kanboard-cli includes a two-layer security fuzzing framework:
# Install security dependencies
pip install -e ".[security]"
# Run Python-native security tests only (no Docker needed)
./scripts/security-fuzz.sh --no-docker
# Run the full suite including API fuzzing (requires Docker)
./scripts/security-fuzz.sh
# Run API fuzzing only
./scripts/security-fuzz.sh --api-only
Layer 1 — JSON-RPC API Fuzzing (tests/security/test_jsonrpc_fuzz.py):
Sends malicious payloads to a live Dockerized Kanboard instance and asserts safe handling — SQL injection, XSS, path traversal, command injection, type confusion, boundary values, null bytes, unicode edge cases, protocol abuse, and auth boundary testing. All 31 plugin API methods are also fuzzed via api-schema.json.
Layer 2 — Python-native Fuzz Testing (tests/security/test_sdk_fuzz.py):
Uses Hypothesis property-based testing (200 examples per test) to verify the SDK client, model deserialization, config resolution, CLI input handling, and response parsing all survive adversarial inputs.
Static analysis:
Bandit for Python security issues and pip-audit for dependency vulnerabilities.
The full suite runs nightly via GitHub Actions (.github/workflows/security-fuzz.yml) and on every release.
Dependencies
| Package | Purpose |
|---|---|
httpx |
HTTP client (JSON-RPC transport) |
click |
CLI framework |
rich |
Colored table output |
tomli-w |
TOML config writing |
pytest |
Test framework (dev) |
pytest-httpx |
HTTP mocking for tests (dev) |
ruff |
Linter and formatter (dev) |
coverage |
Code coverage reporting (dev) |
bandit |
Python static security analysis (security) |
pip-audit |
Dependency vulnerability scanning (security) |
hypothesis |
Property-based fuzz testing (security) |
Exception Hierarchy
The SDK provides structured exceptions for programmatic error handling:
KanboardError (base)
├── KanboardConfigError # Missing/invalid configuration
├── KanboardConnectionError # Network/connection failures
├── KanboardAuthError # HTTP 401/403, invalid credentials
├── KanboardAPIError # JSON-RPC error responses
│ ├── KanboardNotFoundError # Resource not found (null response)
│ └── KanboardValidationError # Invalid parameters
└── KanboardResponseError # Malformed/unparseable responses
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kanboard_cli-1.2.4.tar.gz.
File metadata
- Download URL: kanboard_cli-1.2.4.tar.gz
- Upload date:
- Size: 472.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
993dec37cfa1bb693342078b8bb0f48b3d25d21bc09e1b0b76af8f74ae728189
|
|
| MD5 |
57b3337dda2de7954fef9a2d1b2b4c09
|
|
| BLAKE2b-256 |
4b31ef4a5aff3e5c114e8aca66d941497b9fec10f768d714feac7c27a0b63466
|
Provenance
The following attestation bundles were made for kanboard_cli-1.2.4.tar.gz:
Publisher:
publish.yml on geekmuse/kanboard-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kanboard_cli-1.2.4.tar.gz -
Subject digest:
993dec37cfa1bb693342078b8bb0f48b3d25d21bc09e1b0b76af8f74ae728189 - Sigstore transparency entry: 1240860302
- Sigstore integration time:
-
Permalink:
geekmuse/kanboard-cli@5040f9f73dfb95150988f57fd314545246169ce2 -
Branch / Tag:
refs/tags/v1.2.4 - Owner: https://github.com/geekmuse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5040f9f73dfb95150988f57fd314545246169ce2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file kanboard_cli-1.2.4-py3-none-any.whl.
File metadata
- Download URL: kanboard_cli-1.2.4-py3-none-any.whl
- Upload date:
- Size: 157.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77a4a7e2052324a3f6a8c24d2483e8fd82ed4a7145df1c7aaa6187838d08b0f2
|
|
| MD5 |
39d25e0ce3d8ba56bb74cda5d8ebb40f
|
|
| BLAKE2b-256 |
9066993c2a0c331dfb5cc86b751283eff88dd15127d199d6ff62523613c331e6
|
Provenance
The following attestation bundles were made for kanboard_cli-1.2.4-py3-none-any.whl:
Publisher:
publish.yml on geekmuse/kanboard-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kanboard_cli-1.2.4-py3-none-any.whl -
Subject digest:
77a4a7e2052324a3f6a8c24d2483e8fd82ed4a7145df1c7aaa6187838d08b0f2 - Sigstore transparency entry: 1240860334
- Sigstore integration time:
-
Permalink:
geekmuse/kanboard-cli@5040f9f73dfb95150988f57fd314545246169ce2 -
Branch / Tag:
refs/tags/v1.2.4 - Owner: https://github.com/geekmuse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5040f9f73dfb95150988f57fd314545246169ce2 -
Trigger Event:
push
-
Statement type: