How the Feature Flag Manager Controls Experimental Functionality in Desktop Commander
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 at line 250:
export const featureFlagManager = new FeatureFlagManager();
This singleton is initialized during application boot inside 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 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. Several internal methods handle this lifecycle:
loadFromCache()hydratesthis.flagsfrom 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 at line 69, the welcome page is conditionally rendered using:
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 at line 41, the A/B utility retrieves the entire experiments map:
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')insidesrc/utils/usageTracker.tsat line 225. - Onboarding injection logic at line 434 of
src/utils/usageTracker.tsdetermines whether extra guidance UI is inserted into the user flow. - Welcome page exclusions and enablement rules live in
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, the exported configuration object contains:
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.tsthat centralizes all experimental toggles. - It fetches flags from a remote JSON endpoint every five minutes and caches them in
feature-flags.jsonfor offline resilience. - The
get()andgetAll()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,src/utils/welcome-onboarding.ts, andsrc/utils/ab-test.tsgate 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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →