nette/command-line
Nette Command Line is a lightweight PHP library for parsing command-line arguments, options, and commands. It offers automatic help generation, input validation, and a simple API for building CLI tools and console applications.
Framework fit. nette/command-line is a focused, framework-agnostic argument/option parser plus a small terminal helper (Console for color, TTY detection and width). It is not a console application framework in the Symfony Console sense — there is no command registry, no dispatcher, no lifecycle events, and no DI wiring. The description's "commands" should be read as script-level entrypoints, not Artisan-style command classes. For a Laravel/PHP codebase this puts it in direct functional overlap with Artisan/Symfony Console, which the application already ships and which every team member already knows. The honest TPM read: this is not a replacement candidate for Artisan, and pitching it as one would be a hard sell to the engineering team.
Where it genuinely fits. Narrow, well-bounded cases: (a) standalone ops/maintenance scripts deliberately kept outside the Laravel console stack — cron entrypoints, migration shims, infra probes, build tooling, health-check binaries; (b) small companion packages or internal tooling that must run without bootstrapping the full framework; (c) a pre-parser in front of a heavier bootstrap, where you want --help and argument validation before the container is built. If the requirement is "we need one CLI, and it should be Artisan," this package is the wrong answer and should be rejected early.
Integration feasibility. High on the mechanical axis. Composer-installable, no service provider needed, no config publishing, no facade plumbing. Usage is roughly $opts = CommandLine::process() with an option spec, then Console::setup() for colors. There is a PHPUnit extension for asserting CLI behavior, which is a real plus for CI. Risk is concentrated in organizational integration rather than code: introducing a second CLI idiom means two help formats, two error formats, two exit-code conventions, and two sets of docs.
Technical risk.
2026-10-21 last-release date is in the future relative to a normal read. Treat the package's release feed as unreliable until verified against Packagist/GitHub directly; do not let a scraped field drive a decision.Key questions for the team.
Stack fit. Treat this as a build-and-ops tooling dependency, not an application-layer dependency. It belongs in require-dev or in a dedicated tooling package's require, never in the runtime dependency graph of the Laravel app served to users. That single placement decision neutralizes most of the license exposure and all of the framework-coupling risk.
Migration path. There is nothing to migrate. Adoption is additive: pick one script, rewrite its getopt()/$argv handling against CommandLine, ship it. If you later standardize on Artisan instead, deletion is a single-file revert — this is the strongest argument in the package's favor. Avoid any path where application code, controllers, jobs, or service providers take a dependency on Nette\CommandLine.
Compatibility. Verify the required PHP floor against your runtime matrix before committing; recent majors target PHP 8.x while older lines support 7.2, and Laravel's own floor moves. In practice the parser is small and version-tolerant, but pin it and let Dependabot surface majors. Watch one thing specifically: Console's TTY/width detection behaves differently in CI runners, Docker without a TTY, and piped output. Assert on plain-text output in tests rather than on ANSI-colored output.
Sequencing.
--help, a bad-flag error, and a piped-output run in CI before any second script is touched.getopt() or an Artisan command — both already paid for.Maintenance. Low code-churn, but non-zero ownership. A quiet, feature-complete parser will not generate upgrade work; it will generate convention work, because you now maintain two CLI help/error/exit-code styles. Budget documentation effort, not engineering effort.
Support. Small surface area means small support burden, but the support boundary shifts to you: with 37 stars, there is effectively no community Q&A pool, so internal expertise must be seeded deliberately by whoever runs the spike. That person becomes the go-to. Name them.
Scaling. Technically irrelevant — argument parsing does not scale in any meaningful sense; it is O(number of args) at process start. The scaling concern is organizational: every additional CLI dialect multiplies onboarding friction and the chance a new engineer puts a Laravel-dependent import into a tool that was supposed to run without Laravel. Enforce the boundary with a lint rule or a directory-level README, not good intentions.
Failure modes.
--opt= with empty values, and flags after positional arguments are classic parse surprises; pin behavior with tests.Ramp-up. For a PHP developer, hours — the API is small and the docs are decent. The real ramp-up cost is the decision cost: every future CLI task now starts with "Artisan or nette/command-line?" Unless the answer is structurally obvious (no framework bootstrap allowed), that question is pure friction. Recommend adopting only where the answer is unambiguous, and writing that criterion down before the first merge.
How can I help you explore Laravel packages today?