CLI Reference
Every Laika project ships with a laika executable, generated by laikait/laika-engine when Composer builds the autoloader. Run php laika <command>.
php laika help # every command, grouped
php laika help model:make # full usage for one command (partial names work: help model)
php laika help is always the authoritative list — it includes commands added by packages and by your own lf-app/Command/ classes.
How Arguments Work
- Options are
--key=value only. --table=users works; --table users does not. Option names are case-insensitive.
- Flags are a bare
--flag (for example queue:retry --all).
- Positional arguments come in order after the command:
php laika model:make User.
- Argument counts are strict. Extra or missing arguments print the usage line and exit with status 1.
- An unknown command suggests the closest matches.
- Names you pass to
*:make commands must be letters and underscores only (/^[a-z_]+$/i) — no digits, no slashes.
Global Install (optional)
composer global require laikait/laika-engine
With Composer’s global vendor/bin on your PATH, run laika (no php prefix) from anywhere inside a Laika project — it finds the project by walking up from the current directory to the first folder containing lf-boot/app.php.
Application
| Command |
Description |
app:start [--host=127.0.0.1] [--port=8000] |
Start PHP’s built-in dev server. A busy port moves to the next free one. Serves public/ and sends every request through public/index.php, so static files follow lf-config/assets.php as in production. Dev only. |
app:sync |
Write the laika and worker executables, ensure lf-storage/ (with a Deny from all .htaccess) and uploads/ exist, wipe lf-storage/cache/, write .htaccess if missing, generate the app key if missing or invalid, and rebuild the resource manifest. Runs on every composer install/update/dump-autoload. Run it by hand to restore a deleted laika or worker. |
app:migrate [--table=<table>] |
Run up() on every discovered schema, then seed() on every schema. --table takes a table name (--table=users), not a class name. |
app:cache |
Compile every resource into lf-storage/cache/resources.php. Used when DEBUG is false. |
app:clear |
Delete the compiled resource manifest. |
cache:clear [--data\|--templates] |
Flush the data cache and delete compiled Twig templates. The only command that clears compiled templates, which Twig does not refresh on its own with DEBUG off. With the memcached driver it clears the whole server. |
cache:forget --key=<key> |
Remove one key from the data cache. |
resource:list [--name=<resource>] |
List every resource, where it was declared, its path and entry count. Exits 1 if a class fails to load or breaks its contract — useful in CI. |
Controllers
| Command |
Description |
controller:make <name> [--method=index] |
Create lf-app/Controller/<name>.php. If the file exists, append the method instead. |
controller:list |
List controller classes. |
controller:remove <name> |
Delete a controller (asks for confirmation). |
controller:rename --old=<name> --new=<name> |
Rename the file and the class (asks for confirmation). |
Models & Schemas
| Command |
Description |
model:make <name> [--table=<table>] [--id=id] [--uid=uid] [--connection=default] |
Create lf-app/Model/<name>.php and lf-app/Schema/<name>Schema.php. --table defaults to the lowercased name. |
model:list |
List models, keyed by table. |
model:remove <name> |
Delete the model and its <name>Schema, without asking. |
model:rename --old=<name> --new=<name> [--table=] [--id=] [--uid=] |
Rename the model and its schema, optionally changing table/id/uid names. |
schema:list |
List schemas app:migrate will run, keyed by table. |
Routes
| Command |
Description |
route:make <name> [--method=get] [--file=web] |
Append Url::get('/<name>', '<Name>Controller@index')->name('<name>'); to lf-routes/<file>.php (created if missing). It does not create the controller. |
route:list [--method=get] |
List routes: method, URI, handler and name. |
Pipelines & Filters
| Command |
Description |
pipeline:make <name> |
Create lf-app/Pipeline/<name>.php. |
pipeline:list |
List pipeline classes. |
pipeline:remove <name> |
Delete a pipeline, without asking. |
pipeline:rename --old=<name> --new=<name> |
Rename a pipeline class and file. |
filter:make <name> |
Create lf-app/Filter/<name>.php. |
filter:list |
List filter classes. |
filter:remove <name> |
Delete a filter (asks for confirmation). |
filter:rename --old=<name> --new=<name> |
Rename a filter class and file. |
Jobs & Queue
| Command |
Description |
job:make <name> [--queue=default] [--max=3] |
Create lf-app/Job/<name>.php. |
job:list |
List job classes. |
job:remove <name> |
Delete a job (asks for confirmation). |
job:rename --old=<name> --new=<name> |
Rename a job class and file. |
queue:work [queue] |
Run the worker in the foreground for one queue (default default). Same as php worker [queue]. |
queue:failed [--queue=<name>] |
List failed jobs. |
queue:retry <id> / queue:retry --all [--queue=<name>] |
Push failed jobs back onto their queue with the attempt count reset. |
queue:flush [--hours=N] |
Delete all failed jobs, or those older than N hours (asks for confirmation). |
See Queue.
Services & Relays
| Command |
Description |
service:make --name=<Name> --class=<Concrete\Class> |
Create lf-app/Service/<Name>.php (the relay) and lf-app/Relay/<Name>.php (the provider that binds --class as a singleton under <name>.accessor). --class must be an existing class. |
service:remove <name> |
Delete both files. |
relay:list |
List every container binding: accessor key → class. |
See Services & Relay.
Templates
| Command |
Description |
template:make <name> [--ext=twig\|html] [--path=<sub/dir>] |
Create template/[<path>/]<name>.<ext>. For a sub-directory use --path — template:make dashboard --path=admin creates template/admin/dashboard.twig. |
template:list |
List template files, grouped by directory. |
Secrets
| Command |
Description |
secret:fix [--byte=32] |
Make sure lf-storage/keys/app.key exists and is valid; generate it only if not. Byte range 16–64. |
secret:generate [--byte=32] |
Force a new key. Invalidates every encrypted value, signed value, CSRF token and JWT issued with the old one. |
nginx
| Command |
Description |
nginx:make [--print] [--force] |
Write nginx.conf (deny rules + front-controller rewrite) as a fragment to include from a server block you already maintain. Keeps anything below its “YOU CAN EDIT AFTER THIS LINE” marker unless --force. --print writes to stdout. |
nginx:server [--domain=localhost] [--port=80] [--php=<X.Y>] [--fastcgi=<socket or host:port>] [--root=<path>] [--upload=20M] [--output=<path>] |
Print a complete, self-contained server block rooted at public/ — rules, rewrite and PHP handler included, no include of any project file. --root is the project path on the target server, without /public. --output writes it to a path, e.g. /etc/nginx/sites-available/example.com — it refuses the project’s own nginx.conf, which is a fragment, not a server block. |
See Deployment.
Commands
| Command |
Description |
command:make <name> [--signature=<group:action>] [--description="..."] |
Create lf-app/Command/<Name>Command.php. |
help [command] |
The grouped command list, or detailed usage for one command. |
What the Generators Create
| Command |
Generated class |
controller:make |
App\Controller\<Name> with one method |
model:make |
App\Model\<Name> extending Laika\Engine\Model\Model ($table, $id, $uid, $connection, $softDelete, $casts) plus App\Schema\<Name>Schema |
pipeline:make |
Implements PipelineInterface; handle() returns $next() |
filter:make |
Implements FilterInterface; terminate() returns $next($response) |
job:make |
Extends Laika\Engine\Queue\Abstracts\Job with handle() and failed() |
service:make |
A Relay class plus a RelayProvider |
command:make |
Implements Laika\Engine\Cli\Contracts\CommandInterface |
template:make |
An HTML/Twig skeleton |
Look over a generated schema before migrating. It adds deleted and deleted_at columns, and its seed() inserts an example row (only while the table is empty). Keep, change or delete them. See Models → Schemas.
Writing Your Own Commands
php laika command:make Report --signature=report:daily --description="Email the daily report"
Any class in lf-app/Command/ that implements Laika\Engine\Cli\Contracts\CommandInterface becomes a command — no registration.
namespace App\Command;
use Laika\Engine\Cli\Contracts\CommandInterface;
use Laika\Engine\Cli\Command\{Argument, Message};
use Laika\Engine\Cli\Table;
class ReportCommand implements CommandInterface
{
public function signature(): string
{
return 'report:daily';
}
/** $args = everything after the signature; return 0 on success */
public function handle(array $args, string $basePath): int
{
$date = Argument::getValue('date', $args, date('Y-m-d')); // --date=2026-09-01
$dry = Argument::getBool('dry', $args); // --dry
if (!$dry && !Argument::readline("Send the report for {$date}?")) {
Message::warning('Cancelled.');
return 1;
}
Table::render('REPORT', ['Metric', 'Value'], [['orders', 42]]);
Message::success('Report sent.');
return 0;
}
public function command(): string
{
return 'php laika report:daily [--date=Y-m-d] [--dry]';
}
public function help(): array
{
return [
'signature' => $this->signature(),
'description' => 'Email the daily report',
'command' => $this->command(),
'inputs' => [],
'params' => [],
];
}
}
| Helper |
Signature |
Argument::getValue |
getValue(string $key, array $args, null\|int\|string $default = null): null\|int\|string |
Argument::getBool |
getBool(string $key, array $args, bool $default = false): bool |
Argument::readline |
readline(string $message, array $accepted = ['y','n'], string\|array $positive = 'y'): bool |
Message::success/error/info/warning/suggestion |
(string $message, ...): void — coloured output |
Table::render |
render(string $title, array $headers, array $rows): void |
Things to know:
- Commands are created with
new $class() — no constructor injection. Resolve services through relays inside handle().
- Built-in signatures always win. A command whose signature is already taken is skipped with an error.
- The full framework is booted, so relays,
config(), models and hooks all work.
Example Workflow
# A model + schema for the users table
php laika model:make UsersModel --table=users
# A controller, and a route pointing at it
php laika controller:make UsersController --method=index
php laika route:make users # → Url::get('/users', 'UsersController@index')->name('users')
# Create the table
php laika app:migrate --table=users
# Middleware
php laika pipeline:make Authenticate
php laika filter:make LogAccess
# Check what got registered
php laika route:list
php laika resource:list