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:
--no-interactive/-y— skip prompts, use defaults--no-db— skip database setup files--no-example— skip the example action
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 |
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: "/api/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/-y— overwrite all framework files without confirmation
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.