Data & storage
KanbanAI stores state in a local SQLite database and a set of Git worktrees under your home directory. This page summarizes where data lives and how it is managed.Architecture overview
The data layer follows a repository pattern with clear separation between business logic and data persistence:-
core/ package (database-agnostic):
- Defines abstract repository interfaces in
core/src/repos/interfaces.ts - Defines shared type contracts in
core/src/db/types.ts - Core modules depend on interfaces, not concrete database implementations
- No direct Drizzle ORM dependency; business logic is testable in isolation
- Defines abstract repository interfaces in
-
server/ package (persistence layer):
- Owns Drizzle schema definitions in
server/src/db/schema/ - Implements concrete repository classes in
server/src/repos/ - Wires repositories into the core module via dependency injection
- Handles all SQLite operations through Drizzle ORM
- Owns Drizzle schema definitions in
Database
- Engine:
- SQLite via
bun:sqlite, managed through Drizzle ORM (server layer). - Core package is database-agnostic and accesses data through repository interfaces.
- SQLite via
- Location:
- Production (
bun run prod, compiled binaries): defaults tokanban.dbunder the OS-specific data directory (e.g.~/.local/share/kanbanai/kanban.dbon Linux). - Development (
bun run dev): defaults tokanban-dev.dbin the same data directory, so local experiments never touch the production-style database file. - Overrides:
DATABASE_URL– highest precedence everywhere (dev and prod).KANBANAI_DEV_DATABASE_URL– dev-only override used whenDATABASE_URLis unset; accepts the same formats asDATABASE_URL.
- Production (
- Migrations:
- Drizzle migrations (defined under
server/drizzle/*.sql) are bundled intoserver/drizzle/migration-data.generated.tsviascripts/build-drizzle-migration-bundle.tsand embedded into the server/binary. - On server start, migrations are applied automatically before handling requests.
- You can override the migrations directory with
KANBANAI_MIGRATIONS_DIRwhen using external migration files; it should point at a directory containing ordered.sqlfiles (for example, a copy ofserver/drizzle).
- Drizzle migrations (defined under
- Tables:
card_images– stores base64-encoded images attached to cards. Each row containscard_id(FK tocards),images_json(JSON array of image objects withdata,mime, andnamefields), andcreated_at. Images are limited to PNG, JPEG, or WebP format, max 10MB each, max 5 images per card.
Worktrees
- Purpose:
- Attempts run inside dedicated Git worktrees so changes stay isolated from your main repository.
- Location:
- Under
$HOME/.cache/kanban-ai/worktrees/<project>/<attempt>/.... - Paths are derived from project/board IDs and attempt IDs.
- Under
- Lifecycle:
- Created when an Attempt starts or is resumed and needs a workspace.
- Cleaned up when:
- A card is moved to Done and its Attempt is finished (Tasks cleanup listener).
- A project is deleted (Filesystem listener purges worktrees for that repo).
Static assets
- In development:
- The server is API-only; the React app is served by the Vite dev server.
- In production / binaries:
- The built client (
client/dist) is copied intoserver/staticand bundled into the binary. - The prod entry serves the React app and assets from the embedded static bundle.
- You can override the static directory with
KANBANAI_STATIC_DIRto:- Serve a custom
client/dist. - Apply custom branding or external hosting.
- Serve a custom
- The built client (
Configuration summary
Key environment variables related to data & storage:DATABASE_URL– SQLite database location (defaults to OS data dir).KANBANAI_DEV_DATABASE_URL– dev-only database location override; used only bybun run devwhenDATABASE_URLis unset.KANBANAI_MIGRATIONS_DIR– external migrations directory (optional).KANBANAI_STATIC_DIR– external static assets directory (optional).KANBANAI_HOME– base directory for binaries/CLI cache (used by the CLI wrapper; defaults to$HOME).
ops/cli-and-binaries.md.