Setting the file. One moment.
Subchapter 22.7
references/project-cloning.mdMarkdown11 KBView on GitHub
Patterns for cloning projects across regions, teams, or environments.
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
)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,
});
}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 - UScustomer-ai-eu - Customer Agent - EUcustomer-ai-apac - Customer Agent - APACClone 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 Corpsaas-ai-globex - SaaS Agent - Globex Incsaas-ai-initech - SaaS Agent - InitechClone 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"])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"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 projectClone 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)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;
}Use consistent naming across clones:
{base}-{region} → ai-service-us, ai-service-eu
{team}-{service} → platform-ai, customer-ai
{service}-{tenant} → saas-acme, saas-globexTag clones for easy filtering:
tags = [
"ai-configs",
f"region:{region}",
f"cloned-from:{source_key}",
f"created:{datetime.now().isoformat()}"
]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 projectVerify 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")