[ COPY & CONTENT ]
/copywrite
Production copywriting skill for all 3 businesses (ACME Agency, ACME Agency, IA Outreach) across 5 platforms: Meta ads, Google Ads, landing pages, cold email, and email/newsletter.
ACME Agency, <id> and you@example.com mark values that are per-agency — your install fills them with YOUR clients and accounts. If a section references a helper script you don't have yet, it ships with that workflow's install./copywrite
Platform-specific copy grounded in 12 expert principles. Always reads client context before writing. Always generates 3 variants with different hook types. Always applies the anti-AI sweep before outputting. Saves as a formatted Google Doc in the client's Drive Copywriting folder.
Supported platforms: meta | google | landing | cold-email | email
Triggers
/copywrite meta "ACME Agency" --stage awareness --lang hr— Meta awareness ads in Croatian/copywrite google "ACME Agency" --intent commercial— Google RSA asset set/copywrite landing "ACME Agency" --lang de --funnel lead-gen— German lead-gen landing page/copywrite cold-email "ACME Agency" --icp "SaaS founders"— Cold email sequence/copywrite email "IA Outreach" --type broadcast --goal nurture— Email broadcast- If platform or client is missing, ask the user before proceeding
Phase 0 — Context Load
Always run this phase first, regardless of platform.
Step 0.1 — Parse inputs
Extract from the user's invocation:
platform— meta | google | landing | cold-email | emailclient— the business or client name- Any flags:
--stage,--lang,--funnel,--icp,--seq,--type,--goal,--intent
If platform or client is missing, ask the user. Do not guess.
Step 0.2 — Client context lookup
For ACME Agency clients (any name found in ACME Agency/clients/clients.json):
- Read
ACME Agency/clients/clients.json— getslack_channel,drive_folder_id, and any ad account IDs - Read
ACME Agency/clients/<ClientName>/CLIENT.md— extract: business description, products/services, target audience, brand tone, market, USPs, competitors, pricing, conversion goal - Read
ACME Agency/clients/<ClientName>/brand-dna.mdif it exists — extract: voice adjectives, language, tone direction - Note: if
brand-dna.mdis missing, infer voice from CLIENT.md and website description
For ACME Agency:
- Read
ACME Agency/CLAUDE.md— full business context - Read
ACME Agency/brand-dna.mdif it exists - Slack channel: check
ACME Agency/clients/clients.jsonfor ACME Agency entry, or use#ACME Agencyif not found
For IA Outreach clients (ACME Agency, etc.):
- Read
ia-outreach/CLAUDE.md— business context - Read
ia-outreach/clients/<ClientName>/CLAUDE.mdif it exists - Read all ICP files in
ia-outreach/clients/<ClientName>/icp/ - Slack channel:
#your-channelunless noted otherwise
Step 0.3 — Load existing copy artifacts (to avoid repeating angles)
For Meta platform:
- Read
ACME Agency/clients/<ClientName>/static_ads_manifest.jsonif it exists - Read
ACME Agency/clients/<ClientName>/static_ads_prompts.jsonif it exists — scan headlines and hooks already in production - Do NOT use a hook type already dominant in running ads
For cold-email platform:
- Read all files in
ia-outreach/clients/<ClientName>/sequences/— note existing hooks, subject lines, CTAs
For email platform:
- Read recent email files in
ia-outreach/clients/<ClientName>/sequences/if applicable
For google/landing platforms:
- CLIENT.md is sufficient — no artifact scanning needed
Step 0.4 — Assemble the brief payload
You will hand all the context you've gathered (CLIENT.md notes, brand-dna, existing angles, platform, language, stage, etc.) to the copywriter agent in Phase 2. Do NOT read PRINCIPLES.md or the platform module file yourself — the agent will read them in its own context window. Your job in Phase 0 is gathering, not writing.
Phase 2 — Delegate to the copywriter agent
Invoke the copywriter subagent via the Task tool with subagent_type: "copywriter". Pass:
client: <client name>
business: ACME Agency | ACME Agency | ia-outreach
platform: meta-ad | google-rsa | landing-page | cold-email | newsletter
language: <hr | bs | de | en>
brief: <full brief assembled from Phase 0 — emotional driver candidates, audience, offer, USPs, mechanism, conversation in their mind, banned angles>
constraints: <character limits, must-include claims, banned words, tone constraints from CLIENT.md>
reference_files:
- <absolute path to .claude/skills/copywrite/PRINCIPLES.md>
- <absolute path to the platform-specific module file: .claude/skills/copywrite/META.md, GOOGLE.md, LANDING.md, COLD_EMAIL.md, or EMAIL.md>
- <absolute path to CLIENT.md if it exists>
- <absolute path to brand-dna.md if it exists>
variants: 3
The agent runs its self-test loop internally:
- Picks angle (awareness level, big idea, emotional trigger, proof lever)
- Drafts each variant
- Tests each draft against
.claude/agents/copywriter.tests.md(em-dashes, fragments, banned phrases, naturalness ≥ 8/10) - Revises and re-tests up to 5 iterations per variant
- Returns when all tests pass OR after 5 iterations with explicit failures listed
The agent returns a structured payload:
iterationsper variant (1-5)final_scoreper variant (e.g. 9/10)variant_a,variant_b,variant_c— full Meta-ad-format copyangle_notesper variant — awareness level, big idea, emotional trigger, why it should workfixed_in_revisionper variant — what the test loop caughtstill_imperfect— only if tests are still failing after 5 iterations
Do NOT write copy yourself in this step. If the agent's output isn't good enough, give it specific feedback and re-invoke. Don't hand-edit.
Phase 3 — Output and Delivery
Step 3.1 — Save locally
Save the full output to:
- ACME Agency clients:
ACME Agency/clients/<ClientName>/copy_<platform>_<YYYY-MM-DD>.md - ACME Agency:
ACME Agency/copy_<platform>_<YYYY-MM-DD>.md - IA Outreach clients:
ia-outreach/clients/<ClientName>/copy_<platform>_<YYYY-MM-DD>.md
Step 3.2 — Create Google Doc in Drive
Create a formatted Google Doc in the client's Drive folder under a Copywriting subfolder using createFormattedDoc from ACME Agency/scripts/lib/google_docs.mjs and findOrCreateFolder to create the subfolder if it doesn't exist.
node --input-type=module <<'EOF'
import { createFormattedDoc, getAccessToken, findOrCreateFolder } from './ACME Agency/scripts/lib/google_docs.mjs';
const token = await getAccessToken();
const copywritingFolderId = await findOrCreateFolder(token, 'Copywriting', '<drive_folder_id>');
const { docUrl } = await createFormattedDoc(token, {
folderId: copywritingFolderId,
title: 'Copy — <ClientName> — <Platform> — <YYYY-MM-DD>',
sections: [
{ type: 'title', text: 'Copy — <ClientName> — <Platform> — <YYYY-MM-DD>' },
{ type: 'subtitle', text: 'Kampanja: <campaign> | Stage: <stage> | Jezik: <lang>' },
{ type: 'spacer' },
{ type: 'h1', text: 'VARIANT A — <Hook Type>' },
{ type: 'bold', text: 'Headline: <headline>' },
{ type: 'body', text: '<primary text — each paragraph as separate body section>' },
{ type: 'bullets', items: ['CTA: <cta>', 'Hook Line: <hook line>'] },
{ type: 'spacer' }, { type: 'divider' }, { type: 'spacer' },
{ type: 'h1', text: 'VARIANT B — <Hook Type>' },
// ... repeat for B and C
{ type: 'spacer' }, { type: 'divider' }, { type: 'spacer' },
{ type: 'h2', text: 'Notes' },
{ type: 'bullets', items: ['Hook types: A=..., B=..., C=...', 'Emotional driver: ...', 'Mechanism: ...', 'Avoided angles: ...'] },
],
});
console.log('Doc URL:', docUrl);
EOF
Step 3.3 — Deliver via slack-reporter
Invoke the slack-reporter subagent via the Task tool with subagent_type: "slack-reporter". Pass:
client: <client name>
channel: <resolved via getClientChannel(clientName) — channel ID>
type: copywrite
headline: "*Copywrite — <ClientName> — <Platform> — <YYYY-MM-DD>*"
sections:
- title: "Variant A — <hook type from agent>"
bullets:
- <first 2-3 lines of variant A primary text, truncated>
- title: "Variant B — <hook type from agent>"
bullets:
- <first 2-3 lines of variant B>
- title: "Variant C — <hook type from agent>"
bullets:
- <first 2-3 lines of variant C>
- title: "Info"
bullets:
- "Platform: <platform> | Stage: <stage> | Jezik: <lang>"
- "Iterations: A=<n>, B=<n>, C=<n> | Naturalness: A=<x>/10, B=<x>/10, C=<x>/10"
- "Emotional drivers: <comma-separated>"
links:
- label: "Google Doc — puni copy"
url: <docUrl from Step 3.2>
language: <hr | bs | de | en — match channel>
Do NOT call postMessage() from lib/slack.mjs directly anymore. The slack-reporter agent owns Slack delivery and enforces SLACK_REPORT_STANDARD.md.
Step 3.4 — Ask for iteration
"Which variant do you prefer? Any changes to tone, hook angle, language, or length?"
Verification (run AFTER Step 3.3 — confirm copy actually shipped)
Check ALL of these before declaring done:
- [ ] Copywriter agent returned 3 variants (or
variantscount from input — never fewer without explicit flag) - [ ] Each variant has: primary text, headline (within char limit), description (within char limit if applicable), CTA
- [ ] Each variant's
final_score≥ 8/10 OR the agent explicitly listedstill_imperfectfailures - [ ] All variants are in the requested language (verify with a simple regex/keyword sweep — Croatian should have š/đ/č/ž/ć somewhere, German should have Sie not du, etc.)
- [ ] Each variant uses a DIFFERENT hook type (no two variants on the same angle)
- [ ] Local file saved at
ACME Agency/clients/<Client>/copy_<platform>_<YYYY-MM-DD>.md(or ACME Agency / ia-outreach equivalent) - [ ] Google Doc created in
Copywritingsubfolder of client Drive ANDdocUrlis non-null - [ ] Slack post via slack-reporter returned
tsnon-null with the doc URL embedded - [ ] If
cold-emailplatform: each variant has a P.S. line (T-EN4 from copywriter.tests.md) - [ ] If
googleplatform: every headline ≤ 30 chars, every description ≤ 90 chars (hard API limits) - [ ] No variant contains em-dashes (—) for HR/BS — copywriter test loop should have caught these but verify
If any check fails, name the gap. The most common failure mode is the agent returning 2 variants when 3 were asked because variant 3 couldn't pass the test loop in 5 iterations — that's an acceptable scope reduction BUT must be flagged loudly, never silently delivered.
Important Rules
- All copy is generated by the
copywriteragent in Phase 2 — the main session does NOT write copy itself; if you're tempted to hand-edit, you're doing it wrong. Re-invoke the agent with feedback instead. - PRINCIPLES.md and the platform module file are passed to the agent as
reference_files— the main session does not read them directly anymore. - The agent's self-test loop catches the anti-AI patterns (em-dashes, fragments, banned phrases, naturalness) — those rules now live in
.claude/agents/copywriter.tests.mdand the skill no longer enforces them inline. - Always pass 3 variants — never fewer
- Slack delivery goes through
slack-reporter— never callpostMessage()directly - For cold email: the agent already knows plain text only, no HTML
- For Google Ads: the agent's tests enforce 30/90 char limits per headline/description
- For landing pages: the agent aligns the headline to the traffic source promise as part of its angle selection
- Existing-angle scan still happens in the main session (Phase 0 Step 0.3) — pass the scan results to the agent in the
brieffield so it knows what NOT to repeat
Key Files
| File | Purpose |
|---|---|
.claude/skills/copywrite/PRINCIPLES.md | 12 master principles — read before every generation |
.claude/skills/copywrite/META.md | Meta/Facebook ads module |
.claude/skills/copywrite/GOOGLE.md | Google Ads RSA module |
.claude/skills/copywrite/LANDING.md | Landing page module |
.claude/skills/copywrite/COLD_EMAIL.md | Cold email sequence module |
.claude/skills/copywrite/EMAIL.md | Email marketing/newsletter module |
ACME Agency/scripts/lib/google_docs.mjs | createFormattedDoc, findOrCreateFolder |
ACME Agency/clients/clients.json | Client lookup: Slack channel, Drive folder, account IDs |
ACME Agency/clients/<>/CLIENT.md | Business context, audience, offer, competitors |
ACME Agency/clients/<>/brand-dna.md | Voice profile, language, tone |
.claude/skills/SLACK_REPORT_STANDARD.md | Slack report format rules |