Basestack Docs
Tooling

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

Add to your project
npm install -D @basestack/flags-cli
pnpm add -D @basestack/flags-cli
yarn add -D @basestack/flags-cli
bun add -d @basestack/flags-cli
npm install -g @basestack/flags-cli
pnpm add -g @basestack/flags-cli
yarn global add @basestack/flags-cli
bun add -g @basestack/flags-cli

If 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-refs

Or with a scan root:

npx @basestack/flags-cli code-refs --dir=./src

Configuration

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-cli

With a local install via your package managerโ€™s runner (same idea as Quick start):

npx @basestack/flags-cli

In 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-refs

With explicit paths and keys:

flags-cli code-refs \
  --project-id=proj_xxx \
  --environment-key=env_xxx \
  --api-key=sk_xxx \
  --dir=./src

In 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

OptionDescriptionDefault
--project-idBasestack project key (required)BASESTACK_FLAGS_PROJECT_KEY
--environment-keyBasestack environment key (required)BASESTACK_FLAGS_ENVIRONMENT_KEY
--api-keyAPI key for authentication (required)BASESTACK_FLAGS_API_KEY
--api-urlAPI base URLhttps://flags-api.basestack.co/v1
--dirDirectory to scanCurrent directory
-h, --helpShow helpโ€”

What gets scanned

The scanner looks for common flag references in .ts, .tsx, .js, .jsx, .html, and .htm files:

Patterns
// 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.

.github/workflows/flag-refs.yml (excerpt)
- 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:

HeaderDescription
x-api-keyAPI key (required)
x-project-keyProject key (required)
x-environment-keyEnvironment key (required)

Example payload (shape only; your paths and slugs will differ):

Request body (example)
{
  "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):

Response (example)
{
  "success": true
}

On this page