Skip to main content

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.

markdown default Cards stored as plain .md files with YAML frontmatter. Human-readable, git-friendly, zero dependencies.
sqlite Built-in SQLite provider via kl-plugin-storage-sqlite. Better query performance for large boards. Single-file database.
kl-plugin-storage-mysql External npm package for MySQL/MariaDB-backed card storage. Suitable for shared team deployments.
kl-plugin-attachment-s3 External npm package — store attachments in S3 or any S3-compatible object storage (MinIO, Cloudflare R2, etc.).

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.