Run your app locally
When you run your app on your machine, there is no Keelson login, so requests carry no user information headers such as X-Keelson-User-Id. With keelson dev serve, your app receives the same headers as on Keelson, and you can switch between users to check its behavior.
Two ways to run locally
Section titled “Two ways to run locally”Through keelson dev serve | KEELSON_LOCAL_MODE=1 (no CLI) | |
|---|---|---|
| User | Switch to anyone in the user list | One fixed user |
| How user information arrives | The same headers as in production | The SDK returns test data (no headers) |
Member list and groups (listMembers and so on) | Returned from the user list (no need to enable the Directory API) | Returned from the user list |
| Requires | The latest Keelson CLI | The latest SDK |
Use keelson dev serve normally. If the CLI is not installed, or only an older CLI is available, start with KEELSON_LOCAL_MODE=1. Your app code is the same either way.
Start with keelson dev serve
Section titled “Start with keelson dev serve”After --, write the command that starts your app’s server.
# Node.jskeelson dev serve -- node server.js
# Pythonkeelson dev serve -- uvicorn main:app --host 127.0.0.1 --port {port}
# Gokeelson dev serve -- go run .- The CLI picks a free port for your app and passes it in the
PORTenvironment variable. It also replaces{port}in the command with that number. Your app must listen on that port on127.0.0.1 - Open
http://localhost:5173/in your browser. Change the port with--port - The CLI sits in front of your app and adds the selected user’s headers (
X-Keelson-User-Id/X-Keelson-User-Email/X-Keelson-User-Name/X-Keelson-User-App-Perms) to every request. As in production, the browser’s cookies andAuthorizationheader do not reach your app - On startup, the CLI prints the app URL, the current user, and how to switch users. Press Ctrl-C to stop it; your app’s server stops too
Switch users
Section titled “Switch users”| Method | How to use it |
|---|---|
| Switch page | Open http://localhost:5173/__keelson/dev in your browser and choose a user. Other open tabs keep the previous user until you reload them |
X-Keelson-Dev-As header | Add X-Keelson-Dev-As: <user ID> to a request to act as that user for that request only. Use it when testing with AI agents or curl |
--as | Run keelson dev serve --as <user ID> -- ... to choose the user at startup |
# Call the API as a user with view permission onlycurl -H "X-Keelson-Dev-As: local-user-003" http://localhost:5173/api/itemsAn ID that is not in the user list returns an error.
User list file
Section titled “User list file”Provide the list of users as a JSON file. It is looked up in this order:
keelson dev serve:--users <file>→./.keelson/dev-users.jsonKEELSON_LOCAL_MODE=1: theKEELSON_LOCAL_USERS_FILEenvironment variable →./.keelson/dev-users.json
{ "users": [ { "id": "sample-alice", "email": "[email protected]", "name": "Alice Smith", "perms": ["view", "manage"] }, ]}| Field | Content |
|---|---|
id | User ID. Must be unique within the list. Any readable string works; it does not need to match production IDs |
email / name | Email address and display name. Empty strings are allowed |
perms | ["view"] (view only) or ["view", "manage"] (with manage permission). Becomes the value of X-Keelson-User-App-Perms |
image_url | Optional. Profile image URL |
- The first user in the list with
manageis the default user - If the specified file is missing or invalid, startup fails with an error
- Without a user list file, four built-in users (
local-user-001tolocal-user-004) are used. Withkeelson dev serve,local-user-003andlocal-user-004have view permission only - Restart after changing the user list
Run without the CLI (KEELSON_LOCAL_MODE=1)
Section titled “Run without the CLI (KEELSON_LOCAL_MODE=1)”Start your app’s server directly with the KEELSON_LOCAL_MODE=1 environment variable.
KEELSON_LOCAL_MODE=1 node server.jsIf your app uses its own user list with keelson dev serve --users <file>, also pass KEELSON_LOCAL_USERS_FILE=<same file> when you start it directly. User IDs then stay the same with or without the CLI.
The Identity SDK does not read headers and returns one fixed user (the first user in the list with manage) as the current user. Without a user list file, it returns a test user with manage permission (local-user-001). You cannot switch users. This test data does not apply to code that reads headers directly.
Get the current user and permissions (getRequestUser)
Section titled “Get the current user and permissions (getRequestUser)”getRequestUser returns the current user and their permissions for this app (perms) from the request headers in one call. It makes no external request. The same code works in production and in both local modes above.
import { getRequestUser } from "@keelsonhq/identity";
app.get("/admin", async (req, res) => { const user = await getRequestUser({ headers: req.headers }); // { id, email, name, perms } if (!user.perms.includes("manage")) return res.status(403).end(); res.send(`Hello, ${user.name ?? user.id}`);});from keelson import identity
user = identity.get_request_user(headers=request.headers)if "manage" not in user.perms: ... # Return 403client, err := identity.New("") // Once at startup
// Inside the handleruser, err := client.GetRequestUser(identity.WithHeaders(r.Header))if err != nil { http.Error(w, "unauthorized", http.StatusUnauthorized) return}canManage := slices.Contains(user.Perms, "manage")A missing user ID header raises an error. perms is X-Keelson-User-App-Perms split into a list, or empty when the header is absent. Display names in non-ASCII scripts, such as Japanese, are read correctly.
Not for production
Section titled “Not for production”These local development features do not work in an app deployed on Keelson.
- If
KEELSON_LOCAL_MODEis set in a deployed app, the SDK raises an error instead of returning test data. RemoveKEELSON_LOCAL_MODE keelson dev servealso refuses to start in a deployed environment