public function runCommand($argv, $autoMethod = false, $extra = [])
    {
        $command = isset($argv[0]) ? Inflector::underscore($argv[0]) : null;
        $this->OptionParser = $this->getOptionParser();
        try {
            list($this->params, $this->args) = $this->OptionParser->parse($argv);
        } catch (ConsoleException $e) {
            $this->err('Error: ' . $e->getMessage());

            return false;
        }

        if (!empty($extra) && is_array($extra)) {
            $this->params = array_merge($this->params, $extra);
        }
        $this->_setOutputLevel();
        $this->command = $command;
        if (!empty($this->params['help'])) {
            return $this->_displayHelp($command);
        }

        $subcommands = $this->OptionParser->subcommands();
        $method = Inflector::camelize($command);
        $isMethod = $this->hasMethod($method);

        if ($isMethod && $autoMethod && count($subcommands) === 0) {
            array_shift($this->args);
            $this->startup();

            return $this->$method(...$this->args);
        }

        if ($isMethod && isset($subcommands[$command])) {
            $this->startup();

            return $this->$method(...$this->args);
        }

        if ($this->hasTask($command) && isset($subcommands[$command])) {
            $this->startup();
            array_shift($argv);

            return $this->{$method}->runCommand($argv, false, ['requested' => true]);
        }

        if ($this->hasMethod('main')) {
            $this->command = 'main';
            $this->startup();

            return $this->main(...$this->args);
        }

        $this->err('No subcommand provided. Choose one of the available subcommands.', 2);
        $this->_io->err($this->OptionParser->help($command));

        return false;
    }