CLI
Keryx includes a CLI (keryx) for common project tasks. When installed locally, run it with bunx keryx. When scaffolding a brand-new project, use bunx keryx@latest.
The CLI has two kinds of commands: framework commands that ship with Keryx, and action commands that are automatically generated from the actions you write.
Framework Commands
These are built-in commands for managing your project.
keryx new
Scaffold a new Keryx project. See Getting Started for the full walkthrough.
bunx keryx new my-appOptions:
-y/--yes— skip prompts, use defaults--no-interactive— skip prompts, use defaults (same effect as-y)--no-db— skip database setup files--no-example— skip the example action--force— scaffold into an existing directory; files that already exist are left untouched (merge-skip, never overwrite)
keryx new also scaffolds OAuth template files into templates/ (login/signup page, success page, shared CSS, and the lion SVG). These are customizable — see the MCP guide for details.
keryx generate
Generate a new component file with boilerplate. Aliased as keryx g.
bunx keryx generate <type> <name>Supported Types
| Type | Directory | Example |
|---|---|---|
action | actions/ | keryx g action user:delete |
initializer | initializers/ | keryx g initializer cache |
middleware | middleware/ | keryx g middleware auth |
channel | channels/ | keryx g channel notifications |
ops | ops/ | keryx g ops UserOps |
plugin | plugins/ | keryx g plugin analytics |
Naming Conventions
Colon-separated names create nested directories and map to routes for actions:
keryx g action user:delete
# Creates: actions/user/delete.ts
# Route: /api/user/delete
# Class: UserDeleteSimple names stay flat:
keryx g initializer cache
# Creates: initializers/cache.ts
# Class: CacheOptions
--dry-run— preview what would be generated without writing files--force— overwrite existing files--no-test— skip generating the companion test file
By default, each generated component also creates a matching test file in __tests__/.
Example Output
$ bunx keryx g action user:delete
Generated:
actions/user/delete.ts
__tests__/actions/user/delete.test.tsThe generated action file:
import { z } from "zod";
import { Action, type ActionParams, HTTP_METHOD } from "keryx";
export class UserDelete implements Action {
name = "user:delete";
description = "TODO: describe this action";
inputs = z.object({});
web = { route: "/user/delete", method: HTTP_METHOD.GET };
async run(params: ActionParams<UserDelete>) {
// TODO: implement
return {};
}
}keryx upgrade
Update framework-owned files (config, built-in actions, OAuth templates) to match the installed version of Keryx.
bunx keryx upgradeOptions:
--dry-run— show what would change without writing--force— overwrite all framework files without confirmation-y/--yes— overwrite all framework files without confirmation (same effect as--force)
keryx build
Pre-generate swagger response schemas so the server can skip the expensive and slow ts-morph analysis at startup. This is recommended for production deploys.
bunx keryx buildThe command writes .cache/swagger-schemas.json. When the server starts and finds a valid cache, it skips ts-morph entirely.
Recommended Dockerfile pattern:
COPY . .
RUN bun keryx.ts build
CMD ["bun", "keryx.ts", "start"]If you skip this step, the server will attempt to generate schemas on the fly at startup. On machines with limited memory this may cause an out-of-memory crash. If ts-morph fails without crashing the process, the server will start with empty swagger response schemas.
keryx start
Start the server.
bunx keryx startkeryx actions
List all discovered actions with their routes and descriptions.
bunx keryx actionsAction Commands
Every action you write is automatically registered as a CLI command — no extra configuration needed. Keryx discovers your actions and adds them to the CLI, so you can invoke any action directly from the terminal:
bunx keryx <action-name> [--input value]When you run an action this way, Keryx starts the server in CLI mode (initializers run, but the web server doesn't bind a port), executes the action, prints the JSON result, and exits.
Inputs as Flags
Action inputs map directly to CLI flags. Required inputs in your Zod schema become required CLI options; optional inputs become optional flags:
bunx keryx user:create --name evan --email "evan@example.com" --password secretRun --help on any action to see its available parameters:
bunx keryx user:create --helpQuiet Mode
By default, Keryx logs server startup output alongside the action response. Use -q / --quiet to suppress everything except the action's JSON result — handy for piping into jq or other tools:
bunx keryx status -q | jqYou can also set CLI_QUIET=true as an environment variable to make quiet mode the default.
Error Output
When an action throws a TypedError, the CLI includes the error's message, type, key, and value in the JSON output. Stack traces are included by default; set CLI_INCLUDE_STACK_IN_ERRORS=false to omit them.