Storage Providers
Kanban Lite decouples what you store from where you store it through the capability-based plugin system. card.storage owns cards and comments, while attachment.storage can override attachment handling when you want a different backend such as S3. For first-party storage plugins, attachments are normally auto-derived from the active card.storage provider and reuse the same options.
.md files with YAML frontmatter. Human-readable, git-friendly, zero dependencies.
kl-plugin-storage-sqlite. Better query performance for large boards. Single-file database.
Configure providers
Select providers in .kanban.json at your workspace root:
{
"storage": {
"card.storage": { "provider": "sqlite" },
"attachment.storage": { "provider": "kl-plugin-attachment-s3" }
}
}
Migrate between providers
Migrate in place without losing data using the CLI or REST API:
# Check the current provider status
kl storage status
# Migrate cards to SQLite
kl storage migrate-to-sqlite --sqlite-path .kanban/kanban.db
# Migrate back to markdown files
kl storage migrate-to-markdown
REST API equivalents:
GET /api/storage # provider status
POST /api/storage/migrate-to-sqlite # { "sqlitePath": ".kanban/kanban.db" }
POST /api/storage/migrate-to-markdown
S3 / MinIO attachment storage
Install the package and point it at any S3-compatible endpoint via environment variables or .kanban.json:
npm install kl-plugin-attachment-s3
{
"storage": {
"attachment.storage": {
"provider": "kl-plugin-attachment-s3",
"config": {
"endpoint": "http://127.0.0.1:9000",
"bucket": "kanban",
"region": "us-east-1"
}
}
}
}
Provider Configuration Examples
Below are complete install & configure snippets for every first-party storage provider.
Markdown (default)
The built-in markdown provider requires no extra packages and no .kanban.json entry — it is active by default. Cards are stored as .md files with YAML frontmatter.
{
"version": 2
}
SQLite (card.storage + attachment.storage)
# Install
npm install kl-plugin-storage-sqlite better-sqlite3
# Migrate existing cards into SQLite
kl storage migrate-to-sqlite --sqlite-path .kanban/kanban.db
{
"version": 2,
"plugins": {
"card.storage": {
"provider": "sqlite",
"options": {
"sqlitePath": ".kanban/kanban.db"
}
}
}
}
The matching attachment.storage and card.state providers are auto-derived from the same SQLite package/options, so no extra provider block is needed unless you intentionally choose a different attachment backend.
MySQL (card.storage)
# Install
npm install kl-plugin-storage-mysql mysql2
{
"version": 2,
"plugins": {
"card.storage": {
"provider": "mysql",
"options": {
"host": "localhost",
"port": 3306,
"user": "kanban",
"password": "secret",
"database": "kanban_db"
}
}
}
}
Required option: database. All other options (host, port, user, password, ssl) have sensible defaults. Attachments remain on the local filesystem; pair with kl-plugin-attachment-s3 for cloud attachments.
S3 Attachment Storage (attachment.storage)
# Install
npm install kl-plugin-attachment-s3
# Set required environment variables
export KL_S3_BUCKET=my-kanban-attachments
export AWS_REGION=us-east-1
# AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY picked up automatically
# MinIO / LocalStack users also need:
# export KL_S3_ENDPOINT=http://localhost:9000
# export KL_S3_FORCE_PATH_STYLE=true
{
"version": 2,
"plugins": {
"attachment.storage": {
"provider": "kl-plugin-attachment-s3"
}
}
}
All credentials and endpoint configuration are read from environment variables — nothing sensitive goes into .kanban.json.
The shared Plugin Options form only edits non-secret settings. Keep AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and any default region such as AWS_REGION in the host environment or workspace .env.
Storage-backed Card State (card.state)
{
"version": 2,
"plugins": {
"card.storage": {
"provider": "sqlite",
"options": {
"sqlitePath": ".kanban/kanban.db"
}
}
}
}
Actor-scoped unread and open-card state is automatically derived from the active card.storage plugin. Use the same storage package and connection settings — there is no separate card.state package install or second database form to configure.
Combined Example
Use multiple providers together — for example MySQL cards/state with S3 attachments:
{
"version": 2,
"plugins": {
"card.storage": {
"provider": "mysql",
"options": {
"host": "db.example.com",
"database": "kanban_prod"
}
},
"attachment.storage": {
"provider": "kl-plugin-attachment-s3"
}
}
}
Build your own provider
Any npm package that implements the card.storage or attachment.storage capability contract can be used as a provider. See the Plugin System deep dive and the kanban-storage-plugin-author skill for scaffolding a new plugin package.