Self-host the server
There is no published server image. You run Postgres, the API in apps/api, and the web app in apps/web from a checkout of x0ba/skl. You need Docker for Postgres, Node, and pnpm. CI uses Node 22.
1. Start Postgres
From the repository root:
docker compose up -d postgres
This starts postgres:16-alpine on localhost:5432 with user skl, password skl, and database skl.
2. Start the API
cd apps/api
cp .env.example .env
pnpm install
pnpm migrate
pnpm dev
The API listens on http://localhost:8787. GET /v1/health returns {"ok":true}.
Edit .env to change these values:
DATABASE_URL, defaultpostgres://skl:skl@localhost:5432/skl.PORT, default8787.SKL_WEB_ORIGIN, defaulthttp://localhost:3000. Used in the device login URL and for CORS.SKL_API_ORIGIN, defaulthttp://localhost:8787.CLERK_SECRET_KEYand the other Clerk keys. Required for browser sign-in.ALLOW_DEV_AUTH. Controls whether the API acceptsAuthorization: Bearer dev:<user_id>from anyone, with no password. Unset means on whenCLERK_SECRET_KEYis empty and off when it is set.trueforces it on even with Clerk configured.falseforces it off.
Dev auth lets any caller act as any user. Leave ALLOW_DEV_AUTH unset or set it to false on any API that other machines can reach. Set ALLOW_DEV_AUTH=true only on a machine you trust, for local development.
3. Start the web app
The web app serves /device, where you approve CLI logins.
cd apps/web
cp .env.example .env.local
pnpm install
pnpm dev
Open http://localhost:3000.
4. Point the CLI at your API
skl --api-base http://localhost:8787 login
To make it stick, set API_BASE=http://localhost:8787 in your environment or api_base = "http://localhost:8787" in ~/.config/skl/config.toml. skl login writes api_base to the config file after a successful login.
While dev auth is on, skl login --dev-user <id> stores a dev:<id> token without the browser step:
skl --api-base http://localhost:8787 login --dev-user alice
What you take on
TLS, backups, Clerk, and updates are yours. The server stores skill content as it is, so anyone with access to the database can read every skill.