npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

flagforge

v0.5.0

Published

Open-source, on-premise feature flagging platform

Readme

FlagForge

Tests

Open-source, on-premise feature flagging platform built for speed and simplicity.

Features

  • Multiple Storage Backends: SQLite or JSON file
  • Multi-Environment Support: dev, staging, production, or custom environments
  • Typed Flags: boolean, number or string flags with an active value and a default (off) value
  • Targeting Rules: Enable flags for specific users or attributes
  • Percentage Rollout: Gradual rollout to a percentage of users
  • REST API: Simple HTTP API for integration
  • No External Dependencies: Runs entirely on-premise

Quick Start

Fastest: 1-click installer

npx flagforge init

An interactive wizard asks for the port, storage backend and admin password, creates .env and data/ in the current directory, and starts the server right away. To restart later without reconfiguring:

flagforge start

From source (development)

yarn install
cp .env.example .env

Configuration

Edit .env:

PORT=3000
STORAGE_TYPE=sqlite # or "json"
STORAGE_PATH=./data/flagforge.db

Running

# Development
yarn dev

# Production
yarn build
yarn start

Updating

flagforge update

Updates the global flagforge package to the latest version published on npm. If the update needs elevated permissions (global install owned by root), the command prints the exact commands to run as root instead of failing. It never restarts your service — restart it yourself with whatever process manager you use.

Testing

# Run all tests
yarn test

# Run tests in watch mode
yarn test:watch

# Run tests with coverage
yarn test:coverage

Linting

# Run ESLint
yarn lint

# Auto-fix linting issues
yarn lint:fix

Web App

FlagForge includes a built-in web interface available at http://localhost:3000 (or whichever port you configure). No separate installation is required — the UI is served directly by the same Node.js process.

Authentication

The web app is protected by a password set via the ADMIN_PASSWORD environment variable. On first access you'll be prompted to sign in.

Projects

After login, the Projects page is your home screen. A project groups feature flags by application (e.g. mobile-app, backend, website).

  • Create a project — type a name and press Enter or click "Create project"
  • Delete a project — click Delete on the project row and confirm

Environments

Each project can have multiple environments (e.g. production, staging, development). Environments are fully isolated: flags in production are invisible to staging API keys.

From the Projects page, each project row shows its environments. For each environment you can:

  • Copy the client key (ff_…) — click "Copy" to copy it to the clipboard; distribute this to apps/services that only need to read/evaluate flags
  • Copy the secret key (ffs_…) — keep this only in trusted backends; it can also create, update and delete flags via /api/flags
  • Regenerate a key — invalidates the old client or secret key and generates a new one (confirmation required)
  • Rename the environment — click the pencil icon
  • Delete the environment — confirmation required
  • Navigate to flags — click the environment name to open its flag list

Feature Flags

Clicking an environment name opens the Flags page for that project + environment combination.

Each flag in the list shows:

  • Its key (e.g. new-checkout-flow)
  • Its name (human-readable label)
  • Optional badges: Targeting (if user/attribute rules are set) and Rollout X% (if a percentage rollout is active)
  • A toggle to enable or disable the flag without opening it

Click any flag row to open the edit drawer. Click + New Flag to create one.

Flag editor

The drawer on the right lets you configure:

| Field | Description | |-------|-------------| | Name | Human-readable label (auto-generates the key on creation) | | Key | Immutable identifier used in API calls (e.g. dark-mode) | | Description | Optional free-text note | | Type | boolean (default), number or string. Set on creation and immutable afterwards | | Value (when on) / Default value (when off) | Only shown for number/string flags; required. The typed value returned when the flag is on (enabled + targeting/rollout match) vs. off/no-match | | Enabled | Master on/off switch (new flags start disabled) | | Targeting — User IDs | Comma-tag input; the flag returns true only for listed user IDs | | Targeting — Attributes | Key/value rules (e.g. plan = premium, enterprise) | | Rollout percentage | Enables the flag for N% of users via consistent hashing |

Evaluation order: User IDs → Attributes → Rollout percentage → Enabled value

Live preview

At the bottom of the editor there's a "Test this flag" panel. Enter a userId and optional attributes to see in real time whether the current configuration would return true or false for that context — without making any API call.

Realtime updates

The UI automatically reflects changes when a flag is modified — whether from another user editing the same flag in the web app or from an AI agent via the MCP server. Updates are delivered instantly through a Server-Sent Events (/admin/events) channel, keeping your session in sync without requiring a page reload.

Usage

1. Get an API Key

API keys are created per environment. Create an environment from the web UI (open a project and add an environment) and copy its API key (ff_…) — that key authenticates your requests. Each environment gets its own key, so flags stay isolated per environment.

You'll use this ff_… key as a Bearer token for the requests below.

2. Create a Feature Flag

Each environment has two API keys:

  • Client key (ff_…) — meant to be distributed to apps/services. It can only read and evaluate flags.
  • Secret key (ffs_…) — meant to stay in trusted backends only (never ship it to a browser or mobile app). It can do everything the client key can, plus create, update and delete flags via /api/flags.

Both keys are shown next to their environment in the web UI (Projects page).

Flags can be created and managed from the web UI (admin session), or from any trusted backend using the secret key:

curl -X POST http://localhost:3000/api/flags \
  -H "Authorization: Bearer ffs_xxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "new-checkout-flow",
    "name": "New Checkout Flow",
    "description": "Redesigned checkout experience"
  }'

The same endpoint accepts PATCH /api/flags/:key and DELETE /api/flags/:key with the same secret-key Authorization header, to update or delete a flag.

The client key (ff_…) is read/evaluate only. Write operations on /api/flags (POST/PATCH/DELETE) return 403 when called with the client key — use the secret key (ffs_…) or the web UI instead.

3. Evaluate a Flag

curl -X POST http://localhost:3000/api/evaluate/new-checkout-flow \
  -H "Authorization: Bearer ff_xxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123"
  }'

Response:

{
  "key": "new-checkout-flow",
  "value": true,
  "enabled": true,
  "metadata": {
    "flagEnabled": true,
    "type": "boolean",
    "hasTargeting": false,
    "hasRollout": false
  }
}

value holds the resolved, typed value for the flag: for boolean flags it's true/false (same as enabled); for number/string flags it's the flag's active value when on, or its defaultValue when off/no-match. enabled is kept for backward compatibility. The flag's type is set at creation time in the web app's flag editor and is immutable afterwards.

Advanced Features

User Targeting

Enable a flag only for specific users. Configure targeting from the web UI (flag editor → Targeting); the resulting rule has this shape:

{
  "targeting": {
    "userIds": ["user-123", "user-456"]
  }
}

Attribute Targeting

Target users based on attributes. Configure it from the web UI; the rule has this shape:

{
  "targeting": {
    "attributes": {
      "plan": ["premium", "enterprise"],
      "region": ["us-west"]
    }
  }
}

Evaluate with attributes:

curl -X POST http://localhost:3000/api/evaluate/premium-feature \
  -H "Authorization: Bearer ff_xxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-789",
    "attributes": {
      "plan": "premium",
      "region": "us-west"
    }
  }'

Percentage Rollout

Gradually roll out to a percentage of users. Configure the rollout from the web UI (flag editor → Rollout percentage); the resulting rule has this shape:

{
  "rollout": {
    "percentage": 25
  }
}

This will enable the flag for approximately 25% of users (based on consistent hashing of userId).

Batch Evaluation

Evaluate multiple flags at once:

curl -X POST http://localhost:3000/api/evaluate \
  -H "Authorization: Bearer ff_xxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "flags": ["feature-a", "feature-b", "feature-c"],
    "context": {
      "userId": "user-123",
      "attributes": {
        "plan": "premium"
      }
    }
  }'

Response:

{
  "feature-a": true,
  "feature-b": false,
  "feature-c": true
}

API Reference

Admin Endpoints

These require an admin session (the web UI). Environment API keys are created by creating an environment.

| Method | Endpoint | Description | |--------|----------|-------------| | GET | /admin/projects | List projects | | POST | /admin/projects | Create a project | | DELETE | /admin/projects/:id | Delete a project | | GET | /admin/projects/:id/environments | List a project's environments (with their API keys) | | POST | /admin/projects/:id/environments | Create an environment (generates its API key) | | PATCH | /admin/projects/:id/environments/:envId | Rename an environment | | DELETE | /admin/projects/:id/environments/:envId | Delete an environment | | POST | /admin/environments/:envId/regenerate-key | Regenerate an environment's API key |

Flag Management

Reads work with either API key (Bearer ff_… or Bearer ffs_…). Writes require the secret key (Bearer ffs_…) — calling a write endpoint with the client key (ff_…) returns 403. Writes are also available from the web UI (admin session).

| Method | Endpoint | Description | Auth | |--------|----------|-------------|------| | GET | /api/flags | List all flags | Client or secret key | | GET | /api/flags/:key | Get a specific flag | Client or secret key | | POST | /api/flags | Create a flag | Secret key (403 with client key) | | PATCH | /api/flags/:key | Update a flag | Secret key (403 with client key) | | DELETE | /api/flags/:key | Delete a flag | Secret key (403 with client key) |

Flag Evaluation (Requires Authentication)

| Method | Endpoint | Description | |--------|----------|-------------| | POST | /api/evaluate/:key | Evaluate a single flag | | POST | /api/evaluate | Batch evaluate multiple flags |

MCP Server

FlagForge ships with an opt-in Model Context Protocol endpoint that lets AI agents (Claude, Cursor, etc.) manage your feature flags directly.

The endpoint is mounted at /mcp and is disabled by default. It is only mounted when an MCP_TOKEN is configured.

Enabling it

Either:

  • Answer "yes" to "Setup also FlagForge MCP server?" during flagforge init — a token is generated for you and saved to .env, and a ready-to-paste client config is printed.
  • Or set MCP_TOKEN manually in .env:
MCP_TOKEN=ff_mcp_your_token_here

Restart the server for the change to take effect.

Available tools

| Tool | Description | |------|-------------| | list_projects | List all projects | | list_environments | List environments for a project, identified by name | | list_flags | List flags for a project + environment | | set_flag | Create or update a flag (upsert) | | evaluate_flag | Evaluate a flag for a given context; also returns a reason explaining the outcome (disabled, targeting-miss, rollout-excluded, enabled) |

There is intentionally no delete tool — flag deletion is only available through the web app or the admin API.

Environments are identified by name, not by id, across all of FlagForge. list_environments returns only { name } for this reason — always pass that name as the environment argument to list_flags, set_flag and evaluate_flag. set_flag rejects unknown environment names with an error listing the valid ones instead of writing anything.

Client configuration

Point your MCP-compatible client at the endpoint, sending the token as a bearer Authorization header:

{
  "mcpServers": {
    "flagforge": {
      "url": "http://<host>:<port>/mcp",
      "headers": {
        "Authorization": "Bearer <your-mcp-token>"
      }
    }
  }
}

Security note

The MCP endpoint is opt-in and the token grants full read/write control over all flags (across all projects and environments) — treat it like an admin credential. Do not share it or commit it to source control.

Client Integration Example

Node.js

class FlagForgeClient {
  constructor(apiUrl, apiKey) {
    this.apiUrl = apiUrl;
    this.apiKey = apiKey;
  }

  async isEnabled(flagKey, context) {
    const response = await fetch(`${this.apiUrl}/api/evaluate/${flagKey}`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(context)
    });

    const data = await response.json();
    return data.enabled;
  }

  async evaluateMany(flagKeys, context) {
    const response = await fetch(`${this.apiUrl}/api/evaluate`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ flags: flagKeys, context })
    });

    return await response.json();
  }
}

// Usage
const client = new FlagForgeClient(
  'http://localhost:3000',
  'ff_xxxxxxxxxxxxxxxxxx'
);

const enabled = await client.isEnabled('new-checkout-flow', {
  userId: 'user-123',
  attributes: { plan: 'premium' }
});

if (enabled) {
  // Show new checkout flow
}

Python

import requests

class FlagForgeClient:
    def __init__(self, api_url, api_key):
        self.api_url = api_url
        self.api_key = api_key
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }

    def is_enabled(self, flag_key, context):
        response = requests.post(
            f'{self.api_url}/api/evaluate/{flag_key}',
            headers=self.headers,
            json=context
        )
        return response.json()['enabled']

# Usage
client = FlagForgeClient('http://localhost:3000', 'ff_xxxxxxxxxxxxxxxxxx')

enabled = client.is_enabled('new-checkout-flow', {
    'userId': 'user-123',
    'attributes': {'plan': 'premium'}
})

if enabled:
    # Show new checkout flow
    pass

Storage Options

SQLite (Default)

Best for most use cases. Provides ACID guarantees and good performance.

STORAGE_TYPE=sqlite
STORAGE_PATH=./data/flagforge.db

JSON File

Simple file-based storage. Good for development or low-traffic scenarios.

STORAGE_TYPE=json
STORAGE_PATH=./data/flags.json

Multi-Environment Setup

Create an environment per stage (e.g. development, staging, production) from the web UI — each one gets its own API key. Copy each environment's key and use it from that stage's services.

Flags are isolated per environment: an environment's API key only sees flags in that environment.

License

MIT

Roadmap

  • [ ] Webhooks for flag changes
  • [ ] Audit log
  • [ ] Metrics and analytics
  • [ ] Official SDKs (JS, Python, Go)
  • [ ] Docker image
  • [ ] Flag scheduling (enable/disable at specific times)