Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/content/docs/docs/cli/audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,6 @@ npx flaglint validate ./src --no-direct-launchdarkly

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/audit.md)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/audit.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [Configuration](/docs/cli/configuration/)
1 change: 1 addition & 0 deletions src/content/docs/docs/cli/completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,4 @@ flaglint completion fish > ~/.config/fish/completions/flaglint.fish

- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/completion.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [GitHub Actions](/docs/integrations/github-actions/)
70 changes: 59 additions & 11 deletions src/content/docs/docs/cli/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ Use `--config <path>` to pass a specific file.

## Fields

| Field | Default | Purpose |
| --- | --- | --- |
| `include` | `["**/*.{ts,tsx,js,jsx}"]` | Files to scan. |
| `exclude` | common build/test output | Files to skip. |
| `provider` | `launchdarkly` | Current implemented provider scope. |
| `minFileCount` | `0` | Optional local source review heuristic. |
| `wrappers` | `[]` | Wrapper functions to detect as flag evaluations. Accepts string names or object form (see below). |
| `openFeatureClientBindings` | `[]` | Imported shared client allowlist for `migrate --apply`. |
| `reportTitle` | unset | Optional report title. |
| `outputDir` | `.` | Directory for generated report files. |
| Field | Type | Default | Purpose |
| --- | --- | --- | --- |
| `include` | `string[]` | `["**/*.{ts,tsx,js,jsx}"]` | Files to scan. |
| `exclude` | `string[]` | common build/test output | Files to skip. |
| `provider` | `"launchdarkly"` | `"launchdarkly"` | Provider scope. Currently only `"launchdarkly"` is supported — other values exit 2. |
| `minFileCount` | `number` | `0` | Optional local source review heuristic. |
| `wrappers` | `(string \| WrapperObject)[]` | `[]` | Wrapper functions to detect as flag evaluations. Accepts string names or object form (see below). |
| `openFeatureClientBindings` | `string[]` | `[]` | Imported shared client allowlist for `migrate --apply`. |
| `reportTitle` | `string` (optional) | unset | Optional report title injected into HTML and Markdown reports. |
| `outputDir` | `string` | `"."` | Directory for generated report files. |

## Wrappers — String and Object Form

Expand Down Expand Up @@ -84,6 +84,54 @@ With the example above, `getFlag("my-flag-key", ctx)` is detected only when `get

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/configuration.md)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/configuration.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [Report Formats](/docs/cli/report-formats/)

## OpenFeature Client Bindings

`openFeatureClientBindings` tells `flaglint migrate --apply` which variables in your code hold
an OpenFeature client. When applying transformations, FlagLint substitutes LD SDK evaluation
calls with the corresponding OpenFeature client method calls — but only when it can identify
the client variable to substitute.

Each entry is a **variable name** (not a package name, not a file path) that FlagLint should
treat as an OpenFeature client.

### Example

Your application code:

```typescript
import openFeatureClient from './platform/of-client'

const value = openFeatureClient.getBooleanValue('my-flag', false)
```

Your config:

```json
{
"openFeatureClientBindings": ["openFeatureClient"]
}
```

With this configured, `migrate --apply` can generate the correct OpenFeature replacement call.
Without it, files that use an imported client are listed in the "skipped" output.

### Multiple bindings

If different parts of your codebase use different variable names for the OpenFeature client,
list all of them:

```json
{
"openFeatureClientBindings": ["openFeatureClient", "featureClient", "ofClient"]
}
```

### Difference from wrappers

`openFeatureClientBindings` is for the **OpenFeature client** used in migration output — it
tells FlagLint what to generate, not what to detect. `wrappers` is for **existing LD-compatible
wrappers** — it tells FlagLint what to detect as flag evaluations in your current code.
112 changes: 90 additions & 22 deletions src/content/docs/docs/cli/exit-codes.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,102 @@
---
title: Exit Codes
description: Stable exit code contract for FlagLint v1.x — 0=success, 1=policy failure, 2=invalid input, 3=internal error.
lastUpdated: 2026-06-22
description: Stable exit code contract for FlagLint v1.x — 0=success, 1=policy failure, 2=invalid input, 3=internal error, 130=interrupted.
lastUpdated: 2026-07-01
---

FlagLint uses a stable, machine-readable exit code contract guaranteed across all v1.x releases.
See the [full Exit Codes reference](/docs/reference/exit-codes/) for CI examples and rationale.
FlagLint uses a stable, machine-readable exit code contract. Codes `0`, `1`, `2`, and `130` are
guaranteed stable across all v1.x releases and safe to use in CI pipelines and scripts.

## Exit Code Table

| Code | Meaning | When it occurs |
| --- | --- | --- |
| `0` | Success — no blocking failures. | Scan completed; no policy violations found. |
| `1` | Policy or validation failure. | `validate --no-direct-launchdarkly` found direct LD calls; new findings beyond baseline (`--fail-on-new`); dirty working tree without `--allow-dirty`. |
| `2` | Invalid input. | Bad `--format` value; missing or malformed baseline or config file. |
| `3` | Internal FlagLint error. | Unexpected runtime exception in FlagLint itself. |
| `130` | Interrupted with `SIGINT` (Ctrl-C). | |

## Command Notes

- `audit` always exits `0` — it is informational only.
- `scan` exits `1` when configured stale/review signals produce blocking candidates.
- `migrate --dry-run` exits `0` after printing a plan.
- `migrate --apply` exits `1` on a dirty working tree unless `--allow-dirty` is used.
- `validate --no-direct-launchdarkly` exits `1` when direct LaunchDarkly evaluation calls are found.
- `validate --baseline <file> --fail-on-new` exits `1` when any finding fingerprint is absent from the baseline.
|------|---------|----------------|
| `0` | Success — no blocking failures | Scan or audit completed; no policy violations found; no new findings beyond baseline |
| `1` | Policy or validation failure | `validate --no-direct-launchdarkly` found direct LD calls; new findings beyond baseline (`--fail-on-new`); dirty working tree without `--allow-dirty` |
| `2` | Invalid input | Bad `--format` value; directory not found or not a directory; missing or malformed baseline file; unsupported provider in config |
| `3` | Internal FlagLint error | Unexpected runtime exception in FlagLint itself — please [report as a bug](https://github.com/flaglint/flaglint/issues/new) |
| `130` | Interrupted (SIGINT) | User pressed Ctrl-C |

## Per-Command Notes

| Command | Exit `0` | Exit `1` | Exit `2` |
|---------|----------|----------|----------|
| `scan` | Always on completion (scan is inventory, not enforcement) | — | Invalid `--format`; directory not found; bad config |
| `audit` | Always on completion (audit is informational only) | — | Invalid `--format`; directory not found; bad config |
| `migrate` (default) | Plan written successfully | — | Directory not found; bad config |
| `migrate --dry-run` | Diffs printed | — | Directory not found |
| `migrate --apply` | Transformations applied | Dirty working tree (without `--allow-dirty`) | Directory not found |
| `validate` | No policy violations | Direct LD calls found; new findings beyond baseline | Invalid `--format`; bad baseline; bad config |

## Why exit 1 does not mean the tool crashed

Exit code `1` means **FlagLint ran successfully and found a policy violation** — not that the
tool failed. This distinction matters in CI logs:

- `exit 0` → Clean. No violations found.
- `exit 1` → FlagLint worked correctly; your code has a flag debt issue to address.
- `exit 2` → You passed a bad argument or your config is invalid; fix the command invocation.
- `exit 3` → FlagLint itself hit an unexpected error; please [file a bug report](https://github.com/flaglint/flaglint/issues/new).
- `exit 130` → Interrupted by the user (Ctrl-C).

This matches the POSIX convention used by linters such as ESLint (`exit 1` = lint errors found)
and allows CI steps to distinguish tool failure from policy failure without parsing stdout.

## CI YAML example

The following GitHub Actions workflow runs `flaglint validate` as a policy gate. It expects
`exit 0` (clean) or `exit 1` (violations found), and treats any other exit code as a
misconfiguration or internal error.

```yaml
name: FlagLint Policy Gate

on:
pull_request:
push:
branches: [main]

jobs:
flaglint-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "22"

# Exit 0 → no direct LD calls (clean).
# Exit 1 → direct LD calls found (policy violation — fail the build).
# Exit 2 → bad --format or config error (fix the workflow invocation).
- name: Validate no direct LaunchDarkly calls
run: npx flaglint@latest validate ./src --no-direct-launchdarkly

# Optional: emit SARIF for GitHub Code Scanning annotations
- name: Validate (SARIF output)
if: always()
run: npx flaglint@latest validate ./src --no-direct-launchdarkly --format sarif --output flaglint.sarif
continue-on-error: true

- name: Upload SARIF to GitHub Code Scanning
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: flaglint.sarif
```

See the [GitHub Actions integration guide](/docs/integrations/github-actions/) and
the [`validate` command reference](/docs/cli/validate/) for the full set of options
including `--bootstrap-exclude` for allowing provider setup files.

## Stability guarantee

Codes `0`, `1`, `2`, and `130` are stable across all FlagLint v1.x releases.
Code `3` (internal error) may be refined in future releases but will always indicate
an unexpected tool failure (not a policy result).

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/exit-codes.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- See also: [Exit Codes reference](/docs/reference/exit-codes/)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/exit-codes.md)
- [Report an issue](https://github.com/flaglint/flaglint/issues/new)
- Next: [Express Guide](/docs/guides/express/)
2 changes: 1 addition & 1 deletion src/content/docs/docs/cli/migrate.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ Provider/bootstrap setup is never inserted automatically.

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/migrate.md)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/migrate.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [validate CLI](/docs/cli/validate/)
102 changes: 85 additions & 17 deletions src/content/docs/docs/cli/report-formats.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,112 @@
---
title: Report Formats
description: JSON, Markdown, HTML, and SARIF outputs.
lastUpdated: 2026-05-28
description: When to use JSON, Markdown, HTML, SARIF, and text output — comparison table, usage examples, and GitHub Code Scanning integration.
lastUpdated: 2026-07-01
---

## Scan Formats
FlagLint supports multiple output formats. Choose based on who consumes the output and how.

## Format comparison

| Format | Commands | Best for |
|--------|----------|----------|
| `markdown` | `scan`, `audit` | Human review, GitHub PR comments, Slack sharing |
| `json` | `scan`, `audit` | Automation, CI pipelines, custom dashboards, `jq` filtering |
| `html` | `scan`, `audit` | Sharing with non-technical stakeholders, archiving audit results |
| `sarif` | `scan`, `validate` | GitHub Code Scanning, IDE integrations, VS Code SARIF Viewer |
| `text` | `validate` | Terminal output, CI logs where markdown rendering is not available |

## When to use each format

**`markdown` (default for scan and audit)**

Readable in GitHub PR comments and any Markdown renderer. Use this when you want engineers
to read findings directly — in a PR review, a Slack post, or a shared Notion doc. This is the
default when `--format` is omitted.

**`json`**

Machine-readable structured output. Use with `jq` for filtering, in custom dashboards, or when
building integrations on top of FlagLint output. The full schema is documented at
[JSON Output Reference](/docs/reference/json-output/).

```bash
npx flaglint scan ./src --format json
npx flaglint scan ./src --format markdown
npx flaglint scan ./src --format html --output flaglint-inventory.html
npx flaglint scan ./src --format sarif --output flaglint-inventory.sarif
npx flaglint@latest scan ./src --format json | jq '.usages[] | select(.isStale == true)'
```

Use scan formats for inventory and review.
**`html`**

Self-contained single-file report. Use for sharing audit results with engineering managers or
stakeholders who do not have CLI access. The HTML file embeds all styles — no server needed,
just open in a browser.

```bash
npx flaglint@latest audit ./src --format html --output flaglint-audit.html
```

**`sarif`**

[SARIF 2.1.0](https://sarifweb.azurewebsites.net/) compliant output. Use with:
- **GitHub Code Scanning** — upload via `github/codeql-action/upload-sarif` to get inline PR annotations
- **VS Code SARIF Viewer** extension — view findings inline in your editor
- **Azure DevOps** SARIF integration

## Validation SARIF
**`text`**

Use `validate --format sarif` for direct-SDK policy enforcement:
Plain-text output for `validate`. Use in CI logs where markdown rendering is not available and
you want a human-readable summary without table syntax.

## Usage examples

### Scan formats

```bash
npx flaglint@latest scan ./src --format json
npx flaglint@latest scan ./src --format markdown
npx flaglint@latest scan ./src --format html --output flaglint-inventory.html
npx flaglint@latest scan ./src --format sarif --output flaglint-inventory.sarif
```

### Validation SARIF

Use `validate --format sarif` for direct-SDK policy enforcement with GitHub Code Scanning:

```bash
npx flaglint validate ./src \
npx flaglint@latest validate ./src \
--no-direct-launchdarkly \
--format sarif \
--output flaglint-validation.sarif
```

This is the SARIF output intended for GitHub Code Scanning annotations.
### GitHub Code Scanning integration

Upload SARIF output to get inline annotations on pull requests:

```yaml
- name: Run FlagLint validate
run: npx flaglint@latest validate ./src --no-direct-launchdarkly --format sarif --output flaglint.sarif
continue-on-error: true

- name: Upload SARIF to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: flaglint.sarif
```

Findings appear as inline annotations on the Files Changed tab of your pull request.

## Migration Reports
### Migration reports

```bash
npx flaglint migrate ./src --output MIGRATION.md
npx flaglint migrate ./src --dry-run
npx flaglint@latest migrate ./src --output MIGRATION.md
npx flaglint@latest migrate ./src --dry-run
```

The default migration report summarizes evidence. Dry-run prints diffs.
The default migration report summarizes evidence and migration readiness. `--dry-run` prints
reviewable diffs to stdout without writing any files.

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/report-formats.md)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/report-formats.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [Exit Codes](/docs/cli/exit-codes/)
12 changes: 9 additions & 3 deletions src/content/docs/docs/cli/scan.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,18 @@ Generated from `examples/enterprise-checkout-service/src`:
- Line 67: `checkout-currency` (stringVariation)
```

## Exit Behavior
## Exit Codes

`scan` exits `1` only when configured review signals mark non-dynamic, non-bulk flags as stale candidates. A one-file flag is not stale by default because `minFileCount` defaults to `0`.
`scan` is an inventory command — it never exits `1` due to findings. Use `validate` for CI enforcement.

| Code | Meaning |
| --- | --- |
| `0` | Scan completed. |
| `2` | Invalid input — bad `--format` value, directory not found, or invalid config. |
| `130` | Interrupted (Ctrl+C / SIGINT). |

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/scan.md)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/scan.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [migrate CLI](/docs/cli/migrate/)
2 changes: 1 addition & 1 deletion src/content/docs/docs/cli/validate.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,6 @@ npx flaglint validate ./src \

## Feedback

- [Edit this page on GitHub](https://github.com/flaglint/flaglint/edit/main/docs-src/content/docs/docs/cli/validate.md)
- [Edit this page on GitHub](https://github.com/flaglint/flaglint.dev/edit/main/src/content/docs/docs/cli/validate.md)
- [Report an unsupported pattern](https://github.com/flaglint/flaglint/issues/new?template=unsupported_pattern.yml)
- Next: [Configuration](/docs/cli/configuration/)
Loading
Loading