Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Composer License Checker Laravel Package

lendable/composer-license-checker

A dev tool that checks Composer dependency licenses against configurable rules to ensure open source compliance and reduce legal risk. Define allowed licenses, vendors, and packages in a PHP config file, then run it in CI. Uses installed.json or composer licenses as its data source.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a framework-agnostic Composer CLI tool, not a Laravel package — there's no service provider, no publishable config, and no php artisan command. Expect to interact with it exclusively through vendor/bin and CI.

  1. Check your PHP constraint before installing. The tool's own PHP floor has moved fast: 1.4.x requires PHP 8.4, 1.3.x requires 8.3, 1.2.x requires 8.2. On a PHP 8.2 Laravel app, composer require --dev lendable/composer-license-checker will silently resolve to ^1.2 — fine, but be aware you may not have newer flags.
composer require --dev lendable/composer-license-checker
  1. Create .allowed-licenses.php in the project root (not config/ — see Gotchas):
<?php

declare(strict_types=1);

use Lendable\ComposerLicenseChecker\LicenseConfigurationBuilder;

return (new LicenseConfigurationBuilder())
    ->addLicenses('MIT', 'BSD-2-Clause', 'BSD-3-Clause', 'Apache-2.0', 'ISC')
    ->addAllowedVendor('your-company')
    ->build();
  1. Run it and let the first failure teach you the allowlist:
./vendor/bin/composer-license-checker

The first run on a typical Laravel app will flag a handful of dependencies (often packages declaring proprietary, no license, or an unusual SPDX expression). Add licenses deliberately, and prefer addAllowedPackage() over addLicenses() for one-offs so you don't widen the policy for the whole dependency tree.

First real use case: run it once locally, commit the resulting config, then treat it as a policy file under code review.

Implementation Patterns

Wire it into the fast-feedback CI job. Put it alongside Pint/PHPStan so license failures surface in the same minute as style failures, not after your test matrix:

- run: composer install --no-interaction --prefer-dist
- run: ./vendor/bin/composer-license-checker --format=json > licenses.json

--format (human-readable / JSON) landed in 1.0.3; use JSON if you want to upload the report as an artifact or convert violations into PR annotations.

Expose it as a Composer script so devs and CI run the same thing:

"scripts": {
    "check:licenses": "composer-license-checker"
}

Pick your provider deliberately. The default --provider-id=json parses vendor/composer/installed.json and needs no Composer binary in the environment — ideal for slim CI images and containers (Sail, custom Dockerfiles). --provider-id=licenses shells out to composer licenses, which is a more stable contract but requires Composer and adds process overhead. Use the default unless you hit a schema problem.

Decide which dependency set you audit. The checker reports on what is actually installed. A full composer install includes packages-dev; a --no-dev install does not — and also removes the checker itself. If you want to audit the production set only, use a dedicated CI job that installs fully, runs the check, and only then prunes.

Use the escape hatches with intent. addAllowedVendor('your-company') for first-party packages pulled in via path/VCS repos (they frequently omit a license field). addAllowedPackage('vendor/thing') for a single known exception — keep these grouped and commented in the config file, since the builder has no built-in expiry or reason metadata.

If you maintain a Laravel package, the same config file works there; use -a / --allow-file to place your allowlist anywhere you like, e.g. .config/allowed-licenses.php in a monorepo.

Wrap it if you want an Artisan entry point. A thin command that shells out to the binary via Symfony\Component\Process\Process gives php artisan licenses:check for devs who live in Artisan, without forking the tool.

Gotchas and Tips

  • Don't put the config in config/. Laravel's config loader globs config/*.php and expects each file to return an array; a file returning a LicenseConfiguration object will break config:cache. A dotfile (.allowed-licenses.php) in the project root is skipped by glob() and is safe.
  • The allow-file must be valid PHP returning a configuration. Non-PHP content is validated and rejected (since 1.1.1), but a parse error surfaces as a confusing failure. Sanity-check with php .allowed-licenses.php in isolation.
  • installed.json is Composer-internal. The README says so explicitly. A Composer major upgrade can change the schema; if you see parse/validation errors after a Composer bump, switch to --provider-id=licenses first, then report upstream.
  • Stale installed.json. If you edit composer.lock without reinstalling, you're auditing the old tree. Always run the check immediately after composer install in the same job.
  • Packages with no license at all are a violation, not a crash (fixed in 0.1.1), which is the right behaviour but means private/path packages will fail the build until you allowlist their vendor or package.
  • Disjunctive SPDX expressions (MIT OR Apache-2.0) were mishandled until 1.0.4. On older pins you'll get false positives; upgrade rather than allowlisting the whole vendor.
  • Check for --format support before using it. It arrived in 1.0.3; if Composer resolved you to ^1.2 because of PHP 8.2, verify the flag exists rather than discovering it in CI. Treat the JSON shape as reporting output, not a stable contract — parse defensively.
  • Debugging verbosity. Use -v/-vvv for the Symfony Console side. Verbosity of the composer licenses subprocess is controlled by the SHELL_VERBOSITY environment variable (moved there in 1.0.3), so set it in the job env if subprocess output is missing or noisy.
  • Exit codes are the contract. Treat any non-zero exit as a build failure; don't grep stdout, since human-readable output wording can change between releases.
  • Know what it doesn't do. It checks declared license identifiers from Composer metadata — it doesn't read LICENSE files, doesn't generate NOTICE/attribution files required by Apache-2.0, and doesn't evaluate compatibility between licenses. It's a gate, not a compliance program.
  • Contain the blast radius. With ~14 stars and fast-moving PHP requirements, keep the integration to one Composer script plus one CI step so you can swap to composer licenses plus your own parser with an hour's work. The only real extension point is LicenseConfigurationBuilder; the event system is internal and undocumented, so a custom provider means forking.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin