Claude-code-plugins-plus perplexity-multi-env-setup
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/perplexity-pack/skills/perplexity-multi-env-setup" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-perplexity-multi-env-setup && rm -rf "$T"
manifest:
plugins/saas-packs/perplexity-pack/skills/perplexity-multi-env-setup/SKILL.mdsource content
Perplexity Multi-Environment Setup
Overview
Configure Perplexity Sonar API across dev/staging/prod. Key decisions per environment: which models are allowed (sonar vs sonar-pro), rate limits, and cost caps. All environments use the same base URL (
https://api.perplexity.ai) but different API keys with different budget limits.
Environment Strategy
| Environment | Model | Rate Limit | Key Source | Monthly Budget |
|---|---|---|---|---|
| Development | only | 5 RPM self-imposed | | $10 |
| Staging | only | 20 RPM | CI secrets | $50 |
| Production | + | 50 RPM | Secret manager | $500+ |
Prerequisites
- Separate Perplexity API keys per environment
package installedopenai- Secret management (env files for dev, vault/KMS for prod)
Instructions
Step 1: Configuration Structure
config/ perplexity/ base.ts # OpenAI client + base URL development.ts # Dev: sonar only, low limits staging.ts # Staging: sonar only, moderate limits production.ts # Prod: full model access index.ts # Environment resolver
Step 2: Base Configuration
// config/perplexity/base.ts import OpenAI from "openai"; export const PERPLEXITY_BASE_URL = "https://api.perplexity.ai"; export function createPerplexityClient(apiKey: string): OpenAI { if (!apiKey) throw new Error("Perplexity API key is required"); if (!apiKey.startsWith("pplx-")) throw new Error("Invalid Perplexity API key format"); return new OpenAI({ apiKey, baseURL: PERPLEXITY_BASE_URL }); }
Step 3: Environment Configs
// config/perplexity/development.ts export const devConfig = { apiKey: process.env.PERPLEXITY_API_KEY!, defaultModel: "sonar" as const, deepModel: "sonar" as const, // No sonar-pro in dev (cost) maxTokens: 512, maxConcurrentRequests: 1, cacheTTLMs: 24 * 3600_000, // Long cache in dev }; // config/perplexity/staging.ts export const stagingConfig = { apiKey: process.env.PERPLEXITY_API_KEY_STAGING!, defaultModel: "sonar" as const, deepModel: "sonar" as const, // Keep sonar in staging maxTokens: 1024, maxConcurrentRequests: 2, cacheTTLMs: 4 * 3600_000, }; // config/perplexity/production.ts export const productionConfig = { apiKey: process.env.PERPLEXITY_API_KEY_PROD!, defaultModel: "sonar" as const, // Fast queries use sonar deepModel: "sonar-pro" as const, // Research queries use sonar-pro maxTokens: 4096, maxConcurrentRequests: 10, cacheTTLMs: 1 * 3600_000, // Shorter cache in prod (freshness) };
Step 4: Environment Resolver
// config/perplexity/index.ts import { createPerplexityClient } from "./base"; import { devConfig } from "./development"; import { stagingConfig } from "./staging"; import { productionConfig } from "./production"; type SearchDepth = "quick" | "deep"; const configs = { development: devConfig, staging: stagingConfig, production: productionConfig, }; export function getConfig() { const env = process.env.NODE_ENV || "development"; const config = configs[env as keyof typeof configs]; if (!config) throw new Error(`Unknown environment: ${env}`); if (!config.apiKey) throw new Error(`PERPLEXITY_API_KEY not set for ${env}`); return config; } export function getClient() { return createPerplexityClient(getConfig().apiKey); } export function getModelForDepth(depth: SearchDepth): string { const cfg = getConfig(); return depth === "deep" ? cfg.deepModel : cfg.defaultModel; }
Step 5: Usage with Environment-Aware Search
// lib/search.ts import { getClient, getModelForDepth, getConfig } from "../config/perplexity"; export async function search(query: string, depth: "quick" | "deep" = "quick") { const client = getClient(); const model = getModelForDepth(depth); const config = getConfig(); const result = await client.chat.completions.create({ model, messages: [ { role: "system", content: "Provide accurate, well-sourced answers." }, { role: "user", content: query }, ], max_tokens: depth === "deep" ? config.maxTokens : Math.min(512, config.maxTokens), }); return { answer: result.choices[0].message.content, citations: (result as any).citations || [], model, environment: process.env.NODE_ENV, usage: result.usage, }; }
Step 6: Secret Manager Integration (Production)
set -euo pipefail # Google Cloud Secret Manager gcloud secrets create perplexity-api-key-prod \ --data-file=<(echo -n "$PERPLEXITY_API_KEY_PROD") # AWS Secrets Manager aws secretsmanager create-secret \ --name perplexity/api-key-prod \ --secret-string "$PERPLEXITY_API_KEY_PROD" # HashiCorp Vault vault kv put secret/perplexity api_key="$PERPLEXITY_API_KEY_PROD"
Error Handling
| Issue | Cause | Solution |
|---|---|---|
in staging | Wrong API key for environment | Verify |
in dev | Exceeding self-imposed limit | Add request queuing |
| sonar-pro in dev | Config not restricting models | Set in dev config |
| High dev costs | Using production config locally | Ensure is set |
Output
- Environment-specific Perplexity configurations
- Model routing by environment and query depth
- Secret manager integration for production keys
- Cost controls per environment
Resources
Next Steps
For deployment configuration, see
perplexity-deploy-integration.