Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure Gamma across development, staging, and production environments. Use when setting up multi-environment deployments, configuring per-environment secrets, or implementing environment-specific Gamma configurations. Trigger with phrases like "gamma environments", "gamma staging", "gamma dev prod", "gamma environment setup", "gamma config by env".
.claude/skills/jeremylongshore-gamma-multi-env-setup/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -8% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 106% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 28% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 89% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 77% | 0% |
Configure Gamma API access across development, staging, and production environments. Since Gamma is a SaaS API with no self-hosted option, environment separation is achieved through separate workspaces (API keys), mock servers for development, and environment-aware client configuration.
gamma-install-auth setup┌─────────────────────────────────────────────────────────┐
│ Development │
│ API: localhost:9876 (mock server) or Gamma API │
│ Key: GAMMA_API_KEY=gma_dev_xxx │
│ Mock: enabled (no credits consumed) │
├─────────────────────────────────────────────────────────┤
│ Staging │
│ API: public-api.gamma.app (separate workspace) │
│ Key: GAMMA_API_KEY=gma_stg_xxx │
│ Mock: disabled │
├─────────────────────────────────────────────────────────┤
│ Production │
│ API: public-api.gamma.app (production workspace) │
│ Key: GAMMA_API_KEY=gma_prod_xxx (from secret manager) │
│ Mock: disabled │
└─────────────────────────────────────────────────────────┘typescript// src/config/gamma.ts interface GammaEnvConfig { apiKey: string; baseUrl: string; useMock: boolean; timeoutMs: number; maxRetries: number; } function getGammaConfig(): GammaEnvConfig { const env = process.env.NODE_ENV ?? "development"; const configs: Record<string, Partial<GammaEnvConfig>> = { development: { baseUrl: process.env.GAMMA_MOCK === "true" ? "http://localhost:9876/v1.0" : "https://public-api.gamma.app/v1.0", useMock: process.env.GAMMA_MOCK === "true", timeoutMs: 60000, maxRetries: 1, }, staging: { baseUrl: "https://public-api.gamma.app/v1.0", useMock: false, timeoutMs: 30000, maxRetries: 3, }, production: { baseUrl: "https://public-api.gamma.app/v1.0", useMock: false, timeoutMs: 30000, maxRetries: 5, }, }; const apiKey = process.env.GAMMA_API_KEY; if (!apiKey && !configs[env]?.useMock) { throw new Error(`GAMMA_API_KEY required for ${env} environment`); } return { apiKey: apiKey ?? "mock-key", ...configs[env], } as GammaEnvConfig; } export const gammaConfig = getGammaConfig();
typescript// src/gamma/factory.ts import { createGammaClient } from "./client"; import { gammaConfig } from "../config/gamma"; let client: ReturnType<typeof createGammaClient> | null = null; export function getGammaClient() { if (!client) { client = createGammaClient({ apiKey: gammaConfig.apiKey, baseUrl: gammaConfig.baseUrl, timeoutMs: gammaConfig.timeoutMs, }); } return client; } // Reset for testing export function resetGammaClient() { client = null; }
bash# .env.development GAMMA_API_KEY=gma_dev_xxxxxxxxxxxx GAMMA_MOCK=false NODE_ENV=development LOG_LEVEL=debug # .env.test GAMMA_MOCK=true NODE_ENV=test LOG_LEVEL=warn # .env.staging GAMMA_API_KEY=gma_stg_xxxxxxxxxxxx NODE_ENV=staging LOG_LEVEL=info # .env.production (use secret manager instead) # GAMMA_API_KEY loaded from AWS Secrets Manager / Vault NODE_ENV=production LOG_LEVEL=warn
typescript// src/config/secrets.ts // For production, fetch API key from secret manager at startup import { SecretsManager } from "@aws-sdk/client-secrets-manager"; let cachedKey: string | null = null; let cacheExpiry = 0; async function getProductionApiKey(): Promise<string> { if (cachedKey && Date.now() < cacheExpiry) return cachedKey; const sm = new SecretsManager({ region: "us-east-1" }); const secret = await sm.getSecretValue({ SecretId: "gamma/api-key" }); cachedKey = JSON.parse(secret.SecretString!).apiKey; cacheExpiry = Date.now() + 300000; // Cache for 5 minutes return cachedKey!; }
typescript// src/guards.ts function blockProduction(operation: string) { if (process.env.NODE_ENV === "production") { throw new Error(`${operation} is blocked in production`); } } // Block destructive operations in production async function deleteAllGenerations() { blockProduction("deleteAllGenerations"); // ... cleanup logic for dev/staging } // Warn about credit-consuming operations in non-production function warnCredits(env: string) { if (env !== "production" && !gammaConfig.useMock) { console.warn("WARNING: Using live Gamma API — credits will be consumed"); } }
yaml# .github/workflows/gamma.yml jobs: test: runs-on: ubuntu-latest env: GAMMA_MOCK: 'true' NODE_ENV: test steps: - uses: actions/checkout@v4 - run: npm ci && npm test # Uses mock server — no API key needed, no credits consumed staging: runs-on: ubuntu-latest if: github.ref == 'refs/heads/develop' env: GAMMA_API_KEY: ${{ secrets.GAMMA_STAGING_API_KEY }} NODE_ENV: staging steps: - uses: actions/checkout@v4 - run: npm ci && npm run test:integration production: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' env: GAMMA_API_KEY: ${{ secrets.GAMMA_PRODUCTION_API_KEY }} NODE_ENV: production steps: - uses: actions/checkout@v4 - run: npm ci && npm run deploy
| Check | Dev | Test | Staging | Production | |-------|-----|------|---------|------------| | API key source | .env file | Not needed (mock) | GitHub Secret | Secret Manager | | Mock mode | Optional | Yes | No | No | | Debug logging | On | On | On | Off | | Credit consumption | Optional | None | Real (staging workspace) | Real | | Secret manager | No | No | Optional | Required |
| Issue | Cause | Solution | |-------|-------|----------| | Wrong API key for env | Env var mismatch | Verify NODE_ENV and matching key | | Credits consumed in dev | Mock mode off | Set GAMMA_MOCK=true in development | | Secret fetch fails | IAM permissions | Check secret manager access policy | | Production data in dev | No env guard | Add blockProduction() guards |
Proceed to gamma-observability for monitoring setup.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 23,255 | 17,581 | -24% | 1 | 1 | 0% | 5,174 | 4,773 | -8% | 0 | 0 | — |
case-02 | fail→fail | 23,379 | 19,083 | -18% | 1 | 1 | 0% | 3,735 | 4,652 | +25% | 0 | 0 | — |
case-03 | fail→fail | 21,372 | 15,442 | -28% | 1 | 1 | 0% | 4,263 | 4,830 | +13% | 0 | 0 | — |
case-04 | fail→pass | 9,831 | 13,232 | +35% | 1 | 1 | 0% | 1,613 | 3,322 | +106% | 0 | 0 | — |
case-05 | pass→pass | 23,554 | 19,749 | -16% | 1 | 1 | 0% | 3,767 | 5,892 | +56% | 0 | 0 | — |
case-06 | pass→pass | 12,334 | 13,908 | +13% | 1 | 1 | 0% | 1,962 | 3,668 | +87% | 0 | 0 | — |
case-07 | fail→pass | 16,834 | 9,057 | -46% | 1 | 1 | 0% | 2,149 | 2,759 | +28% | 0 | 0 | — |
case-08 | fail→pass | 8,307 | 8,005 | -4% | 1 | 1 | 0% | 1,362 | 2,570 | +89% | 0 | 0 | — |
case-09 | fail→pass | 16,734 | 16,032 | -4% | 1 | 1 | 0% | 2,096 | 3,715 | +77% | 0 | 0 | — |
case-10 | pass→pass | 13,937 | 17,636 | +27% | 1 | 1 | 0% | 2,620 | 4,400 | +68% | 0 | 0 | — |
case-11 | fail→pass | 11,727 | 10,616 | -9% | 1 | 1 | 0% | 2,248 | 3,056 | +36% | 0 | 0 | — |
case-12 | fail→pass | 15,159 | 11,648 | -23% | 1 | 1 | 0% | 2,591 | 3,079 | +19% | 0 | 0 | — |
case-13 | fail→pass | 16,826 | 15,233 | -9% | 1 | 1 | 0% | 2,463 | 4,163 | +69% | 0 | 0 | — |
case-14 | fail→pass | 10,569 | 2,670 | -75% | 1 | 1 | 0% | 921 | 2,409 | +162% | 0 | 0 | — |
case-15 | fail→fail | 15,005 | 15,019 | +0% | 1 | 1 | 0% | 2,904 | 4,111 | +42% | 0 | 0 | — |
case-16 | fail→fail | 17,931 | 10,364 | -42% | 1 | 1 | 0% | 2,558 | 4,289 | +68% | 0 | 0 | — |
case-17 | fail→pass | 8,399 | 2,167 | -74% | 1 | 1 | 0% | 1,693 | 2,438 | +44% | 0 | 0 | — |
case-18 | fail→pass | 10,383 | 4,929 | -53% | 1 | 1 | 0% | 2,134 | 2,985 | +40% | 0 | 0 | — |
case-19 | fail→pass | 14,375 | 8,400 | -42% | 1 | 1 | 0% | 2,063 | 2,622 | +27% | 0 | 0 | — |
case-20 | fail→pass | 21,526 | 5,090 | -76% | 1 | 1 | 0% | 3,052 | 2,826 | -7% | 0 | 0 | — |
case-21 | fail→pass | 16,312 | 4,650 | -71% | 1 | 1 | 0% | 2,064 | 2,974 | +44% | 0 | 0 | — |
case-22 | pass→fail | 14,238 | 7,441 | -48% | 1 | 1 | 0% | 2,373 | 3,581 | +51% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +59 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.