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.

referencesmulti-language-setup.md

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

Multi-Language Setup

Guidance for polyglot architectures with multiple languages/frameworks.

Overview

In a microservices or polyglot architecture, you may have services in different languages that need to share LaunchDarkly projects or maintain separate projects per service.

Architecture Patterns

Pattern 1: Shared Project, Multiple Services

One project, different services consume from different environments or contexts.

When to use:

  • All services are part of the same application
  • Want centralized config management
  • Services share the same configs
Project: "my-app"
├── Service A (Python)    → Uses "my-app" production SDK key
├── Service B (Node.js)   → Uses "my-app" production SDK key
└── Service C (Go)        → Uses "my-app" production SDK key

Pattern 2: Project Per Service

Each service has its own project.

When to use:

  • Services are independent
  • Different teams own different services
  • Need isolation between services
Project: "service-a" → Service A (Python)
Project: "service-b" → Service B (Node.js)
Project: "service-c" → Service C (Go)

Pattern 3: Hybrid

Shared projects for related services, separate for others.

Project: "frontend-services"
├── Web App (React)
└── Mobile App (React Native)

Project: "backend-services"
├── API Gateway (Node.js)
└── Auth Service (Go)

Project: "ml-services"
├── Recommendation Engine (Python)
└── Model Serving (Python)

Centralized Project Management

Create a central service for project management that other services can use:

Project Management API

# project-manager-service/app.py
from flask import Flask, jsonify, request
from launchdarkly.projects import ProjectManager

app = Flask(__name__)
pm = ProjectManager()

@app.route('/projects', methods=['POST'])
def create_project():
    """Central API to create projects for any service."""
    data = request.json
    project = pm.create_project(
        name=data['name'],
        key=data['key'],
        tags=data.get('tags', [])
    )
    return jsonify(project)

@app.route('/projects/<key>/keys/<env>')
def get_sdk_key(key, env):
    """Get SDK key for any service."""
    sdk_key = pm.get_sdk_key(key, env)
    return jsonify({'sdkKey': sdk_key})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Service Consumption

Each service calls the central API:

Python Service:

import requests

def get_launchdarkly_sdk_key():
    resp = requests.get(
        'http://project-manager:8080/projects/my-service/keys/production'
    )
    return resp.json()['sdkKey']

Node.js Service:

async function getLaunchDarklySdkKey(): Promise<string> {
  const resp = await fetch(
    'http://project-manager:8080/projects/my-service/keys/production'
  );
  const data = await resp.json();
  return data.sdkKey;
}

Go Service:

func getLaunchDarklySdkKey() (string, error) {
    resp, err := http.Get("http://project-manager:8080/projects/my-service/keys/production")
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()
    
    var result struct {
        SdkKey string `json:"sdkKey"`
    }
    json.NewDecoder(resp.Body).Decode(&result)
    return result.SdkKey, nil
}

Shared Configuration Repository

Maintain a central config repo that all services reference:

config-repo/
├── launchdarkly/
│   ├── projects.yaml           # Project definitions
│   ├── sdk-keys/
│   │   ├── production/
│   │   │   ├── service-a.key
│   │   │   ├── service-b.key
│   │   │   └── service-c.key
│   │   └── test/
│   │       ├── service-a.key
│   │       ├── service-b.key
│   │       └── service-c.key
│   └── scripts/
│       ├── create_projects.py
│       └── sync_keys.sh

projects.yaml:

projects:
  - name: Service A
    key: service-a
    tags: [python, backend]
    services:
      - name: service-a
        language: python
        
  - name: Service B
    key: service-b
    tags: [nodejs, api]
    services:
      - name: service-b
        language: nodejs
        
  - name: Service C
    key: service-c
    tags: [go, gateway]
    services:
      - name: service-c
        language: go

Sync script:

#!/bin/bash
# scripts/sync_keys.sh

for env in production test; do
    for service in service-a service-b service-c; do
        sdk_key=$(python scripts/get_sdk_key.py $service $env)
        echo "$sdk_key" > "sdk-keys/$env/$service.key"
        echo "✓ Synced $service/$env"
    done
done

Service Templates

Create templates for each language:

Python Template

# templates/python/launchdarkly_setup.py
import os
from launchdarkly.projects import ProjectManager

def setup_project(service_name: str):
    """Setup LaunchDarkly project for Python service."""
    pm = ProjectManager()
    
    project = pm.create_project(
        name=f"{service_name} Service",
        key=service_name,
        tags=["python", "service"]
    )
    
    sdk_key = pm.get_sdk_key(service_name, "production")
    
    # Save to .env
    with open(".env", "w") as f:
        f.write(f"LAUNCHDARKLY_SDK_KEY={sdk_key}\n")
    
    print(f"✓ Setup complete for {service_name}")

Node.js Template

// templates/nodejs/launchdarkly-setup.ts
import { ProjectManager } from './launchdarkly/projects';
import * as fs from 'fs';

async function setupProject(serviceName: string): Promise<void> {
  const pm = new ProjectManager();
  
  const project = await pm.createProject({
    name: `${serviceName} Service`,
    key: serviceName,
    tags: ['nodejs', 'service'],
  });
  
  const sdkKey = await pm.getSdkKey(serviceName, 'production');
  
  // Save to .env
  fs.writeFileSync('.env', `LAUNCHDARKLY_SDK_KEY=${sdkKey}\n`);
  
  console.log(`✓ Setup complete for ${serviceName}`);
}

Go Template

// templates/go/launchdarkly_setup.go
package main

import (
    "fmt"
    "os"
    "yourmodule/pkg/launchdarkly"
)

func setupProject(serviceName string) error {
    pm := launchdarkly.NewProjectManager("")
    
    project, err := pm.CreateProject(
        fmt.Sprintf("%s Service", serviceName),
        serviceName,
        []string{"go", "service"},
    )
    if err != nil {
        return err
    }
    
    sdkKey, err := pm.GetSDKKey(serviceName, "production")
    if err != nil {
        return err
    }
    
    // Save to .env
    f, err := os.Create(".env")
    if err != nil {
        return err
    }
    defer f.Close()
    
    fmt.Fprintf(f, "LAUNCHDARKLY_SDK_KEY=%s\n", sdkKey)
    
    fmt.Printf("✓ Setup complete for %s\n", serviceName)
    return nil
}

Monorepo Setup

For monorepos with multiple services:

monorepo/
├── services/
│   ├── api/                 (Node.js)
│   ├── worker/              (Python)
│   └── gateway/             (Go)
├── packages/
│   └── launchdarkly-setup/
│       ├── python/
│       │   └── setup.py
│       ├── nodejs/
│       │   └── setup.ts
│       └── go/
│           └── setup.go
└── scripts/
    └── setup-all-projects.sh

setup-all-projects.sh:

#!/bin/bash

echo "Setting up LaunchDarkly projects for all services..."

cd services/api
npm run setup-launchdarkly

cd ../worker
python scripts/setup_launchdarkly.py

cd ../gateway
go run scripts/setup_launchdarkly.go

echo "✓ All services configured"

Environment Variable Convention

Standardize environment variable names across languages:

# Common convention
LAUNCHDARKLY_SDK_KEY=<production-key>
LAUNCHDARKLY_SDK_KEY_TEST=<test-key>
LAUNCHDARKLY_PROJECT_KEY=<project-key>
LAUNCHDARKLY_ENVIRONMENT=<production|test>

Loading in each language:

Python:

import os
sdk_key = os.environ['LAUNCHDARKLY_SDK_KEY']

Node.js:

const sdkKey = process.env.LAUNCHDARKLY_SDK_KEY;

Go:

sdkKey := os.Getenv("LAUNCHDARKLY_SDK_KEY")

Ruby:

sdk_key = ENV['LAUNCHDARKLY_SDK_KEY']

Java:

String sdkKey = System.getenv("LAUNCHDARKLY_SDK_KEY");

Container/K8s ConfigMap

Share SDK keys via Kubernetes ConfigMap:

# k8s/launchdarkly-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: launchdarkly-config
data:
  project-key: "my-app"
  environment: "production"

---
apiVersion: v1
kind: Secret
metadata:
  name: launchdarkly-secrets
type: Opaque
stringData:
  sdk-key: "sdk-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Mount in all services:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-a
spec:
  template:
    spec:
      containers:
      - name: app
        env:
        - name: LAUNCHDARKLY_SDK_KEY
          valueFrom:
            secretKeyRef:
              name: launchdarkly-secrets
              key: sdk-key
        - name: LAUNCHDARKLY_PROJECT_KEY
          valueFrom:
            configMapKeyRef:
              name: launchdarkly-config
              key: project-key

Service Mesh Integration

For service mesh (Istio, Linkerd), use a sidecar pattern:

# Sidecar that manages LaunchDarkly SDK keys
apiVersion: v1
kind: Pod
metadata:
  name: my-service
spec:
  containers:
  # Main application
  - name: app
    image: my-service:latest
    env:
    - name: LAUNCHDARKLY_SDK_KEY
      value: /var/run/secrets/launchdarkly/sdk-key
    volumeMounts:
    - name: ld-keys
      mountPath: /var/run/secrets/launchdarkly
  
  # Sidecar that fetches/refreshes keys
  - name: ld-key-sync
    image: ld-key-sync:latest
    env:
    - name: LAUNCHDARKLY_API_TOKEN
      valueFrom:
        secretKeyRef:
          name: ld-api-token
          key: token
    - name: PROJECT_KEY
      value: my-service
    volumeMounts:
    - name: ld-keys
      mountPath: /var/run/secrets/launchdarkly
  
  volumes:
  - name: ld-keys
    emptyDir: {}

Best Practices

1. Naming Conventions

Project Key Format: {service-name}-{optional-suffix}

Examples:
  - api-gateway
  - user-service
  - recommendation-engine

2. Tagging Strategy

tags = [
    "language:python",      # or nodejs, go, etc.
    "team:platform",        # owning team
    "environment:prod",     # deployment env
    "type:service"          # or frontend, worker, etc.
]

3. Documentation

Maintain a service registry:

# Service Registry

| Service | Language | Project Key | Team | Status |
|---------|----------|-------------|------|--------|
| API Gateway | Node.js | api-gateway | Platform | Active |
| User Service | Go | user-service | Identity | Active |
| ML Engine | Python | ml-engine | Data Science | Active |

4. Automation

Automate project creation for new services:

# scripts/new-service.sh
#!/bin/bash
SERVICE_NAME=$1
LANGUAGE=$2

# Create project
python scripts/create_project.py \
    --name "$SERVICE_NAME Service" \
    --key "$SERVICE_NAME" \
    --tags "language:$LANGUAGE,type:service"

# Generate template
cp -r "templates/$LANGUAGE" "services/$SERVICE_NAME"

# Setup SDK key
cd "services/$SERVICE_NAME"
bash setup.sh

echo "✓ New service $SERVICE_NAME created"

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.