Skip to content
Marketing
Hook

Hooks

What email runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
email
1326 skills4 agents2 hooks

Claude Code

$ npx -y skills add AgriciDaniel/claude-email --agent claude-code

Where it lives

  • hooks/pre-send-check.shGitHub
    Read the script
    #!/usr/bin/env bash
    # pre-send-check.sh — Quality gate before sending emails
    # Hook type: PreToolUse (Bash)
    # Exit 0 = allow, Exit 2 = block with message
    
    set -euo pipefail
    
    # Read email content from arguments or stdin
    EMAIL_SUBJECT="${1:-}"
    EMAIL_BODY="${2:-}"
    
    if [[ -z "$EMAIL_SUBJECT" && -z "$EMAIL_BODY" ]]; then
        # If no args, try stdin
        EMAIL_CONTENT=$(cat)
        EMAIL_SUBJECT=$(echo "$EMAIL_CONTENT" | grep -i "^Subject:" | head -1 | sed 's/^Subject: *//i' || true)
        EMAIL_BODY=$(echo "$EMAIL_CONTENT" | sed '1,/^$/d')
    fi
    
    WARNINGS=()
    WORD_COUNT=$(echo "$EMAIL_BODY" | wc -w | tr -d ' ')
    
    # Check 1: Spam trigger words in subject
    SPAM_WORDS=("FREE!!!" "ACT NOW" "LIMITED TIME" "CLICK HERE" "BUY NOW" "URGENT" "WINNER" "CONGRATULATIONS!!!")
    for word in "${SPAM_WORDS[@]}"; do
        if echo "$EMAIL_SUBJECT" | grep -qi "$word"; then
            WARNINGS+=("⚠️  Subject contains spam trigger word: '$word'")
        fi
    done
    
    # Check 2: All caps subject
    if [[ "$EMAIL_SUBJECT" =~ ^[A-Z0-9[:space:][:punct:]]+$ ]] && [[ ${#EMAIL_SUBJECT} -gt 5 ]]; then
        WARNINGS+=("⚠️  Subject is all caps — may trigger spam filters")
    fi
    
    # Check 3: Email body too short
    if [[ $WORD_COUNT -lt 20 ]]; then
        WARNINGS+=("⚠️  Email body very short ($WORD_COUNT words) — consider adding more context")
    fi
    
    # Check 4: Missing unsubscribe link in marketing emails (block if detected as marketing)
    MARKETING_KEYWORDS=("newsletter" "unsubscribe" "marketing" "promotion" "offer" "discount")
    IS_MARKETING=false
    for keyword in "${MARKETING_KEYWORDS[@]}"; do
        if echo "$EMAIL_BODY" | grep -qi "$keyword"; then
            IS_MARKETING=true
            break
        fi
    done
    
    if $IS_MARKETING && ! echo "$EMAIL_BODY" | grep -qi "unsubscribe"; then
        echo "❌ BLOCKED: Marketing email missing unsubscribe link"
        echo "Add an unsubscribe mechanism to comply with CAN-SPAM and GDPR."
        exit 2
    fi
    
    # Print warnings but allow send
    if [[ ${#WARNINGS[@]} -gt 0 ]]; then
        echo "Pre-send quality checks:"
        for warning in "${WARNINGS[@]}"; do
            echo "$warning"
        done
        echo ""
        echo "✓ Checks passed (warnings above are advisory)"
    fi
    
    exit 0
    
  • hooks/validate-email-html.pyGitHub
    Read the script
    #!/usr/bin/env python3
    """Validate HTML email after editing.
    
    Hook type: PostToolUse (Edit, Write)
    Exit 0 = allow, Exit 2 = block with message
    """
    
    import sys
    import re
    from pathlib import Path
    
    def validate_html_email(file_path: str) -> tuple[bool, list[str]]:
        """Validate HTML email file.
    
        Returns:
            (is_valid, messages) where messages are warnings/errors
        """
        path = Path(file_path)
    
        # Only check .html files
        if path.suffix.lower() != '.html':
            return True, []
    
        try:
            content = path.read_text(encoding='utf-8')
        except Exception as e:
            return False, [f"❌ Cannot read file: {e}"]
    
        errors = []
        warnings = []
    
        # Check 1: File size (Gmail clips at 102KB)
        file_size = len(content.encode('utf-8'))
        if file_size > 102 * 1024:
            errors.append(f"❌ BLOCKED: File size {file_size // 1024}KB exceeds 102KB Gmail limit")
            errors.append("   Gmail will clip your email. Reduce content or move to plain text.")
        elif file_size > 80 * 1024:
            warnings.append(f"⚠️  File size {file_size // 1024}KB approaching 102KB limit")
    
        # Check 2: Contains at least one <table> (email layout best practice)
        if not re.search(r'<table[^>]*>', content, re.IGNORECASE):
            warnings.append("⚠️  No <table> elements found — consider using table-based layout for email")
    
        # Check 3: No CSS Grid or Flexbox (poor email client support)
        if re.search(r'display:\s*grid', content, re.IGNORECASE):
            errors.append("❌ BLOCKED: CSS Grid detected — not supported in most email clients")
        if re.search(r'display:\s*flex', content, re.IGNORECASE):
            errors.append("❌ BLOCKED: CSS Flexbox detected — not supported in most email clients")
    
        # Check 4: Has viewport meta tag
        if not re.search(r'<meta[^>]*name=["\']viewport["\']', content, re.IGNORECASE):
            warnings.append("⚠️  Missing viewport meta tag — may not render properly on mobile")
    
        # Check 5: Inline styles preferred over <style> tags
        if re.search(r'<style[^>]*>', content, re.IGNORECASE):
            style_count = len(re.findall(r'<style[^>]*>', content, re.IGNORECASE))
            warnings.append(f"⚠️  {style_count} <style> tag(s) found — inline styles have better email client support")
    
        is_valid = len(errors) == 0
        messages = errors + warnings
    
        return is_valid, messages
    
    
    def main():
        if len(sys.argv) < 2:
            print("Usage: validate-email-html.py <file_path>", file=sys.stderr)
            sys.exit(1)
    
        file_path = sys.argv[1]
        is_valid, messages = validate_html_email(file_path)
    
        if messages:
            print("HTML email validation results:")
            for msg in messages:
                print(msg)
            print()
    
        if is_valid:
            if messages:
                print("✓ Validation passed (warnings above are advisory)")
            sys.exit(0)
        else:
            print("✗ Validation failed — see errors above")
            sys.exit(2)
    
    
    if __name__ == '__main__':
        main()
    

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

@agricidaniel
Ships withemail

Professional email management, deliverability optimization, and marketing strategy powered by Claude Code

1326 skills4 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
132
Star history of AgriciDaniel/claude-email on GitHub, a chart by star-history.com

More plugins that ship hooks.

claude-seo
Plugin

claude-seo

An open-source SEO analysis plugin for Claude Code covering technical SEO, content quality, Schema.org markup, AI search optimization, local SEO and e-commerce, with specialist skills for keyword data, backlinks, image generation and site crawling.

33 skills+223k
@agricidaniel@agricidaniel
Install Plugin
aaron-marketing
Plugin

aaron-marketing

Gives a marketing team an AI staff for planning and running campaigns across SEO, content, paid ads, email, influencer work and product launches. Each area comes with ready-made commands that work on data you supply.

7 hooks+13k
@aaron-he-zhu@aaron-he-zhu
Install Plugin
ralph-wiggum-marketer
Plugin

ralph-wiggum-marketer

Runs an autonomous loop for SaaS content marketing and copywriting, with commands to initialize, run, check status, and cancel it. A stop hook keeps the loop going when an agent stops.

1 skill+2779
@muratcankoylan@muratcankoylan
Install Plugin
claude-repurpose
Plugin

claude-repurpose

Content Repurposing Engine for Claude Code, Turn 1 piece of content into 10+ platform-optimized posts in seconds.

21 skills+2163
@agricidaniel@agricidaniel
Install Plugin
content-ideas
Plugin

content-ideas

Scrapes tracked competitor accounts on X, Instagram, TikTok and YouTube, scores what is performing well, and turns it into a daily feed of content ideas framed against your own brand.

1 skill+2145
@bradautomates@bradautomates
Install Plugin
claude-seo-ai
Plugin

claude-seo-ai

The SEO + AI-search (GEO/AEO) optimization toolkit for Claude Code, two-score audit + opt-in fixer. Built for 2026-2027.

34 skills+278
@hainrixz@hainrixz
Install Plugin
akii-seo-ai-search-optimizer
Plugin

akii-seo-ai-search-opt…

A free Claude Code toolkit for SEO, AI answer engine optimization, and generative engine optimization. Its skills cover AI visibility checks, broken link audits, competitor scorecards, content briefs, and content strategy plans.

12 skills+377
@akii-technologies-ltd@akii-technologies-ltd
Install Plugin
agentic-seo
Plugin

agentic-seo

A Claude Code plugin for SEO work, with skills for keyword and competitor research, backlink analysis, technical checks, and content planning. Agents handle the research and analysis while the user keeps the final judgment.

21 skills+351
@agencia-conversion@agencia-conversion
Install Plugin

Questions about the hooks in email.

Which coding agents can use the hooks in email?
The hooks in email install in Claude Code and Cursor: each runs Claude Code hooks from .claude/settings.json, so copy the hooks there.