All skills
launchdarkly avatar

/projects

@ef54971 official

Guide for setting up LaunchDarkly projects in your codebase. Helps you assess your stack, choose the right approach, and integrate project management that makes sense for your architecture.

Use this Skill: https://skilld.dev/gh/launchdarkly/agent-skills/projects

This session only. Nothing lands on disk.

referencesproject-cloning.md

≈2.9k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Project Cloning

Patterns for cloning projects across regions, teams, or environments.

Use Cases

  • Multi-region deployments: Clone project structure for US, EU, APAC regions
  • Multi-tenant applications: Separate project per customer/tenant
  • Team isolation: Clone template for different teams
  • Environment parity: Ensure dev/staging/prod have identical structure

Basic Cloning Pattern

Python

def clone_project(source_key: str, new_name: str, new_key: str, tags: List[str] = None) -> Dict:
    """
    Clone a project's structure (metadata only, not flags/configs).
    
    Args:
        source_key: The project to copy settings from
        new_name: Name for the new project
        new_key: Unique key for the new project
        tags: Optional tags (defaults to source tags + 'cloned')
        
    Returns:
        The newly created project
    """
    pm = ProjectManager()
    
    # Get source project settings
    source = pm.get_project(source_key)
    if not source:
        raise ValueError(f"Source project '{source_key}' not found")
    
    # Prepare new project with same settings
    source_tags = source.get("tags", [])
    new_tags = tags or (source_tags + ["cloned"])
    
    # Create new project
    return pm.create_project(
        name=new_name,
        key=new_key,
        tags=new_tags
    )

TypeScript

async function cloneProject(
  sourceKey: string,
  newName: string,
  newKey: string,
  tags?: string[]
): Promise<Project> {
  const pm = new ProjectManager();
  
  // Get source project settings
  const source = await pm.getProject(sourceKey);
  if (!source) {
    throw new Error(`Source project '${sourceKey}' not found`);
  }
  
  // Prepare new project with same settings
  const sourceTags = source.tags || [];
  const newTags = tags || [...sourceTags, 'cloned'];
  
  // Create new project
  return pm.createProject({
    name: newName,
    key: newKey,
    tags: newTags,
  });
}

Multi-Region Cloning

Clone a project for multiple regions:

def clone_for_regions(base_project: str, regions: List[str]):
    """
    Clone a project for multiple regions.
    
    Example:
        clone_for_regions("ai-service", ["us", "eu", "apac"])
        Creates: ai-service-us, ai-service-eu, ai-service-apac
    """
    pm = ProjectManager()
    base = pm.get_project(base_project)
    
    if not base:
        raise ValueError(f"Base project '{base_project}' not found")
    
    created_projects = []
    
    for region in regions:
        new_key = f"{base_project}-{region}"
        new_name = f"{base['name']} - {region.upper()}"
        
        print(f"Creating {new_key}...")
        project = clone_project(
            source_key=base_project,
            new_name=new_name,
            new_key=new_key,
            tags=base.get("tags", []) + [f"region:{region}"]
        )
        
        created_projects.append(project)
        print(f"✓ Created {new_key}")
    
    return created_projects

# Usage
clone_for_regions("customer-ai", ["us", "eu", "apac"])

Result:

  • customer-ai-us - Customer Agent - US
  • customer-ai-eu - Customer Agent - EU
  • customer-ai-apac - Customer Agent - APAC

Multi-Tenant Cloning

Clone for different tenants/customers:

interface Tenant {
  id: string;
  name: string;
}

async function cloneForTenants(
  baseProject: string,
  tenants: Tenant[]
): Promise<Project[]> {
  const pm = new ProjectManager();
  const base = await pm.getProject(baseProject);
  
  if (!base) {
    throw new Error(`Base project '${baseProject}' not found`);
  }
  
  const createdProjects: Project[] = [];
  
  for (const tenant of tenants) {
    const newKey = `${baseProject}-${tenant.id}`;
    const newName = `${base.name} - ${tenant.name}`;
    
    console.log(`Creating ${newKey}...`);
    const project = await cloneProject(
      baseProject,
      newName,
      newKey,
      [...(base.tags || []), `tenant:${tenant.id}`]
    );
    
    createdProjects.push(project);
    console.log(`✓ Created ${newKey}`);
  }
  
  return createdProjects;
}

// Usage
const tenants = [
  { id: 'acme', name: 'Acme Corp' },
  { id: 'globex', name: 'Globex Inc' },
  { id: 'initech', name: 'Initech' },
];

cloneForTenants('saas-ai', tenants);

Result:

  • saas-ai-acme - SaaS Agent - Acme Corp
  • saas-ai-globex - SaaS Agent - Globex Inc
  • saas-ai-initech - SaaS Agent - Initech

Team-Based Cloning

Clone template project for multiple teams:

def clone_for_teams(template_project: str, teams: List[str]):
    """
    Clone a template project for multiple teams.
    
    Example:
        clone_for_teams("ai-template", ["platform", "customer", "product"])
    """
    pm = ProjectManager()
    template = pm.get_project(template_project)
    
    if not template:
        raise ValueError(f"Template project '{template_project}' not found")
    
    created_projects = []
    
    for team in teams:
        new_key = f"{team}-ai"
        new_name = f"{team.title()} Team Agent"
        
        print(f"Creating {new_key} for {team} team...")
        project = clone_project(
            source_key=template_project,
            new_name=new_name,
            new_key=new_key,
            tags=["ai-configs", f"team:{team}"]
        )
        
        # Save SDK keys for team
        save_sdk_key_to_env(
            new_key,
            "production",
            env_file=f".env.{team}",
            var_name="LAUNCHDARKLY_SDK_KEY"
        )
        
        created_projects.append(project)
        print(f"✓ Created {new_key}")
    
    return created_projects

# Usage
clone_for_teams("ai-template", ["platform", "customer", "product"])

Bulk Cloning with CSV

Clone from a CSV file with project specifications:

import csv

def clone_from_csv(source_key: str, csv_file: str):
    """
    Clone projects from CSV file.
    
    CSV format:
        project_key,project_name,tags
        mobile-ai-us,Mobile Agent US,"mobile,us,production"
        mobile-ai-eu,Mobile Agent EU,"mobile,eu,production"
    """
    pm = ProjectManager()
    created_projects = []
    
    with open(csv_file, 'r') as f:
        reader = csv.DictReader(f)
        for row in reader:
            key = row['project_key']
            name = row['project_name']
            tags = row.get('tags', '').split(',') if row.get('tags') else []
            
            print(f"Creating {key}...")
            project = clone_project(source_key, name, key, tags)
            created_projects.append(project)
            print(f"✓ Created {key}")
    
    return created_projects

# Usage
clone_from_csv("ai-template", "projects.csv")

projects.csv:

project_key,project_name,tags
mobile-ai-us,Mobile Agent US,"mobile,us,production"
mobile-ai-eu,Mobile Agent EU,"mobile,eu,production"
web-ai-us,Web Agent US,"web,us,production"
web-ai-eu,Web Agent EU,"web,eu,production"

Automated SDK Key Management

After cloning, automatically save SDK keys:

def clone_and_configure(
    source_key: str,
    new_key: str,
    new_name: str,
    env_file: str = None
):
    """Clone project and automatically save SDK keys."""
    # Clone the project
    project = clone_project(source_key, new_name, new_key)
    print(f"✓ Cloned {source_key} → {new_key}")
    
    # Save SDK keys for both environments
    env_file = env_file or f".env.{new_key}"
    
    for environment in ["production", "test"]:
        var_name = f"LD_SDK_KEY_{environment.upper()}"
        save_sdk_key_to_env(new_key, environment, env_file, var_name)
    
    print(f"✓ Saved SDK keys to {env_file}")
    
    return project

Parallel Cloning

Clone multiple projects in parallel for speed:

import concurrent.futures

def clone_projects_parallel(clones: List[Dict[str, str]], max_workers: int = 5):
    """
    Clone multiple projects in parallel.
    
    Args:
        clones: List of dicts with keys: source_key, new_key, new_name
        max_workers: Max parallel requests
    """
    def clone_single(clone_spec):
        return clone_project(
            source_key=clone_spec['source_key'],
            new_name=clone_spec['new_name'],
            new_key=clone_spec['new_key']
        )
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = {executor.submit(clone_single, spec): spec for spec in clones}
        
        results = []
        for future in concurrent.futures.as_completed(futures):
            spec = futures[future]
            try:
                project = future.result()
                print(f"✓ Cloned {spec['new_key']}")
                results.append(project)
            except Exception as e:
                print(f"✗ Failed to clone {spec['new_key']}: {e}")
        
        return results

# Usage
clones = [
    {"source_key": "template", "new_key": "team-a-ai", "new_name": "Team A Agent"},
    {"source_key": "template", "new_key": "team-b-ai", "new_name": "Team B Agent"},
    {"source_key": "template", "new_key": "team-c-ai", "new_name": "Team C Agent"},
]

clone_projects_parallel(clones)

Cloning with MCP Server

If using the LaunchDarkly MCP server:

// Note: MCP server may not have clone functionality
// You would create projects individually

async function cloneWithMCP(sourceKey: string, newKey: string, newName: string) {
  // Get source project via MCP
  const source = await mcp.getProject(sourceKey);
  
  // Create new project with same settings
  const project = await mcp.createProject({
    name: newName,
    key: newKey,
    tags: [...(source.tags || []), 'cloned'],
  });
  
  return project;
}

Best Practices

1. Naming Conventions

Use consistent naming across clones:

{base}-{region}        →  ai-service-us, ai-service-eu
{team}-{service}       →  platform-ai, customer-ai
{service}-{tenant}     →  saas-acme, saas-globex

2. Tagging Strategy

Tag clones for easy filtering:

tags = [
    "ai-configs",
    f"region:{region}",
    f"cloned-from:{source_key}",
    f"created:{datetime.now().isoformat()}"
]

3. Documentation

Document cloning relationships:

def clone_with_metadata(source_key: str, new_key: str, new_name: str):
    """Clone and document the relationship."""
    project = clone_project(source_key, new_name, new_key)
    
    # Create a mapping file
    with open("project-clones.json", "a") as f:
        f.write(json.dumps({
            "source": source_key,
            "clone": new_key,
            "created_at": datetime.now().isoformat()
        }) + "\n")
    
    return project

4. Verification

Verify clones after creation:

def verify_clones(clones: List[str]):
    """Verify all cloned projects exist and have SDK keys."""
    pm = ProjectManager()
    
    for project_key in clones:
        project = pm.get_project(project_key)
        if not project:
            print(f"✗ {project_key} not found")
            continue
        
        sdk_key = pm.get_sdk_key(project_key, "production")
        if sdk_key:
            print(f"✓ {project_key} verified")
        else:
            print(f"⚠️  {project_key} missing SDK key")

Next Steps

Source: SKILL.md on GitHub

2 alerts2d3 checks · Risk HIGH
  • Gen Agent Trust Hub2d

    The skill facilitates LaunchDarkly project setup but performs high-risk operations, including instructions to automatically extract credentials from sensitive agent configuration files (~/.claude/config.json) and system environment variables. It also generates and executes local scripts to verify integrations, creating a potential path for local code execution.

  • Socket2d

    1 alert: gptAnomaly

  • Snyk2d

    Risk: HIGH · 1 issue

Signed by skilld at ef54971. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 3 days ago
metadata
{
  "author": "launchdarkly",
  "version": "0.4.0"
}
Other metadata
compatibility
Requires LaunchDarkly API access token with projects:write permission or LaunchDarkly MCP server.
  • Python
  • Go
  • Infrastructure
  • launchdarkly
  • project-setup
  • api-integration
  • nodejs
  • configuration-management
  • feature-flags
  • secrets-management

README badge

README badge for launchdarkly/agent-skills/projects

Guides setup of LaunchDarkly projects in a codebase by exploring the stack, assessing architecture, and choosing the right implementation path. Supports Python, Node.js, Go, and polyglot setups, with reference guides for quick setup, environment configuration, project cloning, and infrastructure automation.

Generated from the current SKILL.md.

What permissions do I need to set up LaunchDarkly projects?
Your API access token must have the projects:write permission, or you can use a LaunchDarkly MCP server configured in your environment instead.
Can the skill automatically detect my LaunchDarkly API key?
Yes. The skill checks for LAUNCHDARKLY_API_KEY, LAUNCHDARKLY_API_TOKEN, or LD_API_KEY environment variables, and also checks the Claude MCP config at ~/.claude/config.json before prompting you for the key.
What project key format is required?
Project keys must start with a letter, use only lowercase letters, numbers, and hyphens, and cannot contain uppercase letters, underscores, or dots.
Does this skill create the projects, or just guide me?
The skill guides you through the setup process and follows reference implementations for your tech stack (Python, Node.js, Go, etc.), but you choose which reference path to execute based on your architecture.
What should I do after projects are created?
After setup, verify the project exists and SDK keys are valid, then proceed to the configs-create skill to create feature flags or the sdk skill to integrate into your application.

Generated from the current SKILL.md. These answers refresh after source changes.