CLI entrypoint for installation, maintenance, cron slices, and backend-specific admin commands.
The script bootstraps the same core pieces as other server entrypoints (config, loader.php, api.php, base backend class), but sets $cli = true and never speaks HTTP. It connects to PostgreSQL (via PDOExt), Redis, and ensures required backends (authentication, authorization, accounting, users) load before running commands.
-
Global (built-in) commands — flags only, no backend prefix:
php server/cli.php --reindex php server/cli.php --cron=dailyThese are registered under the internal key
#in the global CLI registry (see below). -
Backend-scoped commands — first argument is the backend name from
config.json→backends, then flags for that backend:php server/cli.php mongo --list-indexesThe dispatcher loads that backend instance and calls its
cli($args)method. The backend is responsible for interpreting which flag was passed (often several flags are documented under onecliUsage()tree).
Detection: if argv[1] exists and does not start with -- (e.g. it is mongo), it is treated as the backend name, removed from the parsed $args map, and cli("run", "<backend>", $args) runs. Otherwise dispatch uses #.
After chdir to server/, cli.php scans:
server/cli/*.phpserver/cli/custom/*.php
Each file is expected to define namespace cli { class <Name> { ... } } matching the basename (e.g. cron.php → class cron). The constructor receives &$global_cli and writes command entries.
Built-in modules use the # slot — “global” namespace — and group them under human-readable section titles, for example:
$global_cli["#"]["cron"]["cron"] = [ "value" => [...], "exec" => ... ];$global_cli["#"]["initialization and update"]["reindex"] = [ ... ];
So: # = commands implemented in server/cli/*, not tied to a named backend instance.
For each backend in config["backends"], cli.php calls loadBackend($name) and cliUsage(). The returned array is merged into $global_cli[$backendName].
- Base class
backendimplementscliUsage()as[]andcli($args)as “no-op”. - Concrete backends override
cliUsage()to return nested sections: section title →--flag-name→ metadata (description, optionalvalue/params, optionalstage, etc.). - When a user runs
php cli.php <backend> ..., the matching path calls$instance->cli($args)so the backend can branch on$args(see e.g.files/mongofor GridFS maintenance flags).
Important: For # commands, the registry’s "exec" callable runs directly. For a named backend, any registered flag match triggers the same cli($args) on that backend; the method should handle all flags that backend advertises in cliUsage().
cli($stage, $backend, $args) only runs handlers whose entry matches the current stage (default stage is run if omitted).
init— runs before the database connection is opened (after config is read). Use for early hooks that must not depend on PDO.pre— runs after DB/Redis and required backends are up, beforestartup()(process row, maintenance gate). Entries can set"stage" => "pre"(e.g. exit maintenance mode without hitting the maintenance blocker).run— normal command execution afterstartup().
- Common options:
--parent-pid=<pid>,--debug. - Other
argventries are parsed as--nameor--name=valueinto an$argsassociative array (keys include the--prefix as in code).
If no matching command runs, cliUsage() rebuilds the registry from all backends’ cliUsage(), then prints usage grouped by backend (# first as usage: … <params>, then usage: … <backend> <params>).
core_running_processes: long-running jobs can register; duplicate invocations with the same param string may exit early as “already running”.- Maintenance mode: unless skipped, a DB flag can block CLI until
--exit-maintenance-mode(typicallystage: pre). - Cron: scheduled slices call
cli.phpwith--cron=<part>; the cron CLI module iterates all backends and invokes each backend’scron($part)with Redis locking (seeserver/cli/cron.php).
- Backend base class and
cli/cliUsagehooks - Catalog of backend-defined CLI flags
- Dynamic loading:
loadBackend - Built-in CLI modules live under
server/cli/(and optionalserver/cli/custom/).