Skip to content

Command-line interface

bin/keayl drives an application from the shell. It is a thin dispatcher over MVC::Keayl::CLI, where each command is a plain function, so the same behavior is available to call directly and to test.

1
keayl <command> [options]

Run keayl help for the command list and keayl version for the installed version.

new

Scaffold a new application skeleton in a subdirectory named after the app:

1
keayl new blog

This writes a starter layout: config/application.json, config/application.raku (which loads the config and routes, wires static asset serving, and returns an MVC::Keayl::Application), config/routes.raku with a root route, a HomeController, an application layout, a HAML view for the index action, bin/server, bin/dev, and bin/test scripts, an assets/ directory with a favicon and stylesheet, a browser spec for the home page, a META6.json, a README.md, and a .gitignore.

scaffold-app($name, :$into) returns the list of files it created, relative to the new application directory. :into defaults to the current directory. The bin/ scripts are written executable.

Running a new app

A scaffolded app ships its own runner scripts so it does not depend on keayl being on the PATH:

1
bin/dev

bin/dev sets the development environment and host/port, then execs bin/server, which loads config/application.raku and serves it with the Cro adapter. Both honor KEAYL_HOST and KEAYL_PORT; bin/dev defaults them to 127.0.0.1:3000.

1
bin/test

bin/test runs the specs/ with behave, filtering the benign socket-teardown noise that browser specs produce. Setting SHOW_CHROME runs the browser specs in a visible window, serially.

The generated META6.json depends on MVC::Keayl and ORM::ActiveRecord, and test-depends on BDD::Behave, BDD::Behave::Playwright, WWW::Playwright, and ORM::Factory, so zef install --deps-only . provisions everything the app and its specs need.

server

Boot the application and serve it over HTTP with the Cro adapter:

1
2
keayl server
keayl s --host 0.0.0.0 --port 8080

server loads config/application.raku, builds the endpoint, and listens until interrupted. The host defaults to 127.0.0.1 and the port to 3000.

build-server($app, :$host, :$port, :$scheme) constructs the Adapter::Cro around the application's endpoint without binding a socket, so the wiring can be inspected on its own.

routes

Print the route table for config/routes.raku:

1
keayl routes

Each row lists the route name, its verbs (joined with a comma), the path, and the target. routes-table(@table) renders the table that route introspection produces; an unnamed route renders with a blank name column.

console

Open a REPL with the application booted and available:

1
2
keayl console
keayl c

console loads and boots config/application.raku, binds it to the $*KEAYL-APP dynamic variable, then reads lines and evaluates each in turn, printing the result. An evaluation error is reported without ending the session.

1
2
keayl> $*KEAYL-APP.environment
development

generate

Run a generator to write controllers, views, models, and route stubs:

1
2
keayl generate controller posts index show
keayl g scaffold post

Each generated file is reported as create; an existing file is reported as exists and left untouched, so a generator can be re-run safely. Names are inflected with a small built-in inflector (camelize, pluralize, singularize) covering the common cases; irregular words may need editing.

controller

1
keayl generate controller posts index show

Writes app/controllers/PostsController.rakumod with a method per action, a HAML view under app/views/posts/ for each action, and a get route stub per action inserted into config/routes.raku. An action method left empty renders its view through the controller's implicit render.

scaffold

1
keayl generate scaffold post

Takes a singular resource name and writes the full CRUD set: an ORM::ActiveRecord model (app/models/Post.rakumod), a controller with index, show, new, create, edit, update, and destroy actions, HAML views (index, show, new, edit, and a shared _form partial), and a resources route inserted into config/routes.raku. The resource name is pluralized for the controller, views, and route.

mailer, job, channel

1
2
3
keayl generate mailer user welcome
keayl generate job cleanup
keayl generate channel chat

mailer writes a MVC::Keayl::Mailer subclass with a method per action and an html and text view for each. job writes a MVC::Keayl::Job subclass with a perform method. channel writes a MVC::Keayl::Cable::Channel subclass with subscribed and unsubscribed callbacks. Each also writes a matching t/ test and specs/ spec stub.

model, migration, resource

1
2
3
keayl generate model post title:string body:text
keayl generate migration create-comments body:text
keayl generate resource post title:string

model writes an ORM::ActiveRecord model and a timestamped db/migrate migration that creates the table, with each name:type becoming a typed column. migration writes just the migration. resource writes a model plus a controller and a resources route. Fields default to string when no type is given.

helper

1
keayl generate helper posts

Writes a helper module (app/helpers/PostsHelper.rakumod). The controller and scaffold generators also write a matching helper module, and keayl new writes a global ApplicationHelper. See view helpers for how helper module subs become bare template calls.

Route insertion

A generator inserts its route stubs just inside the routes (or draw) block of config/routes.raku, skipping any stub already present. If the file has no routes block, the generator still writes the other files and reports that it could not add the routes.

Defaults a new app ships

keayl new writes a few framework defaults:

  • A health-check endpoint at /up (MVC::Keayl::HealthController) that returns 200 with a green page.
  • A PWA manifest at /manifest.json and a service worker at /service-worker.js (MVC::Keayl::PWAController).
  • Static exception pages public/404.html, public/422.html, and public/500.html.
  • An application layout under app/views/layouts/ that the HomeController renders through, linking the generated favicon and stylesheet.
  • MVC::Keayl::Middleware::Static prepended to the stack, serving the assets/ directory under /assets.

The health and PWA controllers are registered in the generated config/application.raku, and the routes are wired in config/routes.raku.