Utopia CLI

A dependency-free PHP micro-framework for building command-line tools with task routing, DI, and lifecycle hooks.

Framework
Composer
v0.24.3
42stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
55/100Fair
Development Activity56
Maintenance64
Community28
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
67/100Good
Architecture78
Code Quality75
Innovation58
Learning Curve55

Utopia CLI is a lightweight PHP library, maintained by the Appwrite team, for building command-line applications on top of the Utopia Framework family. It gives PHP developers a structured way to define CLI commands as tasks, wire dependencies through a small container, and hook into init, shutdown, and error stages of a command’s lifecycle, without pulling in a heavyweight framework.

The library is intentionally minimal: a CLI class parses argv into a command name and flags, matches the command against registered Task objects, resolves each task’s declared parameters and dependencies, and runs the callback through a pluggable Adapter. The default Generic adapter runs synchronously; a Swoole adapter is available for coroutine-based worker pools, so the same task definitions can scale from a simple one-off script to a long-running, concurrent CLI daemon.

What You Get

  • A CLI class that parses argv into a command name plus --key=value flags, with automatic camelCase conversion of hyphenated flag names
  • A Task/Hook-based command model where each task declares typed, validated parameters with aliases and defaults
  • A lightweight dependency-injection Container for registering and lazily resolving shared resources across tasks
  • Init, shutdown, and error hooks that run before, after, and on failure of a matched task
  • Pluggable execution adapters: a synchronous Generic adapter and a Swoole adapter for coroutine worker pools
  • Automatic coercion of string CLI input to native PHP types (e.g. boolean flags) at the dispatch boundary, without mutating the underlying validators

Common Use Cases

  • Internal tooling scripts - teams building one-off or scheduled PHP scripts (migrations, cache warmers, data backfills) that need argument parsing and validation without a full framework
  • Framework-adjacent CLIs - projects already using other utopia-php packages (Appwrite included) that want a consistent task/hook model for their command-line entry points
  • Worker daemons - long-running CLI processes that use the Swoole adapter to process jobs across a coroutine worker pool instead of exiting after a single run
  • Composable multi-command apps - applications registering many named tasks (build, deploy, migrate, etc.) behind one entry script, each with independently validated parameters

Under The Hood

Architecture The CLI class is the single dispatch point: its constructor parses $_SERVER['argv'] (or an injected array) into a command name and a flat map of --key=value flags in parse(), then run() hands a closure to the active Adapter which matches the command against registered Task objects (in src/CLI/Task.php, extending Hook from the sibling utopia-php/servers package), resolves each parameter’s validator and each dependency through the internal Container, and calls the task’s action. Init, shutdown, and error hooks wrap that dispatch, and a private Container per CLI instance (optionally chained to a parent container via setContainer()/reset()) provides resource resolution shared across a run. Swapping Generic for Swoole in src/CLI/Adapters/ changes only how start() invokes the callback (once inline vs. across a Swoole\Process\Pool with coroutines), so task and container code is unaffected by the execution model.

Tech Stack The library targets PHP 7.4+ and declares a single runtime dependency, utopia-php/servers (^0.4), for the shared Hook base class; the optional Swoole worker-pool adapter is exercised only via swoole/ide-helper in require-dev, keeping the base install dependency-free as advertised. Autoloading is PSR-4 (Utopia\CLI\ mapped to src/CLI) via Composer, with no build step. Code quality is enforced with PHP_CodeSniffer against the PSR12 standard (phpcs.xml) and Psalm at strict level 7 (psalm.xml), and tests run through PHPUnit (phpunit.xml).

Code Quality Tests exist in tests/CLI/CLITest.php and TaskTest.php, covering resource resolution (including resources that depend on other resources), successful and failing parameter validation, and task dispatch through CLI::run(), using output buffering to assert on task side effects. Exception handling is explicit and typed (Exception with numeric status-like codes on validation failures), naming is consistent camelCase with a dedicated camelCaseIt() helper for flag normalization, and the codebase uses PHP 8-style typed properties and union types (e.g. Validator|callable) despite the 7.4 minimum, gated behind runtime checks rather than static typing alone.

API Design The public surface is small and consistent: task(), init(), shutdown(), error(), setResource()/getResource(), and run() cover the entire lifecycle, and every hook-returning method follows the same fluent pattern. The most distinctive design choice is the coercion layer added at the dispatch boundary in coerce(): rather than mutate the existing pure Validator classes to fix PHP’s implicit string-to-bool casting for boolean CLI flags, the library isolates that behavior in one narrowly-scoped method, keeping validators side-effect-free while still fixing a real correctness gap (--commit=false silently becoming true).

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search