Flags CLI
The @basestack/flags-cli scans your repository for feature flag usage and uploads code references to Basestack so your team can see where each flag is used, directly from the Feature Flags dashboard. The tool is under active development; new commands and options may ship in minor releases.
What it does
- Code refs โ Finds
useFlag("slug")hooks and<Feature slug="slug">components in your source files. - Rich context โ Records file path, line number, and surrounding code (two lines before and after the match).
- Validation โ Drops references with empty or invalid flag slugs.
- Grouping โ Aggregates hits by flag slug before upload.
- Repo metadata โ Detects Git branch and project name automatically when possible.
- API upload โ Submits references to the Basestack API.
Install @basestack/flags-cli with npm, pnpm, Yarn, or Bun. Use a dev dependency for local development, or install globally if you want flags-cli on your PATH.
Installation
Dev dependency
npm install -D @basestack/flags-clipnpm add -D @basestack/flags-cliyarn add -D @basestack/flags-clibun add -d @basestack/flags-cliGlobal install (recommended)
npm install -g @basestack/flags-clipnpm add -g @basestack/flags-cliyarn global add @basestack/flags-clibun add -g @basestack/flags-cliIf you use Yarn 2+ (Berry), global installs behave differently than Yarn Classic; prefer a dev dependency and yarn dlx @basestack/flags-cli (or npx) when in doubt.
After a local install, run the CLI without a global install using your package managerโs runner (npx, pnpm exec, yarn dlx, or bunx), or add a script to package.json. A global install exposes the flags-cli command on your PATH.
Quick start
Install the CLI
Add @basestack/flags-cli with your preferred package manager (see Installation).
Add credentials
Provide project key, environment key, and a project API key using CLI flags, a .flagsrc file, or environment variables (see Configuration). Keys are available in the dashboard under project settings.
Upload references
From your app root (examples use npx; use pnpm exec, yarn dlx, or bunx as needed):
npx @basestack/flags-cli code-refsOr with a scan root:
npx @basestack/flags-cli code-refs --dir=./srcConfiguration
The CLI reads configuration from three sources, highest priority first: CLI flags โ .flagsrc โ environment variables.
Usage
Launcher (no subcommand)
When you run the CLI without a subcommand in an interactive terminal, it opens an OpenTUI interface so you can navigate available commands and options instead of typing them on the shell first.
flags-cliWith a local install via your package managerโs runner (same idea as Quick start):
npx @basestack/flags-cliIn non-interactive environments (for example CI), run an explicit subcommand such as code-refs so behavior does not depend on a TTY.
Command: code-refs
Scan the tree and submit references to Basestack:
flags-cli code-refsWith explicit paths and keys:
flags-cli code-refs \
--project-id=proj_xxx \
--environment-key=env_xxx \
--api-key=sk_xxx \
--dir=./srcIn an interactive terminal, code-refs opens an OpenTUI UI with progress, a scrollable results pane, and keyboard shortcuts. In CI or other non-interactive environments, it falls back to plain text output automatically.
Options
| Option | Description | Default |
|---|---|---|
--project-id | Basestack project key (required) | BASESTACK_FLAGS_PROJECT_KEY |
--environment-key | Basestack environment key (required) | BASESTACK_FLAGS_ENVIRONMENT_KEY |
--api-key | API key for authentication (required) | BASESTACK_FLAGS_API_KEY |
--api-url | API base URL | https://flags-api.basestack.co/v1 |
--dir | Directory to scan | Current directory |
-h, --help | Show help | โ |
What gets scanned
The scanner looks for common flag references in .ts, .tsx, .js, .jsx, .html, and .htm files:
// Hook usage
const isEnabled = useFlag("my-feature");
const flag = useFlag<{ variant?: string }>("my-feature");
const enabled = useBooleanFlagValue("my-feature", false);
const config = useObjectFlagValue("checkout-config", {});
// Component usage
<Feature slug="my-feature">
<MyComponent />
</Feature>
// SDK usage
const flag = await fetchFlag("my-feature", flagsConfig);
const value = await client.getFlag("my-feature");
client.clearFlagCache("my-feature");
client.getBooleanValue("my-feature", false);
client.getObjectValue("checkout-config", {});
client.getBooleanDetails("my-feature", false);
// Modal usage
const { openFeedbackModal } = useFlag("my-feature");
openFeedbackModal({ featureName: "My Feature" });
const { openFeedbackModal } = useFeatureFlagModals();
openFeedbackModal("my-feature", { featureName: "My Feature" });
// Preload usage
const sdkOptions = {
preloadFlags: ["header", "footer"],
};
// Web component usage
<feature-flag-feedback-modal flag-key="my-feature" />For simple dynamic cases, the scanner can resolve identifier arguments when they are backed by a nearby string literal โ for example fetchFlag(slug, ...) with slug = "header" or const slug = "header".
These directories are skipped: node_modules, dist, build, .git, coverage, .next, .turbo, and out.
CI/CD
Run the same command in your pipeline so references stay aligned with the branch being built. Store keys in your CI secret store.
- name: Update flag references
run: npx @basestack/flags-cli code-refs
env:
BASESTACK_FLAGS_PROJECT_KEY: ${{ secrets.BASESTACK_FLAGS_PROJECT_KEY }}
BASESTACK_FLAGS_ENVIRONMENT_KEY: ${{ secrets.BASESTACK_FLAGS_ENVIRONMENT_KEY }}
BASESTACK_FLAGS_API_KEY: ${{ secrets.BASESTACK_FLAGS_API_KEY }}How it talks to the API
The CLI submits flag references with POST {baseUrl}/flags/code-refs, where baseUrl comes from --api-url or BASESTACK_FLAGS_API_URL (default https://flags-api.basestack.co/v1). The contract matches REST API โ Submit code references.
Set BASESTACK_FLAGS_API_URL (or --api-url) to the base URL your deployment uses (hosted vs self-hosted). The REST API page lists paths and response codes for Basestack Cloud.
Headers:
| Header | Description |
|---|---|
x-api-key | API key (required) |
x-project-key | Project key (required) |
x-environment-key | Environment key (required) |
Example payload (shape only; your paths and slugs will differ):
{
"branch": "main",
"projectName": "@my-org/my-app",
"references": {
"my-feature": [
{
"filePath": "src/App.tsx",
"lineNumber": 12,
"lineContent": "function App() {\n const isEnabled = useFlag(\"my-feature\");\n const showBanner = useFlag(\"banner\");\n\n return ("
}
]
}
}The lineContent field includes up to two lines before and two lines after the matched line for context.
Success response (201):
{
"success": true
}