TL;DR
- A skill is a
SKILL.mdfile that Claude Code loads when it is relevant or when you type/skill-name. For an admin, three cover most of the week: audit, enrich, size. - It takes about 30 minutes. Testing on a sandbox spends about 3 of your 1,000 free LeadOcean records. The audit and the count cost nothing.
- Claude Code drafts the query and the update. You read the diff and approve the write. Run all of it in a sandbox first.
Admins already know what they want: find the gaps, fix them, prove the fix. A skill packs that routine into a file the whole team can run. Claude Code skills follow the open Agent Skills standard (Claude Code docs, September 2026), so the same files travel between tools.
The design rule for all three is the same. Reads are automatic, writes are manual. A skill that audits can run any time. A skill that updates a Lead or spends a record waits for you.
Prerequisites
- Claude Code installed, and the Salesforce CLI (
sf) authenticated to a sandbox with the aliassandbox. - A free LeadOcean key from app.leadocean.io, exported as
$LEADOCEAN_API_KEY. - A project folder under git, so skills in
.claude/skills/are shared with the team. Claude Code docs list project skills at.claude/skills/<skill-name>/SKILL.md(checked September 2026). - Admin rights to edit Lead fields in the sandbox.
Step 1: Create a read-only audit skill
Start with the skill that cannot break anything. It runs a SOQL query through sf data query, which the Salesforce CLI reference describes as executing a SOQL query (September 2026).
mkdir -p .claude/skills/lead-audit---
description: Audits Salesforce Leads for missing data. Use when the user asks which Leads lack email, title or company, or wants a data quality report.
allowed-tools: Bash(sf data query *)
---
Run this query against the sandbox and report counts by gap:
!`sf data query --target-org sandbox --json --query "SELECT Id, Email, Title, Company FROM Lead WHERE IsConverted = false AND (Email = null OR Title = null) LIMIT 200"`
Group the rows into: no email, no title, both missing. Show five Ids per group.
Do not update anything. Do not run any command except sf data query.The ! line is dynamic context injection: Claude Code runs the command and puts its output into the skill before Claude reads it (Claude Code docs, September 2026). The allowed-tools line pre-approves only the query command.
Step 2: Create the enrichment skill
This skill takes one Lead email, enriches it with LeadOcean and proposes a field update. POST /v1/people/enrich takes exactly one of linkedin_url, email, phone or person_id, and costs one record when it finds someone. A 404 costs nothing.
mkdir -p .claude/skills/lead-enrich---
description: Enriches one Salesforce Lead from LeadOcean by email and proposes a Title and Company update. Use when the user names a Lead to fill in.
disable-model-invocation: true
arguments: lead_id
---
1. Read the Lead:
sf data get record --target-org sandbox --sobject Lead --record-id $lead_id --json
2. Enrich by the Lead's Email (never send a name):
curl -s -X POST https://api.leadocean.io/v1/people/enrich \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "Content-Type: application/json" \
-d '{"email": "<Email from step 1>"}'
3. If the answer is 404, stop and say nobody matched. It cost nothing.
4. Show a before and after table for Title and Company. Ask me to confirm.
5. Only after I say yes, run:
sf data update record --target-org sandbox --sobject Lead --record-id $lead_id --values "Title='<new>' Company='<new>'"disable-model-invocation: true means only you can start it, with /lead-enrich 00Q000000000001. Claude Code docs say this flag stops Claude from loading the skill on its own (September 2026). A skill that spends records and writes data should be manual.
Step 3: Create the free sizing skill
Before you ask for a bulk enrichment, size the audience. The leadocean_count_leads MCP tool is free, so this skill costs no records.
claude mcp add --transport http leadocean https://api.leadocean.io/mcp
mkdir -p .claude/skills/list-size---
description: Sizes a prospect list with LeadOcean before any records are spent. Use when the user asks how many people match a title, country or industry.
---
Call the leadocean_count_leads tool with the filters the user gave. Pass facets=false.
Report: total, totalAll, distinctCompanies.
Say that total counts mailable addresses only (verified, catch_all_valid, catch_all).
Check enum filter values first with leadocean_list_enum_values.
Never call search or get_lead from this skill.The MCP server uses OAuth sign-in, so no key is pasted. Run /mcp in Claude Code to approve it (see the Salesforce MCP setup guide).
Step 4: Run the skills
Open Claude Code in the project and type the commands. Skills load from the folder without any build step.
> /lead-audit
> /lead-enrich 00Q000000000001
> /list-size US Salesforce AdministratorsFor batch work beyond one Lead, move to the larger patterns in the workflow automation guide. If you need Apex instead of the CLI, see Claude Code for Salesforce Apex development.
Guardrails worth keeping
Three habits keep admin skills safe. They matter more than the prompt wording.
- Sandbox alias only. Hard-code
--target-org sandboxin the skill, so production needs a deliberate edit and a code review. - One Lead per run for writes. Batch updates belong in a reviewed Bulk API job, not a chat. The Salesforce CLI has
data update bulkfor that (CLI reference, September 2026). - Log what changed. Ask the skill to print the before and after values, so you can paste them into a change ticket.
What you get
The sizing skill returned this on 21 October 2026 (leadocean_count_leads, title "Salesforce Administrator", country US, facets off). It spent 0 records.
{
"total": 4640,
"totalIsExact": true,
"totalAll": 13548,
"distinctCompanies": 3106,
"credits": 0
}total is mailable addresses only (verified, catch_all_valid or catch_all). totalAll is the same filter with no email condition.
The enrichment call returns this shape (response shape from the API reference, placeholder values).
{
"success": true,
"data": {
"profile_data": { "profile_full_name": "Jane Doe" },
"contact_data": {
"has_email": true,
"email_status": "verified",
"contact_current_experiences": [{ "job_title": "Head of RevOps", "company_name": "Acme" }]
},
"resume_data": { "experiences": [] }
},
"meta": { "credits": 1 }
}Since 17 October 2026 the same call also returns career history in resume_data: past roles, education and certifications, each when held. Past employers carry no company_id yet, so do not use them to match Salesforce Accounts.
Where each skill fits
Use /lead-audit first, every time. It tells you how big the gap is, and it costs nothing. If 40 of 200 sampled Leads have no title, enrichment is worth a test. If 2 do, fix the form instead.
Use /list-size before any bulk idea. Sizing is free, so ask as often as you like. The count describes mailable addresses by default, so report it as that and not as everyone who matches.
Use /lead-enrich last, and one Lead at a time until you trust the match. Compare the returned company with the Lead's Company field. If they differ, the person may have changed jobs, and a human should decide which record is right.
Tuning the skills
Keep each description specific. Claude decides when to load a skill from that line, so "audits Leads for missing data" works better than "Salesforce helper". Put the exact command in the file rather than describing it, which stops Claude from inventing flags.
Add a LIMIT to every SOQL query. A skill that selects every Lead in a large org will run slowly and flood the context. Pull a sample of 200, fix the pattern, then ask for the next 200.
When a skill grows past a page, split it. Claude Code loads a skill body only when it is used, so long reference material in a separate file costs little until needed (Claude Code docs, September 2026).
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key | Check echo $LEADOCEAN_API_KEY in the same shell Claude Code runs in. |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Enrich one Lead at a time, or wait for the Retry-After seconds. |
| 402 | The 1,000 free records are spent | Check GET /v1/account, then see pricing. |
| 404 on enrich | Nobody matched that email | Costs nothing. Try linkedin_url instead. |
| Count returns 0 | A filter value is not an exact enum string, such as vp for jobLevel | Run leadocean_list_enum_values for the filter and copy the value. |
Skill not in the / menu | Skill sits in a subfolder below where you started Claude Code | Start Claude Code at the repo root or run /add-dir. |
FAQ
Do skills replace a Salesforce flow?
No. A skill is a prompt that Claude runs with your approval. A flow runs unattended inside Salesforce. Use skills for admin investigation and one-off fixes, flows for anything that must run on every record.
Is it safe to let Claude Code write to Salesforce?
Only with limits. Keep allowed-tools narrow, keep write steps behind a confirmation, set disable-model-invocation: true on them and run against a sandbox first. Claude Code drafts, you approve.
How many records does enrichment spend?
One per person found. An enrichment that finds nothing is free, and so is a count. On the Free plan you have 1,000 records, once. Solo is $97 a month and Agency is $497 a month, both with a fair-use pace instead of credits.
Can I share these skills with my team?
Yes. Commit .claude/skills/ to the repo. Teammates get them the next time they open Claude Code in that project. Personal skills in ~/.claude/skills/ stay on one machine.
Give your Salesforce skills a data source
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →