Specialized Commands
Use the standalone commands when you want one tool instead of the full
standards
pipeline.
External Changelog CLI
Run the latest published independent Fast Forward Changelog CLI through
cpx --skip-local
. CPX and PHP 8.5 must be available on its execution path;
the consumer's PHP 8.3 requirement stays unchanged.
cpx --skip-local fast-forward/changelog add "Fixes release-note rendering." --category=fixed --no-interaction
cpx --skip-local fast-forward/changelog check --no-interaction
cpx --skip-local fast-forward/changelog status --source=tags --no-interaction
Contributions use independent .changelog/*.md
files. Inspect external command
help for its options and output contracts. See External Fast Forward Changelog for
runtime requirements and release-preview boundaries.
tests
Runs PHPUnit with the resolved phpunit.xml
.
composer tests
composer tests -- --filter=EventTracerTest
Important details:
- local
phpunit.xmlis preferred over the packaged default; --coverage=<path>creates HTML, Testdox, Clover, and raw coverage output;--coverage-summarykeeps coverage text output to PHPUnit's summary;- cache stays enabled by default;
--cacheforces it on and--no-cacheforces it off for a single run; - when
--cache-diris omitted, PHPUnit keeps its default cache directory; --cache-dironly affects PHPUnit's result cache when caching is enabled;- progress output is disabled by default;
--progressre-enables PHPUnit progress output in text mode;--jsonand--pretty-jsonstill suppress PHPUnit progress output automatically;--pretty-jsonstays valid JSON and does not add ANSI color escapes;- in agent-driven runs, the command also captures PHPUnit output in structured
mode automatically and stores the bundled PHPUnit agent-reporter payload in
output.--jsonand--pretty-jsontherefore keep the same structured shape, withraw_outputpreserved underoutputwhen PHPUnit writes extra text before the final JSON; - the packaged configuration registers the DevTools PHPUnit extension.
dependencies
Analyzes missing, unused, misplaced, and outdated Composer dependencies.
composer dependencies
composer dependencies --max-outdated=10
composer dependencies --max-outdated=-1
composer dependencies --dev
composer dependencies --dump-usage=symfony/console
composer dependencies --show-shadow-dependencies
composer dependencies --upgrade --dev
Important details:
- it ships
shipmonk/composer-dependency-analyserandrector/swiss-knifeas direct dependencies offast-forward/dev-tools; - it uses
composer-dependency-analyserfor missing, unused, and misplaced dependency checks, with a packaged config that consumer repositories can override locally; --dump-usage=<package>forwards tocomposer-dependency-analyser --dump-usages <package> --show-all-usages;--show-shadow-dependencieskeeps shadow dependency findings visible for audits; without it, DevTools hides intentional Fast Forward dependency-group shadows so CI does not fail on ecosystem or meta packages that deliberately install related dependencies for consumers;- it uses
swiss-knife breakpoint --limit=<max-outdated>to fail when too many outdated dependencies accumulate; --max-outdated=-1keeps the Rector Swiss Knife outdated report in the output but ignores Rector Swiss Knife's failure so only dependency-analyser findings fail the command;- the packaged
tests.ymlworkflow uses--max-outdated=-1by default, so dependency health stays required in CI while outdated-package counts are reported without failing the workflow on their own; - it previews
swiss-knife raise-to-installedandswiss-knife open-versionsbefore the analyzers; --upgraderunsswiss-knife raise-to-installed,swiss-knife open-versions,composer update -W, andcomposer normalizebefore the analyzers;- it returns a non-zero exit code when missing, unused, misplaced, or too many outdated dependencies are found.
metrics
Analyzes code metrics with PhpMetrics.
composer metrics
composer metrics --target=.dev-tools/metrics
FAST_FORWARD_WORKSPACE_DIR=.artifacts composer metrics
composer --working-dir=packages/example metrics
Important details:
- it ships
phpmetrics/phpmetricsas a direct dependency offast-forward/dev-tools; - when invoked through Composer, you MAY use Composer's inherited
--working-diroption to analyze another checkout without changing directories first; --targetstores the HTML report plusreport.jsonandreport-summary.jsonin the same directory for CI artifacts or manual review;- when
--targetis omitted, metrics output is written under the selected DevTools workspace, usually.dev-tools/metrics; --jsonand--pretty-jsonkeep the top-level DevTools response structured while forwarding JSON or quieter modes to the wrapped tools where available;- it suppresses deprecation notices emitted by the PhpMetrics dependency itself so the command output stays readable;
- it keeps PhpMetrics' Composer analysis enabled so report generation includes root package metadata, while default exclusions keep nested fixture projects out of that Composer scan;
- it limits PhpMetrics' per-package Packagist socket wait so package freshness enrichment cannot leave report generation stuck indefinitely.
code-style
Runs Composer Normalize and ECS.
composer code-style
composer code-style --fix
Important details:
- it always executes
composer update --lock --quietfirst; - without
--fix, Composer Normalize runs in--dry-runmode; - ECS uses local
ecs.phpwhen present, otherwise the packaged fallback; - progress output is disabled by default;
--progressre-enables it for text mode; --jsonand--pretty-jsonforward JSON mode to ECS and suppress its progress bar.
refactor
Runs Rector against the current project.
composer refactor --fix
Important details:
- without
--fix, Rector runs in dry-run mode; - local
rector.phpis preferred when present; - the packaged default includes Fast Forward custom Rector rules plus shared Rector sets;
- progress output is disabled by default;
--progressre-enables it for text mode; --jsonand--pretty-jsonforward--output-format jsonto Rector and disable its progress bar.
phpdoc
Coordinates PHP-CS-Fixer and a focused Rector pass for missing method PHPDoc.
composer phpdoc
composer phpdoc --fix
Important details:
- it creates
.docheaderfrom the packaged template when the file is missing; - it uses
.php-cs-fixer.dist.phpandrector.phpthrough the same local-first fallback logic; - the Rector phase explicitly runs
FastForward\DevTools\Rector\AddMissingMethodPhpDocRector; - cache stays enabled by default;
--cacheforces it on and--no-cacheforces it off for the PHP-CS-Fixer phase; - when
--cache-diris omitted, PHP-CS-Fixer keeps its default cache directory; --cache-dironly affects PHP-CS-Fixer when caching is enabled;- progress output is disabled by default;
--progressre-enables it for text mode; --jsonand--pretty-jsonswitch PHP-CS-Fixer to JSON output with progress disabled and run the Rector phase in JSON mode without its progress bar.
docs
Builds the HTML documentation site with phpDocumentor.
composer docs --source=docs --target=.dev-tools
Important details:
docs/must exist unless you pass another--sourcedirectory;- API pages are built from the PSR-4 paths declared in
composer.json; - guide pages are built from the selected source directory;
--templatedefaults tovendor/fast-forward/phpdoc-bootstrap-template;- cache stays enabled by default;
--cacheforces it on and--no-cacheforces it off for a single run; - when
--cache-diris omitted, phpDocumentor keeps its default cache directory; --cache-dironly affects phpDocumentor when caching is enabled;- progress output is disabled by default;
--progressre-enables it for text mode; --jsonand--pretty-jsonalso disable phpDocumentor's progress output.
wiki
Builds Markdown API pages for a GitHub wiki.
composer wiki
Important details:
- the default output directory is
.github/wiki; - normal
dev-tools:syncand the direct Wiki workflow explicitly use.dev-tools/wiki-generatedwithout initializing a submodule; --initremains an explicit legacy option for submodule users;- it uses the Markdown template from
vendor/saggre/phpdocumentor-markdown/themes/markdown; - cache stays enabled by default;
--cacheforces it on and--no-cacheforces it off for a single run; - when
--cache-diris omitted, phpDocumentor keeps its default cache directory; --cache-dironly affects phpDocumentor when caching is enabled;- it is especially useful together with the reusable wiki workflow.
reports
Runs the documentation and test-report pipeline used by GitHub Pages.
composer reports
Important details:
- it calls
docs,tests --coverage, andmetricswith defaults rooted in the selected DevTools workspace; - with the default workspace, that is equivalent to
docs --target .dev-tools,tests --coverage .dev-tools/coverage --coverage-summary, andmetrics --target .dev-tools/metrics --junit .dev-tools/coverage/junit.xml; docsremains detached, whiletestsandmetricsrun in sequence so PhpMetrics can reuse the JUnit report generated by PHPUnit;- cache stays enabled by default for the nested
docsandtestssteps;--cacheforces that explicit intent on and--no-cacheforces it off; - when
--cache-diris omitted, nested tools keep their own default cache directories; - progress output stays disabled by default across the nested steps, and
--progressre-enables it for human-readable runs; --jsonand--pretty-jsonare propagated to each subprocess, while their progress output is suppressed where supported;- human-readable runs keep nested command output grouped with concise local section boundaries, pass color-friendly environment variables to subprocesses, and forward explicit ANSI flags to Symfony Console tools;
- queued subprocesses run with
XDEBUG_MODE=offwhen Xdebug is loaded but the command does not need Xdebug for coverage, or when PCOV can provide coverage instead; - it is the reporting stage used by
standards.
skills
Synchronizes packaged agent skills into the consumer repository.
composer skills
Important details:
- it verifies the packaged
.agents/skillsdirectory before doing any work; - it creates the consumer
.agents/skillsdirectory when missing; - it creates missing symlinks and repairs broken ones;
- it preserves an existing non-symlink directory instead of overwriting it.
agents
Synchronizes packaged project-agent prompts into the consumer repository.
composer agents
Important details:
- it verifies the packaged
.agents/agentsdirectory before doing any work; - it creates the consumer
.agents/agentsdirectory when missing; - it creates missing symlinks and repairs broken ones;
- it preserves an existing non-symlink directory instead of overwriting it;
- it uses the same generic synchronization rules as
skillsthroughFastForward\\DevTools\\Sync\\PackagedDirectorySynchronizer.
funding
Synchronizes supported funding metadata between Composer and GitHub formats.
composer funding
composer funding --dry-run
composer funding --check
Important details:
- it keeps
composer.jsonfundingentries and.github/FUNDING.ymlin sync for GitHub Sponsors andcustomURLs; - it preserves unsupported Composer funding providers and unsupported YAML keys instead of rewriting them;
- it creates
.github/FUNDING.ymlwhen Composer already declares supported funding metadata; - it supports
--dry-run,--check, and--interactiveso funding drift can be surfaced in CI and reviewed locally.
codeowners
Generates managed CODEOWNERS files from repository metadata.
composer codeowners
composer codeowners --dry-run
composer codeowners --interactive
Important details:
- it inspects
composer.jsonauthor homepages to infer GitHub handles for.github/CODEOWNERS; - when direct ownership cannot be inferred, it renders a commented fallback instead of copying hard-coded owners into the consumer repository;
--interactivelets maintainers provide explicit owners before writing the catch-all*rule;dev-tools:syncrunscodeownersautomatically alongside the other consumer bootstrap steps.
dev-tools:sync
Synchronizes consumer-facing automation and defaults.
composer dev-tools:sync
Important details:
- it updates
composer.jsonscripts and removes only deprecated DevTools-managedextra.grumphp.config-default-pathvalues; - it calls
fundingso supported funding metadata stays aligned betweencomposer.jsonand.github/FUNDING.yml; - it copies missing workflow stubs,
.editorconfig, anddependabot.yml; - it calls
codeownersto generate.github/CODEOWNERSfrom local metadata; - in normal mode it generates local API Markdown in
.dev-tools/wiki-generatedwithout creating a Git submodule; - it calls
gitignoreto merge the canonical .gitignore with the project's .gitignore; - it calls
gitattributesto manage export-ignore rules in .gitattributes; - it refreshes packaged Git hooks that prefer a local
grumphp.ymloverride and otherwise use a project-relative reference to the active packaged DevToolsgrumphp.ymlpath resolved when sync installs them; - it calls
skillsso.agents/skillscontains links to the packaged skill set; - it calls
agentsso.agents/agentscontains links to the packaged project-agent set.
gitattributes
Manages .gitattributes export-ignore rules for leaner Composer package archives.
composer gitattributes
Important details:
- it adds export-ignore entries for repository-only files and directories;
- it only adds entries for paths that actually exist in the repository;
- it respects the
extra.gitattributes.keep-in-exportconfiguration to keep specific paths in exported archives; - it preserves existing custom .gitattributes rules;
- it deduplicates equivalent entries and sorts them with directories before files, then alphabetically;
- it uses CandidateProvider, ExistenceChecker, ExportIgnoreFilter, Merger, Reader, and Writer components from the GitAttributes namespace.
gitignore
Merges and synchronizes .gitignore files.
composer gitignore --source=/path/to/source/.gitignore --target=/path/to/target/.gitignore
Important details:
- it reads the canonical .gitignore from dev-tools and merges with the project's existing .gitignore;
- by default, the source is the packaged .gitignore and the target is the project's root .gitignore;
- duplicates are removed and entries are sorted alphabetically;
- it uses the Reader, Merger, and Writer components from the GitIgnore namespace.
license
Generates a LICENSE file from composer.json license information.
composer license
Important details:
- it reads the
licensefield fromcomposer.json; - it supports common open-source licenses (MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, GPL-3.0, LGPL-3.0, and MPL-2.0);
- it resolves placeholders such as
[year],[author], and[project]using information fromcomposer.json; - it uses template files from
resources/license-templates/; - it skips generation if a LICENSE file already exists.
copy-resource
Copies packaged or local resources into the consumer repository.
composer copy-resource --source <path> --target <path> --overwrite
Important details:
- source is resolved using
FileLocatorInterface; - target is resolved to an absolute path using
FilesystemInterface; - both
--sourceand--targetare required options; - without
--overwrite, existing target files are skipped; - supports both files and directories as sources.
git-hooks
Installs packaged Fast Forward Git hooks.
composer git-hooks
Important details:
- copies hook files from source to target directory;
- sets executable permissions on copied hooks with
0o755; - removes an existing drifted hook before recopying it so stale target permissions do not block replacements;
--sourcedefaults toresources/git-hooks;--targetdefaults to.git/hooks;--no-overwritepreserves existing hook files.
update-composer-json
Updates composer.json with Fast Forward dev-tools scripts and metadata.
composer update-composer-json --file=composer.json
Important details:
- adds
dev-toolsscript entrypoint to composer.json; - adds
dev-tools:fixscript for automated fixing; - removes only deprecated DevTools-managed
extra.grumphp.config-default-pathvalues; - if the target file does not exist, exits silently with code 0;
- existing scripts with the same name are overwritten;
- preserves consumer-owned GrumPHP settings.