KESTREL docs
v1.0.0
Get help
● Start · Without Docker

Local development
the server and the app on your own computer.

For developers who want to change the code. You run the server with Node.js and the app with Flutter, both on your computer, with a SQLite file as the database.

Node.js 22pnpm 10tsxflutter run

01Run the server

  1. Install dependencies.
    cd server
    corepack enable
    pnpm install --frozen-lockfile
  2. Create server/.env.
    cp .env.example .env
    openssl rand -base64 32     # paste the output after KESTREL_MASTER_KEY=
    For local work also set PUBLIC_URL=http://localhost:8080 and CORS_ORIGINS=* in .env.
  3. Start it. The server reads its settings from the environment and does not parse .env itself; pnpm dev passes the file to the runner:
    pnpm dev     # = tsx watch --env-file=.env src/index.ts, restarts on every change
    The log shows [kestrel] 1.0.0 listening on :8080 (sqlite) and, on the first start, the console setup code. The database is ./data/kestrel.db, the console's tables are in ./data/admin.sqlite.
  4. Check it. curl http://localhost:8080/health answers {"ok":true,…}.
pnpm dev

pnpm dev needs server/.env to exist (--env-file stops with an error when the file is missing). pnpm start uses --env-file-if-exists=.env instead, so in production the variables can come from the environment alone.

02Type check, lint, tests and build

pnpm check          # TypeScript type check + ESLint + the test suite (vitest)
pnpm lint           # ESLint only (typescript-eslint, flat config in eslint.config.js)
pnpm format         # Prettier on src/ and test/ (pnpm format:check only reports)
pnpm test           # tests only
pnpm build          # compiles to dist/
pnpm start          # = node --env-file-if-exists=.env dist/src/index.js, as in production

The vendored console in packages/admin-kit is excluded from lint and format.

Production runs the compiled JavaScript with plain node; tsx is a development tool only.

03Run the app

cd app
flutter pub get
flutter run -d chrome --dart-define=KESTREL_API_URL=http://localhost:8080

Use -d macos, an Android emulator or an iOS simulator instead of chrome as you like. An Android emulator reaches your computer at http://10.0.2.2:8080, not localhost.

flutter analyze     # static analysis
flutter test        # the app's tests

The demo build needs no server at all: flutter run -d chrome --dart-define=KESTREL_DEMO=true.

04Where things are

FolderContents
server/src/The server: accounts/, exchanges/ (ccxt adapters, paper, permissions, broker ids), smart/, bots/, algo/, copy/, signals/, scanner/, ai/, journal/, alerts/, notify/, telegram/, safety/, health/, auth/, vault/, admin/, ws/, db/
server/packages/admin-kit/The operator console (MIKODES Admin Kit): server code, contract, built UI and the UI source in ui-src/
server/test/The server tests
app/lib/The Flutter app: config/, core/ (theme, languages), data/ (API client, demo data), domain/, state/, ui/, push/
docs/INSTALL.md, ADMIN.md, PUSH.md, and the API contract API.md with api/*.md
deploy/CaddyfileThe web server configuration used by Docker

The API the app uses is documented in docs/API.md: every route, request and answer. Use it if you build your own client or integration.