Agent skill

salesforce-local-dev-loop

Configure Salesforce local development with scratch orgs, SFDX, and testing. Use when setting up a development environment, configuring test workflows, or establishing a fast iteration cycle with Salesforce. Trigger with phrases like "salesforce dev setup", "salesforce local development", "salesforce scratch org", "sfdx project", "develop with salesforce".

Stars 1,803
Forks 241

Install this agent skill to your Project

npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/main/plugins/saas-packs/salesforce-pack/skills/salesforce-local-dev-loop

SKILL.md

Salesforce Local Dev Loop

Overview

Set up a fast, reproducible local development workflow using Salesforce CLI (sf), scratch orgs, and jsforce with hot reload.

Prerequisites

  • Completed salesforce-install-auth setup
  • Salesforce CLI installed (npm install -g @salesforce/cli)
  • Dev Hub enabled in your production org (Setup > Dev Hub)
  • Node.js 18+ with npm/pnpm

Instructions

Step 1: Create SFDX Project Structure

bash
# Initialize a new SFDX project
sf project generate --name my-sf-project --template standard

# Project structure created:
# my-sf-project/
# ├── config/
# │   └── project-scratch-def.json   # Scratch org definition
# ├── force-app/
# │   └── main/default/              # Metadata source (Apex, LWC, etc.)
# ├── scripts/
# │   └── apex/                      # Anonymous Apex scripts
# ├── sfdx-project.json              # Project config
# └── .sf/                           # Local CLI state

Step 2: Create a Scratch Org

bash
# Authenticate to your Dev Hub first
sf org login web --set-default-dev-hub --alias DevHub

# Create a scratch org (expires in 7 days by default)
sf org create scratch \
  --definition-file config/project-scratch-def.json \
  --alias my-scratch \
  --duration-days 7 \
  --set-default

# Open scratch org in browser
sf org open --target-org my-scratch

Step 3: Configure scratch-def for development

json
{
  "orgName": "My Dev Org",
  "edition": "Developer",
  "features": ["EnableSetPasswordInApi", "MultiCurrency"],
  "settings": {
    "lightningExperienceSettings": {
      "enableS1DesktopEnabled": true
    },
    "securitySettings": {
      "passwordPolicies": {
        "enableSetPasswordInApi": true
      }
    }
  }
}

Step 4: Node.js Integration Dev Loop

my-integration/
├── src/
│   ├── salesforce/
│   │   ├── connection.ts     # jsforce connection wrapper
│   │   ├── accounts.ts       # Account operations
│   │   ├── contacts.ts       # Contact operations
│   │   └── queries.ts        # SOQL query builders
│   └── index.ts
├── tests/
│   ├── unit/
│   │   └── queries.test.ts   # Mock-based tests
│   └── integration/
│       └── accounts.test.ts  # Live org tests
├── .env.local                # Local secrets (git-ignored)
├── .env.example              # Template for team
└── package.json

Step 5: Configure Hot Reload

json
{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:integration": "SF_ENV=scratch vitest run tests/integration/",
    "push": "sf project deploy start --target-org my-scratch",
    "pull": "sf project retrieve start --target-org my-scratch"
  }
}

Step 6: Configure Testing with Mocked Connections

typescript
import { describe, it, expect, vi } from 'vitest';

// Mock jsforce for unit tests — no live org needed
vi.mock('jsforce', () => ({
  default: {
    Connection: vi.fn().mockImplementation(() => ({
      login: vi.fn().mockResolvedValue({ id: '005xx', organizationId: '00Dxx' }),
      query: vi.fn().mockResolvedValue({
        totalSize: 1,
        done: true,
        records: [{ Id: '001xx', Name: 'Test Account', Industry: 'Tech' }],
      }),
      sobject: vi.fn().mockReturnValue({
        create: vi.fn().mockResolvedValue({ id: '001xx', success: true }),
        update: vi.fn().mockResolvedValue({ id: '001xx', success: true }),
        destroy: vi.fn().mockResolvedValue({ id: '001xx', success: true }),
      }),
    })),
  },
}));

describe('Account Service', () => {
  it('should query accounts with SOQL', async () => {
    const conn = new (await import('jsforce')).default.Connection({});
    const result = await conn.query("SELECT Id, Name FROM Account LIMIT 5");
    expect(result.totalSize).toBe(1);
    expect(result.records[0].Name).toBe('Test Account');
  });
});

Output

  • SFDX project with scratch org configured
  • Hot reload development server running
  • Unit tests with mocked jsforce connections
  • Integration tests against scratch org
  • Fast iteration cycle: edit, auto-reload, test

Error Handling

Error Cause Solution
ERROR: No default dev hub Dev Hub not set Run sf org login web --set-default-dev-hub
INVALID_OPERATION: scratch org limit Hit scratch org limit (6 active) Delete old orgs: sf org delete scratch --target-org old-alias
SourceConflictError Local/remote metadata conflicts Run sf project retrieve start to sync
MODULE_NOT_FOUND: jsforce Not installed Run npm install jsforce
sf: command not found CLI not installed Run npm install -g @salesforce/cli

Resources

Next Steps

See salesforce-sdk-patterns for production-ready code patterns.

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results