Documentation

The CLI

Check, build, and clean a mixed project with predictable selection and machine-readable diagnostics.

The CLI has two daily commands: check finds problems in your source, while build produces the PHP that runs. Both commands understand the complete project even when you focus the report or output on one path.

Command map

Command Purpose Writes generated PHP
ppphp init Create the project configuration and generated-code directories No
ppphp check [path] Check selected source with the rest of the project No
ppphp build [path] Check, compile .ppphp, and copy .php source Yes
ppphp clean [--dry-run] Remove generated output and compiler cache paths Deletes generated files

Use the Composer-installed executable in project scripts:

vendor/bin/ppphp check
vendor/bin/ppphp build

Complete-project and focused commands

With no path, check validates every .ppphp and .php file under the configured source roots. A path narrows the diagnostic selection:

vendor/bin/ppphp check src/Checkout
vendor/bin/ppphp check src/Checkout/CheckoutService.ppphp

The compiler still loads valid unselected source, Composer metadata, dependencies, PHPDoc, and configured stubs when they are needed to resolve the selected code. An unrelated invalid file outside the selection does not block a focused command, but a project-wide name conflict can still make the selected target ambiguous.

build follows the same selection model:

vendor/bin/ppphp build
vendor/bin/ppphp build src/Checkout
vendor/bin/ppphp build src/Checkout/CheckoutService.ppphp
vendor/bin/ppphp build src/Legacy/Formatter.php

A complete build emits every owned source. A directory build emits that subtree. A focused .ppphp build compiles that file; a focused .php build copies it byte-for-byte. Dependencies used for understanding a selection are not silently added to its output. Use a pathless build when you need a complete deployable application.

Read a diagnostic

Console diagnostics point directly to the original source:

src/Checkout/CheckoutService.ppphp:18:9
P2009 Assignment Is Not Assignable To Declared Type

The assigned value of type string is not assignable to local $attempts of type int.

Help: Keep the assignment compatible with int, or change the declaration if the
variable models a different value.

Diagnostic families make failures recognizable across CLI, editor, CI, and playground integrations:

Range Concern
P0xxx project and configuration
P1xxx syntax
P2xxx variables and strict types
P3xxx generics and typed arrays
P4xxx checked errors
P5xxx when expressions
P6xxx PHP and Composer interoperability
P7xxx emitted PHP
P9xxx guarded compiler failures

Use JSON in automation

Every project command accepts --format=json:

vendor/bin/ppphp check --format=json

The response has a versioned envelope, source ranges, related labels, help, and a summary:

{
    "version": 1,
    "diagnostics": [],
    "summary": {
        "errors": 0,
        "warnings": 0,
        "notes": 0
    }
}

Consumers should branch on structured fields, not scrape colored console output. Paths and ranges refer to the original project source.

The stable process statuses are useful in CI:

Exit Meaning
0 success
1 source diagnostics were reported
2 invalid command, project, or configuration
3 generated output validation failed
70 guarded internal compiler failure

Work with another project root

You do not have to change the process directory:

vendor/bin/ppphp check \
  --working-directory=/srv/example \
  --config=config/ppphp.json

Relative source selections resolve from the selected project root and must remain beneath a configured source root.

Clean safely

Preview cleanup before deleting generated files and cached data:

vendor/bin/ppphp clean --dry-run
vendor/bin/ppphp clean

clean validates every target, refuses paths outside the project root, and never deletes a source directory. It does not remove Composer dependencies or application-owned build assets.

Next, read Strict project-wide types to understand what check proves, or Mixed projects to plan a gradual migration.