Claude-code-plugins-plus maintainx-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/maintainx-pack/skills/maintainx-multi-env-setup" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-maintainx-multi-env-setup && rm -rf "$T"
manifest:
plugins/saas-packs/maintainx-pack/skills/maintainx-multi-env-setup/SKILL.mdsource content
MaintainX Multi-Environment Setup
Overview
Configure and manage multiple MaintainX environments for development, staging, and production with proper secret management and client isolation.
Prerequisites
- Separate MaintainX accounts or organizations for each environment
- Secret management solution (environment variables, GCP Secret Manager, or AWS SSM)
- Node.js 18+
Instructions
Step 1: Environment Configuration
// src/config/environments.ts interface MaintainXEnvConfig { apiKey: string; orgId?: string; baseUrl: string; label: string; rateLimit: { requestsPerSecond: number }; } type Environment = 'development' | 'staging' | 'production'; function getConfig(env: Environment): MaintainXEnvConfig { const configs: Record<Environment, () => MaintainXEnvConfig> = { development: () => ({ apiKey: process.env.MAINTAINX_API_KEY_DEV!, orgId: process.env.MAINTAINX_ORG_ID_DEV, baseUrl: 'https://api.getmaintainx.com/v1', label: 'Development', rateLimit: { requestsPerSecond: 5 }, }), staging: () => ({ apiKey: process.env.MAINTAINX_API_KEY_STAGING!, orgId: process.env.MAINTAINX_ORG_ID_STAGING, baseUrl: 'https://api.getmaintainx.com/v1', label: 'Staging', rateLimit: { requestsPerSecond: 10 }, }), production: () => ({ apiKey: process.env.MAINTAINX_API_KEY_PROD!, orgId: process.env.MAINTAINX_ORG_ID_PROD, baseUrl: 'https://api.getmaintainx.com/v1', label: 'Production', rateLimit: { requestsPerSecond: 20 }, }), }; const config = configs[env](); if (!config.apiKey) { throw new Error(`Missing API key for ${env} environment`); } return config; } export const currentEnv = (process.env.MAINTAINX_ENV || 'development') as Environment; export const config = getConfig(currentEnv);
Step 2: Client Factory
// src/client-factory.ts import { MaintainXClient } from './client'; const clients = new Map<string, MaintainXClient>(); export function getClient(env?: Environment): MaintainXClient { const targetEnv = env || currentEnv; if (!clients.has(targetEnv)) { const cfg = getConfig(targetEnv); clients.set(targetEnv, new MaintainXClient(cfg.apiKey, cfg.orgId)); } return clients.get(targetEnv)!; } // Usage const devClient = getClient('development'); const prodClient = getClient('production');
Step 3: Environment Files
# .env.development MAINTAINX_ENV=development MAINTAINX_API_KEY_DEV=dev-key-here MAINTAINX_ORG_ID_DEV=org-dev-123 # .env.staging MAINTAINX_ENV=staging MAINTAINX_API_KEY_STAGING=staging-key-here MAINTAINX_ORG_ID_STAGING=org-staging-456 # .env.production MAINTAINX_ENV=production MAINTAINX_API_KEY_PROD=prod-key-here MAINTAINX_ORG_ID_PROD=org-prod-789
# .gitignore — never commit real keys .env .env.development .env.staging .env.production
Step 4: GCP Secret Manager Integration
// src/config/secrets.ts import { SecretManagerServiceClient } from '@google-cloud/secret-manager'; const secretClient = new SecretManagerServiceClient(); async function getSecret(name: string): Promise<string> { const [version] = await secretClient.accessSecretVersion({ name: `projects/your-project/secrets/${name}/versions/latest`, }); return version.payload!.data!.toString(); } async function loadProductionConfig(): Promise<MaintainXEnvConfig> { return { apiKey: await getSecret('maintainx-api-key-prod'), orgId: await getSecret('maintainx-org-id-prod'), baseUrl: 'https://api.getmaintainx.com/v1', label: 'Production', rateLimit: { requestsPerSecond: 20 }, }; }
Step 5: Validation Script
// scripts/validate-environments.ts import 'dotenv/config'; const envs: Environment[] = ['development', 'staging', 'production']; async function validateAll() { for (const env of envs) { try { const cfg = getConfig(env); const client = new MaintainXClient(cfg.apiKey, cfg.orgId); const { data } = await client.getUsers({ limit: 1 }); console.log(`${cfg.label}: OK (${data.users.length} user(s) found)`); } catch (err: any) { console.error(`${env}: FAILED - ${err.message}`); } } } validateAll();
# Run validation npx tsx scripts/validate-environments.ts # Development: OK (1 user(s) found) # Staging: OK (1 user(s) found) # Production: OK (1 user(s) found)
Output
- Environment-specific configuration with type-safe config loader
- Client factory producing isolated clients per environment
files with.env.*
protection.gitignore- GCP Secret Manager integration for production secrets
- Validation script to verify all environment credentials
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Missing API key | Environment variable not set | Check file for target environment |
| Wrong environment data | Using prod key in dev | Verify is set correctly |
| Secret Manager 403 | Missing IAM permissions | Grant role |
| Config mismatch after deploy | Old secrets cached | Clear client cache, reload secrets |
Resources
Next Steps
For observability setup, see
maintainx-observability.
Examples
GitHub Actions with per-environment secrets:
# .github/workflows/deploy.yml jobs: deploy: runs-on: ubuntu-latest environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} steps: - uses: actions/checkout@v4 - run: npm ci && npm run build - run: npm run validate-env env: MAINTAINX_ENV: ${{ vars.MAINTAINX_ENV }} MAINTAINX_API_KEY_PROD: ${{ secrets.MAINTAINX_API_KEY }}