VOOZH about

URL: https://deepwiki.com/guanguans/ai-commit/5.3-cli-based-generators

⇱ CLI-Based Generators | guanguans/ai-commit | DeepWiki


Loading...
Menu

CLI-Based Generators

This page documents the three CLI-based commit message generators: BitoCliGenerator, GithubCopilotCliGenerator, and GithubModelsCliGenerator. These generators differ from API-based generators in that they shell out to locally installed command-line tools rather than making HTTP requests. For API-based generators (OpenAI, Moonshot, ErnieBot), see 5.2. For the shared generator infrastructure (AbstractGenerator, GeneratorContract, GeneratorManager), see 5.1.


Overview

All three CLI-based generators extend AbstractGenerator and implement GeneratorContract. Their generate(string $prompt) method:

  1. Constructs a command array referencing a configured binary path.
  2. Appends any configured CLI options via ensureWithOptions().
  3. Delivers the prompt either as a stdin stream or as a command-line argument, depending on the tool's interface.
  4. Runs the process and returns its stdout as the generated commit message.

Prompt delivery comparison:

GeneratorClassBinary Config KeyPrompt DeliveryAdditional Args
Bito CLIBitoCliGeneratorbinarystdin (setInput)none
GitHub Copilot CLIGithubCopilotCliGeneratorbinaryCLI argumentcopilot explain
GitHub Models CLIGithubModelsCliGeneratorbinarystdin (setInput)models run <model>

Sources: app/Generators/BitoCliGenerator.php1-33 app/Generators/GithubCopilotCliGenerator.php1-29 app/Generators/GithubModelsCliGenerator.php1-33


Execution Flow

The following diagram maps the generate() call path from GeneratorManager through each CLI-based generator to the underlying process.

Diagram: CLI Generator Execution Flow


Sources: app/Generators/BitoCliGenerator.php20-32 app/Generators/GithubCopilotCliGenerator.php20-28 app/Generators/GithubModelsCliGenerator.php20-32 app/Generators/AbstractGenerator.php42-70


BitoCliGenerator

File: app/Generators/BitoCliGenerator.php1-33

BitoCliGenerator wraps the Bito CLI tool. It passes the entire prompt via stdin, which allows arbitrarily large prompts without hitting shell argument length limits.

Command construction:

[<binary>] + hydratedOptions()

The Process is constructed with the command array, then setInput($prompt) pipes the prompt string to the process's stdin. The process is run via mustRunProcess() (from AbstractGenerator), which delegates to Symfony's ProcessHelper::run() and throws ProcessFailedException on a non-zero exit code.

Config keys used:

KeyPurpose
binaryPath to the bito executable
parametersExtra Process constructor parameters (e.g. timeout, cwd)
optionsCLI flags appended to the command via hydratedOptions()

Sources: app/Generators/BitoCliGenerator.php20-32 app/Generators/AbstractGenerator.php42-70 app/Generators/AbstractGenerator.php89-105


GithubCopilotCliGenerator

File: app/Generators/GithubCopilotCliGenerator.php1-29

GithubCopilotCliGenerator wraps the github-copilot-cli tool. Unlike the other two CLI generators, it passes the prompt as a positional command-line argument directly to the copilot explain subcommand, not via stdin.

Command construction:

[<binary>, 'copilot', 'explain', <prompt>] + hydratedOptions()

This generator also differs in how it runs the process: it calls ->mustRun($this->runningCallback()) directly on the Process object rather than delegating to mustRunProcess(). The runningCallback() method (defined in AbstractGenerator) streams stdout to the console output and wraps stderr in red formatting.

app/Generators/AbstractGenerator.php82-87

Config keys used:

KeyPurpose
binaryPath to the github-copilot-cli executable
parametersExtra Process constructor parameters
optionsCLI flags appended via hydratedOptions()

Note: Because the prompt is a shell argument, extremely long diffs could hit OS argument-length limits. This is a design constraint of the tool's interface.

Sources: app/Generators/GithubCopilotCliGenerator.php20-28 app/Generators/AbstractGenerator.php82-87


GithubModelsCliGenerator

File: app/Generators/GithubModelsCliGenerator.php1-33

GithubModelsCliGenerator wraps the gh CLI's models run subcommand. Like BitoCliGenerator, it delivers the prompt via stdin. It also requires a model configuration value to specify which model to invoke.

Command construction:

[<binary>, 'models', 'run', <model>] + hydratedOptions()

The prompt is piped to the process's stdin via setInput($prompt), and the process is executed via mustRunProcess().

Config keys used:

KeyPurpose
binaryPath to the gh executable
modelModel identifier passed as a positional argument
parametersExtra Process constructor parameters
optionsCLI flags appended via hydratedOptions()

Sources: app/Generators/GithubModelsCliGenerator.php20-32 app/Generators/AbstractGenerator.php42-70


Shared Infrastructure from AbstractGenerator

All CLI generators rely on the following methods from AbstractGenerator:

Diagram: AbstractGenerator Methods Used by CLI Generators


Sources: app/Generators/AbstractGenerator.php1-106

ensureWithOptions(array $command): array

app/Generators/AbstractGenerator.php89-92

Merges the base command array with the output of hydratedOptions(). This allows generator config to declare additional CLI flags without modifying the generator code.

hydratedOptions(): array

app/Generators/AbstractGenerator.php97-105

Reads the options key from the generator's config repository. Each entry is URL-decoded into a flat list of ['--flag', 'value'] pairs, which are spread into the command array.

mustRunProcess(...) and runProcess(...)

app/Generators/AbstractGenerator.php42-70

  • runProcess delegates to Symfony's ProcessHelper::run(), which logs the command to the console output at the configured verbosity level.
  • mustRunProcess calls runProcess, then throws ProcessFailedException if the process exits with a non-zero status code.

runningCallback(): callable

app/Generators/AbstractGenerator.php82-87

Returns a closure used as the mustRun callback (directly used by GithubCopilotCliGenerator). It writes stdout data as plain text and stderr data wrapped in <fg=red>...</> Symfony console markup.


Driver Registration

CLI generators are registered in the main config under the generators key. The GeneratorManager::createDriver() method maps driver names like bito_cli to class names like BitoCliGenerator using Laravel's studly() helper.

app/GeneratorManager.php63-77

Driver name to class mapping:

Config Driver KeyResolved Class
bito_cliApp\Generators\BitoCliGenerator
github_copilot_cliApp\Generators\GithubCopilotCliGenerator
github_models_cliApp\Generators\GithubModelsCliGenerator

To activate a CLI generator, set generator in your config to one of the driver keys above, or pass it via --generator=bito_cli on the command line. See 3.2 for command-line flag usage and 7.4 for the full generator config reference.

Sources: app/GeneratorManager.php63-77 tests/Unit/GeneratorManagerTest.php48-51


Error Handling

All three CLI generators will raise Symfony\Component\Process\Exception\ProcessFailedException when the external binary:

  • Is not found on $PATH or at the configured binary path.
  • Exits with a non-zero status code.
  • Times out (controlled by the timeout key in parameters).

The tests confirm this behavior by deliberately setting invalid binary paths and asserting ProcessFailedException is thrown:

tests/Unit/Generators/BitoGeneratorTest.php28-31 tests/Unit/Generators/GithubCopilotCliGeneratorTest.php28-31 tests/Unit/Generators/GithubModelsCliGeneratorTest.php28-31

For troubleshooting binary-not-found errors and process failures, see 8.