Local override files let a consumer project keep the Fast Forward baseline without forking the whole package.
Commands use Symfony\Component\Config\FileLocatorInterface to locate
configuration files. The locator resolves configuration in this order:
- Check whether the file exists in the current working directory.
- Use the local file when it exists.
- Otherwise fall back to the packaged file inside
fast-forward/dev-tools.
This behavior is consistent across all commands through the DI container
and FileLocatorInterface.
| Command | Local file | Fallback behavior |
|---|---|---|
code-style |
ecs.php |
Falls back to the packaged ECS configuration. |
refactor |
rector.php |
Falls back to the packaged Rector configuration. |
tests |
phpunit.xml |
Falls back to the packaged PHPUnit configuration. |
dependencies |
composer-dependency-analyser.php |
Falls back to the packaged Composer Dependency Analyser configuration. |
phpdoc |
.php-cs-fixer.dist.php and rector.php |
Falls back to the packaged files; .docheader is created locally
when missing. |
docs |
docs/ or another path passed with --source |
The selected guide source must exist locally. |
skills |
.agents/skills/ |
Creates missing local links to packaged skills and preserves existing non-symlink directories. |
agents |
.agents/agents/ |
Creates missing local links to packaged project agents and preserves existing non-symlink directories. |
dev-tools:sync |
Consumer repository files | Works directly against local project files such as composer.json and
.github/*. |
To customize Rector for one library, create rector.php in the consumer
project root. The refactor command and the Rector phase inside phpdoc
will use that file instead of the packaged default.
Instead of copying the entire ecs.php file, consumers can extend the
default configuration using the ECSConfig class:
<?php
use FastForward\DevTools\Config\ECSConfig;
use PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer;
$config = ECSConfig::configure();
$config->withRules([CustomRule::class]);
$config->withConfiguredRule(PhpdocAlignFixer::class, ['align' => 'right']);
return $config;Instead of copying the entire rector.php file, consumers can extend the
default configuration using the RectorConfig class:
<?php
use FastForward\DevTools\Config\RectorConfig;
return RectorConfig::configure(
static function (\Rector\Config\RectorConfig $rectorConfig): void {
$rectorConfig->rules([
// custom rules
]);
$rectorConfig->skip([
// custom skips
]);
}
);This approach:
- Eliminates duplication of the base configuration
- Automatically receives upstream updates
- Only requires overriding what is needed
Instead of copying the entire composer-dependency-analyser.php file,
consumers can extend the default configuration using the
ComposerDependencyAnalyserConfig class:
<?php
use FastForward\DevTools\Config\ComposerDependencyAnalyserConfig;
use ShipMonk\ComposerDependencyAnalyser\Config\Configuration;
use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType;
return ComposerDependencyAnalyserConfig::configure(
static function (Configuration $configuration): void {
$configuration->ignoreErrorsOnPackage(
'vendor/package',
[ErrorType::UNUSED_DEPENDENCY],
);
}
);This approach keeps the Fast Forward baseline while letting consumer repositories add project-specific ignores or scan rules.
The baseline ignores SHADOW_DEPENDENCY findings by default because Fast
Forward packages may intentionally require dependency groups, ecosystem bundles,
or meta packages that install related dependencies for consumers. Run
composer dependencies --show-shadow-dependencies when you want to audit
those findings and decide whether a package should keep, document, or remove a
direct dependency.
- existing workflow files in
.github/workflows/; - an existing
.editorconfig; - an existing
.github/dependabot.yml; - an existing non-symlink directory inside
.agents/skills/; - an existing non-symlink directory inside
.agents/agents/; - an existing
.github/wikidirectory or submodule.
Tip
Start with the packaged defaults, copy only the file you need to customize, and keep the rest on the shared baseline. That gives you the least maintenance overhead across Fast Forward libraries.