fallow coverage groups the paid Runtime Coverage workflow commands:
setup
The setup flow is resumable: run it once to bootstrap, follow the generated recipe, then run it again after traffic has been captured. It performs four steps:
- check license state
- locate or install
fallow-cov - write a framework-specific collection recipe to
docs/collect-coverage.md - if coverage already exists, hand off directly to
fallow health --runtime-coverage <path>
Flags
What setup detects automatically
fallow coverage setup inspects package.json, lockfiles, and scripts to tailor the instructions:
If the project does not match a built-in framework recipe, fallow still writes a fallback
docs/collect-coverage.md with a link to the public coverage docs for manual setup.
Agent-readable JSON
fallow coverage setup --yes --json is the agent-driven entry point. The payload is deterministic and stable across reruns; --explain adds the optional _meta keys without changing schema_version.
On a workspace monorepo (Elysia API at root + two Vite browser apps in dashboard/ and site/):
framework_detected uses canonical ids (nextjs, nestjs, nuxt, sveltekit, astro, remix, vite, plain_node, unknown). Workspace projects emit one members[] entry per runtime-bearing workspace, each with its own framework_detected, runtime_targets, files_to_edit, snippets, and dockerfile_snippet. Top-level fields mirror the first emitted runtime member (the root when the root itself is a runtime app, otherwise the first runtime workspace), so on a browser-rooted monorepo with a Node child agents should read each member’s dockerfile_snippet rather than the top-level one. Single-app projects emit a members array of length 1 (path "."), so consumers can treat members[] uniformly.
Aggregator-only repos (workspaces whose only runtime indicator is a Turbo/Nx-style dev script delegating to children, plus build-only library packages) are not runtime-bearing and emit an empty payload: framework_detected: "unknown", runtime_targets: [], members: [], plus a warnings entry of "No runtime workspace members were detected; emitted install commands only.". Agents can branch on members.length === 0 (or framework_detected === "unknown") to detect this case and skip the snippet-application step.
Generated recipe
The generateddocs/collect-coverage.md recipe typically looks like:
build, start, or preview scripts when they exist and falls back to common framework commands otherwise.
Typical flow
analyze
Use local mode when you have a coverage artifact on disk:
FALLOW_API_KEY alone never selects cloud mode. You must pass --cloud, --runtime-coverage-cloud, or set FALLOW_RUNTIME_COVERAGE_SOURCE=cloud.
Analyze flags
Cloud analysis emits the same
runtime_coverage JSON block as local mode. Its summary includes data_source: "cloud", last_received_at, and capture_quality derived from the pulled runtime window. Cloud functions that cannot be matched to the local AST/static index are omitted from findings and reported through a cloud_functions_unmatched warning.
The join does not require the two sides to spell a function the same way. Stable-id matching runs first. A runtime path such as /app/src/a.ts from a containerized service is then rebased onto the local tree by file name plus a segment-wise suffix comparison, and a function whose runtime name disagrees with the static index (an anonymous callback reported as map, then, or get, or an accessor keeping its get prefix) is matched on its position within the resolved file. Both tiers refuse an ambiguous answer rather than guess: two local files equally entitled to one runtime path, or two definitions opening on the same line with no end line between them, stay unmatched. Pass --debug-unmatched to list whatever is left.
Each finding’s actions[].type uses the canonical kebab-case vocabulary: delete-cold-code is emitted on verdict=safe_to_delete, review-runtime on verdict=review_required. The sidecar may emit additional protocol-specific identifiers, so consumers should treat unknown values as forward-compat extensions rather than schema violations.
Sidecar installation
Iffallow-cov is missing, setup tells you exactly what it checked and suggests the correct install command for your package manager, for example:
FALLOW_COV_BIN first, then FALLOW_COV_BINARY_PATH, then project-local auto-discovery. Both fail hard with a clear error if the configured path does not exist (they never silently fall through to the next step). FALLOW_COV_BINARY_PATH exists for air-gapped enterprise installs, Linux distro-packaged sidecars, and Docker multi-user setups where ~/.fallow/bin is not writable.
Sidecar signature verification
Every sidecar spawn runs an Ed25519 signature check against the compiled-in public key. The sidecar binary must ship with an adjacent<binary>.sig file. A missing, wrong-length, or invalid signature fails hard with exit code 4 rather than executing an unverified binary. There is no warn-and-run mode and no opt-out env var. If verification fails, reinstall the signed distribution with the install command above.
upload-inventory
fallow coverage upload-inventory walks every JS/TS source in the project and POSTs a static function inventory (one row per declaration, expression, arrow, or method) to fallow cloud. The server computes inventory − runtime-seen = untracked for the matching git SHA, which lights up the dashboard’s Untracked filter.
Defaults and inference
Flags
Function naming
Inventory entries use names that matchoxc-coverage-instrument byte-for-byte so the runtime join succeeds. Precedence:
- Parent context (method key, variable binding, property key,
export default). - The function’s own
id(function foo() {}, named function expression). (anonymous_N)whereNis a file-scoped monotonic counter.
*.d.ts, *.d.mts, *.d.cts, *.d.tsx) and overload signatures with no body are intentionally skipped: they have no runtime footprint, so including them would pollute the dashboard with permanently untracked entries.
Path prefix (containerized deployments)
The runtime beacon reports V8’sfilePath as it sees it at runtime. In a container, that is the path inside the image (e.g. /app/src/foo.ts when the Dockerfile sets WORKDIR /app). The static inventory walker, running in CI against the checkout, emits repo-relative paths (src/foo.ts) by default. The server joins runtime and inventory on the exact (filePath, functionName) pair; if the two sides don’t share a prefix shape, the Untracked filter never lights up and the dashboard surfaces a mismatched state.
The fix: pass --path-prefix matching your deployed WORKDIR:
After upload, the server samples up to 100 recent runtime rows and reports the overlap with the inventory. The CLI prints a yellow warning if overlap < 50% with an example mismatch, and the dashboard renders a configuration-needed state on the repo detail page until the prefix is corrected.
Exit codes
Example CI job (GitHub Actions)
Dry-run output
upload-source-maps
fallow coverage upload-source-maps scans a build output directory for source maps and POSTs each map to fallow cloud under the current repo and git SHA. The production beacon reports coverage against deployed bundles; uploaded source maps let the cloud resolver remap those bundle positions back to original source files.
Source-map defaults
The API key comes only from
FALLOW_API_KEY; there is intentionally no --api-key flag, so secrets do not land in shell history or process lists. Set FALLOW_CA_BUNDLE=/path/to/bundle.pem when CI needs a custom PEM trust bundle for fallow cloud. The bundle replaces the default WebPKI roots, so private-CA environments should pass a complete bundle containing public roots plus the private CA. Relative bundle paths resolve from the process working directory.
Uploads retry network failures, HTTP 429, and HTTP 502/503/504 up to three attempts. HTTP 429 honors Retry-After delta seconds and HTTP-date values, capped at 60 seconds. Setup or transport failures that prevent every map from uploading exit 7; mixed per-map failures still exit 1.
Source-map CI snippets
- GitHub Actions
- GitLab CI
- CircleCI
Source-map failure modes
See also
License commands
Start a trial, refresh a token, or inspect feature status.
Runtime coverage
Learn what runtime coverage adds and how it differs from static reachability.