Customer.io Local Dev Loop

VerifiedSafe

Set up a local development workflow for Customer.io integrations with proper testing and isolation.

Sby Skills Guide Bot
DevelopmentIntermediate
7/24/2026
Claude CodeCursorCodex
#customerio#local-development#dry-run#environment-config#test-mocks

Recommended for

Automated summary

Sets up an isolated local development workflow for Customer.io integrations, with per-environment credentials, a dry-run client wrapper, Vitest mocks, and npm scripts.

Strengths

  • Dry-run mode and `dev_` event prefixing keep local test data out of production analytics
  • Ships a directly reusable Vitest mock helper for `@customerio/track`
  • Explicitly separates `.env.development` and `.env.production` with US/EU region selection
  • Includes ready-made npm scripts for dry-run, live dev, and test runs

Limitations

  • Covers only the Track v2 client — no App API, campaigns, or webhook testing
  • The error-handling table in the SKILL.md is truncated mid-row
  • Assumes Node/TypeScript with dotenv; no guidance for Python or other SDKs
When to use it

Use it when bootstrapping or cleaning up a local dev environment for a Node/TypeScript app that sends events to Customer.io.

When not to use it

Skip it if you need to validate real Customer.io campaigns, segments, or delivery behavior, since it only isolates client-side calls.

Security analysis

Safe
Quality score88/100

The skill provides standard local-development setup guidance for Customer.io, including environment files, a dry-run client wrapper, mocks, and npm scripts. It uses placeholder API keys and recommends separate development workspaces and dry-run mode. There are no destructive commands, secret exfiltration, obfuscated payloads, or attempts to disable safety controls.

No concerns found

How this analysis is made

Examples

Set up local dev workflow
Set up a local development workflow for our Customer.io integration: separate dev/prod env vars, a dry-run client wrapper, and Vitest mocks so tests never hit the real API.
Add a dry-run script
Add a dry-run script that logs Customer.io identify and track calls instead of sending them, and wire it into package.json as dev:cio.
Mock track calls in tests
Mock @customerio/track in our Vitest suite so we can assert that identify is called with the right attributes when a user signs up.

name: customerio-local-dev-loop description: | Configure Customer.io local development workflow. Use when setting up local testing, development environment, or offline development for Customer.io integrations. Trigger with phrases like "customer.io local dev", "test customer.io locally", "customer.io development environment", "customer.io sandbox". allowed-tools: Read, Write, Edit, Bash(npm:), Bash(pip:), Grep version: 1.0.0 license: MIT author: Jeremy Longshore jeremy@intentsolutions.io

Customer.io Local Dev Loop

Overview

Set up an efficient local development workflow for Customer.io integrations with proper testing and isolation.

Prerequisites

  • Customer.io SDK installed
  • Separate development workspace in Customer.io (recommended)
  • Environment variable management tool (dotenv)

Instructions

Step 1: Create Environment Configuration

# .env.development
CUSTOMERIO_SITE_ID=dev-site-id
CUSTOMERIO_API_KEY=dev-api-key
CUSTOMERIO_REGION=us

# .env.production
CUSTOMERIO_SITE_ID=prod-site-id
CUSTOMERIO_API_KEY=prod-api-key
CUSTOMERIO_REGION=us

Step 2: Create Dev Client Wrapper

// lib/customerio.ts
import { TrackClient, RegionUS, RegionEU } from '@customerio/track';

const getRegion = () => {
  return process.env.CUSTOMERIO_REGION === 'eu' ? RegionEU : RegionUS;
};

const isDevelopment = process.env.NODE_ENV !== 'production';

class CustomerIOClient {
  private client: TrackClient;
  private dryRun: boolean;

  constructor() {
    this.client = new TrackClient(
      process.env.CUSTOMERIO_SITE_ID!,
      process.env.CUSTOMERIO_API_KEY!,
      { region: getRegion() }
    );
    this.dryRun = process.env.CUSTOMERIO_DRY_RUN === 'true';
  }

  async identify(userId: string, attributes: Record<string, any>) {
    if (this.dryRun) {
      console.log('[DRY RUN] Identify:', { userId, attributes });
      return;
    }
    if (isDevelopment) {
      attributes._dev = true;
      attributes._dev_timestamp = new Date().toISOString();
    }
    return this.client.identify(userId, attributes);
  }

  async track(userId: string, eventName: string, data?: Record<string, any>) {
    if (this.dryRun) {
      console.log('[DRY RUN] Track:', { userId, eventName, data });
      return;
    }
    const eventData = {
      name: isDevelopment ? `dev_${eventName}` : eventName,
      data: { ...data, _dev: isDevelopment }
    };
    return this.client.track(userId, eventData);
  }
}

export const cio = new CustomerIOClient();

Step 3: Set Up Test Helpers

// test/helpers/customerio-mock.ts
import { vi } from 'vitest';

export const mockCustomerIO = () => {
  const mocks = {
    identify: vi.fn().mockResolvedValue(undefined),
    track: vi.fn().mockResolvedValue(undefined),
    trackAnonymous: vi.fn().mockResolvedValue(undefined),
  };

  vi.mock('@customerio/track', () => ({
    TrackClient: vi.fn().mockImplementation(() => mocks),
    RegionUS: 'us',
    RegionEU: 'eu',
  }));

  return mocks;
};

// Usage in tests
import { mockCustomerIO } from './helpers/customerio-mock';

describe('User Registration', () => {
  const cioMocks = mockCustomerIO();

  it('identifies user on signup', async () => {
    await registerUser({ email: 'test@example.com' });
    expect(cioMocks.identify).toHaveBeenCalledWith(
      expect.any(String),
      expect.objectContaining({ email: 'test@example.com' })
    );
  });
});

Step 4: Create Dev Scripts

{
  "scripts": {
    "dev:cio": "CUSTOMERIO_DRY_RUN=true ts-node scripts/test-customerio.ts",
    "dev:cio:live": "dotenv -e .env.development ts-node scripts/test-customerio.ts",
    "test:cio": "vitest run --reporter=verbose tests/customerio/"
  }
}

Output

  • Environment-aware Customer.io client
  • Dry-run mode for safe testing
  • Test mocks for unit testing
  • Prefixed events for development isolation

Error Handling

| Error | Cause | Solution | |-------|-------|----------| | Wrong environment | Env vars not loaded | Use dotenv or env-specific files | | Dev events in prod | Environment check failed | Verify NODE_ENV is set correctly | | Mock not working | Import order issue | Mock before importing client |

Resources

Next Steps

After setting up local dev, proceed to customerio-sdk-patterns for production-ready patterns.

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/customer-io-local-dev-loop-mryiqhkf' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/customer-io-local-dev-loop-mryiqhkf/download' --output '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md.part' && mv '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md.part' '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

Tools declared by the author (check availability in your agent): Read, Write, Edit, Bash(npm:*), Bash(pip:*), Grep

Original excerpt: Prerequisites
  • Customer.io SDK installed
  • Separate development workspace in Customer.io (recommended)
  • Environment variable management tool (dotenv)

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.

Claude Code
test -f '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md' && test -s '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/customerio-local-dev-loop' && cp -R '.skill-downloads/customer-io-local-dev-loop-mryiqhkf' '.claude/skills/customerio-local-dev-loop'

Cursor
test -f '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md' && test -s '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/customerio-local-dev-loop' && cp -R '.skill-downloads/customer-io-local-dev-loop-mryiqhkf' '.cursor/skills/customerio-local-dev-loop'

Codex
test -f '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md' && test -s '.skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/customerio-local-dev-loop' && cp -R '.skill-downloads/customer-io-local-dev-loop-mryiqhkf' '.agents/skills/customerio-local-dev-loop'

OpenSkills

OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.

Official OpenSkills installation
openskills install './.skill-downloads/customer-io-local-dev-loop-mryiqhkf'

openskills read 'customer-io-local-dev-loop-mryiqhkf'

Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.

For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.

openskills sync

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/customer-io-local-dev-loop-mryiqhkf/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills