{"id":19039611,"url":"https://github.com/windwalker-io/console","last_synced_at":"2026-03-11T23:33:54.227Z","repository":{"id":20779959,"uuid":"24064884","full_name":"windwalker-io/console","owner":"windwalker-io","description":"[DEPRECATED] A powerful console package for PHP, an alternative of Symfonys.","archived":false,"fork":false,"pushed_at":"2023-07-18T08:29:54.000Z","size":228,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-12-21T15:09:04.990Z","etag":null,"topics":["cli","cli-app","cli-framework","console","console-application","console-framework"],"latest_commit_sha":null,"homepage":"https://github.com/ventoviro/windwalker","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/windwalker-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2014-09-15T16:56:00.000Z","updated_at":"2024-12-16T13:47:11.000Z","dependencies_parsed_at":"2022-08-24T14:09:30.621Z","dependency_job_id":null,"html_url":"https://github.com/windwalker-io/console","commit_stats":{"total_commits":94,"total_committers":2,"mean_commits":47.0,"dds":"0.010638297872340385","last_synced_commit":"f942e801656d28be5f603e532bdb251da2e9a607"},"previous_names":["ventoviro/windwalker-console"],"tags_count":80,"template":false,"template_full_name":null,"purl":"pkg:github/windwalker-io/console","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwalker-io%2Fconsole","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwalker-io%2Fconsole/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwalker-io%2Fconsole/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwalker-io%2Fconsole/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/windwalker-io","download_url":"https://codeload.github.com/windwalker-io/console/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwalker-io%2Fconsole/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30406998,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T22:36:59.286Z","status":"ssl_error","status_checked_at":"2026-03-11T22:36:57.544Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","cli-app","cli-framework","console","console-application","console-framework"],"created_at":"2024-11-08T22:17:54.005Z","updated_at":"2026-03-11T23:33:54.211Z","avatar_url":"https://github.com/windwalker-io.png","language":"PHP","readme":"# Windwalker Console\n\nThe Windwalker Console package provides an elegant and nested command structure for your cli application.\n\n## Installation via Composer\n\nAdd this to the require block in your `composer.json`.\n\n``` json\n{\n    \"require\": {\n        \"windwalker/console\": \"~3.0\"\n    }\n}\n```\n\n## The Nested Command Structure\n\n```\n          Console Application (RootCommand)\n                         |\n              ----------------------\n              |                    |\n          CommandA              CommandB\n              |                    |\n        ------------          ------------\n        |          |          |          |\n    CommandC   CommandD    CommandE   CommandF\n```\n\nIf we type:\n\n``` bash\n$ php cli/console.php commandA commandC foo bar -a -bc -d=e --flower=sakura\n```\n\nThen we will been direct to `CommandC` class, and the following `foo bar` will be arguments.\n\n``` php\nclass CommandC extend AbstractCommand\n{\n    public function execute()\n    {\n        $arg1 = $this-\u003egetArgument(0); // foo\n        $arg2 = $this-\u003egetArgument(0); // bar\n        \n        $opt = $this-\u003eio-\u003eget('d') // e\n        $opt = $this-\u003eio-\u003eget('flower') // sakura\n    }\n}\n```\n\n## Initialising Console\n\nConsole is the main application help us create a command line program.\n\nAn example console application skeleton in `cli/console.php` file:\n\n``` php\n\u003c?php\n\n// Load the Composer autoloader\ninclude __DIR__ . '/../vendor/autoload.php';\n\nuse Windwalker\\Console\\Console;\n\n$console = new Console;\n\n$console-\u003eexecute();\n```\n\nThe `execute()` will find commands matched the cli input argument. If there are not any command registered,\nconsole will execute the `Default Command`.\n\n### Default RootCommand\n\n`RootCommand` is a command object extends from base `Command`. It provides some useful helpers,\nwe can list all commands by typing:\n\n``` bash\n$ php cli/app.php\n```\n\nBy default, the output is:\n\n``` bash\nWindwalker Console - version: 1.0\n------------------------------------------------------------\n\n[console.php Help]\n\nThe default application command\n\nUsage:\n  console.php \u003ccommand\u003e [option]\n\n\nOptions:\n\n  -h | --help       Display this help message.\n  -q | --quiet      Do not output any message.\n  -v | --verbose    Increase the verbosity of messages.\n  --ansi            Set 'off' to suppress ANSI colors on unsupported terminals.\n\n\nWelcome to Windwalker Console.\n```\n\n### Set Handler for RootCommand\n\nWe can add closure to every commands, that this command will execute this function first. Use `setHandler()` on\n`$console`, the Console will auto pass the code to RootCommand:\n\n``` php\n\u003c?php\n// cli/console.php\n\n// ...\n\n$console-\u003esetHandler(\n\tfunction($command)\n\t{\n\t\t$command-\u003eout('This is default command.');\n\n\t\treturn 0; // Return exit code.\n\t}\n);\n\n$console-\u003eexecute();\n```\n\nThis code will do same action:\n\n``` php\n\u003c?php\n// cli/console.php\n\n// ...\n\n$console-\u003egetRootCommand()\n    -\u003esetHandler(\n        function($command)\n        {\n            $command-\u003eout('This is default command.');\n\n            return 0; // Return exit code.\n        }\n    );\n\n$console-\u003eexecute();\n```\n\nRetype `$ php cli/console.php` and output:\n\n```\nThis is default command.\n```\n\nIf we want to get help again, just type:\n\n``` bash\n$ cli/console.php help\n\n# OR\n\n$ cli/console.php --help\n```\n\n\u003e Note: Command only return integer between 0 and 255, `0` means success, while others means failure or other status.\n  The exit code of Unix/Linux meaning please see: [Exit Codes Meanings](http://www.tldp.org/LDP/abs/html/exitcodes.html)\n\n## Add Help Message to Console\n\nConsole includes some help message like: `name`, `version`, `description`, `usage` and `help`.\n\nIf we add this messages to Console:\n\n``` php\n// cli/console.php\n\n// ...\n\n$console = new \\Windwalker\\Console\\Console;\n\n$console-\u003esetName('Example Console')\n\t-\u003esetVersion('1.2.3')\n\t-\u003esetUsage('console.php \u003ccommands\u003e \u003carguments\u003e [-h|--help] [-q|--quiet]')\n\t-\u003esetDescription('Hello World')\n\t-\u003esetHelp(\n\u003c\u003c\u003cHELP\nHello, this is an example console, if you want to do something, see above:\n\n$ foo bar -h =\u003e foo bar --help\n\n---------\n\n$ foo bar yoo -q =\u003e foo bar yoo --quiet\nHELP\n\t);\n\n// ...\n```\n\nThe help will show:\n\n![console example](https://cloud.githubusercontent.com/assets/1639206/4477512/bae50278-497e-11e4-92a6-0f998461442b.png)\n\n## Add First Level Command to Console\n\nNow, we just use the default root command. But there are no first level command are available to call except `HelpCommand`.\n\nWe can add a new command by this code:\n\n``` php\n\u003c?php\n// cli/console.php\n\n$console-\u003eregister('foo')\n\t-\u003esetDescription('This is first level foo command.')\n\t-\u003esetUsage('foo command [--option]')\n\t-\u003esetHelp('foo help')\n\t-\u003esetHandler(\n\t\tfunction($command)\n\t\t{\n\t\t\t$command-\u003eout('This is Foo Command executing code.');\n\t\t}\n\t);\n```\n\nThen we type:\n\n``` bash\n$ cli/console.php foo\n```\n\nWe will get:\n\n```\nThis is Foo Command executing code.\n```\n\nIf we type help:\n\n```\n$ cli/console.php -h\n```\n\nThe foo command description has auto added to default command arguments list.\n\n![foo-help](http://cl.ly/SOfp/p2013-11-10-3.jpg)\n\n## Declaring Command Class\n\nWe can create our own command object instead setting it in runtime.\n\nThis is an example FooCommand declaration:\n\n``` php\n\u003c?php\n// src/Myapp/Command/FooCommand.php\n\nnamespace Myapp\\Command;\n\nuse Windwalker\\Console\\Command\\Command;\n\nclass FooCommand extends Command\n{\n    protected $name  = 'foo';\n    protected $usage = 'foo command [--option]';\n    protected $help  = 'foo help';\n    protected $description = 'This is first level foo command.';\n\n    public function initialise()\n    {\n        // We can also set help message in initialise method \n        $this-\u003esetDescription('This is first level foo command.')\n            -\u003esetUsage('foo command [--option]')\n            -\u003esetHelp('foo help');\n    }\n\n    public function doExecute()\n    {\n        $this-\u003eout('This is Foo Command executing.');\n    }\n}\n\n```\n\nThen we register it in Console:\n\n``` php\n\u003c?php\n// cli/console.php\n\n$console-\u003eaddCommand(new FooCommand);\n```\n\n## Get Arguments and Options\n\nWe can use this code to get arguments and options, setting them in `FooCommand`.\n\n``` php\n// src/Myapp/Command/FooCommand.php\n\npublic function initialise()\n{\n    // Define options first that we can set option aliases.\n    $this-\u003eaddOption(array('y', 'yell')) // First element `y` will be option name, others will be alias\n        -\u003ealias('Y') // Add a new alias\n        -\u003edefaultValue(0)\n        -\u003edescription('Yell will make output upper case.');\n        \n    // Global options will pass to every child.\n    $this-\u003eaddGlobalOption('s')\n        -\u003edefaultValue(0)\n        -\u003edescription('Yell will make output upper case.');\n}\n\npublic function doExecute()\n{\n    $name = #this-\u003egetArgument(0);\n\n    if (!$name)\n    {\n        $this-\u003eio-\u003ein('Please enter a name: ');\n    }\n\n    $reply = 'Hello ' . $name;\n\n    if ($this-\u003egetOption('y'))\n    {\n        $reply = strtoupper($reply);\n    }\n\n    if ($this-\u003egetOption('q'))\n    {\n        $reply = strtolower($reply);\n    }\n\n    $this-\u003eout($reply);\n}\n```\n\nIf we type:\n\n``` bash\n$ php cli/console.php foo Asika --yell\n\n# OR\n\n$ php cli/console.php foo Asika -y\n```\n\nThe `getOption()` method will auto detect option aliases, then we can get:\n\n```\nHELLO: ASIKA\n```\n\n\u003e Note: We have to use `addOption()` to define options first, then the `$this-\u003egetOption('x')` will be able to \nget the input option which we want. If we didn't do this, we have to use `$this-\u003eio-\u003eget('x')` \nto get option value, but this way do not support option aliases.\n\n## Add Second Level Commands and more...\n\nNow, FooCommand is the first level commands in our command tree, if we want to add several commands under FooCommand, \nwe can use `addCommand()` method. Now we add two `bar` and `yoo` command under `FooCommand`.\n\n### Adding command in runtime.\n\nWe can use `addCommand()` to add a command as other commands' child.\n\nIf a command has one or more children, the arguments means to call children which the name equals to this argument.\n\nIf a command has no child, Command object will run handler closure if has set, or run `doExecute()` if handler not set. \nThen the remaining arguments will be able to get by `$this-\u003egetArgument({offset})`.\n\n``` php\n\u003c?php\n// src/Myapp/Command/FooCommand.php\n\nuse Windwalker\\Console\\Option\\Option;\n\n//...\n\n    public function initialise()\n    {\n        $this-\u003eaddCommand('bar')\n            -\u003edescription('Bar description.');\n            \n        $this-\u003eaddCommand('yoo')\n            -\u003edescription('Yoo description.')\n            -\u003eaddOption(new Option(array('y', 'yell'), 0))\n            -\u003eaddGlobalOption(new Option('s', 0, 'desc'));\n    }\n```\n\n### Adding command by classes\n\nWe declare `BarCommand` and `YooCommand` class first.\n\n``` php\n\u003c?php\n// src/Myapp/Command/Foo/BarCommand.php\n\nnamespace Myapp\\Command\\Foo;\n\nuse Windwalker\\Console\\Command\\Command;\n\nclass BarCommand extends Command\n{\n    protected $name = 'bar';\n    protected $usage = 'bar command [--option]';\n    protected $help  = 'bar help';\n    protected $description = 'This is second level bar command.';\n\n    public function initialise()\n    {\n        $this-\u003eaddOption(new Option(array('y', 'yell'), 0))\n            -\u003eaddGlobalOption(new Option('s', 0, 'desc'));\n    }\n\n    public function doExecute()\n    {\n        $this-\u003eout('This is Bar Command executing.');\n        \n        $arg1 = $this-\u003egetArgument(0);\n        \n        if ($arg1)\n        {\n            $this-\u003eout('Argument1: ' . $arg1);\n        }\n    }\n}\n```\n\nThen register them to `FooCommand`:\n\n``` php\n\u003c?php\n// src/Myapp/Command/FooCommand.php\n\nuse Myapp\\Command\\Foo\\BarCommand;\nuse Myapp\\Command\\Foo\\YooCommand;\n\n//...\n\n    public function initialise()\n    {\n        $this-\u003eaddCommand(new BarCommand)\n            -\u003eaddCommand(new YooCommand);\n    }\n```\n\nOK, let's typing:\n\n``` bash\n$ cli/console.php foo bar\n```\n\nWe get:\n\n```\nThis is Bar Command executing code.\n```\n\nAnd typing\n\n``` bash\n$ cli/console.php foo bar sakura\n```\n\nget:\n\n```\nThis is Bar Command executing code.\nArgument1: sakura\n```\n\n### Get Child by Path\n\n``` php\n$command = $console-\u003egetCommand('foo/bar'); // BarCommand\n\n// OR\n\n$command = $command-\u003egetChild('foo/bar/baz');\n```\n\n## The Prompter\n\nPrompter is a set of dialog tools help us asking questions for user.\n\n``` php\n$prompter = new \\Windwalker\\Console\\Prompter\\TextPrompter;\n\n$name = $prompter-\u003eask('Tell me your name:', 'default');\n```\n\nOR set question in constructor.\n\n``` php\n$prompter = new TextPrompter('Tell me your name: ', $this-\u003eio);\n\n// If argument not exists, auto ask user.\n$name = $this-\u003egetArgument(0, $prompter);\n```\n\n### Validate Input Value\n\n``` php\n$prompter = new \\Windwalker\\Console\\Prompter\\ValidatePrompter;\n\n$prompter-\u003esetAttempt(3);\n\n$prompter-\u003eask('Please enter username: ');\n```\n\nIf we didn't type anything, ValidatePrompter will try ask us three times (We set this number by `setAttempt()`).\n\n```\nPlease enter username:\n  Not a valid value.\n\nPlease enter username:\n  Not a valid value.\n\nPlease enter username:\n  Not a valid value.\n```\n\nWe can set closure to validate our rule:\n\n``` php\n$prompter-\u003esetAttempt(3)\n    -\u003esetNoValidMessage('No valid number.')\n    -\u003esetHandler(\n    function($value)\n    {\n        return $value == 9;\n    }\n);\n\n$prompter-\u003eask('Please enter right number: ');\n```\n\nResult\n\n```\nPlease enter right number: 1\nNo valid number.\n\nPlease enter right number: 2\nNo valid number.\n\nPlease enter right number: 3\nNo valid number.\n```\n\nIf validate fail, we can choose shut down our process:\n \n``` php\n// ...\n\n$prompter-\u003efailToClose(true, 'Number validate fail and close');\n\n$prompter-\u003eask('Please enter right number: ');\n```\n\nResult\n\n```\nPlease enter right number:\nNo valid number.\n\nPlease enter right number:\nNo valid number.\n\nPlease enter right number:\nNo valid number.\n\nNumber validate fail and close\n```\n\n### Select List\n\n``` php\n$options = array(\n    's' =\u003e 'sakura',\n    'r' =\u003e 'Rose',\n    'o' =\u003e 'Olive'\n);\n\n$prompter = new \\Windwalker\\Console\\Prompter\\SelectPrompter('Which do you want: ', $options);\n\n$result = $prompter-\u003eask();\n\n$command-\u003eout('You choose: ' . $result);\n```\n\nOutput\n\n```\n  [s] - sakura\n  [r] - Rose\n  [o] - Olive\n\nWhich do you want: r\nYou choose: r\n```\n\n### Boolean Prompter\n\nBooleanPrompter convert input string to boolean type, the (y, yes, 1) weill be `true`, (n, no, 0, null) will be `false`.\n\n``` php\n$prompter = new \\Windwalker\\Console\\Prompter\\BooleanPrompter;\n\n$result = $prompter-\u003eask('Do you wan to do this [Y/n]: ');\n\nvar_dump($result);\n```\n\nResult\n\n```\nDo you wan to do this [Y/n]: y\nbool(true)\n```\n\n### Available Prompters\n\n- TextPrompter\n- SelectPrompter\n- CallbackPrompter\n- ValidatePrompter\n- NotNullPrompter\n- PasswordPrompter\n\n### Available Prompters\n\n## HelpCommand\n\n`HelpCommand` will auto generate help list for us.\n\nWhen we use `addCommand()`, `addOption()` and set some description or other information to these objects, they will save all information in it. Then when we type `$ cli/console.php help somethine` or `$ cli/console.php somethine --help`, The HelpCommand will return the help message to us.\n\nEvery command has these information, you can use setter and getter to access them:\n\n* `Name` (Command name. The name of RootCommand is file name.)\n* `Description` (Command description, will show after title in help output.)\n* `Usage` (Will show in help output of current command.)\n* `Help` (Will show in the help output bottom as a manual of current command)\n\nThe Console information:\n\n* `Name` (Name of this application, will show as title in help output.)\n* `Description` (RootCommand description.)\n* `Usage` (RootCommand usage.)\n* `Help` (RootCommand help)\n\n### Use Your Own Descriptor\n\nIf you want to override the `Descriptor` for your apps, you can do this:\n\n``` php\n\u003c?php\nuse Myapp\\Command\\Descriptor\\XmlDescriptorHelper;\nuse Myapp\\Command\\Descriptor\\XmlCommandDescriptor;\nuse Myapp\\Command\\Descriptor\\XmlOptionDescriptor;\n\n// ...\n\n$descriptor = new new XmlDescriptorHelper(\n    new XmlCommandDescriptor,\n    new XmlOptionDescriptor\n);\n\n$console-\u003egetRootCommand()\n    -\u003egetChild('help')\n    -\u003esetDescriptor($descriptor);\n\n// ...\n```\n\n## Use Command Without Console\n\nWe can using `Command` without, please see [Command README](Command).\n\n## Credits\n\nWindwalker Console incorporated many ideas from other CLI packages. \nBelow is a short list of projects which Windwalker drew inspiration.\n\n- [Symfony Console](https://github.com/symfony/Console)\n- [Commando](https://github.com/symfony/Console)\n- [CLIFramework](https://github.com/c9s/CLIFramework)\n- [Composer](https://github.com/composer/composer)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwindwalker-io%2Fconsole","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwindwalker-io%2Fconsole","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwindwalker-io%2Fconsole/lists"}