Spiral: what this is, in plain English

A beginner-friendly tour. If you've never used Claude Code or Claude Skills, start here.


1. What's a Claude Skill?

A Claude Skill is a folder with a SKILL.md instruction file plus optional Python scripts and reference docs. You invoke it inside Claude Code by typing /skill-name (e.g. /spiral-ingest-leads). When invoked, Claude reads the SKILL.md, follows the steps, runs the scripts, and reports back.

Think of a skill as a runbook Claude can execute — but the runbook can also call APIs, parse files, and decide things on its own. Claude is the orchestrator; the Python scripts are the deterministic muscle.

Skills live in ~/.claude/skills/<skill-name>/. The folder must contain SKILL.md with a YAML frontmatter block at the top defining the name, description, and what tools Claude is allowed to use.


2. What is Spiral?

Spiral is a cold-email pipeline for Spiral Studios. It automates the parts that are repetitive and error-prone, while keeping you (the human) in control of the moments that matter (which leads to target, which drafts to send, which replies to approve).

The system orchestrates four external services:

ServiceRole
ApolloLead database — gives you contact info, company facts, intent signals
Google SheetsThe master DB. Every lead, reply, and decision lives here
InstantlySends the cold emails and tracks replies
HubSpotWhere your client reviews and approves draft replies

And Claude itself does the creative work: writing personalized email copy and replying to leads in your voice.


3. The pipeline at a glance

Four skills, each invoked when needed. The yellow nodes are the human-judgment moments (sending cold emails, approving reply drafts). The system stops there. No surprises, no auto-blast.


4. The four skills, one line each

/spiral-ingest-leads

Reads apollo_to_spreadsheet.csv from spiral-shared/inbox/, parses it, dedupes against existing rows, and appends new leads to the Google Sheet with processing_status=pending.

/spiral-weekly-enrichment

Picks the next batch of pending leads. For each one:

You then review and send the drafts manually from the Instantly UI.

/spiral-daily-replies

Pulls new replies from Instantly. For each:

Replies labeled OOO, Not Interested, or Wrong Person are just logged — no draft.

/spiral-sync-approvals

Fetches all HubSpot records where the client has set approval_status=approved. For each, sends the approved reply through Instantly (so it threads natively in the inbox), logs it, and deletes the HubSpot record so the client's view only ever shows pending items.


5. How you actually use it (the rhythm)

Setup (one time)

  1. Create .env from .env.example, fill in API keys
  2. Drop google-service-account.json in spiral-shared/
  3. pip install -r spiral-shared/scripts/requirements.txt
  4. Run python spiral-shared/scripts/healthcheck.py — all green
  5. Run python spiral-shared/scripts/bootstrap_sheet.py — creates Sheet tabs
  6. Run python spiral-shared/scripts/bootstrap_hubspot.py — creates the HubSpot object
  7. Fill in the real Instantly campaign UUIDs in references/campaigns.json

For step-by-step setup see runbook.md.

Monday morning (lead acquisition)

  1. In Apollo, tag your search contacts with two lists: icp_type:dream (or normal/lookalike) and tier:T1 (or T2/T3 — funding-based, see sheet_schema.md)
  2. Export CSV → save as apollo_to_spreadsheet.csv in spiral-shared/inbox/
  3. In Claude Code: /spiral-ingest-leads
  4. Then: /spiral-weekly-enrichment
  5. Open Instantly → review drafts → send

Tue–Fri morning

  1. /spiral-daily-replies — drafts get pushed to HubSpot
  2. Your client reviews + approves drafts in HubSpot whenever
  3. You run /spiral-sync-approvals (or it can run on a schedule)

6. Why this design

Sheets is canonical. Every lead, every state, every timestamp lives in Google Sheets. HubSpot is temporary (records appear only when client approval is needed). Instantly is the sender. If two systems disagree, Sheets wins (except when it's about what was actually mailed — there Instantly wins).

Idempotent everywhere. Every skill checks state before acting. If a skill crashes mid-run, just run it again — it picks up where it left off. Safe to over-run, never under-run.

Human gates on the dangerous things. Spiral never auto-sends a cold email and never auto-sends a reply without client approval. Both moments require explicit human action through a UI.

Claude inside Claude Code. All creative writing (email variables, reply drafts) happens through the Claude that's running the skill — no separate Anthropic API key, no background workers, no daemons. When your Claude Code session is idle, the system is paused.

Sheet columns match Instantly column names. The Leads tab uses Instantly's exact field names for everything that gets pushed to Instantly (firstName, companyName, icp_type, tier, activity, cadence, signal_fact, vertical, matched_case, case_link, plus the email vars opener, bridge, proof, asset_line, fu1_linefu3_line, breakup_line, cta, cta_soft, subject_t1subject_t5). Apollo enrichment fields and Spiral pipeline state stay in snake_case. Routing goes by {icp_type_lowercased}_{tier} → Instantly campaign UUID. 5 valid combinations (C1–C5): Dream/T1, Normal/T2, Normal/T3, Lookalike/T2, Lookalike/T3. Dream is T1-only; Normal and Lookalike skip T1. enrich_one.py clamps invalid combos automatically.


6.5. The voice guide is non-negotiable

Cold email is where AI tells become obvious. The voice guide (voice_guide.md) is loaded into Claude on every drafting run with hard rules:

The email templates have been written to match. If you notice Claude reaching for a phrase you don't like, add it to the avoid list — the next drafting run will respect it.


6.75. Case study setup

The proof line in every email references a Spiral Studios case study. Today that's a constant:

When you add more case studies, set up a verticalmatched_case mapping table in email_templates.md and the enrichment flow will pick the right one per lead. case_link is its own Instantly column — don't paste the URL inside the proof text.


7. Where to go next

If you want to…Read…
Run the system day-to-dayrunbook.md (the operator playbook)
Understand the data model + state machinearchitecture.md
Debug a specific errorerror_handling.md
Know what's in each Sheet columnsheet_schema.md
Tune Claude's writing tonevoice_guide.md and spiral-weekly-enrichment/references/email_templates.md
Add a new campaigncampaigns.json

  Have your own?

Paste your markdown, get a link like this.

Write your own
Spiral: what this is, in plain English · DocHouse