Kanso Documentation

Get started

A running instance, and a ticket in it.

Two things to configure, one wizard, and six keys. Everything else has a defensible default or is derived, and can be changed later from settings.

Run it against your own Postgres

One image — the front end, the API and a proxy that routes between them — on one origin. Kanso does not ship a database: a container that owns your data is a container you cannot restart without thinking about it.

docker run -d -p 80:80 -p 443:443 -v kanso-data:/data \
  -e KANSO_PUBLIC_URL=https://kanso.example.com \
  -e SPRING_DATASOURCE_URL='jdbc:postgresql://db.internal:5432/kanso?sslmode=require' \
  -e SPRING_DATASOURCE_USERNAME=kanso -e SPRING_DATASOURCE_PASSWORD=… \
  ghcr.io/tykok/kanso

Those two things — the URL it lives at and the database it writes to — are the whole configuration. Caddy obtains a certificate for that host on its own, for linux/amd64 and linux/arm64 alike.

No database yet? docker/docker-compose.yml ships a postgres:16-alpine beside the image. Copy it, change KANSO_PUBLIC_URL and the password, then docker compose up -d.

The host in SPRING_DATASOURCE_URL is resolved from inside the container. On Compose it is the service name; for a Postgres running on this machine but outside Docker it is host.docker.internal. It is never localhost, which is the container itself.

Or run it from source

The repository's own docker-compose.yml is a different thing: it builds both applications from source and serves them on two ports, which is what the Playwright suite drives. Fill in OIDC credentials in .env, or set KANSO_AUTH_MODE=dev.

cp .env.example .env
docker compose up
localhost:3000
The web application
localhost:8080
The REST API, the WebSocket and the MCP endpoint
localhost:8080/actuator/health
Liveness, readiness and the database check

To run the applications outside Docker and keep only Postgres in it:

docker compose up -d db                      # Postgres only
cd apps/api && ./gradlew bootRun             # http://localhost:8080
cd apps/web && pnpm install && pnpm dev      # http://localhost:3000

The setup wizard

The first launch opens a wizard rather than a login screen, because there is nobody to log in as yet. It has four steps and only the first is required.

  1. The owner account. An email address and a password. This account can configure the instance; nothing else can.
  2. Notion. Optional, and reopenable. Connecting it is a page of its own — see Notion.
  3. Google sign-in. Optional. An instance can run on passwords alone.
  4. Preferences. Theme, accent, sidebar. Per person, not per instance.

Every step after the account is skippable and reopenable from settings — , — so you can be filing tickets in under a minute and decide the rest later.

Whoever comes next arrives through an invitation link the owner generates, and sees only the preferences step. Notion and Google are instance-wide, so a member has nothing to decide there and the steps are hidden rather than shown disabled.

The first team, and the first ticket

A ticket belongs to a team, so a team comes first — the sidebar creates one. From then on the keyboard is the interface, and the same keys work in the list, on the board and on the timeline.

c
Create, from anywhere
e
Rename in place
1 … 6
Your team's first six statuses, in its own order
⇧s
Pick a status by name, including a seventh
⌘K
The command palette (Ctrl+K elsewhere)
?
Every shortcut, as this account has them bound

The ticket gets a short identifier of its team's own — KAN-1, then KAN-2 — allocated inside the insert transaction from a counter on the team row. Two people pressing c at the same moment get 41 and 42: no gaps, no collisions.

Where to go next

  • The model — teams, projects, tickets, statuses and the documents beside them.
  • Working in Kanso — one query drawn three ways, filters, cycles, workload, triage.
  • Notion — what is mirrored, what is not, and why Notion never wins.
  • Agents and the API — the MCP door for an agent, tokens and webhooks for a service.
  • Self-hosting — TLS, what /data holds, and what to back up.