mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-13 07:30:52 -07:00
1187 lines
40 KiB
Markdown
1187 lines
40 KiB
Markdown
# Client-Side Experimentation Framework Proposal for Gemini CLI
|
|
|
|
> **Status:** Proposal **Author:** Generated Analysis **Date:** January 2026
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
This document proposes a standardized framework for implementing client-side
|
|
experimental features in Gemini CLI. The goal is to enable developers to ship
|
|
features that users can opt into in a controlled, standardized way while
|
|
protecting users who don't opt-in.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [Current State Summary](#current-state-summary)
|
|
2. [Proposed Design](#proposed-design)
|
|
3. [Implementation Details](#implementation-details)
|
|
4. [Workflow Integration](#workflow-integration)
|
|
5. [User Experience](#user-experience)
|
|
6. [Graduation Process](#graduation-process)
|
|
7. [Industry Comparison](#industry-comparison)
|
|
8. [References](#references)
|
|
|
|
---
|
|
|
|
## Current State Summary
|
|
|
|
### What Gemini CLI Already Has
|
|
|
|
| Capability | Location | Description |
|
|
| ------------------------- | ------------------- | --------------------------------------------------- |
|
|
| `experimental.*` settings | `settingsSchema.ts` | Boolean toggles for experimental features |
|
|
| `general.previewFeatures` | `settingsSchema.ts` | Preview model access control |
|
|
| Settings merge hierarchy | `settings.ts` | Schema defaults → System → User → Workspace → Admin |
|
|
| Agent experimental flags | `registry.ts` | `definition.experimental` on agent definitions |
|
|
| Remote admin controls | `settings.ts` | Server-side overrides for enterprise |
|
|
|
|
### Current Experimental Features
|
|
|
|
| Feature | Setting | Default | Purpose |
|
|
| ---------------------- | ----------------------------------------- | ------- | ------------------------------ |
|
|
| Agents | `experimental.enableAgents` | `false` | Enable subagent system |
|
|
| JIT Context | `experimental.jitContext` | `false` | Just-in-time context loading |
|
|
| Event-Driven Scheduler | `experimental.enableEventDrivenScheduler` | `true` | Event-based task orchestration |
|
|
| Plugin Hot-Reload | `experimental.extensionReloading` | `false` | Runtime plugin loading |
|
|
| Plugin Configuration | `experimental.extensionConfig` | `false` | Plugin settings management |
|
|
| Plugin Management | `experimental.extensionManagement` | `true` | Plugin lifecycle features |
|
|
| Plan Mode | `experimental.plan` | `false` | Read-only planning mode |
|
|
| OSC 52 Paste | `experimental.useOSC52Paste` | `false` | Remote session clipboard |
|
|
| Preview Models | `general.previewFeatures` | `false` | Access to preview models |
|
|
|
|
### What's Missing
|
|
|
|
- ❌ Standardized lifecycle for experimental features
|
|
- ❌ Clear graduation criteria (experimental → stable)
|
|
- ❌ Discoverability of experimental features
|
|
- ❌ Telemetry integration for experiment usage tracking
|
|
- ❌ Documentation automation for experimental features
|
|
- ❌ CLI-level opt-in flags (like Cargo's `-Z` flags)
|
|
- ❌ Feature dependency management
|
|
- ❌ Deprecation tracking and warnings
|
|
|
|
---
|
|
|
|
## Proposed Design
|
|
|
|
### Multi-Tier Feature Gate System
|
|
|
|
#### Tier 1: Feature Lifecycle Stages
|
|
|
|
Adopt a **Kubernetes-inspired maturity model** with clear stages:
|
|
|
|
| Stage | Default | Stability | Can Remove? | Flag Required |
|
|
| -------------- | ------------ | ---------------------------------- | ------------------------ | --------------- |
|
|
| **Alpha** | `false` | May break, incomplete | Yes, any time | Explicit opt-in |
|
|
| **Beta** | `false` | Mostly stable, collecting feedback | Yes, with deprecation | Explicit opt-in |
|
|
| **GA** | `true` | Stable | No (breaking change) | None |
|
|
| **Deprecated** | `true→false` | Stable but discouraged | After deprecation period | None |
|
|
|
|
#### Tier 2: Architecture Overview
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Feature Gate Registry │
|
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
│ │ Feature Definition │ │
|
|
│ │ - name: string │ │
|
|
│ │ - stage: 'alpha' | 'beta' | 'ga' | 'deprecated' │ │
|
|
│ │ - description: string │ │
|
|
│ │ - owner: string (GitHub team/individual) │ │
|
|
│ │ - trackingIssue: string (GitHub issue URL) │ │
|
|
│ │ - addedIn: string (version) │ │
|
|
│ │ - targetGAVersion?: string │ │
|
|
│ │ - telemetryKey?: string │ │
|
|
│ │ - requiresRestart: boolean │ │
|
|
│ │ - dependencies?: string[] (other feature names) │ │
|
|
│ └──────────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Activation Methods │
|
|
│ │
|
|
│ 1. Settings File (persistent) │
|
|
│ experimental.<featureName>: true │
|
|
│ │
|
|
│ 2. CLI Flag (session-only, like Cargo's -Z) │
|
|
│ gemini --feature=<name> --feature=<name2> │
|
|
│ gemini -X <name> │
|
|
│ │
|
|
│ 3. Environment Variable (CI/testing) │
|
|
│ GEMINI_FEATURES=<name1>,<name2> │
|
|
│ │
|
|
│ 4. Admin Override (enterprise) │
|
|
│ Remote admin controls can force-enable/disable │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
#### Tier 3: Activation Priority (highest to lowest)
|
|
|
|
1. **Admin Override** - Enterprise admins can force-enable or force-disable
|
|
2. **CLI Flags** - Session-specific activation via `--feature=X`
|
|
3. **Environment Variables** - `GEMINI_FEATURES=X,Y` for CI/testing
|
|
4. **Workspace Settings** - `.gemini/settings.json` (if workspace is trusted)
|
|
5. **User Settings** - `~/.gemini/settings.json`
|
|
6. **System Defaults** - Built-in defaults from feature definition
|
|
|
|
---
|
|
|
|
## Implementation Details
|
|
|
|
### 1. Feature Gate Registry
|
|
|
|
**File:** `packages/core/src/features/featureGate.ts`
|
|
|
|
```typescript
|
|
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
export enum FeatureStage {
|
|
/** Experimental, may break, can be removed any time */
|
|
ALPHA = 'alpha',
|
|
/** Mostly stable, collecting feedback, requires deprecation to remove */
|
|
BETA = 'beta',
|
|
/** Stable, always enabled, feature gate no longer needed */
|
|
GA = 'ga',
|
|
/** Stable but discouraged, will be removed in future version */
|
|
DEPRECATED = 'deprecated',
|
|
}
|
|
|
|
export interface FeatureDefinition {
|
|
/** Unique identifier, kebab-case (e.g., "jit-context") */
|
|
name: string;
|
|
|
|
/** Current lifecycle stage */
|
|
stage: FeatureStage;
|
|
|
|
/** Human-readable description */
|
|
description: string;
|
|
|
|
/** GitHub team or individual responsible */
|
|
owner: string;
|
|
|
|
/** GitHub issue URL for tracking */
|
|
trackingIssue?: string;
|
|
|
|
/** Version when this feature was added */
|
|
addedInVersion: string;
|
|
|
|
/** Target version for GA (if alpha/beta) */
|
|
targetGAVersion?: string;
|
|
|
|
/** Version when deprecated (if deprecated) */
|
|
deprecatedInVersion?: string;
|
|
|
|
/** Version when feature will be removed (if deprecated) */
|
|
removalVersion?: string;
|
|
|
|
/** Whether enabling/disabling requires CLI restart */
|
|
requiresRestart: boolean;
|
|
|
|
/** Other features this depends on */
|
|
dependencies?: string[];
|
|
|
|
/** Key for telemetry tracking */
|
|
telemetryKey?: string;
|
|
|
|
/** Warning message shown when feature is enabled */
|
|
warningMessage?: string;
|
|
|
|
/** Features that are mutually exclusive with this one */
|
|
conflictsWith?: string[];
|
|
}
|
|
|
|
/**
|
|
* Central registry of all feature gates.
|
|
*
|
|
* To add a new feature:
|
|
* 1. Create a tracking issue
|
|
* 2. Add entry here with stage: ALPHA
|
|
* 3. Implement feature gated by FeatureGateService.isEnabled()
|
|
* 4. Graduate through stages based on feedback
|
|
*/
|
|
export const FEATURE_GATES: Record<string, FeatureDefinition> = {
|
|
'jit-context': {
|
|
name: 'jit-context',
|
|
stage: FeatureStage.ALPHA,
|
|
description: 'Just-in-time context loading for improved memory usage',
|
|
owner: '@anthropics/gemini-cli',
|
|
trackingIssue: 'https://github.com/google-gemini/gemini-cli/issues/XXX',
|
|
addedInVersion: '0.25.0',
|
|
targetGAVersion: '1.0.0',
|
|
requiresRestart: true,
|
|
telemetryKey: 'feature_jit_context',
|
|
warningMessage:
|
|
'JIT context is experimental and may affect response quality.',
|
|
},
|
|
|
|
agents: {
|
|
name: 'agents',
|
|
stage: FeatureStage.ALPHA,
|
|
description: 'Enable subagent system for complex multi-step tasks',
|
|
owner: '@anthropics/gemini-cli',
|
|
trackingIssue: 'https://github.com/google-gemini/gemini-cli/issues/XXX',
|
|
addedInVersion: '0.20.0',
|
|
requiresRestart: false,
|
|
telemetryKey: 'feature_agents',
|
|
warningMessage: 'Agents run in YOLO mode and will auto-approve tool calls.',
|
|
},
|
|
|
|
'plan-mode': {
|
|
name: 'plan-mode',
|
|
stage: FeatureStage.BETA,
|
|
description:
|
|
'Read-only planning mode for reviewing changes before execution',
|
|
owner: '@anthropics/gemini-cli',
|
|
trackingIssue: 'https://github.com/google-gemini/gemini-cli/issues/XXX',
|
|
addedInVersion: '0.22.0',
|
|
targetGAVersion: '0.30.0',
|
|
requiresRestart: false,
|
|
telemetryKey: 'feature_plan_mode',
|
|
},
|
|
|
|
'event-driven-scheduler': {
|
|
name: 'event-driven-scheduler',
|
|
stage: FeatureStage.BETA,
|
|
description: 'Event-based task orchestration system',
|
|
owner: '@anthropics/gemini-cli',
|
|
addedInVersion: '0.18.0',
|
|
requiresRestart: true,
|
|
telemetryKey: 'feature_event_scheduler',
|
|
},
|
|
|
|
// Example of a deprecated feature
|
|
'legacy-context-loading': {
|
|
name: 'legacy-context-loading',
|
|
stage: FeatureStage.DEPRECATED,
|
|
description: 'Legacy context loading (use jit-context instead)',
|
|
owner: '@anthropics/gemini-cli',
|
|
addedInVersion: '0.10.0',
|
|
deprecatedInVersion: '0.25.0',
|
|
removalVersion: '1.0.0',
|
|
requiresRestart: true,
|
|
warningMessage:
|
|
'This feature is deprecated and will be removed in v1.0.0. Migrate to jit-context.',
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Get all features at a specific stage
|
|
*/
|
|
export function getFeaturesByStage(stage: FeatureStage): FeatureDefinition[] {
|
|
return Object.values(FEATURE_GATES).filter((f) => f.stage === stage);
|
|
}
|
|
|
|
/**
|
|
* Get a feature definition by name
|
|
*/
|
|
export function getFeature(name: string): FeatureDefinition | undefined {
|
|
return FEATURE_GATES[name];
|
|
}
|
|
|
|
/**
|
|
* Check if a feature name is valid
|
|
*/
|
|
export function isValidFeature(name: string): boolean {
|
|
return name in FEATURE_GATES;
|
|
}
|
|
```
|
|
|
|
### 2. Feature Gate Service
|
|
|
|
**File:** `packages/core/src/features/featureGateService.ts`
|
|
|
|
```typescript
|
|
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import {
|
|
FEATURE_GATES,
|
|
FeatureStage,
|
|
getFeature,
|
|
isValidFeature,
|
|
type FeatureDefinition,
|
|
} from './featureGate.js';
|
|
import { debugLogger } from '../utils/debugLogger.js';
|
|
|
|
export interface FeatureGateServiceConfig {
|
|
/** Features enabled via settings file */
|
|
settingsFeatures: Record<string, boolean>;
|
|
|
|
/** Features enabled via CLI flags */
|
|
cliFeatures: string[];
|
|
|
|
/** Features enabled via environment variable */
|
|
envFeatures: string[];
|
|
|
|
/** Admin overrides (highest priority) */
|
|
adminOverrides: Record<string, boolean>;
|
|
}
|
|
|
|
export class FeatureGateService {
|
|
private readonly enabledFeatures: Set<string> = new Set();
|
|
private readonly config: FeatureGateServiceConfig;
|
|
|
|
constructor(config: FeatureGateServiceConfig) {
|
|
this.config = config;
|
|
this.computeEnabledFeatures();
|
|
}
|
|
|
|
/**
|
|
* Check if a feature is enabled
|
|
*/
|
|
isEnabled(featureName: string): boolean {
|
|
const definition = getFeature(featureName);
|
|
|
|
if (!definition) {
|
|
debugLogger.warn(`Unknown feature gate: ${featureName}`);
|
|
return false;
|
|
}
|
|
|
|
// GA features are always enabled
|
|
if (definition.stage === FeatureStage.GA) {
|
|
return true;
|
|
}
|
|
|
|
// Admin override takes highest priority
|
|
if (this.config.adminOverrides[featureName] !== undefined) {
|
|
return this.config.adminOverrides[featureName];
|
|
}
|
|
|
|
return this.enabledFeatures.has(featureName);
|
|
}
|
|
|
|
/**
|
|
* Get all currently enabled features
|
|
*/
|
|
getEnabledFeatures(): FeatureDefinition[] {
|
|
return [...this.enabledFeatures]
|
|
.map((name) => getFeature(name))
|
|
.filter((f): f is FeatureDefinition => f !== undefined);
|
|
}
|
|
|
|
/**
|
|
* Get enabled features at a specific stage
|
|
*/
|
|
getEnabledFeaturesAtStage(stage: FeatureStage): FeatureDefinition[] {
|
|
return this.getEnabledFeatures().filter((f) => f.stage === stage);
|
|
}
|
|
|
|
/**
|
|
* Get warnings for enabled experimental features
|
|
*/
|
|
getStartupWarnings(): string[] {
|
|
const warnings: string[] = [];
|
|
|
|
for (const feature of this.getEnabledFeatures()) {
|
|
if (feature.stage === FeatureStage.ALPHA && feature.warningMessage) {
|
|
warnings.push(`⚠️ [ALPHA] ${feature.name}: ${feature.warningMessage}`);
|
|
} else if (
|
|
feature.stage === FeatureStage.DEPRECATED &&
|
|
feature.warningMessage
|
|
) {
|
|
warnings.push(
|
|
`⚠️ [DEPRECATED] ${feature.name}: ${feature.warningMessage}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
return warnings;
|
|
}
|
|
|
|
/**
|
|
* Validate feature dependencies
|
|
*/
|
|
validateDependencies(): string[] {
|
|
const errors: string[] = [];
|
|
|
|
for (const featureName of this.enabledFeatures) {
|
|
const feature = getFeature(featureName);
|
|
if (!feature?.dependencies) continue;
|
|
|
|
for (const dep of feature.dependencies) {
|
|
if (!this.isEnabled(dep)) {
|
|
errors.push(
|
|
`Feature "${featureName}" requires "${dep}" to be enabled`,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Check for conflicts
|
|
if (feature.conflictsWith) {
|
|
for (const conflict of feature.conflictsWith) {
|
|
if (this.isEnabled(conflict)) {
|
|
errors.push(
|
|
`Feature "${featureName}" conflicts with "${conflict}"`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
private computeEnabledFeatures(): void {
|
|
this.enabledFeatures.clear();
|
|
|
|
// Process in order of priority (lowest to highest)
|
|
// 1. Settings file
|
|
for (const [name, enabled] of Object.entries(
|
|
this.config.settingsFeatures,
|
|
)) {
|
|
if (enabled && isValidFeature(name)) {
|
|
this.enabledFeatures.add(name);
|
|
}
|
|
}
|
|
|
|
// 2. Environment variables
|
|
for (const name of this.config.envFeatures) {
|
|
if (isValidFeature(name)) {
|
|
this.enabledFeatures.add(name);
|
|
} else {
|
|
debugLogger.warn(`Unknown feature in GEMINI_FEATURES: ${name}`);
|
|
}
|
|
}
|
|
|
|
// 3. CLI flags (can also disable with --no-feature=X)
|
|
for (const name of this.config.cliFeatures) {
|
|
if (name.startsWith('no-')) {
|
|
const featureName = name.slice(3);
|
|
this.enabledFeatures.delete(featureName);
|
|
} else if (isValidFeature(name)) {
|
|
this.enabledFeatures.add(name);
|
|
} else {
|
|
debugLogger.warn(`Unknown feature flag: ${name}`);
|
|
}
|
|
}
|
|
|
|
// Note: Admin overrides are checked at runtime in isEnabled()
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. CLI Flag Support
|
|
|
|
**File:** `packages/cli/src/config/config.ts` (additions)
|
|
|
|
```typescript
|
|
// Add to yargs options
|
|
.option('feature', {
|
|
alias: 'X',
|
|
type: 'array',
|
|
string: true,
|
|
description: 'Enable experimental feature(s) for this session. Use --feature=<name> or -X <name>',
|
|
coerce: (features: string[]) =>
|
|
features.flatMap(f => f.split(',').map(x => x.trim())),
|
|
})
|
|
.option('no-feature', {
|
|
type: 'array',
|
|
string: true,
|
|
description: 'Disable a feature for this session',
|
|
coerce: (features: string[]) =>
|
|
features.flatMap(f => f.split(',').map(x => x.trim())),
|
|
})
|
|
.option('list-features', {
|
|
type: 'boolean',
|
|
description: 'List all available feature gates and exit',
|
|
})
|
|
```
|
|
|
|
### 4. Environment Variable Support
|
|
|
|
```typescript
|
|
// In loadCliConfig or similar
|
|
function parseEnvFeatures(): string[] {
|
|
const envValue = process.env['GEMINI_FEATURES'];
|
|
if (!envValue) return [];
|
|
|
|
return envValue
|
|
.split(',')
|
|
.map((f) => f.trim())
|
|
.filter((f) => f.length > 0);
|
|
}
|
|
```
|
|
|
|
### 5. `/features` Slash Command
|
|
|
|
**File:** `packages/cli/src/commands/features.ts`
|
|
|
|
```typescript
|
|
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import {
|
|
FEATURE_GATES,
|
|
FeatureStage,
|
|
getFeaturesByStage,
|
|
} from '@google/gemini-cli-core';
|
|
import type { Config } from '@google/gemini-cli-core';
|
|
|
|
export async function featuresCommand(config: Config): Promise<void> {
|
|
const featureService = config.getFeatureGateService();
|
|
|
|
console.log('
|
|
📋 Gemini CLI Feature Gates
|
|
');
|
|
console.log(
|
|
'Feature gates allow you to opt-in to experimental functionality.
|
|
',
|
|
);
|
|
|
|
// Alpha features
|
|
const alphaFeatures = getFeaturesByStage(FeatureStage.ALPHA);
|
|
if (alphaFeatures.length > 0) {
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
console.log('ALPHA Features (experimental, may change without notice)');
|
|
console.log(
|
|
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
',
|
|
);
|
|
|
|
for (const feature of alphaFeatures) {
|
|
const enabled = featureService.isEnabled(feature.name);
|
|
const status = enabled ? '✓ ENABLED' : '○ disabled';
|
|
|
|
console.log(` ${feature.name}`);
|
|
console.log(` Status: ${status}`);
|
|
console.log(` ${feature.description}`);
|
|
if (feature.trackingIssue) {
|
|
console.log(` Tracking: ${feature.trackingIssue}`);
|
|
}
|
|
if (feature.targetGAVersion) {
|
|
console.log(` Target GA: v${feature.targetGAVersion}`);
|
|
}
|
|
console.log();
|
|
}
|
|
}
|
|
|
|
// Beta features
|
|
const betaFeatures = getFeaturesByStage(FeatureStage.BETA);
|
|
if (betaFeatures.length > 0) {
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
console.log('BETA Features (mostly stable, feedback welcome)');
|
|
console.log(
|
|
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
',
|
|
);
|
|
|
|
for (const feature of betaFeatures) {
|
|
const enabled = featureService.isEnabled(feature.name);
|
|
const status = enabled ? '✓ ENABLED' : '○ disabled';
|
|
|
|
console.log(` ${feature.name}`);
|
|
console.log(` Status: ${status}`);
|
|
console.log(` ${feature.description}`);
|
|
if (feature.trackingIssue) {
|
|
console.log(` Tracking: ${feature.trackingIssue}`);
|
|
}
|
|
console.log();
|
|
}
|
|
}
|
|
|
|
// Deprecated features
|
|
const deprecatedFeatures = getFeaturesByStage(FeatureStage.DEPRECATED);
|
|
if (deprecatedFeatures.length > 0) {
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
console.log('DEPRECATED Features (will be removed)');
|
|
console.log(
|
|
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
',
|
|
);
|
|
|
|
for (const feature of deprecatedFeatures) {
|
|
const enabled = featureService.isEnabled(feature.name);
|
|
const status = enabled ? '✓ ENABLED' : '○ disabled';
|
|
|
|
console.log(` ${feature.name}`);
|
|
console.log(` Status: ${status}`);
|
|
console.log(` ${feature.description}`);
|
|
if (feature.removalVersion) {
|
|
console.log(` ⚠️ Will be removed in: v${feature.removalVersion}`);
|
|
}
|
|
console.log();
|
|
}
|
|
}
|
|
|
|
// Usage instructions
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
console.log('How to Enable Features');
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
');
|
|
console.log(' CLI flag (session only):');
|
|
console.log(' gemini --feature=<name>');
|
|
console.log(' gemini -X <name>');
|
|
console.log();
|
|
console.log(' Environment variable (CI/testing):');
|
|
console.log(' GEMINI_FEATURES=<name1>,<name2> gemini');
|
|
console.log();
|
|
console.log(' Settings file (persistent):');
|
|
console.log(' Add to ~/.gemini/settings.json:');
|
|
console.log(' { "experimental": { "<name>": true } }');
|
|
console.log();
|
|
}
|
|
```
|
|
|
|
### 6. Settings Schema Auto-Generation
|
|
|
|
**File:** `packages/cli/src/config/settingsSchema.ts` (additions)
|
|
|
|
```typescript
|
|
import { FEATURE_GATES, FeatureStage } from '@google/gemini-cli-core';
|
|
|
|
/**
|
|
* Auto-generate experimental settings schema from feature definitions.
|
|
* This ensures the settings schema stays in sync with feature gates.
|
|
*/
|
|
function generateExperimentalSchema(): Record<string, SettingDefinition> {
|
|
const schema: Record<string, SettingDefinition> = {};
|
|
|
|
for (const [name, def] of Object.entries(FEATURE_GATES)) {
|
|
// GA features don't need settings (always enabled)
|
|
if (def.stage === FeatureStage.GA) continue;
|
|
|
|
// Convert kebab-case to camelCase for settings
|
|
const settingName = name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
|
|
schema[settingName] = {
|
|
type: 'boolean',
|
|
default: false,
|
|
label: `[${def.stage.toUpperCase()}] ${def.name}`,
|
|
description:
|
|
def.description +
|
|
(def.warningMessage ? ` ⚠️ ${def.warningMessage}` : ''),
|
|
showInDialog: def.stage === FeatureStage.BETA, // Only show beta in settings UI
|
|
requiresRestart: def.requiresRestart,
|
|
ignoreInDocs: def.stage === FeatureStage.ALPHA, // Don't document alpha features
|
|
};
|
|
}
|
|
|
|
return schema;
|
|
}
|
|
|
|
// Use in schema definition
|
|
export const settingsSchema = {
|
|
// ... other settings ...
|
|
|
|
experimental: {
|
|
type: 'object',
|
|
label: 'Experimental Features',
|
|
description:
|
|
'Enable experimental features. Use /features to see all available.',
|
|
properties: generateExperimentalSchema(),
|
|
},
|
|
};
|
|
```
|
|
|
|
### 7. Telemetry Integration
|
|
|
|
**File:** `packages/core/src/telemetry/featureTelemetry.ts`
|
|
|
|
```typescript
|
|
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { getFeature } from '../features/featureGate.js';
|
|
import type { Config } from '../config/config.js';
|
|
|
|
export interface FeatureUsageEvent {
|
|
featureName: string;
|
|
stage: string;
|
|
action: 'enabled' | 'used' | 'error';
|
|
clientVersion: string;
|
|
sessionId: string;
|
|
timestamp: string;
|
|
}
|
|
|
|
/**
|
|
* Log when a feature is enabled at startup
|
|
*/
|
|
export function logFeatureEnabled(config: Config, featureName: string): void {
|
|
const definition = getFeature(featureName);
|
|
if (!definition?.telemetryKey) return;
|
|
|
|
// Use existing telemetry infrastructure
|
|
config.getTelemetryService()?.recordEvent({
|
|
name: 'feature_enabled',
|
|
attributes: {
|
|
feature: featureName,
|
|
stage: definition.stage,
|
|
version: config.getClientVersion(),
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log when a feature is actively used
|
|
*/
|
|
export function logFeatureUsed(config: Config, featureName: string): void {
|
|
const definition = getFeature(featureName);
|
|
if (!definition?.telemetryKey) return;
|
|
|
|
config.getTelemetryService()?.recordEvent({
|
|
name: 'feature_used',
|
|
attributes: {
|
|
feature: featureName,
|
|
stage: definition.stage,
|
|
version: config.getClientVersion(),
|
|
},
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Workflow Integration
|
|
|
|
### 1. Feature Tracking Issue Template
|
|
|
|
**File:** `.github/ISSUE_TEMPLATE/feature-gate.yml`
|
|
|
|
```yaml
|
|
name: Feature Gate Proposal
|
|
description: Propose a new experimental feature gate
|
|
title: '[Feature Gate] '
|
|
labels: ['type/feature-gate', 'stage/alpha']
|
|
body:
|
|
- type: markdown
|
|
attributes:
|
|
value: |
|
|
## Feature Gate Proposal
|
|
|
|
Use this template to propose a new experimental feature for Gemini CLI.
|
|
All new features should start as Alpha and graduate through stages.
|
|
|
|
- type: input
|
|
id: feature-name
|
|
attributes:
|
|
label: Feature Name
|
|
description: Lowercase, kebab-case identifier (e.g., "jit-context")
|
|
placeholder: my-feature-name
|
|
validations:
|
|
required: true
|
|
|
|
- type: dropdown
|
|
id: initial-stage
|
|
attributes:
|
|
label: Initial Stage
|
|
description: Most features should start as Alpha
|
|
options:
|
|
- alpha
|
|
- beta
|
|
default: 0
|
|
validations:
|
|
required: true
|
|
|
|
- type: textarea
|
|
id: description
|
|
attributes:
|
|
label: Description
|
|
description: What does this feature do? (This will be shown to users)
|
|
placeholder: A brief description of the feature's functionality
|
|
validations:
|
|
required: true
|
|
|
|
- type: textarea
|
|
id: motivation
|
|
attributes:
|
|
label: Motivation
|
|
description: Why is this feature needed? What problem does it solve?
|
|
validations:
|
|
required: true
|
|
|
|
- type: input
|
|
id: target-ga
|
|
attributes:
|
|
label: Target GA Version
|
|
description: When do you expect this to be stable? (e.g., "1.0.0")
|
|
placeholder: '1.0.0'
|
|
|
|
- type: textarea
|
|
id: graduation-criteria
|
|
attributes:
|
|
label: Graduation Criteria
|
|
description: What needs to happen for this to move from Alpha → Beta → GA?
|
|
value: |
|
|
### Alpha → Beta
|
|
- [ ] Feature is functionally complete
|
|
- [ ] No critical bugs reported for 2 weeks
|
|
- [ ] Basic documentation exists
|
|
- [ ] Telemetry shows stable usage patterns
|
|
|
|
### Beta → GA
|
|
- [ ] Feature has been in Beta for 4+ weeks
|
|
- [ ] Documentation is complete
|
|
- [ ] No breaking changes planned
|
|
- [ ] Team consensus achieved
|
|
validations:
|
|
required: true
|
|
|
|
- type: textarea
|
|
id: warning-message
|
|
attributes:
|
|
label: Warning Message
|
|
description: Optional warning shown when users enable this feature
|
|
placeholder: 'This feature may affect performance in large codebases.'
|
|
|
|
- type: checkboxes
|
|
id: requirements
|
|
attributes:
|
|
label: Requirements
|
|
options:
|
|
- label: Requires CLI restart when toggled
|
|
- label: Has dependencies on other features
|
|
- label: Conflicts with other features
|
|
```
|
|
|
|
### 2. Automated Documentation Workflow
|
|
|
|
**File:** `.github/workflows/docs-features.yml`
|
|
|
|
```yaml
|
|
name: Update Feature Documentation
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'packages/core/src/features/featureGate.ts'
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
update-docs:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Generate feature documentation
|
|
run: npm run docs:generate-features
|
|
|
|
- name: Check for changes
|
|
id: changes
|
|
run: |
|
|
if [[ -n $(git status --porcelain docs/experimental-features.md) ]]; then
|
|
echo "changed=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Create Pull Request
|
|
if: steps.changes.outputs.changed == 'true'
|
|
uses: peter-evans/create-pull-request@v5
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
commit-message: 'docs: Update experimental features documentation'
|
|
title: 'docs: Update experimental features documentation'
|
|
body: |
|
|
This PR was automatically generated to update the experimental features documentation.
|
|
|
|
The feature gate definitions in `packages/core/src/features/featureGate.ts` have changed.
|
|
branch: docs/update-features
|
|
labels: documentation,automated
|
|
```
|
|
|
|
### 3. Feature Gate Validation in CI
|
|
|
|
**File:** `.github/workflows/ci.yml` (additions)
|
|
|
|
```yaml
|
|
validate-features:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Validate feature gates
|
|
run: npm run validate:features
|
|
# This script should:
|
|
# - Check all features have tracking issues
|
|
# - Check deprecated features have removal versions
|
|
# - Check feature names follow conventions
|
|
# - Check for orphaned feature flags in code
|
|
```
|
|
|
|
---
|
|
|
|
## User Experience
|
|
|
|
### Enabling via CLI Flag
|
|
|
|
```bash
|
|
# Single feature
|
|
gemini --feature=jit-context "Analyze this codebase"
|
|
|
|
# Short form
|
|
gemini -X jit-context "Analyze this codebase"
|
|
|
|
# Multiple features
|
|
gemini --feature=jit-context --feature=agents "Help me refactor"
|
|
|
|
# Comma-separated
|
|
gemini -X jit-context,agents
|
|
|
|
# Disable a feature for this session
|
|
gemini --no-feature=event-driven-scheduler
|
|
```
|
|
|
|
### Enabling via Environment Variable
|
|
|
|
```bash
|
|
# For CI/CD or testing
|
|
GEMINI_FEATURES=jit-context,agents gemini -p "Run tests"
|
|
|
|
# In a shell profile for persistent enablement
|
|
export GEMINI_FEATURES=jit-context
|
|
```
|
|
|
|
### Enabling via Settings File
|
|
|
|
```json
|
|
// ~/.gemini/settings.json
|
|
{
|
|
"experimental": {
|
|
"jitContext": true,
|
|
"agents": true,
|
|
"planMode": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Listing Features
|
|
|
|
```
|
|
$ gemini --list-features
|
|
|
|
📋 Gemini CLI Feature Gates
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
ALPHA Features (experimental, may change without notice)
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
jit-context
|
|
Status: ○ disabled
|
|
Just-in-time context loading for improved memory usage
|
|
Tracking: https://github.com/google-gemini/gemini-cli/issues/XXX
|
|
Target GA: v1.0.0
|
|
|
|
agents
|
|
Status: ○ disabled
|
|
Enable subagent system for complex multi-step tasks
|
|
Tracking: https://github.com/google-gemini/gemini-cli/issues/XXX
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
BETA Features (mostly stable, feedback welcome)
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
plan-mode
|
|
Status: ○ disabled
|
|
Read-only planning mode for reviewing changes before execution
|
|
Tracking: https://github.com/google-gemini/gemini-cli/issues/XXX
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
How to Enable Features
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
CLI flag (session only):
|
|
gemini --feature=<name>
|
|
gemini -X <name>
|
|
|
|
Environment variable (CI/testing):
|
|
GEMINI_FEATURES=<name1>,<name2> gemini
|
|
|
|
Settings file (persistent):
|
|
Add to ~/.gemini/settings.json:
|
|
{ "experimental": { "<name>": true } }
|
|
```
|
|
|
|
### Startup Warnings
|
|
|
|
```
|
|
$ gemini --feature=agents
|
|
|
|
⚠️ Experimental features enabled:
|
|
• [ALPHA] agents: Agents run in YOLO mode and will auto-approve tool calls.
|
|
|
|
Type /features to learn more about experimental features.
|
|
|
|
>
|
|
```
|
|
|
|
---
|
|
|
|
## Graduation Process
|
|
|
|
### Stage Transitions
|
|
|
|
```
|
|
┌─────────────┐
|
|
│ ALPHA │
|
|
│ (2+ weeks) │
|
|
└──────┬──────┘
|
|
│
|
|
┌──────────────┼──────────────┐
|
|
│ │ │
|
|
▼ │ ▼
|
|
┌─────────────┐ │ ┌─────────────┐
|
|
│ BETA │ │ │ REMOVED │
|
|
│ (4+ weeks) │ │ │ (failed) │
|
|
└──────┬──────┘ │ └─────────────┘
|
|
│ │
|
|
│ │
|
|
▼ │
|
|
┌─────────────┐ │
|
|
│ GA │◄──────┘
|
|
│ (stable) │
|
|
└──────┬──────┘
|
|
│
|
|
▼
|
|
┌─────────────┐
|
|
│ DEPRECATED │
|
|
│ (optional) │
|
|
└──────┬──────┘
|
|
│
|
|
▼
|
|
┌─────────────┐
|
|
│ REMOVED │
|
|
└─────────────┘
|
|
```
|
|
|
|
### Alpha → Beta Criteria
|
|
|
|
- [ ] Feature is functionally complete
|
|
- [ ] At least 2 weeks since Alpha release
|
|
- [ ] No critical bugs reported
|
|
- [ ] Basic documentation exists
|
|
- [ ] Telemetry shows no major issues
|
|
- [ ] Tracking issue updated with feedback summary
|
|
|
|
### Beta → GA Criteria
|
|
|
|
- [ ] At least 4 weeks in Beta
|
|
- [ ] Telemetry shows stable usage patterns
|
|
- [ ] Documentation is complete
|
|
- [ ] No breaking changes planned
|
|
- [ ] Team consensus in tracking issue
|
|
- [ ] Feature gate can be removed (always enabled)
|
|
|
|
### GA → Deprecated Criteria
|
|
|
|
- [ ] Replacement feature available (if applicable)
|
|
- [ ] Deprecation warning added to feature definition
|
|
- [ ] Migration guide published
|
|
- [ ] Removal version announced (typically N+2 major versions)
|
|
|
|
### Deprecation Timeline
|
|
|
|
| Action | Timeline |
|
|
| ------------------------ | ----------- |
|
|
| Mark as deprecated | Version N |
|
|
| Log deprecation warnings | Version N |
|
|
| Disable by default | Version N+1 |
|
|
| Remove feature | Version N+2 |
|
|
|
|
---
|
|
|
|
## Industry Comparison
|
|
|
|
| Aspect | Gemini CLI (Proposed) | [Cargo (Rust)](https://doc.rust-lang.org/cargo/reference/unstable.html) | [Kubernetes](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/) |
|
|
| ------------------ | ------------------------ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
| **Stages** | Alpha/Beta/GA/Deprecated | Unstable/Stable | Alpha/Beta/GA |
|
|
| **CLI Flag** | `--feature=X` / `-X` | `-Z flag` | `--feature-gates=X=true` |
|
|
| **Config File** | `experimental.X: true` | `[unstable] X = true` | Component flags |
|
|
| **Default Off** | Alpha, Beta | All unstable | Alpha only |
|
|
| **Nightly Only** | No (available in all) | Yes | No |
|
|
| **Tracking** | GitHub Issues | Tracking Issues | KEPs |
|
|
| **Telemetry** | Optional | None | Metrics endpoint |
|
|
| **Admin Override** | Yes | No | No |
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
### Open Source Feature Flag Tools
|
|
|
|
- [OpenFeature](https://openfeature.dev/) - Vendor-agnostic feature flagging
|
|
specification (CNCF)
|
|
- [GrowthBook](https://www.growthbook.io/) - Open source feature flags and A/B
|
|
testing
|
|
- [Flagsmith](https://www.flagsmith.com/) - Open source feature flag service
|
|
- [Unleash](https://www.getunleash.io/) - Open source feature management
|
|
|
|
### CLI Tool Implementations
|
|
|
|
- [Cargo Unstable Features](https://doc.rust-lang.org/cargo/reference/unstable.html) -
|
|
Rust's package manager experimental features
|
|
- [Kubernetes Feature Gates](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/) -
|
|
K8s feature gate system
|
|
- [Feature Flags Best Practices - LaunchDarkly](https://launchdarkly.com/blog/what-are-feature-flags/)
|
|
|
|
### Internal References
|
|
|
|
- Current experimental settings: `packages/cli/src/config/settingsSchema.ts`
|
|
- Settings merge logic: `packages/cli/src/config/settings.ts`
|
|
- Agent experimental flags: `packages/core/src/agents/registry.ts`
|
|
- Release workflows: `.github/workflows/release-*.yml`
|
|
|
|
---
|
|
|
|
## Appendix: Migration Path
|
|
|
|
### Migrating Existing Experimental Features
|
|
|
|
The following existing experimental settings should be migrated to the new
|
|
feature gate system:
|
|
|
|
| Current Setting | New Feature Gate | Stage |
|
|
| ----------------------------------------- | ------------------------ | ----- |
|
|
| `experimental.enableAgents` | `agents` | Alpha |
|
|
| `experimental.jitContext` | `jit-context` | Alpha |
|
|
| `experimental.plan` | `plan-mode` | Beta |
|
|
| `experimental.enableEventDrivenScheduler` | `event-driven-scheduler` | Beta |
|
|
| `experimental.extensionReloading` | `extension-reloading` | Alpha |
|
|
| `experimental.extensionConfig` | `extension-config` | Alpha |
|
|
| `experimental.useOSC52Paste` | `osc52-paste` | Alpha |
|
|
| `general.previewFeatures` | `preview-models` | Beta |
|
|
|
|
A migration script should:
|
|
|
|
1. Read existing settings
|
|
2. Map to new feature gate names
|
|
3. Preserve user preferences
|
|
4. Log migration actions
|