# How the Feature Flag Manager Controls Experimental Functionality in Desktop Commander

> Discover how Desktop Commander's Feature Flag Manager controls experimental functionality. Learn about remote flag fetching, local caching, and runtime gating for seamless updates.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-08-06

---

**Desktop Commander centralizes experimental feature control through a singleton `FeatureFlagManager` that fetches remote flags, caches them locally, and exposes a simple `get()` API for runtime gating without redeploying the application.**

The `wonderwhy-er/DesktopCommanderMCP` repository implements a robust system to manage unfinished or experimental capabilities. A dedicated **feature flag manager** controls experimental functionality in Desktop Commander by loading a remote JSON configuration, persisting it to a local cache, and providing a unified runtime interface that modules use to toggle behavior dynamically.

## Core Architecture of the Feature Flag Manager

### Singleton Pattern and Initialization

The manager is exported as a single instance from [`src/utils/feature-flags.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/feature-flags.ts) at line 250:

```typescript
export const featureFlagManager = new FeatureFlagManager();

```

This singleton is initialized during application boot inside [`src/index.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/index.ts) at line 67. Calling `await featureFlagManager.initialize()` primes the internal state before other subsystems begin querying flags.

### Remote Flag Source and Background Refresh

The `initialize()` method between lines 12 and 33 of [`src/utils/feature-flags.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/feature-flags.ts) loads a JSON payload from a default remote endpoint: `https://desktopcommander.app/flags/v2/production.json`. To prevent UI blocking, the manager performs a background fetch at startup while continuing to serve any previously cached values.

The system refreshes this data every five minutes. This ensures that experimental features can be enabled or disabled in near real time without a client restart or code change.

### Local Cache and Offline Resilience

The manager writes fetched data to a local file named [`feature-flags.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/feature-flags.json). Several internal methods handle this lifecycle:

- `loadFromCache()` hydrates `this.flags` from disk when the app starts.
- `fetchFlags()` downloads the latest payload, updates memory, and rewrites the cache file.
- `wasLoadedFromCache()` reports whether the active flags were sourced from local storage.
- `waitForFreshFlags()` allows callers to block until the first successful network request finishes.

## How Experimental Features Are Gated at Runtime

### Simple Boolean Checks with get()

Consumer code checks individual flags through `featureFlagManager.get(name, defaultValue)`. If a flag is absent, the supplied default is returned immediately.

In [`src/utils/welcome-onboarding.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/welcome-onboarding.ts) at line 69, the welcome page is conditionally rendered using:

```typescript
const enabled = featureFlagManager.get('welcome_page_enabled', true) !== false;

```

### A/B Test Variant Selection

The manager also drives experiment assignment. In [`src/utils/ab-test.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/ab-test.ts) at line 41, the A/B utility retrieves the entire experiments map:

```typescript
const experiments = featureFlagManager.get('experiments', {});

```

This object is then used to place users into variant groups, making the feature flag manager the single source of truth for all experimental behavior.

### Subsystem-Specific Feature Gating

Multiple utilities query the manager to decide whether to activate advanced or experimental flows:

- **User surveys** are toggled by `featureFlagManager.get('user_surveys')` inside [`src/utils/usageTracker.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/usageTracker.ts) at line 225.
- **Onboarding injection** logic at line 434 of [`src/utils/usageTracker.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/usageTracker.ts) determines whether extra guidance UI is inserted into the user flow.
- **Welcome page exclusions** and enablement rules live in [`src/utils/welcome-onboarding.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/welcome-onboarding.ts), keeping the onboarding experience configurable from a remote dashboard.

## Configuration Export and System-Wide Visibility

The full current flag set is surfaced globally for diagnostics and tooling. At line 111 of [`src/tools/config.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/config.ts), the exported configuration object contains:

```typescript
featureFlags: featureFlagManager.getAll()

```

This integration lets other parts of the system serialize the experimental state for logging or support requests.

## Summary

- The **FeatureFlagManager** is a singleton defined in [`src/utils/feature-flags.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/feature-flags.ts) that centralizes all experimental toggles.
- It fetches flags from a remote JSON endpoint every five minutes and caches them in [`feature-flags.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/feature-flags.json) for offline resilience.
- The `get()` and `getAll()` methods provide a simple runtime API used by onboarding, surveys, and A/B tests across the codebase.
- Consumer modules such as [`src/utils/usageTracker.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/usageTracker.ts), [`src/utils/welcome-onboarding.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/welcome-onboarding.ts), and [`src/utils/ab-test.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/ab-test.ts) gate behavior without requiring code deployment.

## Frequently Asked Questions

### Where does Desktop Commander store cached feature flags?

The manager writes a local file named [`feature-flags.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/feature-flags.json) to disk via the `fetchFlags()` method. On subsequent starts, `loadFromCache()` reads this file so the application can initialize even when the remote URL is unreachable.

### How often does the Feature Flag Manager refresh its configuration?

The manager refreshes the flag payload every five minutes after initialization. It also triggers a background fetch immediately during startup, allowing the UI to continue using cached values while new data is downloaded.

### What happens if the remote flag endpoint is unavailable?

If the network request fails, the manager continues to operate using the last known values from the local cache. The `wasLoadedFromCache()` method indicates when the active state originated from disk, and `waitForFreshFlags()` lets callers pause until a successful network fetch occurs.

### How are A/B experiments connected to the feature flag system?

The A/B test module in [`src/utils/ab-test.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/ab-test.ts) reads a structured `experiments` object directly from the manager via `featureFlagManager.get('experiments', {})`. Because experiments are just another key in the remote JSON payload, product teams can launch, modify, or retire A/B tests from the same remote configuration without shipping code changes.