Agent Skills: Salesforce Local Dev Loop

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/salesforce-local-dev-loop

Install this agent skill to your local

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

Skill Files

Browse the full folder contents for salesforce-local-dev-loop.

Download Skill

Loading file tree…

plugins/saas-packs/salesforce-pack/skills/salesforce-local-dev-loop/SKILL.md

Skill Metadata

Name
salesforce-local-dev-loop
Description
|

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

# 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

# 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

{
  "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

{
  "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

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.