PHPackages                             nette/command-line - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. nette/command-line

ActiveLibrary[CLI &amp; Console](/categories/cli)

nette/command-line
==================

Nette Command Line: options and arguments parser.

v1.9.1(2mo ago)371.7M↓47.9%5[1 issues](https://github.com/nette/command-line/issues)10BSD-3-ClausePHPPHP 8.2 - 8.5CI passing

Since Aug 13Pushed 2mo ago19 watchersCompare

[ Source](https://github.com/nette/command-line)[ Packagist](https://packagist.org/packages/nette/command-line)[ Docs](https://nette.org)[ RSS](/packages/nette-command-line/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (5)Versions (16)Used By (10)

Nette Command-Line
==================

[](#nette-command-line)

[![Downloads this Month](https://camo.githubusercontent.com/b6179a6cbf535c2e54a4995559ee745e0e10281d8e1832d2625ceaf19b98a6b0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f6e657474652f636f6d6d616e642d6c696e652e737667)](https://packagist.org/packages/nette/command-line)[![Tests](https://github.com/nette/command-line/workflows/Tests/badge.svg?branch=master)](https://github.com/nette/command-line/actions)[![Coverage Status](https://camo.githubusercontent.com/a66e219678b85c55dd23a7abda6201a588b5849f784ef2c8d782a14e5e4b0705/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6e657474652f636f6d6d616e642d6c696e652f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/nette/command-line?branch=master)[![Latest Stable Version](https://camo.githubusercontent.com/04a50b51b0817a80f0ddbaffb87a530de547b33560f630d80d0d6bc0fe9f3b4a/68747470733a2f2f706f7365722e707567782e6f72672f6e657474652f636f6d6d616e642d6c696e652f762f737461626c65)](https://github.com/nette/command-line/releases)[![License](https://camo.githubusercontent.com/fa7d5fcf2c84b580327af52da95dd751703af65f079dc3c5a0081beac0789718/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4e65772532304253442d626c75652e737667)](https://github.com/nette/command-line/blob/master/license.md)

A lightweight library for building command-line applications in PHP. It provides:

- **Argument parsing** with switches, options, and positional arguments
- **Colorful terminal output** with ANSI support

Install it using Composer:

```
composer require nette/command-line

```

It requires PHP version 8.2 and supports PHP up to 8.5.

If you like Nette, **[please make a donation now](https://nette.org/donate)**. Thank you!

Parsing Command-Line Arguments
==============================

[](#parsing-command-line-arguments)

Every CLI script needs to handle arguments like `--verbose`, `-o output.txt`, or plain file names. The `Parser` class offers the fastest way to get started: just write your help text and let the parser extract option definitions from it:

```
use Nette\CommandLine\Parser;

$parser = new Parser;
$parser->addFromHelp('
	-h, --help              Show this help
	-v, --verbose           Enable verbose mode
	-o, --output      Output file
	-f, --format [type]     Output format (default: json)
	-I, --include ... Include paths
	--dry-run               Show what would be done
');

$args = $parser->parse();
```

That's it. The parser understands that `--verbose` is a switch, `--output` requires a value, `--format` has an optional value with `json` as fallback. Your help text stays in sync with actual option definitions.

The `parse()` method returns an associative array. Keys match option names exactly as defined, including the dashes:

```
[
	'--help' => true,         // or null if not used
	'--verbose' => null,
	'--output' => 'file.txt', // or null if not used
	'--format' => 'json',     // fallback from (default: json)
	'--include' => ['src', 'lib'],
	'--dry-run' => null,
]
```

By default, `parse()` reads from `$_SERVER['argv']`. You can pass a custom array for testing:

```
$args = $parser->parse(['--verbose', '-o', 'out.txt']);
```

Help Text Syntax
----------------

[](#help-text-syntax)

The parser extracts option definitions from formatted help text:

SyntaxMeaning`--verbose`Switch (no value)`-v, --verbose`Switch with short alias`--output `Option with required value`--format [type]`Option with optional value`(default: json)`Sets fallback value`...`Repeatable optionEach line defines one option. Option names must be separated from descriptions by at least two spaces.

Additional Configuration
------------------------

[](#additional-configuration)

Some settings can't be expressed in help text. Pass an array as the second parameter, keyed by option name:

```
$parser->addFromHelp('
	-c, --config    Configuration file
	-I, --include   Include path
	-n, --count      Number of iterations
', [
	'--config' => [
		Parser::RealPath => true,
	],
	'--include' => [
		Parser::Repeatable => true,
	],
	'--count' => [
		Parser::Normalizer => fn($v) => (int) $v,
	],
]);
```

Available keys:

KeyDescription`Parser::Repeatable`Collect multiple values into array`Parser::RealPath`Validate file exists and resolve to absolute path`Parser::Normalizer`Transform function `fn($value) => ...``Parser::Default`Fallback value (same as `(default: x)` in help text)`Parser::Enum`Array of allowed valuesFluent API
==========

[](#fluent-api)

When you need more control over option definitions, use the fluent API with `addSwitch()`, `addOption()`, and `addArgument()` methods. This approach gives you access to all features including normalizers, enums, and precise control over each parameter:

```
use Nette\CommandLine\Parser;

$parser = new Parser;
$parser
	->addSwitch('--verbose', '-v')
	->addOption('--output', '-o')
	->addArgument('file');

$args = $parser->parse();
```

By default, `parse()` reads from `$_SERVER['argv']`. You can pass a custom array for testing:

```
$args = $parser->parse(['--verbose', '-o', 'out.txt', 'input.txt']);
```

Switches, Options, and Arguments
--------------------------------

[](#switches-options-and-arguments)

There are three types of command-line inputs:

**Switches** are flags without values, like `--verbose` or `-v`. They parse as `true` when present, `null` when absent:

```
$parser->addSwitch('--verbose', '-v');
// --verbose  → true
// -v         → true
// (not used) → null
```

**Options** accept values, like `--output file.txt`. The value can be separated by space or `=`:

```
$parser->addOption('--output', '-o');
// --output file.txt    → 'file.txt'
// --output=file.txt    → 'file.txt'
// -o file.txt          → 'file.txt'
// --output             → throws exception (value required)
// (not used)           → null
```

Note that the option itself is always optional - not using it returns null. However, when used, the value is required by default. Set `optionalValue: true` to allow the option without a value (parses as `true`):

```
$parser->addOption('--format', '-f', optionalValue: true);
// --format json        → 'json'
// --format             → true
// (not used)           → null
```

When the same option is used multiple times without `repeatable: true`, the last value wins:

```
$parser->addOption('--output', '-o');
// -o first.txt -o second.txt  → 'second.txt'
```

**Arguments** are positional values without dashes. By default they are required. Set `optional: true` to make them optional:

```
$parser->addArgument('input');
// script.php file.txt  → 'file.txt'
// (not used)           → throws exception

$parser->addArgument('output', optional: true);
// (not used)           → null

$parser->addArgument('output', optional: true, fallback: 'out.txt');
// (not used)           → 'out.txt'
```

Use `fallback` to specify the value when an option or argument is not provided. For options with `optionalValue: true`, note that using the option without a value still parses as `true`, while the fallback is used only when the option is not present at all:

```
$parser->addOption('--format', '-f', optionalValue: true, fallback: 'json');
// --format xml  → 'xml'
// --format      → true (option used without value)
// (not used)    → 'json' (fallback)
```

Arguments can appear anywhere on the command line - they don't have to come after options:

```
// all of these are equivalent:
// script.php --verbose input.txt
// script.php input.txt --verbose
```

Restricting Values with Enum
----------------------------

[](#restricting-values-with-enum)

Limit accepted values to a specific set:

```
$parser->addOption('--format', '-f', enum: ['json', 'xml', 'csv']);
// --format yaml  → throws "Value of option --format must be json, or xml, or csv."
```

Repeatable Options
------------------

[](#repeatable-options)

Set `repeatable: true` to collect multiple values into an array:

```
$parser->addOption('--include', '-I', repeatable: true);
// -I src -I lib  → ['src', 'lib']
// (not used)     → []

$parser->addArgument('files', optional: true, repeatable: true);
// a.txt b.txt    → ['a.txt', 'b.txt']
```

Transforming Values
-------------------

[](#transforming-values)

Use `normalizer` to transform parsed values:

```
$parser->addOption('--count', normalizer: fn($v) => (int) $v);
// --count 42  → 42 (integer)
```

For file path validation, use the built-in `normalizeRealPath`:

```
$parser->addOption('--config', normalizer: Parser::normalizeRealPath(...));
// --config app.ini     → '/full/path/to/app.ini'
// --config missing.ini → throws "File path 'missing.ini' not found."
```

Mixing Both Approaches
----------------------

[](#mixing-both-approaches)

You can combine `addFromHelp()` with fluent methods when you need normalizers for some options:

```
$parser
	->addFromHelp('
		-v, --verbose  Enable verbose mode
		-q, --quiet    Suppress output
	')
	->addOption('--config', '-c', normalizer: Parser::normalizeRealPath(...),
		description: 'Configuration file')
	->addArgument('input', description: 'Input file');
```

Error Handling
--------------

[](#error-handling)

The parser throws `\Exception` for invalid input:

```
use Nette\CommandLine\Parser;

$parser = new Parser;
$parser
	->addOption('--output', '-o')
	->addArgument('file');

try {
	$args = $parser->parse();
} catch (\Exception $e) {
	fwrite(STDERR, "Error: {$e->getMessage()}\n");
	exit(1);
}
```

Common error messages:

ErrorCause`Option --output requires argument.`Option used without required value`Unknown option --foo.`Unrecognized option`Missing required argument .`Required argument not provided`Unexpected parameter foo.`Extra positional argument`Value of option --format must be json, or xml.`Value not in enumUse `isEmpty()` to check if no command-line arguments were provided (i.e., user ran just `script.php` with nothing after it):

```
if ($parser->isEmpty()) {
	$parser->help();
	exit;
}
```

Handling --help and --version
-----------------------------

[](#handling---help-and---version)

When your script has required arguments, running `script.php --help` would normally fail because the required argument is missing. Use `parseOnly()` to check for info options first:

```
$parser = new Parser;
$parser
	->addSwitch('--help', '-h')
	->addSwitch('--version', '-V')
	->addArgument('input');  // required

// First, check info options (no validation, no exceptions)
$info = $parser->parseOnly(['--help', '--version']);

if ($info['--help']) {
	$parser->help();
	exit;
}

if ($info['--version']) {
	echo "1.0.0\n";
	exit;
}

// Now do full parsing with validation
$args = $parser->parse();
```

The `parseOnly()` method:

- Parses only the specified options, ignoring everything else
- Respects aliases (`-h` → `--help`)
- Never throws exceptions
- Returns `null` for options that weren't used

Complete Example
================

[](#complete-example)

Here's a real-world file converter script combining Parser and Console:

```
#!/usr/bin/env php
