Authorize and require the plugin in the application:
{
"require": {
"php-forge/foxy": "^0.3"
},
"config": {
"allow-plugins": {
"php-forge/foxy": true
},
"foxy": {
"manager": "npm"
}
}
}The project may provide its own frontend dependencies in package.json:
{
"private": true,
"dependencies": {
"@foo/bar": "^1.2.0"
}
}During Composer install and update operations, Foxy merges eligible Composer package assets into this file and runs the selected frontend manager. Existing non-Foxy dependencies are preserved.
Run an explicit frontend dependency audit from Composer:
composer foxy:auditThe command requires the selected manager's native lockfile, validates the manager version, and asks the manager for a machine-readable security report. It reads the lockfile and does not run an install, update, fix, or fallback. Foxy supports npm audit report version 2 starting with npm 10.9.8 and the current report schemas emitted by pnpm 11, Yarn 4, and Bun 1.4; legacy report formats are rejected instead of being interpreted heuristically.
Foxy reports every advisory returned by the manager. --audit-level controls only the CI exit threshold:
composer foxy:audit --audit-level=highValid levels are low, moderate, high, and critical; the default is low. Use --no-dev to audit only the
production dependency graph:
composer foxy:audit --no-devFor npm workspace roots, Foxy explicitly includes every workspace and the root package so ambient npm workspace selection cannot silently narrow the audited lock graph.
Foxy also overrides pnpm and Yarn settings that could silently filter the requested dependency graph or known
advisories. Bun 1.4 cannot safely reset every inherited scope setting while retaining project registry and
authentication configuration. A Bun audit therefore returns status 2 when a loaded .npmrc or bunfig.toml excludes
a dependency type that the requested audit must cover. Development-only restrictions are accepted with --no-dev;
optional and peer dependency restrictions are not. Bun configuration must be UTF-8 and use canonical [install] table
syntax with single-line values so the preflight can verify it without heuristics. Restrictive declarations are rejected
even when another setting would override them.
Select table, plain, json, or summary with --format or -f:
composer foxy:audit --format=table
composer foxy:audit --format=plain
composer foxy:audit --format=json
composer foxy:audit --format=summaryThe default table identifies the package, severity, advisory ID, CVE, vulnerable range, and advisory title. The JSON
document has schema_version: 1 and is suitable for CI artifacts. Diagnostic and CVE lookup warnings are written to
standard error so JSON on standard output remains valid.
Native npm registry audit data normally identifies advisories by a numeric ID and GHSA rather than a CVE. Unless
--no-cve or --format=summary is used, Foxy resolves each unique public GHSA once through the
GitHub global security advisories API. A
failed optional lookup is reported as unavailable and does not discard the native finding or change its audit exit
status.
Bun can skip packages from a registry that does not answer its audit request while still returning a successful native
status. Foxy therefore treats any diagnostic emitted by bun audit --json as an unreliable partial report and returns
status 2 instead of allowing CI to pass on incomplete data.
The exit status is stable across all supported managers:
| Status | Meaning |
|---|---|
| 0 | The audit succeeded and no advisory met --audit-level. |
| 1 | The audit succeeded and at least one advisory met --audit-level. |
| 2 | A configuration, manager, lockfile, execution, or report validation failure prevented a reliable audit. |
Gate a production build on high and critical findings while retaining a compact log:
composer foxy:audit --no-dev --audit-level=high --format=summaryThe explicit command still runs when run-asset-manager is false; that setting controls automatic install and
update execution, not a user-requested audit. Foxy must be enabled, the selected binary must satisfy its supported
version constraint, and the matching native lockfile must exist.
A Composer library becomes eligible for Foxy when it contains the selected manager's package definition and uses one of the activation methods below.
Use a runtime dependency when every consumer of the library must process its frontend package:
{
"require": {
"php-forge/foxy": "^0.3"
}
}Use a development dependency when Foxy is optional for library development:
{
"require-dev": {
"php-forge/foxy": "^0.3"
}
}The consuming application must still require and authorize Foxy because dependencies of a library are not installed
from its require-dev section.
A library can declare itself eligible without adding a Foxy dependency:
{
"extra": {
"foxy": true
}
}The consuming application must require and authorize Foxy in this case as well.
When a library stores its frontend package outside its root, declare the relative directory in that library's
composer.json:
{
"config": {
"foxy": {
"root-package-json-dir": "resources"
}
}
}Foxy then reads resources/package.json from the installed library. In the root application, the same option controls
where Foxy reads and writes the project package.json and where it runs the frontend manager.
The embedded manifest must resolve inside the installed library's Composer directory. Foxy rejects a
root-package-json-dir value that resolves outside that boundary.
Foxy creates a local package representation for each eligible Composer dependency. It copies only metadata required
for dependency resolution and compatibility checks. Package lifecycle scripts, devDependencies, executable
definitions, entry points, and unrelated publishing metadata are not propagated to the consuming application.
Library authors should declare runtime frontend requirements in dependencies, optionalDependencies, or
peerDependencies. Any build step needed to publish those assets should run before the Composer package is released,
or be configured explicitly by the consuming application.
The root application can use config.foxy.enable-packages to include a package that does not declare Foxy or to
exclude a package that does. See Package selection.
- Foxy-managed dependencies use the
@composer-asset/scope and localfile:references. - Existing project dependencies and development dependencies are retained.
package.jsonwrites use four-space indentation and preserve empty object and array semantics.root-package-json-dircontrols project reads, writes, and manager working directory.- Manager execution does not change the PHP process working directory.
- Asset restoration occurs when package merging or manager execution fails and
fallback-assetis enabled. - Composer lock and vendor restoration occurs after any solve exception or non-zero manager result when
fallback-composeris enabled. - Read, write, and remove failures are reported through exceptions instead of being silently ignored.
Composer restoration does not include the root composer.json bytes. Review that file after a failed
composer require or composer remove operation.