Files
BrowserOS/docs/dev_cli_design.md
Nikhil Sonti 424cf1ec94 design doc
2025-09-17 17:38:30 -07:00

29 KiB

Dev CLI Design Document

1. Overview

1.1 Purpose

The Dev CLI is a patch management system for Chromium development that acts like git but specifically for managing patches against the Chromium codebase. It enables developers to:

  • Extract patches from git commits in a Chromium repository
  • Store patches as individual file diffs
  • Track which files belong to which features
  • Apply patches to new Chromium versions with conflict resolution
  • Manage the upgrade process when moving to newer Chromium versions

1.2 Key Design Principles

  • Simplicity: Mirror git's command structure and workflow
  • Transparency: Store patches as readable diff files
  • Flexibility: Support both individual file and feature-based operations
  • Robustness: Handle conflicts gracefully during Chromium upgrades

2. Architecture

2.1 Directory Structure

nxtscape/
├── build/
│   ├── dev.py                          # Main CLI entry point
│   ├── context.py                      # Shared BuildContext (used by both build.py and dev.py)
│   └── modules/
│       └── dev_cli/                    # Dev CLI modules
│           ├── __init__.py
│           ├── extract.py              # Extract commands (extract, extract-range)
│           ├── apply.py                # Apply commands (apply --all, apply --feature)
│           ├── feature.py              # Feature management (add, list, show, generate-patch)
│           └── utils.py                # Shared utilities (diff parsing, git commands)
├── chromium_src/                       # Individual file patches (mirrors Chromium structure)
│   ├── chrome/
│   │   ├── app/
│   │   │   └── chrome_command_ids.h.patch
│   │   └── browser/
│   │       └── ui/
│   │           ├── ui_features.h.patch
│   │           └── views/
│   │               └── side_panel/
│   │                   └── third_party_llm/
│   │                       ├── third_party_llm_panel_coordinator.cc.patch
│   │                       └── third_party_llm_view.cc.patch  # New file (diff against /dev/null)
│   └── ...
├── features.yaml                       # Feature to file mapping
└── patches/                            # Legacy patches directory (existing)
    └── browseros/
        └── llm-chat.patch              # Combined patch for reference

2.2 Module Structure

Each module in build/modules/dev_cli/ is self-contained and registers its own Click commands:

2.2.1 Module Organization

  • extract.py: Handles extracting patches from git commits
  • apply.py: Handles applying patches with conflict resolution
  • feature.py: Manages feature-to-file mappings
  • utils.py: Shared utilities for git operations, diff parsing, etc.

2.2.2 BuildContext Integration

The Dev CLI reuses the existing BuildContext from build/context.py with additional methods:

# In context.py - extended for dev CLI
class BuildContext:
    # ... existing code ...

    def get_dev_patches_dir(self) -> Path:
        """Get individual patches directory (chromium_src/)"""
        return join_paths(self.root_dir, "chromium_src")

    def get_features_yaml_path(self) -> Path:
        """Get features.yaml file path"""
        return join_paths(self.root_dir, "features.yaml")

    def get_patch_path_for_file(self, file_path: str) -> Path:
        """Convert a chromium file path to patch file path"""
        return join_paths(self.get_dev_patches_dir(), f"{file_path}.patch")

2.2 File Formats

2.2.1 Patch Files (.patch)

Standard unified diff format (git diff output):

--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -290,6 +290,8 @@
 #define IDC_SHOW_HISTORY_SIDE_PANEL     40293
 #define IDC_OPEN_GLIC                   40294
 #define IDC_FIND_EXTENSIONS  40295
+#define IDC_SHOW_THIRD_PARTY_LLM_SIDE_PANEL  40296
+#define IDC_CYCLE_THIRD_PARTY_LLM_PROVIDER  40297

New files use /dev/null as the source:

--- /dev/null
+++ b/chrome/browser/ui/views/side_panel/third_party_llm/third_party_llm_view.cc
@@ -0,0 +1,11 @@
+// Copyright 2024 The Chromium Authors
+// ... file contents ...

2.2.2 Features YAML

version: 1.0
features:
  llm-chat:
    description: "LLM chat integration in side panel"
    files:
      - chrome/app/chrome_command_ids.h
      - chrome/browser/ui/ui_features.h
      - chrome/browser/ui/views/side_panel/third_party_llm/third_party_llm_panel_coordinator.cc
      - chrome/browser/ui/views/side_panel/third_party_llm/third_party_llm_view.cc

  another-feature:
    description: "Another feature description"
    files:
      - chrome/app/chrome_command_ids.h  # Note: can be in multiple features
      - chrome/browser/some_other_file.cc

3. Implementation Structure

3.1 Main Entry Point (build/dev.py)

The main entry point uses Click's group mechanism to register subcommands from modules:

#!/usr/bin/env python3
"""Dev CLI for Chromium patch management"""

import click
from pathlib import Path
from context import BuildContext
from modules.dev_cli import extract, apply, feature
from utils import log_info, log_error

@click.group()
@click.option('--chromium-src', '-S', type=click.Path(exists=True, path_type=Path),
              help='Path to Chromium source directory')
@click.pass_context
def cli(ctx, chromium_src):
    """Dev CLI - Chromium patch management tool"""
    # Store chromium_src in context for subcommands
    ctx.ensure_object(dict)
    ctx.obj['chromium_src'] = chromium_src or None

# Register subcommand groups from modules
cli.add_command(extract.extract_group)
cli.add_command(apply.apply_group)
cli.add_command(feature.feature_group)

if __name__ == '__main__':
    cli()

3.2 Module Implementation Examples

3.2.1 Extract Module (build/modules/dev_cli/extract.py)

import click
from pathlib import Path
from context import BuildContext
from modules.dev_cli.utils import run_git_command, parse_diff_output
from utils import log_info, log_error, log_success

@click.group(name='extract')
def extract_group():
    """Extract patches from git commits"""
    pass

@extract_group.command(name='commit')
@click.argument('commit')
@click.pass_context
def extract_commit(ctx, commit):
    """Extract patches from a single commit"""
    chromium_src = ctx.obj.get('chromium_src')
    if not chromium_src:
        log_error("--chromium-src is required")
        return

    # Create BuildContext
    build_ctx = BuildContext(
        root_dir=Path.cwd(),
        chromium_src=chromium_src,
        architecture="",  # Not needed for patch operations
        build_type="debug"  # Not needed for patch operations
    )

    if extract_single_commit(build_ctx, commit):
        log_success(f"Successfully extracted patches from {commit}")
    else:
        log_error(f"Failed to extract patches from {commit}")

@extract_group.command(name='range')
@click.argument('base_commit')
@click.argument('head_commit')
@click.pass_context
def extract_range(ctx, base_commit, head_commit):
    """Extract patches from a range of commits"""
    # Similar implementation...

def extract_single_commit(ctx: BuildContext, commit_hash: str) -> bool:
    """Implementation of single commit extraction"""
    # Implementation as detailed in section 4
    pass

3.2.2 Apply Module (build/modules/dev_cli/apply.py)

import click
from pathlib import Path
from context import BuildContext
from modules.dev_cli.utils import apply_single_patch
from utils import log_info, log_error, log_success

@click.group(name='apply')
def apply_group():
    """Apply patches to Chromium source"""
    pass

@apply_group.command(name='all')
@click.option('--commit-each', is_flag=True, help='Create git commit after each patch')
@click.option('--dry-run', is_flag=True, help='Test patches without applying')
@click.pass_context
def apply_all(ctx, commit_each, dry_run):
    """Apply all patches from chromium_src/"""
    chromium_src = ctx.obj.get('chromium_src')
    if not chromium_src:
        log_error("--chromium-src is required")
        return

    build_ctx = BuildContext(
        root_dir=Path.cwd(),
        chromium_src=chromium_src,
        architecture="",
        build_type="debug"
    )

    apply_all_patches(build_ctx, commit_each, dry_run)

@apply_group.command(name='feature')
@click.argument('feature_name')
@click.option('--commit-each', is_flag=True, help='Create git commit after each patch')
@click.option('--dry-run', is_flag=True, help='Test patches without applying')
@click.pass_context
def apply_feature(ctx, feature_name, commit_each, dry_run):
    """Apply patches for a specific feature"""
    # Implementation...

3.2.3 Feature Module (build/modules/dev_cli/feature.py)

import click
import yaml
from pathlib import Path
from context import BuildContext
from utils import log_info, log_error, log_success

@click.group(name='feature')
def feature_group():
    """Manage feature-to-file mappings"""
    pass

@feature_group.command(name='add')
@click.argument('feature_name')
@click.argument('commit')
@click.pass_context
def add_feature(ctx, feature_name, commit):
    """Add files from a commit to a feature"""
    # Implementation...

@feature_group.command(name='list')
@click.pass_context
def list_features(ctx):
    """List all features"""
    build_ctx = BuildContext(
        root_dir=Path.cwd(),
        chromium_src=Path.cwd(),  # Not used for listing
        architecture="",
        build_type="debug"
    )

    features = load_features_yaml(build_ctx)
    for name, data in features.items():
        file_count = len(data.get('files', []))
        description = data.get('description', 'No description')
        log_info(f"  {name} ({file_count} files) - {description}")

@feature_group.command(name='show')
@click.argument('feature_name')
@click.pass_context
def show_feature(ctx, feature_name):
    """Show details of a specific feature"""
    # Implementation...

4. Command Specifications

4.1 Extract Commands

4.1.1 extract commit - Extract patches from a single commit

dev-cli --chromium-src <path> extract commit <commit-hash>
# or
dev-cli extract commit <commit-hash>  # if chromium-src is in config

Implementation Steps:

  1. Validate commit exists in the repository
  2. Get diff for the commit: git diff <commit>^..<commit>
  3. Parse diff output to identify changed files
  4. For each changed file:
    • Extract the file path relative to chromium src
    • Detect if file is new (doesn't exist in parent commit) or modified
    • Create directory structure in chromium_src/ mirroring the file path
    • Write individual patch file with .patch extension
  5. Log summary of extracted patches

Code Structure:

def extract_single_commit(commit_hash: str, chromium_src: Path) -> bool:
    # Step 1: Validate commit
    if not validate_commit_exists(commit_hash, chromium_src):
        return False

    # Step 2: Get diff
    diff_output = run_git_command(['git', 'diff', f'{commit_hash}^..{commit_hash}'],
                                  cwd=chromium_src)

    # Step 3: Parse diff into file patches
    file_patches = parse_diff_output(diff_output)

    # Step 4: Write individual patches
    for file_path, patch_content in file_patches.items():
        write_patch_file(file_path, patch_content)

    # Step 5: Log summary
    log_extraction_summary(file_patches)
    return True

4.1.2 extract range - Extract patches from a range of commits

dev-cli --chromium-src <path> extract range <base-commit> <head-commit>

Implementation Steps:

  1. Validate both commits exist
  2. Get cumulative diff: git diff <base>..<head>
  3. Parse diff to identify all changed files
  4. For each file:
    • Detect if new or modified (check if exists at base commit)
    • Create/update patch file in chromium_src/
  5. Handle file deletions (create .deleted marker files)
  6. Log summary with statistics

Code Structure:

def extract_commit_range(base_commit: str, head_commit: str, chromium_src: Path) -> bool:
    # Step 1: Validate commits
    if not validate_commit_exists(base_commit, chromium_src):
        return False
    if not validate_commit_exists(head_commit, chromium_src):
        return False

    # Step 2: Get cumulative diff
    diff_output = run_git_command(['git', 'diff', f'{base_commit}..{head_commit}'],
                                  cwd=chromium_src)

    # Step 3-5: Process diff
    file_patches = parse_diff_output(diff_output)

    for file_path, patch_content in file_patches.items():
        if patch_content is None:  # File was deleted
            create_deletion_marker(file_path)
        else:
            write_patch_file(file_path, patch_content)

    # Step 6: Log summary
    log_extraction_summary(file_patches)
    return True

4.2 Apply Commands

4.2.1 apply all - Apply all patches

dev-cli --chromium-src <path> apply all [--commit-each] [--dry-run]

Implementation Steps:

  1. Validate chromium_src is a git repository
  2. If --dry-run, check which patches would apply cleanly
  3. Recursively find all .patch files in chromium_src/ directory
  4. Sort patches alphabetically by path (deterministic order)
  5. For each patch:
    • Apply using git apply -p1 <patch>
    • If conflict, handle based on conflict resolution flow
    • If --commit-each, create git commit after successful application
  6. Report summary of applied/failed patches

Conflict Resolution Flow:

def handle_patch_conflict(patch_path: Path, chromium_src: Path) -> bool:
    print(f"CONFLICT: {patch_path}")
    print("Options:")
    print("  1) Fix manually and continue")
    print("  2) Skip this patch")
    print("  3) Abort all remaining patches")

    while True:
        choice = input("Enter choice (1-3): ")
        if choice == "1":
            input("Fix the conflicts and press Enter to continue...")
            return True  # Continue with next patch
        elif choice == "2":
            print(f"Skipping {patch_path}")
            return True  # Skip but continue
        elif choice == "3":
            return False  # Abort

4.2.2 apply feature - Apply patches for a specific feature

dev-cli --chromium-src <path> apply feature <feature-name> [--commit-each] [--dry-run]

Implementation Steps:

  1. Load features.yaml file
  2. Validate feature exists in the YAML
  3. Get list of files for the feature
  4. For each file in the feature:
    • Construct patch file path in chromium_src/
    • Apply patch using same logic as apply --all
  5. Handle conflicts with same resolution flow
  6. Report feature-specific summary

Code Structure:

def apply_feature_patches(feature_name: str, chromium_src: Path,
                         commit_each: bool = False) -> bool:
    # Step 1-2: Load and validate
    features = load_features_yaml()
    if feature_name not in features:
        print(f"Feature '{feature_name}' not found")
        return False

    # Step 3: Get file list
    file_list = features[feature_name]['files']

    # Step 4-5: Apply patches
    success_count = 0
    fail_count = 0

    for file_path in file_list:
        patch_path = construct_patch_path(file_path)
        if apply_single_patch(patch_path, chromium_src):
            success_count += 1
            if commit_each:
                create_git_commit(f"Apply {feature_name}: {file_path}")
        else:
            fail_count += 1

    # Step 6: Report
    print(f"Feature '{feature_name}': {success_count} applied, {fail_count} failed")
    return fail_count == 0

4.3 Feature Management Commands

4.3.1 feature add - Add files from a commit to a feature

dev-cli --chromium-src <path> feature add <feature-name> <commit-hash>

Implementation Steps:

  1. Get list of files changed in the commit
  2. Load or create features.yaml
  3. Add/update feature entry with file list
  4. Detect duplicates and warn
  5. Save updated YAML

Code Structure:

def add_feature_from_commit(feature_name: str, commit_hash: str,
                           chromium_src: Path) -> bool:
    # Step 1: Get changed files
    changed_files = get_commit_changed_files(commit_hash, chromium_src)

    # Step 2: Load features
    features = load_features_yaml()

    # Step 3-4: Update feature
    if feature_name in features:
        existing_files = set(features[feature_name]['files'])
        new_files = set(changed_files) - existing_files
        if new_files:
            features[feature_name]['files'].extend(new_files)
            print(f"Added {len(new_files)} new files to '{feature_name}'")
        else:
            print(f"All files already in '{feature_name}'")
    else:
        features[feature_name] = {
            'description': f"Feature added from commit {commit_hash}",
            'files': changed_files
        }
        print(f"Created new feature '{feature_name}' with {len(changed_files)} files")

    # Step 5: Save
    save_features_yaml(features)
    return True

4.3.2 feature list - List all features

dev-cli feature list

Implementation Steps:

  1. Load features.yaml
  2. Display formatted list of features with file counts
  3. Show features sorted alphabetically

Output Example:

Features:
  llm-chat (4 files) - LLM chat integration in side panel
  another-feature (2 files) - Another feature description

Total: 2 features, 6 unique files

4.3.3 feature show - Show details of a feature

dev-cli feature show <feature-name>

Implementation Steps:

  1. Load features.yaml
  2. Validate feature exists
  3. Display feature details and file list
  4. Check patch status for each file

Output Example:

Feature: llm-chat
Description: LLM chat integration in side panel
Files (4):
  ✓ chrome/app/chrome_command_ids.h
  ✓ chrome/browser/ui/ui_features.h
  ✗ chrome/browser/ui/views/side_panel/third_party_llm/third_party_llm_panel_coordinator.cc (patch missing)
  ✓ chrome/browser/ui/views/side_panel/third_party_llm/third_party_llm_view.cc

4.3.4 feature generate-patch - Generate combined patch for a feature

dev-cli feature generate-patch <feature-name> [--output <path>]

Implementation Steps:

  1. Load feature file list from YAML
  2. Concatenate all individual patches in order
  3. Generate unified patch header
  4. Write to output file or stdout

4. Core Modules Implementation

4.1 Diff Parser Module

# modules/diff_parser.py

def parse_diff_output(diff_output: str) -> Dict[str, Optional[str]]:
    """
    Parse git diff output into individual file patches.

    Returns:
        Dict mapping file path to patch content.
        None value indicates file was deleted.
    """
    patches = {}
    current_file = None
    current_patch = []

    for line in diff_output.splitlines():
        if line.startswith('diff --git'):
            # Save previous patch if exists
            if current_file:
                patches[current_file] = '\n'.join(current_patch)

            # Parse new file path
            parts = line.split()
            current_file = parts[2][2:] if parts[2].startswith('a/') else parts[2]
            current_patch = [line]

        elif line.startswith('deleted file'):
            patches[current_file] = None  # Mark as deleted

        elif current_file:
            current_patch.append(line)

    # Save last patch
    if current_file:
        patches[current_file] = '\n'.join(current_patch) if current_patch else None

    return patches

4.2 Patch Writer Module

# modules/patch_writer.py

def write_patch_file(file_path: str, patch_content: str) -> bool:
    """
    Write a patch file to chromium_src directory structure.
    """
    # Construct output path
    output_path = Path('chromium_src') / file_path
    output_path = output_path.with_suffix(output_path.suffix + '.patch')

    # Create directory structure
    output_path.parent.mkdir(parents=True, exist_ok=True)

    # Write patch content
    output_path.write_text(patch_content)

    print(f"  Written: {output_path}")
    return True

def create_deletion_marker(file_path: str) -> bool:
    """
    Create a marker file for deleted files.
    """
    marker_path = Path('chromium_src') / file_path
    marker_path = marker_path.with_suffix(marker_path.suffix + '.deleted')

    marker_path.parent.mkdir(parents=True, exist_ok=True)
    marker_path.write_text(f"File deleted in patch\n")

    print(f"  Marked deleted: {marker_path}")
    return True

4.3 Patch Application Module

# modules/patch_apply.py

def apply_single_patch(patch_path: Path, chromium_src: Path,
                       interactive: bool = True) -> bool:
    """
    Apply a single patch file to chromium source.
    """
    if not patch_path.exists():
        print(f"Patch file not found: {patch_path}")
        return False

    # Try standard apply
    cmd = ['git', 'apply', '-p1', str(patch_path)]
    result = run_command(cmd, cwd=chromium_src, capture=True)

    if result.returncode == 0:
        print(f"  ✓ Applied: {patch_path.name}")
        return True

    # Try 3-way merge
    cmd.append('--3way')
    result = run_command(cmd, cwd=chromium_src, capture=True)

    if result.returncode == 0:
        print(f"  ✓ Applied (3-way): {patch_path.name}")
        return True

    # Handle conflict
    if interactive:
        return handle_patch_conflict(patch_path, chromium_src)
    else:
        print(f"  ✗ Failed: {patch_path.name}")
        return False

4.4 Feature Manager Module

# modules/feature_manager.py

def load_features_yaml() -> Dict:
    """Load features.yaml file."""
    features_path = Path('features.yaml')
    if not features_path.exists():
        return {'version': '1.0', 'features': {}}

    with open(features_path) as f:
        data = yaml.safe_load(f)

    return data.get('features', {})

def save_features_yaml(features: Dict) -> None:
    """Save features to YAML file."""
    features_path = Path('features.yaml')

    data = {
        'version': '1.0',
        'features': features
    }

    with open(features_path, 'w') as f:
        yaml.dump(data, f, default_flow_style=False, sort_keys=False)

5. Error Handling

5.1 Common Error Scenarios

  1. Invalid Chromium Source Path

    • Check if path exists and is a git repository
    • Check for presence of chromium markers (BUILD.gn, chrome/ directory)
  2. Git Command Failures

    • Wrap all git commands in try-except
    • Provide clear error messages with git stderr output
    • Suggest fixes (e.g., "commit not found, check if you're in the right branch")
  3. Patch Conflicts

    • Detect via git apply return code
    • Offer interactive resolution
    • Allow skipping problematic patches
  4. File Permission Issues

    • Check write permissions before operations
    • Provide clear error messages about permission requirements
  5. Malformed YAML

    • Validate YAML structure on load
    • Provide line numbers for syntax errors
    • Create backup before modifying

5.2 Error Recovery

def safe_operation(operation_func, *args, **kwargs):
    """
    Wrapper for safe execution with rollback capability.
    """
    backup_created = False
    try:
        # Create backup if modifying files
        if kwargs.get('create_backup', True):
            create_backup()
            backup_created = True

        # Execute operation
        result = operation_func(*args, **kwargs)

        # Clean up backup on success
        if backup_created:
            cleanup_backup()

        return result

    except Exception as e:
        print(f"Error: {e}")

        if backup_created:
            if prompt_yes_no("Restore from backup?"):
                restore_backup()

        raise

6. Configuration

6.1 CLI Configuration File (.dev-cli.yaml)

# Optional configuration file
defaults:
  chromium_src: /path/to/chromium/src
  auto_commit: false
  interactive: true

aliases:
  # Short aliases for common operations
  up: "extract-range HEAD~1 HEAD"
  fix: "apply --all --commit-each"

6.2 Environment Variables

DEV_CLI_CHROMIUM_SRC=/path/to/chromium/src
DEV_CLI_AUTO_COMMIT=true
DEV_CLI_INTERACTIVE=false

7. Testing Strategy

7.1 Unit Tests

  • Test diff parsing with various git diff outputs
  • Test patch file writing and directory creation
  • Test YAML loading/saving
  • Test conflict detection

7.2 Integration Tests

  • Create test repository with known commits
  • Test extract commands with various commit scenarios
  • Test apply commands with clean and conflicting patches
  • Test feature management operations

7.3 End-to-End Tests

  • Full workflow: extract → apply → fix conflicts → re-extract
  • Chromium version upgrade simulation
  • Multi-feature patch management

8. Implementation Phases

Phase 1: Core Infrastructure (Foundation)

  1. Create main CLI entry point with argument parsing
  2. Implement configuration loading (CLI args, config file, env vars)
  3. Create basic project structure and modules
  4. Implement logging and error handling framework

Phase 2: Extract Commands

  1. Implement git command execution wrapper
  2. Create diff parser module
  3. Implement extract command for single commits
  4. Implement extract-range command for commit ranges
  5. Add patch file writer with directory structure creation

Phase 3: Apply Commands

  1. Implement patch discovery (finding .patch files)
  2. Create patch application logic with git apply
  3. Add conflict detection and resolution flow
  4. Implement apply --all command
  5. Add --commit-each support
  6. Implement --dry-run mode

Phase 4: Feature Management

  1. Create YAML file handler for features.yaml
  2. Implement feature add command
  3. Implement feature list command
  4. Implement feature show command
  5. Add apply --feature command
  6. Implement feature generate-patch command

Phase 5: Polish and Optimization

  1. Add progress bars for long operations
  2. Implement caching for repeated operations
  3. Add verbose and quiet modes
  4. Create comprehensive help documentation
  5. Add shell completion scripts

9. CLI Usage Examples

9.1 Initial Setup

# Set chromium source path (can also be in config)
export CHROMIUM_SRC=~/chromium/src

# Extract patches from existing work
dev-cli --chromium-src $CHROMIUM_SRC extract range chromium-base HEAD

# Create feature from recent commit
dev-cli --chromium-src $CHROMIUM_SRC feature add llm-chat HEAD~1

9.2 Daily Development

# Make changes in chromium repo, commit them
cd ~/chromium/src
git add -A
git commit -m "Fix: Updated LLM chat UI"

# Extract the changes to patches
dev-cli --chromium-src . extract commit HEAD

# Or update patches from a range
dev-cli --chromium-src . extract range main HEAD

9.3 Chromium Upgrade Workflow

# Check what will apply cleanly
dev-cli --chromium-src $CHROMIUM_SRC apply all --dry-run

# Apply all patches with commit tracking
dev-cli --chromium-src $CHROMIUM_SRC apply all --commit-each

# If conflicts occur:
# 1. Fix conflicts in chromium/src
# 2. Press Enter to continue applying remaining patches
# 3. Build and test
# 4. Extract all changes to update patches

dev-cli --chromium-src $CHROMIUM_SRC extract range chromium-base HEAD

9.4 Feature-based Operations

# Apply only LLM chat feature
dev-cli --chromium-src $CHROMIUM_SRC apply feature llm-chat

# See what's in a feature
dev-cli feature show llm-chat

# Generate combined patch for sharing
dev-cli feature generate-patch llm-chat --output llm-chat-combined.patch

10. Future Enhancements (Not in MVP)

  1. Patch Dependencies: Track which patches depend on others
  2. Automatic Conflict Resolution: Use AI/heuristics for simple conflicts
  3. Patch Versioning: Track patch history across Chromium versions
  4. Collaboration Features: Share patches via git/cloud
  5. Build Integration: Trigger builds after successful patch application
  6. Patch Validation: Pre-check if patches will build before applying
  7. Bisect Support: Find which patch broke the build
  8. Patch Statistics: Track success rates across versions

11. Success Criteria

The dev CLI will be considered successful when:

  1. Developers can extract patches from any git commit or range
  2. Patches can be applied to clean Chromium with clear conflict resolution
  3. Features can be tracked and managed independently
  4. The Chromium upgrade process is streamlined and predictable
  5. The tool requires minimal manual intervention for common operations
  6. Error messages are clear and actionable
  7. The tool is faster than manual patch management

12. Non-Goals

The following are explicitly NOT goals for this tool:

  1. Managing chromium source code fetching/syncing (use depot_tools)
  2. Building chromium (use existing build system)
  3. Managing git branches (use git directly)
  4. Automatic merge conflict resolution (manual resolution required)
  5. Patch optimization or combination (maintain 1:1 file mapping)