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
46 changes: 23 additions & 23 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,9 @@ export default defineConfig({
pagination: true,
credits: false,
sidebar: [
{
label: "Blog",
items: [
{ label: "All posts", link: "/blog/" },
],
},
{
label: "Start Here",
collapsed: true,
collapsed: false,
items: [
{ label: "Overview", slug: "docs" },
{ label: "Quickstart", slug: "docs/quickstart" },
Expand All @@ -56,13 +50,19 @@ export default defineConfig({
],
},
{
label: "Tutorials",
label: "CLI",
collapsed: true,
items: [
{ label: "Migrate a Node Service", slug: "docs/tutorials/migrate-a-node-service" },
{ label: "Add OpenFeature Provider", slug: "docs/tutorials/add-openfeature-provider" },
{ label: "Enforce in GitHub Actions", slug: "docs/tutorials/enforce-in-github-actions" },
{ label: "Shared Client Architecture", slug: "docs/tutorials/shared-client-architecture" },
{ label: "init", slug: "docs/cli/init" },
{ label: "audit", slug: "docs/cli/audit" },
{ label: "Effort Estimation", slug: "docs/cli/effort-estimate" },
{ label: "scan", slug: "docs/cli/scan" },
{ label: "migrate", slug: "docs/cli/migrate" },
{ label: "validate", slug: "docs/cli/validate" },
{ label: "Configuration", slug: "docs/cli/configuration" },
{ label: "Report Formats", slug: "docs/cli/report-formats" },
{ label: "Exit Codes", slug: "docs/cli/exit-codes" },
{ label: "completion", slug: "docs/cli/completion" },
],
},
{
Expand All @@ -77,19 +77,13 @@ export default defineConfig({
],
},
{
label: "CLI",
label: "Tutorials",
collapsed: true,
items: [
{ label: "init", slug: "docs/cli/init" },
{ label: "audit", slug: "docs/cli/audit" },
{ label: "Effort Estimation", slug: "docs/cli/effort-estimate" },
{ label: "scan", slug: "docs/cli/scan" },
{ label: "migrate", slug: "docs/cli/migrate" },
{ label: "validate", slug: "docs/cli/validate" },
{ label: "Configuration", slug: "docs/cli/configuration" },
{ label: "Report Formats", slug: "docs/cli/report-formats" },
{ label: "Exit Codes", slug: "docs/cli/exit-codes" },
{ label: "completion", slug: "docs/cli/completion" },
{ label: "Migrate a Node Service", slug: "docs/tutorials/migrate-a-node-service" },
{ label: "Add OpenFeature Provider", slug: "docs/tutorials/add-openfeature-provider" },
{ label: "Enforce in GitHub Actions", slug: "docs/tutorials/enforce-in-github-actions" },
{ label: "Shared Client Architecture", slug: "docs/tutorials/shared-client-architecture" },
],
},
{
Expand Down Expand Up @@ -131,6 +125,12 @@ export default defineConfig({
{ label: "Privacy", slug: "docs/trust/privacy" },
],
},
{
label: "Blog",
items: [
{ label: "All posts", link: "/blog/" },
],
},
],
head: [
{
Expand Down
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/)
Loading
Loading