Deptrac: enforcing PHP architecture rules in CI
Keep your architecture clean.
At a glance
- What is it?
- Deptrac is a static analysis tool for PHP that turns architectural rules into a YAML or PHP config and fails the build when a class crosses a layer boundary. The tutorial below covers install, init and a first analyse run.
- Who is it for?
- Adopt Deptrac if your PHP codebase has modules, bundles or bounded contexts that must stay independent, and you want that rule checked on every pull request rather than in review comments. Skip it if your project is a single flat namespace with no boundaries worth naming, or if you cannot maintain a depfile as the code moves: a stale layer definition produces violations that nobody trusts.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Deptrac solves, and for whom
A PHP project can drift into a shape nobody chose. A service class reaches into a repository from another module, a controller calls an entity from a package that was supposed to be internal, and the dependency is invisible until someone tries to extract the module and discovers it cannot be moved. Code review catches some of this. It does not catch it reliably, and it does not catch it at all when the person reviewing has not memorised the intended boundaries.
Deptrac addresses that gap by making the boundaries explicit and machine-checked. The README frames the tool as a way to define architectural layers over classes and the rules that apply between them, and it names the canonical example: ensuring that bundles, modules or extensions in a project are truly independent of each other so they are easier to reuse. The audience is therefore teams with an architecture they can name. If you can write down which namespaces belong together and which must never depend on which, Deptrac can enforce it. If you cannot, the tool has nothing to check.
The second audience is the CI pipeline. The README states plainly that Deptrac can be used in a CI pipeline to make sure a pull request does not violate the architectural rules you defined. That is the real product: not a diagram generator, not a report you read once, but a gate that fails a build.
Layers, rules and violations as a data flow
The mechanism is a static analysis pass over PHP source, not a runtime check and not a test. The README describes the shape: you define layers over classes, and you define which rules apply to them. The configuration reference lives in docs/configuration.md, and the concepts behind layers, rules and violations are spelled out in docs/concepts.md. Those two documents, not this article, are the authority on the exact keys.
What matters for adoption is the pipeline. Deptrac parses your code, assigns each class to a layer through collectors, and then compares every dependency edge it finds against the ruleset. A dependency that a rule forbids becomes a violation, and violations drive the exit code. The README notes a constraint that follows from this design: running Deptrac requires PHP 8.2 or newer, but you can analyse projects that target older PHP versions as long as nikic/php-parser can parse them. The tool's runtime and the codebase's runtime are separate concerns, which is why a legacy application can still be checked.
Collectors are the part that decides whether the model fits your code. docs/collectors.md is the reference for what is available. If your layers map cleanly onto namespaces or directory conventions, the config is short. If they cut across those conventions, you will need a collector that expresses the cut, and that is where most of the configuration effort goes.
Output is configurable too. The README mentions optional Graphviz and Mermaidjs formatters for visualising layers, rules and violations, and docs/formatters.md lists the supported formats. Visualisation is a side benefit; the CI gate is the primary use.
Install and first analyse run
Deptrac installs as a development dependency through Composer. The README recommends the deptrac package for this. Run the following in your project root; it adds the tool to require-dev and puts the binary in vendor/bin.
composer require --dev deptrac/deptracOnce installed, you need a configuration file. The README says it is written in YAML or PHP and that by default it is stored as deptrac.php in your project's root directory. Rather than writing one from scratch, Deptrac can generate a template with the init command.
vendor/bin/deptrac initAfter the file exists, the analyse command is the entry point. The README gives the bare invocation and its explicit equivalent.
vendor/bin/deptrac
# which is equivalent to
vendor/bin/deptrac analyse --config-file=deptrac.phpExpect the first run to be noisy. A generated template cannot know your intended boundaries, so treat the initial output as a description of your current dependency graph rather than a list of bugs. Read the violations, adjust the layers and rules in deptrac.php until the model matches the architecture you actually want, and only then wire the command into CI. The README also points at docs/debugging.md for the debug commands, which is where to look when a class lands in a layer you did not expect.
One practical note from the repository layout: Deptrac's own project keeps both deptrac.php and deptrac.baseline.yaml at the top level. A baseline is the standard way to adopt a checker on a codebase that already has violations, and the related searches around generating a baseline suggest people hit this early. The README does not document baseline generation, so read docs/configuration.md before assuming how it works in your version.
Where Deptrac is the wrong tool
Deptrac checks dependencies between layers. It does not check whether the code inside a layer is good, and it does not replace a general static analyser. If your problem is an untyped array returned from a service method, Deptrac will not see it. Teams sometimes install it expecting a broad quality gate and are disappointed by how narrow the output is.
The narrowness is the point, but it has a cost. The depfile is a second model of your architecture that has to be maintained alongside the code. When a module is renamed or a namespace is split, the config does not update itself. A stale layer definition produces either false violations or, worse, silent gaps where a rule no longer matches anything. Nothing in the README suggests Deptrac warns you when a layer matches zero classes, so that failure mode is on you to notice.
There is also an adoption cliff. On a codebase with many existing violations, the first run is unusable as a gate, and the answer is a baseline or a long cleanup. Either way, the tool is only as valuable as the discipline behind it. If the team is not prepared to treat a violation as a blocker, Deptrac becomes another report nobody reads.
Finally, the config surface is real. Layers, collectors, rules and formatters are separate concerns documented in separate files. That is appropriate for a tool whose whole job is expressing architecture, but it means the setup is not a five-minute task on a large project.
How it differs from PHPStan, PHPat and Phparkitect
The related searches around Deptrac cluster with PHPStan, PHPat and Phparkitect, which is a fair grouping. All of them read PHP statically and all of them can fail a build. The difference is the unit of analysis.
PHPStan is a type and correctness analyser. Its rules are about the language and about known error patterns in code, and it ships an extension mechanism for framework-specific knowledge. It does not have a native concept of an architectural layer that you declare and then enforce. You can approximate architecture rules through custom rules, but you are writing an analyser extension rather than filling in a depfile.
PHPat takes the opposite route: it expresses architecture rules as PHPStan rules, so architecture checking rides on the analyser you probably already run. That is attractive if PHPStan is already central to your pipeline and you would rather not add a second binary and a second config format. The trade-off is that your architecture rules are now written in PHPStan's rule idiom rather than in a declarative layer-and-rule model, and the visualisation story is different.
Phparkitect is the closest in intent: it also describes architectural constraints and checks them. The distinction to verify for your project is the rule vocabulary and the configuration format each one offers, since that is what you will live with. Deptrac's own answer to the format question is YAML or PHP with a generator command, plus optional Graphviz and Mermaidjs output for diagrams.
None of these tools is a superset of the others. A reasonable pipeline runs a type analyser for correctness and Deptrac for boundaries, and accepts that two configs need to be kept current.
Maintenance, release cadence and the MIT licence
The repository is not archived, and the last push was on 2026-09-20. Recent releases are 4.7.0 on 2026-07-21, 4.7.1 on 2026-07-23 and 4.7.2 on 2026-09-15, with the default branch named 4.x. That is a steady minor-release rhythm rather than a burst, which matters for a tool you put in CI: you want to know that a PHP version bump will be handled.
Upgrade cost is documented rather than left to guesswork. The README links docs/bc_policy.md for how the project approaches backwards compatibility and docs/upgrade.md for the list of backwards breaking changes and how to address them when upgrading. That is the file to read before moving a major version, and it is the honest signal about how much work an upgrade will be. The versioning scheme is visible in the release names, and the 4.x branch is where current development sits.
The licence is MIT, per the repository's LICENCE.md. MIT is permissive: it allows use, modification and redistribution with the licence and copyright notice retained. That is the general shape of the terms, not legal advice, and if your organisation has rules about the licences of development dependencies you should have someone check how MIT interacts with your own distribution model, particularly if you ship tooling or generated artefacts.
One cost worth naming: Deptrac requires PHP 8.2 or newer to run. On a team standardised on an older runtime, the tool cannot be installed until the build environment is updated, even though the code being analysed can be older.
Editorial conclusion
Adopt Deptrac if your PHP codebase has modules, bundles or bounded contexts that must stay independent, and you want that rule checked on every pull request rather than in review comments. Skip it if your project is a single flat namespace with no boundaries worth naming, or if you cannot maintain a depfile as the code moves: a stale layer definition produces violations that nobody trusts. Before rollout, verify three things on your own repository: that PHP 8.2 or newer is available to the tool, that your config file parses under the version you installed, and that the first analyse run's violation list matches what you already know about your dependency graph. Deptrac's own repository keeps a deptrac.baseline.yaml next to its depfile, which is the pattern to copy when you need to land the tool without fixing every existing violation on day one.
Frequently asked questions
What PHP version does Deptrac require?
The README states that running Deptrac requires at least PHP 8.2. You can still analyse a project that requires an older PHP version, as long as nikic/php-parser can parse that code.
How do I install Deptrac with Composer?
The README recommends installing the deptrac/deptrac package as a development dependency with composer require --dev deptrac/deptrac. The binary then lives at vendor/bin/deptrac.
What file does Deptrac use for its configuration?
The configuration is written in YAML or PHP and by default is stored as deptrac.php in the project root. The init command generates a template for you.
Can Deptrac run in a CI pipeline?
Yes. The README says Deptrac can be used in a CI pipeline to make sure a pull request does not violate the architectural rules you defined, which is its primary use case.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/deptrac-deptrac)