Claude-code-plugins intercom-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/intercom-pack/skills/intercom-multi-env-setup" ~/.claude/skills/jeremylongshore-claude-code-plugins-intercom-multi-env-setup && rm -rf "$T"
manifest:
plugins/saas-packs/intercom-pack/skills/intercom-multi-env-setup/SKILL.mdsource content
Intercom Multi-Environment Setup
Overview
Configure separate Intercom workspaces for development, staging, and production with environment-specific access tokens, webhook URLs, and safety guards.
Prerequisites
- Separate Intercom workspaces (or at minimum, separate apps in Developer Hub)
- Secret management solution (Vault, AWS Secrets Manager, GCP Secret Manager)
- CI/CD pipeline with environment variable support
Environment Strategy
| Environment | Workspace | Token Type | Data | Webhooks |
|---|---|---|---|---|
| Development | Dev/sandbox workspace | Dev access token | Test data | localhost via ngrok |
| Staging | Staging workspace | Staging token | Seed data | staging.example.com |
| Production | Production workspace | Production token | Real data | api.example.com |
Instructions
Step 1: Environment Configuration
// src/config/intercom.ts interface IntercomEnvironmentConfig { accessToken: string; webhookSecret: string; identitySecret: string; environment: "development" | "staging" | "production"; baseUrl: string; debug: boolean; cache: { enabled: boolean; ttlSeconds: number }; rateLimit: { maxConcurrency: number }; } function loadConfig(): IntercomEnvironmentConfig { const env = (process.env.NODE_ENV || "development") as IntercomEnvironmentConfig["environment"]; const shared = { accessToken: process.env.INTERCOM_ACCESS_TOKEN!, webhookSecret: process.env.INTERCOM_WEBHOOK_SECRET!, identitySecret: process.env.INTERCOM_IDENTITY_SECRET || "", environment: env, baseUrl: "https://api.intercom.io", }; const envDefaults: Record<string, Partial<IntercomEnvironmentConfig>> = { development: { debug: true, cache: { enabled: false, ttlSeconds: 0 }, rateLimit: { maxConcurrency: 2 }, }, staging: { debug: false, cache: { enabled: true, ttlSeconds: 60 }, rateLimit: { maxConcurrency: 5 }, }, production: { debug: false, cache: { enabled: true, ttlSeconds: 300 }, rateLimit: { maxConcurrency: 10 }, }, }; return { ...shared, ...envDefaults[env] } as IntercomEnvironmentConfig; } export const intercomConfig = loadConfig();
Step 2: Environment-Aware Client Factory
// src/intercom/client.ts import { IntercomClient } from "intercom-client"; import { intercomConfig } from "../config/intercom"; let client: IntercomClient | null = null; export function getClient(): IntercomClient { if (!client) { if (!intercomConfig.accessToken) { throw new Error( `INTERCOM_ACCESS_TOKEN not set for ${intercomConfig.environment}. ` + `Create a .env.${intercomConfig.environment} file.` ); } client = new IntercomClient({ token: intercomConfig.accessToken, }); if (intercomConfig.debug) { console.log(`[Intercom] Connected to ${intercomConfig.environment} workspace`); } } return client; }
Step 3: Secret Management by Platform
# Local development (.env.development - git-ignored) INTERCOM_ACCESS_TOKEN=dG9rOmRldl90b2tlbg== INTERCOM_WEBHOOK_SECRET=dev-webhook-secret NODE_ENV=development # GitHub Actions (for CI) gh secret set INTERCOM_DEV_TOKEN --body "dev-token" gh secret set INTERCOM_STAGING_TOKEN --body "staging-token" gh secret set INTERCOM_PROD_TOKEN --body "prod-token" # AWS Secrets Manager aws secretsmanager create-secret \ --name intercom/production/access-token \ --secret-string "prod-token" # GCP Secret Manager echo -n "prod-token" | gcloud secrets create intercom-prod-token --data-file=- # HashiCorp Vault vault kv put secret/intercom/production \ access_token="prod-token" \ webhook_secret="prod-webhook-secret"
Step 4: Production Safety Guards
// Prevent destructive operations in wrong environment class EnvironmentGuard { constructor(private env: string) {} requireProduction(operation: string): void { if (this.env !== "production") { throw new Error( `${operation} is only allowed in production (current: ${this.env})` ); } } preventProduction(operation: string): void { if (this.env === "production") { throw new Error( `${operation} is blocked in production for safety` ); } } } const guard = new EnvironmentGuard(intercomConfig.environment); // Usage async function deleteAllTestContacts() { guard.preventProduction("deleteAllTestContacts"); // Blocks in prod const contacts = await client.contacts.search({ query: { field: "custom_attributes.is_test", operator: "=", value: true }, }); for (const contact of contacts.data) { await client.contacts.delete({ contactId: contact.id }); } } async function sendBulkMessages(contactIds: string[], message: string) { guard.requireProduction("sendBulkMessages"); // Only works in prod // ... send messages }
Step 5: Webhook URL per Environment
// CI/CD: Set webhook URL based on environment const webhookUrls: Record<string, string> = { development: "https://dev-abc123.ngrok.io/webhooks/intercom", staging: "https://staging.example.com/webhooks/intercom", production: "https://api.example.com/webhooks/intercom", }; // In your webhook handler, log the environment for debugging app.post("/webhooks/intercom", (req, res) => { console.log(`[${intercomConfig.environment}] Webhook received: ${req.body.topic}`); // ... process webhook });
Step 6: Environment Validation on Startup
async function validateIntercomSetup(): Promise<void> { const client = getClient(); const config = intercomConfig; console.log(`[Intercom] Validating ${config.environment} setup...`); try { const admins = await client.admins.list(); const appName = admins.admins[0]?.name || "Unknown"; console.log(`[Intercom] Connected to workspace (admin: ${appName})`); // Verify we're in the right workspace if (config.environment === "production") { // In production, verify the token has expected permissions try { await client.contacts.list({ perPage: 1 }); console.log("[Intercom] Contact access: OK"); } catch { console.error("[Intercom] WARNING: Cannot access contacts"); } } } catch (err) { console.error(`[Intercom] Setup validation FAILED for ${config.environment}:`, err); if (config.environment === "production") { throw err; // Fail fast in production } } } // Call during application startup validateIntercomSetup().catch(console.error);
GitHub Actions Environment Matrix
jobs: test: strategy: matrix: environment: [development, staging] runs-on: ubuntu-latest env: NODE_ENV: ${{ matrix.environment }} INTERCOM_ACCESS_TOKEN: ${{ secrets[format('INTERCOM_{0}_TOKEN', matrix.environment)] }} steps: - uses: actions/checkout@v4 - run: npm ci - run: npm test
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Wrong workspace | Dev token used in staging | Validate workspace on startup |
| Token not found | Missing env file | Copy to |
| Guard blocked operation | Environment mismatch | Verify is correct |
| Webhook URL mismatch | Forgot to update URL | Use env-based URL config |
Resources
Next Steps
For observability setup, see
intercom-observability.