How Cline Manages Feature Flags and Telemetry: Architecture and Implementation
Cline separates feature flags from telemetry into distinct services while allowing them to interact, ensuring feature flags remain functional even when telemetry is disabled and maintaining strict user privacy controls through provider-level filtering.
The Cline VS Code extension (cline/cline) implements a privacy-first architecture for managing feature flags and telemetry. This system allows the extension to roll out features gradually while respecting user consent, ensuring that Cline feature flags and telemetry operate independently yet maintain the ability to track flag usage without violating opt-out preferences.
Feature Flag Architecture in Cline
Flag Definitions and Defaults
All feature flags are centrally defined in src/shared/services/feature-flags/feature-flags.ts. The architecture uses a FeatureFlag enum to enumerate available flags (such as WEBTOOLS, WORKTREES, and ONBOARDING_MODELS) and a FeatureFlagDefaultValue map that specifies the default enabled state and payload for each flag.
This separation ensures that the extension has deterministic fallback values when remote configuration is unavailable.
The FeatureFlagsService Layer
The core implementation resides in src/services/feature-flags/FeatureFlagsService.ts. This service wraps an IFeatureFlagsProvider interface (implemented by PostHog or remote config sources) and provides:
- Caching: Flag values are cached for one hour (
DEFAULT_CACHE_TTL) to minimize network requests. - Polling: The
poll(userId)method refreshes the cache periodically and updates state when flags change. - Synchronous Reads: Methods like
getBooleanFlagEnabled(flag)andgetFlagPayload(flag)provide immediate access to cached values.
Crucially, the service emits a $feature_flag_called telemetry event whenever a flag value is read and differs from the cached version. This allows the team to track flag usage without requiring full telemetry to be enabled.
UI Integration with React Hooks
In the webview UI, webview-ui/src/hooks/useFeatureFlag.ts exports the useHasFeatureFlag hook. This hook calls PostHog’s useFeatureFlagEnabled but includes a critical safety check:
// webview-ui/src/hooks/useFeatureFlag.ts
import { useFeatureFlagEnabled } from "posthog-js/react";
import { useExtensionState } from "../context/ExtensionStateContext";
/**
* Returns true only if the named feature flag is enabled.
* Works even when telemetry (PostHog) is disabled.
*/
export const useHasFeatureFlag = (flagName: string): boolean => {
const { environment } = useExtensionState();
const isSelfHosted = !environment || environment === "selfHosted";
// Hook must be called unconditionally (React rule)
const flagEnabled = useFeatureFlagEnabled(isSelfHosted ? "" : flagName);
if (isSelfHosted) return false;
return typeof flagEnabled === "boolean" ? flagEnabled : false;
};
When running in self-hosted mode (where PostHog is disabled), the hook returns false, ensuring UI components never break due to missing telemetry infrastructure.
State Management and User Overrides
The extension’s global state (webview-ui/src/context/ExtensionStateContext.tsx) stores both user preferences (e.g., clineWebToolsEnabled.user) and feature flag status (clineWebToolsEnabled.featureFlag). UI components read featureVisibility to determine whether to render a feature, allowing feature flags to override user settings when necessary.
Telemetry Architecture and Privacy Controls
Telemetry Provider Configuration
Configuration is handled in src/shared/services/config/posthog-config.ts, which builds the PostHog client configuration from build-time constants (BUILD_CONSTANTS) and environment helpers. The configuration is validated via isPostHogConfigValid, with special handling for test mode to allow incomplete configurations for mocking.
Core Telemetry Service
The TelemetryService in src/services/telemetry/TelemetryService.ts manages multiple providers (PostHog, OpenTelemetry) through a TelemetryProviderFactory. It maintains a comprehensive catalog of events in the EVENTS object, covering user actions, task lifecycle, tool usage, and focus-chain progress.
Methods like captureFeatureToggle standardize event payloads:
// src/services/telemetry/TelemetryService.ts (excerpt)
public captureFeatureToggle(ulid: string, featureName: string, enabled: boolean, modelId: string) {
this.capture({
event: TelemetryService.EVENTS.TASK.FEATURE_TOGGLED,
properties: { ulid, featureName, enabled, modelId },
});
}
Respecting User Privacy
Privacy controls are enforced in webview-ui/src/CustomPostHogProvider.tsx. The provider checks isTelemetryEnabled and filters events accordingly:
// webview-ui/src/CustomPostHogProvider.tsx (excerpt)
useEffect(() => {
if (!isTelemetryEnabled && payload?.event !== "$feature_flag_called") {
// Drop all events except feature‑flag checks when the user opts out
return null;
}
// …send event…
}, [/* deps */]);
This ensures that when users disable telemetry, all events are dropped except for $feature_flag_called, allowing the team to track feature usage without capturing personal data.
How Feature Flags and Telemetry Interact
The two systems intersect in FeatureFlagsService when the getFeatureFlag method detects a change in flag values. It captures a $feature_flag_called event via telemetryService.capture, which is always sent to the provider layer. However, CustomPostHogProvider filters this event only when telemetry is disabled, allowing the extension to record flag usage analytics without violating user privacy preferences.
UI components such as FeatureSettingsSection.tsx listen to both user-controlled toggles and feature flag status to determine final feature visibility, creating a system where remote configuration can override local settings when necessary.
Summary
- Feature flags are defined in
src/shared/services/feature-flags/feature-flags.tswith default values, whileFeatureFlagsService.tshandles caching, polling, and synchronous reads with a one-hour TTL. - Telemetry is managed through
TelemetryService.tswith multiple provider support, respecting VS Code's global telemetry settings and user opt-in status. - Privacy-first design ensures feature flags function in self-hosted mode (returning
falseviauseHasFeatureFlag) and that$feature_flag_calledevents bypass telemetry filters to track usage without personal data. - State integration allows feature flags to override user settings through
ExtensionStateContext, while UI hooks ensure components never break when telemetry is disabled.
Frequently Asked Questions
How does Cline handle feature flags when telemetry is disabled?
Cline ensures feature flags remain functional even when telemetry is disabled by implementing a fallback mechanism in the useHasFeatureFlag hook. When running in self-hosted mode (where PostHog is unavailable), the hook returns false for all flags, preventing UI errors. Additionally, the CustomPostHogProvider specifically allows $feature_flag_called events to pass through even when isTelemetryEnabled is false, ensuring flag usage analytics are captured without collecting other user data.
What is the cache duration for feature flags in Cline?
Feature flags are cached for one hour (DEFAULT_CACHE_TTL) in the FeatureFlagsService. This TTL minimizes network requests while ensuring flag values remain relatively fresh. The service also implements a polling mechanism via the poll(userId) method that periodically refreshes the cache and updates the extension state when flag values change, allowing for dynamic feature rollouts without requiring extension restarts.
How does Cline ensure user privacy while tracking feature flag usage?
Cline implements a two-layer privacy approach. First, the TelemetryService checks VS Code's global telemetryLevel and user opt-in status before sending any events, showing warnings when telemetry is disabled but the extension attempts to capture data. Second, the CustomPostHogProvider filters out all events except $feature_flag_called when telemetry is disabled. This specific event contains only the flag name and response value, allowing product teams to understand feature adoption without accessing personal user data or usage patterns.
Can users override feature flag settings in Cline?
Yes, Cline supports user overrides through the ExtensionStateContext system. The global state stores both user preferences (e.g., clineWebToolsEnabled.user) and feature flag evaluations (clineWebToolsEnabled.featureFlag). UI components calculate featureVisibility by considering both values, allowing feature flags to override user settings when necessary for staged rollouts or emergency disables. However, users retain control through the settings interface, where toggles reflect the final computed state based on both local preferences and remote flag configuration.
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 →