FlagShark CLI
Open-source CLI that scans your codebase for stale feature flags. No account required.
flagshark is the open-source CLI that powers FlagShark. Drop it into any repo, run one command, and get a report of stale feature flags — no account, no configuration required to get started, no telemetry. It uses the same detection engine (@flagshark/core) as the FlagShark dashboard and GitHub Action, so results are consistent across all three.
Install
The fastest path is npx — no install needed:
npx flagshark scan
Or install globally if you run it often:
npm install -g flagshark
flagshark scan
The package is published as flagshark on npm. Source at FlagShark/flagshark on GitHub. MIT licensed.
Quickstart
Run from the root of any repo:
$ npx flagshark scan
🦈 FlagShark
Scanned 156 files across 4 languages
Detected providers: LaunchDarkly (JS SDK), Unleash (Go SDK)
Found 23 feature flags, 7 stale
Stale flags:
┌──────────────────┬────────────────────────┬───────────────┬────────────────────────┐
│ Flag │ File │ Last Modified │ Signal │
├──────────────────┼────────────────────────┼───────────────┼────────────────────────┤
│ CHECKOUT_V2 │ src/checkout.ts:47 │ 14 months ago │ age │
│ NEW_NAV │ src/layout.tsx:12 │ 8 months ago │ age, low-usage │
│ BETA_SEARCH │ src/search.ts:91 │ 11 months ago │ age, low-usage │
└──────────────────┴────────────────────────┴───────────────┴────────────────────────┘
Flag Health Score: 70/100 (7/23 flags are stale)
The CLI exits with code 0 if no stale flags are found, 1 if stale flags are detected, and 2 if something went wrong. That makes it directly usable in CI without extra glue.
CLI options
The CLI has a single subcommand, scan. Running flagshark with no arguments behaves the same as flagshark scan.
Both --flag value and --flag=value forms are accepted for all options.
| Flag | Description | Default |
|---|---|---|
--format <fmt> | Output format: text, json, markdown, csv, or sarif | text |
--output <path>, -o | Write output to a file instead of stdout | — |
--json | Deprecated — shorthand for --format json. will be removed in v2. | — |
--diff <ref> | Only scan files changed since <ref> (e.g. HEAD~1, main, origin/main) | scan everything |
--threshold <days> | Staleness threshold in days; must be a positive integer | 30 |
--verbose | Show all stale flags (not just the top 10) and print the effective exclude rules (paths, files, presets, ignore-file) to stderr — useful for debugging why files are skipped. See also --show-excluded. | top 10 |
--config <path> | Use this config file, overrides .flagshark.yml discovery | — |
--no-config | Skip .flagshark.yml discovery entirely | — |
--no-ignore-file | Skip .flagsharkignore discovery | — |
--show-excluded | List excluded files in text output | — |
--no-cache | Skip the platform-flag cache and force a re-fetch from the connected flag platform | — |
--fail-on-error / --no-fail-on-error | Exit 1 on any missing-in-platform flag | on |
--help, -h | Print help text | — |
--version, -v | Print version | — |
--show-excluded lists the actual file paths that were excluded, while --verbose prints the effective exclude rules that caused them to be skipped.
Output formats
The --format flag controls how results are rendered:
text(default) — human-readable table with color, printed to stdout.json— structured JSON object; safe to pipe tojqor another tool.markdown— GitHub-flavored Markdown table; useful for posting to issues or Slack.csv— comma-separated values; import directly into a spreadsheet.sarif— SARIF 2.1 format for IDE and security tool integrations.
Use --output <path> (or -o) to write the report to a file instead of stdout:
flagshark scan --format sarif --output flagshark.sarif
flagshark scan --format csv -o stale-flags.csv
[info], [warn], [error], etc.) go to stderr. Only the report goes to stdout. That means --format json (and the deprecated --json) are safe to pipe into jq, another script, or a file without log lines polluting the output.
Exit codes
| Code | Meaning |
|---|---|
0 | No stale flags found |
1 | One or more stale flags detected (or a missing-in-platform flag when --fail-on-error is on) |
2 | Runtime or configuration error (bad arguments, scan failure, etc.) |
This is the standard CI shape — drop the command into any script and let the exit code drive the rest.
Staleness signals
A flag reference is only evaluated if the file imports a known flag SDK. A function literally named isEnabled() in a file with no flag SDK import is ignored, which keeps false positives down.
The CLI fires two staleness signals:
age—git blameon the flag reference line shows it was last modified more than--thresholddays ago (default: 30 days).low-usage— the flag name appears in only one file across the entire repo. That usually means a rollout is finished and the losing branch was cleaned up, leaving a lone reference behind.
Two additional signals require a connected FlagShark platform integration and are reported as errors or warnings:
missing-in-platform— the flag is referenced in code but does not exist in the flag platform. This is an error-severity signal that triggers exit code1when--fail-on-erroris on (the default).archived-in-platform— the flag has been archived in the platform (warning severity).
See LaunchDarkly integration for setup details.
Common usage
Scan only what changed in this PR
Useful in CI when you don't want to penalize a PR for stale flags it didn't introduce:
flagshark scan --diff origin/main
Pipe JSON output into another tool
flagshark scan --format json | jq '.staleFlags[] | {name, file: .filePath, age}'
Tune the staleness threshold
Tighter threshold for aggressive cleanup teams:
flagshark scan --threshold 7
Looser threshold for kill-switch-heavy or long-lived codebases:
flagshark scan --threshold 90
Use it in any CI (not just GitHub Actions)
# Example: generic CI step
- run: npx flagshark scan --diff $BASE_REF
Add a pre-push git hook
# .git/hooks/pre-push
npx flagshark scan --threshold 14 || {
echo "Stale flags detected. Run 'npx flagshark scan' for details."
exit 1
}
CLI vs the dashboard
The CLI is a snapshot tool. Each run scans your current checkout and reports what it sees. It has no memory of prior runs.
The FlagShark dashboard tracks the lifecycle of each flag: when it was added, who added it, when it crossed thresholds, and (with auto-cleanup enabled) opens cleanup PRs when a flag is safe to remove.
You can use both. Many teams adopt the CLI first — zero setup, single npm command — then connect the GitHub App for tracking and automation.
Related Documentation
- GitHub Action — Same scanner, runs in GitHub Actions, posts PR comments
- Supported Languages — the full language + SDK matrix
- Configuration —
.flagshark.ymlfor custom provider patterns and exclude rules @flagshark/corelibrary — Use the detection engine directly in your own scripts