TL;DR: Use a Claude Code skill to write cold email, and use FirstSales to launch it, and keep those two jobs apart. The skill outputs a markdown brief and a sequence file, a person signs off on both, and only then do the CLI gates (campaigns readiness, campaigns send-test-email, campaigns start) put anything in front of a recipient.
#The angle: writing and launching are different jobs
Most people who use an AI agent for outbound let one session do everything. It researches the audience, writes the copy, builds the campaign and starts it, often in a single long conversation.
That design hides a risk. The same agent that produced a sentence is now judging whether the sentence is good, and a session that has been talking for an hour has drifted from your original rules. Nobody has read the output with fresh eyes before it reaches a stranger.
This guide separates the jobs. A skill handles writing and produces files, and a person reads the files.
FirstSales handles launching, through gates that ask for evidence. The files are the handoff, and the handoff is where the human sits.
FirstSales is an AI SDR and cold email product. The commands in this post come from the @firstsales.io/cli README (version 0.1.11 as of October 2026), and the package ships three Claude Code skill folders. Nothing here was run against a live account while this was written.
If you want the plain connection first, read the five-minute MCP setup. For the launch half in detail, see building a cold email campaign from Claude Code.
#What a skill is and why it fits
A Claude Code skill is a folder with a SKILL.md file that holds instructions and a short description. Claude loads the skill when the description matches the task, so you get consistent behavior without retyping your rules every session. Anthropic documents skills in the Claude Code skills guide.
Skills fit cold email for three reasons.
First, cold email has stable rules. Your voice, your claims policy and your compliance basics change slowly, so they belong in a file and not in your memory.
Second, a skill can force a format. If it always produces a brief and a sequence file with the same headings, your review becomes a quick comparison and not a fresh read each time.
Third, a skill can be reviewed like code. You can put it in git, ask a colleague to read it, and track how it changes.
A skill is also a boundary. The text of this guide's example skill tells the model what to write and, just as important, what not to do.
It does not tell the model to call any FirstSales tool. That omission is deliberate, and it keeps the writing step from touching your account.
#The pipeline at a glance
| Stage | Who or what | Output | Touches FirstSales? |
|---|---|---|---|
| 1. Write | Claude Code skill | brief.md and sequence.md | ✗ no |
| 2. Sign off | A person | A dated approval note | ✗ no |
| 3. Create | CLI, campaigns create | A draft campaign | ✓ yes |
| 4. Load | CLI or MCP workflow update | Copy in the workflow | ✓ yes |
| 5. Check | CLI readiness | A clean result | ✓ yes |
| 6. Test | CLI send-test-email | An email in your inbox | ✓ yes |
| 7. Launch | CLI start, by a person | A running campaign | ✓ yes |
flowchart LR A[Skill writes brief.md and sequence.md] --> B{Human sign-off} B -->|changes needed| A B -->|approved| C[CLI campaigns create] C --> D[Load copy into workflow] D --> E[CLI campaigns readiness] E --> F[CLI campaigns send-test-email] F --> G{Test looks right?} G -->|no| D G -->|yes| H[Person runs campaigns start] H --> I[MCP progress and analytics]
Everything left of the sign-off box is reversible and free. Everything right of it touches your account and, eventually, other people.
#Step 1: write the skill
Create a folder in your project, such as .claude/skills/cold-email-writer/, and add a SKILL.md file. The text below is an original example written for this post. It is not part of the FirstSales package, so edit it to match your own voice and rules.
markdown--- name: cold-email-writer description: Writes a cold email brief and a short email sequence as markdown files. Use when asked to draft outbound email copy. Never contacts any external service. --- # Cold email writer ## Output Write exactly two files in the current folder: 1. brief.md with these headings: Audience, Trigger, Offer, Proof, Risks, Open questions. 2. sequence.md with one section per email: Subject, Body, Gap before next email. ## Rules for the brief - Audience is one sentence that a stranger could apply to a list of companies. - Trigger says why this person hears from us today. If it is not given, write "unknown". - Offer is one thing a reader can say yes or no to. - Proof lists only facts I supplied, each with its source. Never invent a statistic, a customer or a quote. - Risks lists any claim in the sequence that lacks a source. ## Rules for the sequence - Three emails at most. One idea and one ask per email. - First email under 90 words. Plain words. No filler openers. - No fake urgency, no fake "Re:" subjects, no pretending we spoke before. - Every email includes a plain line telling the reader how to opt out. - Do not mention competitors by name. - Mark any merge field as {{field_name}} and list the fields at the end of sequence.md. ## Boundaries - Do not call any MCP tool. Do not run any shell command that sends data. - Do not ask for or print credentials. - If an input is missing, list it under Open questions and stop. Do not guess.
Read the skill the way a reviewer would. Each rule exists for a reason you can name.
The output rule forces files, which is the handoff. The proof rule blocks invented facts. The risk rule makes the model confess its own weak claims. The boundary rule keeps the skill away from your account.
Avoid the temptation to add a long personality paragraph. Models follow concrete rules better than moods. Short, checkable lines beat a page of tone advice.
If you want help with the craft, load reference material into the session. Our guides on writing cold emails, cold email templates, subject lines and one-line cold emails are good starting points, and offer clarity helps with the hardest field in the brief.
#Step 2: run the skill and read the outputs
Give the skill real inputs, and make them specific. Vague inputs produce fluent nonsense.
Use the cold-email-writer skill. Audience: independent accounting firms with 2 to 10 staff in the US. Trigger: they posted a job ad for a bookkeeper this month. Offer: a free 15-minute review of how they chase late client documents. Proof I can show: our public customer count is X (source: our pricing page).
Replace the placeholders with facts you can source. If you have none for the proof field, say so and let the model write "none supplied".
The skill writes two files. Open them in your editor, not in the chat window. Reading in a different place helps you see the text as a reader would.
Start with brief.md. Do the Risks and Open questions sections look honest? A skill that reports no risks and no open questions is either perfect or hiding something. Assume the second.
Then read sequence.md aloud. Check each email against five questions.
- Can a stranger understand the first line without context?
- Is there exactly one ask?
- Is every claim traceable to the brief's Proof section?
- Does the opt-out line read like a human wrote it?
- Would you be comfortable if the recipient forwarded this to a colleague?
The list of warning signs for machine-written filler is in AI slop in cold email, and the post on AI email quality at scale explains why quality checks must come before volume.
Personalization deserves a close look. A first line that references the trigger is useful. A first line that flatters a company with a generic compliment is noise. The guide to cold email personalization at scale draws the line, and buying signals for cold email explains how to build a trigger you can verify.
Iterate with the skill, not around it. If the copy is weak, tell the model what is wrong and rerun, so the rules stay in force. If a rule is missing, add it to SKILL.md, since the fix then helps every future run.
#Step 3: the sign-off gate
This gate is the heart of the guide. Nothing moves to FirstSales until a person approves the files.
Create a short approval note in the repo.
markdown# Approval: accounting-firms pilot Date: 2026-10-08 Reviewer: <name> brief.md reviewed: yes sequence.md reviewed: yes Every claim has a source: yes Opt-out line present in every email: yes Merge fields listed and checked: yes Approved for loading into a draft campaign: yes
The note looks bureaucratic, and it earns its keep. It records who looked, when and what they checked. It also creates a moment of friction, which is exactly what you want between a model and a stranger's inbox.
Make the reviewer someone other than the person who ran the skill, when you can. A fresh reader notices what the author stopped seeing. On a solo project, wait a few hours and review as if the work came from someone else.
The Model Context Protocol specification states a principle that applies here too. Its tools page says there should always be a human in the loop with the ability to deny tool invocations, and you can read it in the specification. The sign-off gate extends that idea from tool calls to content.
If the reviewer rejects the files, rerun the skill with the reviewer's notes as inputs. Do not edit around the skill by hand and forget why. Capture the lesson in SKILL.md.
The guides on human-in-the-loop cold email and guardrails for email-sending agents go deeper on where humans belong in an automated program.
#Step 4: create the campaign with the CLI
With approved files in hand, switch surfaces. Campaign creation is a CLI job. The MCP server has no confirmed tool for creating a campaign, so create with the CLI and use MCP afterward to edit and watch.
Check your session first.
bashfirstsales whoami --json firstsales doctor --pretty
Then look at the command on your installed version. The README does not publish the request body for campaigns create, so read it from the tool itself.
bashfirstsales commands --json firstsales campaigns create --help
The command reference is at developer.firstsales.io, and the request bodies are in the OpenAPI document.
Rehearse the creation with --dry-run, and add an idempotency key so a retry does not create a second campaign.
bashfirstsales campaigns create \ --org org_123 --workspace ws_123 \ --data-file campaign.json \ --idempotency-key accounting-pilot-create-001 \ --dry-run --json
Replace the identifiers with your own from firstsales orgs list and firstsales workspaces list. Read the output with Claude Code in the room, and run the command without --dry-run only when the body is right.
Never put an API key in campaign.json or in a prompt. Export FIRSTSALES_API_KEY in your shell, and create keys with firstsales api-keys create using the narrowest access that covers the work. The guide to API keys for outbound agents covers least access in detail.
After creation, read the campaign back and confirm it is a draft that has not started.
bashfirstsales campaigns get --campaign <campaign-id> --org org_123 --workspace ws_123 --json
#Step 5: move the approved copy into the workflow
Now the approved copy goes into the campaign. Use the MCP workflow tools if your tool list has them, and the CLI otherwise.
The confirmed MCP session had campaign workflow get and update. Your tool list is the authority, and the product skill describes the released catalog as read-only today, so check before you plan around it.
Follow the same loop as in editing a campaign workflow with Claude: read the workflow, save it to git, make one change, write it, read it again and diff. The loop matters even more when you load copy, because a bulk write is where fields get dropped.
Use the campaign workflow get tool for campaign <campaign-id>. Save the raw result to workflow.json. Do not change anything. Then show me where each email in sequence.md would go. Do not call a write tool.
Check the mapping before any write. Every subject, body and gap in sequence.md should have a clear home in the workflow. If the structure does not fit, stop and ask a human. Do not let the model invent a mapping.
Check merge fields next. The skill listed them at the end of sequence.md. Compare that list with the fields your workspace knows.
bashfirstsales contact-fields list --org org_123 --workspace ws_123 --json
A merge field with no matching contact field will render as a blank or a placeholder in a real email. That is the bug the test email exists to catch, and it is cheaper to catch it here.
Write the copy one email at a time, and re-read after each write. The CLI route is firstsales campaigns workflow update, and the README example sends only the included list ids and the sender connector ids as one PATCH. For copy fields, the README mentions campaigns workflow-update as a PUT without documenting its body, so use --dry-run and the OpenAPI document before you trust it.
Attach the audience at this stage too. The list comes from the import steps in the terminal import guide, and the README's PATCH example includes a list id flag.
#Step 6: readiness, test email, start
These three commands are the launch gates. Run them in order, and read each result yourself.
bashfirstsales campaigns readiness --campaign <campaign-id> --org org_123 --workspace ws_123 --json firstsales campaigns send-test-email --campaign <campaign-id> --org org_123 --workspace ws_123 --json
The readiness response format is not in the README, so read your own output. Ask Claude Code to quote each blocker exactly, and fix them one at a time.
The test email is the check no file review can replace. Open it in a real inbox and look at the sender, the subject, the rendering, the links and the opt-out line. The README does not document the body of send-test-email or prepare-test-email, so check --help and use --dry-run first.
Compare the arrived email with sequence.md. They should match, apart from merge fields filled with real values. A mismatch means the load step went wrong, and you should return to step 5.
For the start request, the README example shows a JSON body with savedVersionId, readinessVersion, idempotencyKey and confirmation. Use --dry-run with the same body, read it, and run the real command yourself.
bashfirstsales campaigns start --campaign <campaign-id> \ --org org_123 --workspace ws_123 \ --data-file start.json --dry-run --json
Two final cautions. Do not start from a stale readiness result, since the version matters. And do not let the skill or the session run campaigns start for you. The decision to send to real people belongs to the person who signed off.
After launch, switch to watching. The guide on asking Claude how your campaign is doing shows how to read progress without fooling yourself, and starting and pausing campaigns from the CLI covers the stop controls.
#A worked pass with invented details
The scenario here is hypothetical, and every name, input and outcome is made up to show the flow. No real account or customer is involved.
A two-person agency wants to reach independent veterinary clinics about an after-hours phone answering service. One person runs the skill, and the other signs off.
The inputs are plain. The audience is independent clinics with one to three vets in a single country. The trigger is a clinic that recently posted a front-desk vacancy. The offer is a free review of how after-hours calls are handled today. The proof is empty, because the agency has no public customer numbers yet.
The skill writes both files. The brief lists the proof as "none supplied", and the risks section flags a sentence in email two that says "most clinics lose calls at night". The model could not source it, so it flagged its own line.
The reviewer reads the files in an editor, agrees the claim has no source, and deletes the sentence. She also shortens the first email from 110 words to 80, and she rewrites the opt-out line so it sounds like a person wrote it.
The agency adds a rule to the skill: no sentence about industry behavior without a supplied source. The next run respects it.
The team then creates a draft campaign with the CLI, rehearses the body with --dry-run, and loads the three emails into the workflow one at a time. After each write they re-read and diff.
The readiness check reports a missing sender. They attach one and rerun it. The test email arrives with a blank first-name field, because the skill used {{first_name}} and the workspace field was named differently. They fix the mapping, send a second test and read it again.
One person runs campaigns start after reading the dry run. The model then reports progress counts on request, and nothing more.
The story has three lessons. The skill flagged its own weak claim. The human removed it. The test email caught a bug no file review would have found.
#Prompts that keep the skill honest
A few prompts help you audit the skill's output without rewriting it.
Source audit. "List every factual claim in sequence.md. For each, name the line in brief.md Proof that supports it, or write unsupported."
Reader test. "Pretend you are the recipient and have never heard of us. What do you think we want, and what would you do next?"
Tone check. "Quote any phrase that sounds like marketing copy and not like a person writing to a person."
Compliance check. "List each email's opt-out line and confirm there is no misleading subject or fake reply marker."
Consistency check. "Do the three emails agree on the offer, the ask and the facts? List contradictions."
Run these in a fresh session, not the one that wrote the copy. A fresh context has no memory of the justifications, so it judges the text on its own.
None of the prompts replaces the human sign-off. They make the reviewer's job faster and the findings easier to record.
#When to skip the skill
A skill adds structure, and structure has a cost. For a one-off note to a single person you know, write the email yourself.
Skip the skill when the audience is tiny and the message is personal. Hand-written work wins when you have a real reason to write to one person.
Use the skill when you write to many people with a shared reason, where consistency and review matter more than craft in each message. That is the zone where drift and filler grow.
Whatever you choose, keep the launch gates. The skill is optional, and the readiness check and the test email are not.
#Keeping the copy compliant
A skill can carry compliance basics into every draft. It cannot replace judgment, and it does not constitute legal advice.
In the United States, the Federal Trade Commission's CAN-SPAM compliance guide lists the core rules for commercial email: do not use false or misleading header information, do not use deceptive subject lines, identify the message as an ad where required, include your valid physical postal address, give a clear way to opt out, and honor opt-outs promptly. Put the ones that apply to you into the skill as rules.
For Gmail recipients, the bar is higher for large senders. Google's email sender guidelines say bulk senders, those who send close to 5,000 or more messages to Gmail accounts in a day, need SPF, DKIM and DMARC and one-click unsubscribe. The guidelines also ask senders to keep the spam rate reported in Postmaster Tools below 0.10% and to avoid reaching 0.30%. As of October 2026, those are the numbers to hold in mind.
RFC 8058 defines the one-click unsubscribe mechanism behind that requirement, and RFC 7489 defines DMARC. You do not need to read either to write good copy, but your sending setup needs to honor them. Our guides on one-click unsubscribe in cold email, SPF, DKIM and DMARC setup and the Google bulk sender rules for 2026 cover the practical side.
Whether cold email is legal depends on where your recipients are. The post on whether cold email is legal in 2026 is a starting map. Check your own situation with a qualified person.
Add copy rules that protect trust. Never fake a reply thread, never claim a past conversation that did not happen and never imply a relationship you lack. These practices damage the brand even when they are not illegal.
#The skills FirstSales ships
The @firstsales.io/cli package includes three skill folders: firstsales-cli, firstsales-developer-api and firstsales-product-mcp. They teach Claude Code how to use the CLI, the public API and the MCP server.
These are different from the writing skill in this guide. They help the model operate FirstSales correctly. Your writing skill helps it produce copy. Keep the two roles apart.
The firstsales-cli skill treats firstsales commands --json as the local authority for what commands exist. The firstsales-product-mcp skill treats the live tools/list as the authority for MCP, and it says to switch to the CLI or Developer API when an action is mutating, destructive, billing-related or approval-backed.
How to load the shipped skills into a given project depends on your Claude Code version and setup. This post has not verified the exact install steps, so follow the Claude Code documentation and the package README. If the package README gives instructions, they win over anything written here.
A sensible arrangement uses both. The writing skill creates files and stays away from the account. The operating skills help with the launch gates and know the command names.
If you are wondering where all this sits in a broader setup, see the five layers of an AI outbound agent stack and where FirstSales fits in an outbound stack.
#Improving the skill over time
A skill is a living document. Treat edits to it the way you treat edits to code.
Keep it in git, and write commit messages that state the rule you changed and why. A line such as "ban fake reply subjects after review found one" is more useful than "update skill".
Track the rejection reasons. Every time a reviewer sends copy back, write down the reason. After ten rejections, patterns appear. If three of them mention unsourced claims, strengthen the proof rule. If four mention length, set a tighter limit.
Test changes against fixed cases. Keep a small set of inputs with known good and bad outputs, and rerun them after each skill edit. The post on building an outbound AI eval set describes this approach, and AI SDR prompt drift explains why unchecked prompts degrade.
Compare results with reality. After a campaign runs, read the replies and the numbers, and ask whether the skill's assumptions held. Use the cautions in the analytics guide: counts before rates, denominators for every rate and no celebration over tiny samples.
Share the skill with teammates, and invite edits through review. Two sets of eyes find more holes than one.
Prune. A skill with fifty rules is a skill the model will partly ignore. Keep the rules that earn their place, and remove the ones that never fire.
#Failure modes of skill-written copy
Even a good skill produces predictable problems. Know them in advance.
Sameness. A skill produces consistent output, which can read as templated. If every email opens the same way, recipients notice. Vary structures on purpose and review a batch side by side.
Confident filler. Fluent sentences with no content, such as claims about "saving your team time" with no number or source behind them. The cure is the proof rule and a reviewer who asks what each sentence tells the reader.
Invented specifics. The model adds a detail to sound credible, such as a number, a customer type or a feature. The cure is the rule against invention and a source check at sign-off.
Over-personalization. A first line that shows the writer scraped something creepy backfires. Reference only information the recipient would expect you to know.
Drift between steps. The follow-up contradicts the first email, or repeats it. Read the sequence as one story.
Compliance gaps. A missing opt-out line or a misleading subject. Check each email against the compliance rules, every time.
Rule decay. The skill's instructions fade in a long session. Start a fresh session for each run, and keep inputs short.
None of these problems is fatal, and all of them are cheaper to catch before launch. The sign-off gate and the test email are your two best filters.
#FAQs
#What is a Claude Code skill?
It is a folder with a SKILL.md file that holds instructions and a description. Claude loads it when the task matches, so your rules apply without retyping.
#Why separate writing from launching?
The agent that writes a sentence should not be the only judge of it. Separation puts a human review between the draft and the recipient.
#Should the writing skill call FirstSales tools?
No. Keep it away from your account. It should read inputs and write files only.
#What files should the skill output?
A brief.md with audience, trigger, offer, proof, risks and open questions, and a sequence.md with subject, body and gap for each email.
#Who should sign off?
A person other than the one who ran the skill, if you can. On a solo project, review after a few hours as if someone else wrote it.
#Can the skill create the campaign?
No. Campaign creation is a CLI job: firstsales campaigns create. Creation through MCP is not confirmed.
#How do I load the approved copy into the workflow?
Use the MCP workflow tools if your tool list has them, or firstsales campaigns workflow update. Read, save, write, re-read and diff, one change at a time.
#What if the copy has merge fields?
Have the skill list them, and compare the list with firstsales contact-fields list. A missing field renders badly in a real email.
#What must I run before starting a campaign?
Run firstsales campaigns readiness and firstsales campaigns send-test-email before firstsales campaigns start. Read both results yourself.
#Can the model run campaigns start?
It can prepare the command, but you should run it. The start body carries a confirmation field that should come from you.
#Do the shipped FirstSales skills write copy?
No. They teach Claude Code to operate the CLI, the Developer API and the MCP server. They are separate from a writing skill.
#How do I install the shipped skills?
Follow the Claude Code documentation and the package README. This post has not verified the install steps.
#How long should a first email be?
The example skill sets a cap of 90 words as a house rule. That is a style choice for this guide, not a FirstSales limit.
#How many emails should a sequence have?
The example caps it at three. Shorter sequences are easier to review, and you can extend a sequence after you see results.
#What should every email include for compliance?
At least a clear way to opt out, honest headers and subject lines, and, for the United States, a physical postal address. Check your own region's rules too.
#Does the skill make the copy legal?
No. A skill can carry rules, and a qualified person should confirm your legal position.
#How do I stop the model inventing facts?
Add a proof rule that allows only supplied facts with sources, a risks section and a human source check at sign-off.
#How do I improve the skill?
Log rejection reasons, add rules for repeated problems, test against fixed cases and prune rules that never fire.
#Where do the API keys go?
In environment variables, created with the narrowest access. Never put a key in a skill, a prompt or a file in git.
#What should I read next?
Read Build a cold email campaign from Claude Code for the launch half, then Edit campaign workflow with Claude.
#Conclusion
Writing and launching are different jobs, and a safe program gives them different owners. The skill writes files. A person reads them. FirstSales launches through gates that ask for evidence.
Keep three rules. Never let the writing skill touch your account, run campaigns readiness and campaigns send-test-email before campaigns start, and keep keys out of prompts and files.
The skill gets better each time a reviewer sends copy back, so treat rejection as data. A month of notes teaches you more about your audience than any template.
Ready to try it? Create the skill folder, run it on one real input and review the files before you open a terminal for FirstSales. When the sign-off note is written, start with firstsales whoami --json and follow the MCP setup guide.