fallow plugin-check
Find out why a custom plugin does not activate or seeds no entries. Fallow plugin-check is a read-only dry run that reports, for each external plugin, if it activated and what each manifestEntries rule matched and seeded.
Use fallow plugin-check to debug an external plugin while you write it. The command does a dry run of your external plugins and does not run a full analysis. For each plugin, it tells you if the plugin activated, and what each manifestEntries rule matched and seeded. The command is read-only, so you can run it again after each change to a fallow-plugin-* file.
plugin-check is advisory, and never a gate. It always exits 0, and it rejects the output-gating flags (--ci, --fail-on-issues, --sarif-file, --output-file) with exit code 2. Use it to debug why a plugin does not activate or seeds nothing. Do not use it to fail CI.
fallow plugin-check
fallow plugin-check --format json
fallow plugin-check --format json --root packages/app
fallow list --plugins tells you if a plugin is active. For an active plugin, plugin-check also shows what each manifestEntries rule matched and seeded. For the plugin file format, the field reference, and manifestEntries interpolation, see Custom plugins.
What it reports
Fallow finds external plugins in the plugins config field, the .fallow/plugins/ directory, and fallow-plugin-* files in the project root. For each of these plugins, it reports:
active. For an inactive plugin, anactivation_requirementstring names the unmet condition. A plugin with a failingdetectionthus shows why it did not activate.- For an active plugin with
manifestEntries, a report for each rule:- the manifests that the glob matched (
manifests_matched) - the result of the
whengate for each matched manifest (when_passed) - the seeded entries, each a resolved path with a
path_existsflag - any
warnings
- the manifests that the glob matched (
The output is deterministic and sorted. --format json gives the same bytes on each machine, so you can diff it in CI or use it as a test snapshot.
path_exists reports if a file on disk matches the seeded glob. false means that the entry is broken for certain. true is necessary but not sufficient. It does not prove that the entry became reachable, because file discovery still removes gitignored files and files with the wrong extension.
Warnings
Each manifestEntries rule reports typed warnings[]. When a rule seeds nothing, read these warnings first. Agents branch on the kebab-case kind. Each warning has only the fields for its kind: glob, field_path, manifest, or entry. The two limit warnings also have a limit number.
kind | Emitted when |
|---|---|
manifests-matched-none | The manifests glob matched no files. |
when-excluded-all | The rule's when gate excluded every matched manifest. |
field-path-unresolved | A ${dotted.field} path did not resolve in any of the gated manifests (probably a typo). |
entries-empty | The rule's entries list is empty, so it seeds nothing. |
manifest-parse-failed | Fallow could not read or parse a matched manifest (one warning for each failing manifest). |
field-values-limit-exceeded | A field path in a manifest gave more values than the limit (1,024). Make the manifest array smaller or split the rule. |
entry-expansion-limit-exceeded | An entry template gave more concrete paths for one manifest than the limit (4,096). Use less interpolation in the template. |
entry-outside-root | A seeded entry resolved outside the project root, and fallow skipped it. |
seeded-paths-missing | The rule seeded entries, but none of the seeded paths exist on disk. |
Options
| Flag | Description |
|---|---|
--root <ROOT> | Project root directory |
--config <CONFIG> | Path to a config file. The file can declare extra plugin paths in plugins |
--format <FORMAT> | Output format (human default, json for agents) |
--quiet | Suppress progress output |
Global flags such as --no-cache and --threads still apply. See global flags.
JSON output
This example shows both shapes in one run:
- an inactive plugin, with its
activation_requirement - an active plugin with a rule that seeded an entry that does not exist on disk yet (
path_exists: false). The rule reports aseeded-paths-missingwarning.
{
"kind": "plugin-check",
"schema_version": "1",
"note": "path_exists reports whether a file matches the seeded glob on disk. false means the entry is definitely broken; true is necessary but NOT sufficient (it does not prove the entry became reachable, since discovery still filters gitignored and wrong-extension files).",
"plugins": [
{
"name": "acme-framework",
"active": false,
"activation_requirement": "no enabler present; requires one of these dependencies: @acme/core"
},
{
"name": "internal-manifests",
"active": true,
"manifest_rules": [
{
"manifests": "**/service.jsonc",
"manifests_matched": ["svc/service.jsonc"],
"matched": [
{
"path": "svc/service.jsonc",
"when_passed": true,
"seeded": [
{ "path": "svc/src/main.{ts,tsx}", "path_exists": false }
]
}
],
"warnings": [
{ "kind": "seeded-paths-missing", "glob": "**/service.jsonc" }
]
}
]
}
]
}
A healthy active plugin reports when_passed: true, path_exists: true for each seeded entry, and an empty warnings array.
plugin-check is a CLI-only tool for plugin authors. The MCP server does not expose it.