Problem
DevTools is currently optimized for project-local Composer usage, but a global installation would benefit from Composer-like runtime affordances. In particular, users should be able to run DevTools against a specific project directory without first changing directories, and long-lived global installations should provide a safe way to detect and apply updates.
Without this, a global dev-tools binary can drift behind the version used by projects, and users need to remember both where the command should run and how to update the installed package.
Proposal
Introduce a global execution and update flow for the main DevTools binary:
- add a global
--working-dir option, similar to Composer's --working-dir, so any command can target a project directory consistently;
- add a
self-update command that updates the installed fast-forward/dev-tools package;
- add a non-blocking version freshness check when the binary starts;
- optionally support opt-in automatic updates through
--auto-update and/or FAST_FORWARD_AUTO_UPDATE.
The update check MUST be advisory by default. If checking the latest version fails because of network, Packagist, GitHub, Composer, or filesystem issues, DevTools MUST continue running the requested command and MAY emit only a warning or debug-level context.
Expected Behavior
A user with a global DevTools installation can run commands such as:
dev-tools --working-dir=/path/to/project tests
dev-tools --working-dir=/path/to/project standards --fix
dev-tools self-update
dev-tools self-update --global
FAST_FORWARD_AUTO_UPDATE=1 dev-tools --working-dir=/path/to/project reports
The update behavior should distinguish installation context:
- local project install:
self-update SHOULD run the equivalent of composer update fast-forward/dev-tools in the resolved working directory;
- global install:
self-update --global SHOULD run the equivalent of composer global update fast-forward/dev-tools;
- auto-update: when explicitly enabled by CLI option or environment variable, DevTools MAY run the same safe update path before delegating to the requested command.
When the installed version is not the latest known version, normal command execution should continue and DevTools should show an actionable warning, for example:
A newer fast-forward/dev-tools version is available. Run `dev-tools self-update` to update this installation.
Implementation Strategy
Consider implementing this as an application-level capability rather than duplicating logic inside individual commands:
- add a working-directory resolver that applies before command execution and updates process context consistently;
- evaluate Symfony Console application events or a small application bootstrap hook for the update check, while ensuring it never blocks normal command execution;
- isolate version discovery from console rendering and from Composer process execution;
- isolate update execution so local/global Composer invocation can be tested independently;
- expose deterministic behavior for disabled checks, failed checks, stale versions, current versions, local updates, global updates, and auto-update.
The version freshness check should avoid becoming a startup tax. It should be bounded by timeout/cache policy, and it should be possible to disable or bypass in CI if needed.
Requirements
- Add a global
--working-dir option to the main DevTools binary and ensure commands resolve project-relative paths from that directory.
- Add a
self-update command with local and global update modes.
- Add a non-blocking freshness check that warns when the installed version is stale.
- Support opt-in automatic update through
--auto-update and/or FAST_FORWARD_AUTO_UPDATE only when safe and explicit.
- Ensure update-check failures never prevent the requested command from running.
- Document global installation,
--working-dir, self-update, update warnings, and auto-update behavior.
- Include tests for working-directory resolution, stale-version warnings, failed update checks, local update execution, global update execution, and auto-update opt-in.
Non-goals
- Do not make automatic updates the default behavior.
- Do not require network access for normal command execution.
- Do not replace project-local Composer workflows.
- Do not make the update checker responsible for release publishing or Packagist synchronization.
- Do not couple command implementations directly to Composer process details; keep update orchestration isolated.
Benefits
This would make DevTools safer and more ergonomic as a global binary while preserving local project workflows. It also creates a clearer path for users who want a shell alias or startup configuration that always runs against the intended project and optionally keeps the global tool current.
Acceptance Criteria
Functional Criteria
Architectural / Isolation Criteria
- MUST: The core logic MUST be isolated into dedicated classes or services instead of living inside command or controller entrypoints.
- MUST: Responsibilities MUST be separated across input resolution, domain logic, processing or transformation, and output rendering when the change is non-trivial.
- MUST: The command or controller layer MUST act only as an orchestrator.
- MUST: The implementation MUST avoid tight coupling between core behavior and CLI or framework-specific I/O.
- MUST: The design MUST allow future extraction or reuse with minimal changes.
- MUST: The solution MUST remain extensible without requiring major refactoring for adjacent use cases.
- MUST: Argument and option resolution MUST be validated separately from command execution logic.
- MUST: Console formatting and rendering MUST stay separate from domain processing.
- MUST: Exit behavior, error messaging, and generated output MUST remain deterministic and testable.
Problem
DevTools is currently optimized for project-local Composer usage, but a global installation would benefit from Composer-like runtime affordances. In particular, users should be able to run DevTools against a specific project directory without first changing directories, and long-lived global installations should provide a safe way to detect and apply updates.
Without this, a global
dev-toolsbinary can drift behind the version used by projects, and users need to remember both where the command should run and how to update the installed package.Proposal
Introduce a global execution and update flow for the main DevTools binary:
--working-diroption, similar to Composer's--working-dir, so any command can target a project directory consistently;self-updatecommand that updates the installedfast-forward/dev-toolspackage;--auto-updateand/orFAST_FORWARD_AUTO_UPDATE.The update check MUST be advisory by default. If checking the latest version fails because of network, Packagist, GitHub, Composer, or filesystem issues, DevTools MUST continue running the requested command and MAY emit only a warning or debug-level context.
Expected Behavior
A user with a global DevTools installation can run commands such as:
The update behavior should distinguish installation context:
self-updateSHOULD run the equivalent ofcomposer update fast-forward/dev-toolsin the resolved working directory;self-update --globalSHOULD run the equivalent ofcomposer global update fast-forward/dev-tools;When the installed version is not the latest known version, normal command execution should continue and DevTools should show an actionable warning, for example:
Implementation Strategy
Consider implementing this as an application-level capability rather than duplicating logic inside individual commands:
The version freshness check should avoid becoming a startup tax. It should be bounded by timeout/cache policy, and it should be possible to disable or bypass in CI if needed.
Requirements
--working-diroption to the main DevTools binary and ensure commands resolve project-relative paths from that directory.self-updatecommand with local and global update modes.--auto-updateand/orFAST_FORWARD_AUTO_UPDATEonly when safe and explicit.--working-dir,self-update, update warnings, and auto-update behavior.Non-goals
Benefits
This would make DevTools safer and more ergonomic as a global binary while preserving local project workflows. It also creates a clearer path for users who want a shell alias or startup configuration that always runs against the intended project and optionally keeps the global tool current.
Acceptance Criteria
Functional Criteria
dev-tools --working-dir=/path/to/project <command>runs the command as if invoked from that project directory.dev-tools self-updateupdates a local installation using the resolved working directory.dev-tools self-update --globalupdates a global installation using Composer global update semantics.--auto-updateand/orFAST_FORWARD_AUTO_UPDATEtrigger update behavior only when explicitly enabled.--working-dir,self-update, auto-update, and failure behavior.Architectural / Isolation Criteria