Claude Code Plugins

Community-maintained marketplace

Feedback

format-cover-letter

@AJBcoding/claude-sync
0
0

Intelligent cover letter formatting with semantic understanding of structure and content (project, gitignored)

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name format-cover-letter
description Intelligent cover letter formatting with semantic understanding of structure and content (project, gitignored)

Format Cover Letter Skill

Purpose

Format cover letters with intelligent style application and automatic play title italicization. Uses the shared career documents template with 19 semantic styles and learns from your corrections over time.

Usage

Format with just body text (metadata auto-inferred):

Format this cover letter: [paste body paragraphs only]

I'll infer contact block, date, recipient, and RE line!

Format with complete JSON:

Format this cover letter: [paste full JSON with metadata]

Format from file:

Format my-cover-letter.txt

How It Works

  1. Semantic Analysis: I analyze content to understand elements (contact info, recipient address, RE line, body text, etc.)

  2. Style Mapping: Based on context, I assign appropriate styles:

    • "ANTHONY BYRNES" at top → Contact Name
    • "RE: Position Title" → RE Line (bold orange)
    • Body text mentioning "Louis & Keely: Live at the Sahara" → Auto-italicized via dictionary
  3. Hybrid Inline Styling: Play/production titles automatically italicized:

    • Dictionary lookup (95% of cases - no manual markup needed)
    • Manual override for new/unknown plays
    • Exclusion for edge cases
  4. Generate Document: Create formatted .docx using template

  5. Visual Preview: Show PDF preview for review

  6. Learn from Corrections: If you correct a style choice, I remember for next time

The 19 Styles

Paragraph Styles:

  • CV Name - Your name at top
  • Contact Name - Bold, 10pt (cover letter header)
  • Contact Info - Regular, 10pt (phone/email)
  • Recipient Address - Regular, 11pt (organization address)
  • RE Line - Bold, 13pt, ORANGE (position/subject line)
  • Date Line - Right-aligned, 11pt (document date)
  • Section Header - Bold, ORANGE (11pt for CV, 13pt for cover letter)
  • Body Text - Standard paragraphs, 11pt
  • Timeline Entry - Date + institution with hanging indent (CV only)
  • Page Header - Bold, 10pt (page 2+ headers)
  • Bullet Standard, Bullet Gray, Bullet Emphasis - List variations

Character Styles (inline):

  • Play Title - Italic for productions (auto-styled via dictionary!)
  • Institution - Bold for school/company names
  • Job Title - Bold italic for positions
  • Orange Emphasis - Highlight text
  • Gray Text - Dates, secondary info

Cover Letter Elements

Contact Block (top of page):

ANTHONY BYRNES
T: 213.305.3132
E: anthonybyrnes@mac.com

Recipient Address:

Colburn School
200 South Grand Avenue
Los Angeles, CA 90012

RE Line (bold orange, same as section headers):

RE: General Manager of Performances & Events Division

Body Text with auto-italicized play titles:

For Louis & Keely: Live at the Sahara, I generated $1.4 million...

→ "Louis & Keely: Live at the Sahara" automatically italicized from dictionary

Signature:

Sincerely,

[signature image]

Anthony Byrnes

Metadata Inference (NEW!)

You provide: Raw text or minimal JSON (just body paragraphs)

I infer:

  • Contact block (from defaults.yaml)
  • Date line (today's date)
  • Recipient address (from job description or content)
  • RE line (from job title)
  • Salutation (extracted from content)

Smart Job Description Matching:

  1. I search career-applications/*/00-job-description.md files
  2. Match based on organization/position mentioned in your letter
  3. Confirm with you: "Found job description for UCLA - Associate Dean. Use this?"
  4. Extract recipient and RE line from confirmed job description

Confirmation Before Formatting:

Inferred Metadata:

Contact:       ✓ ANTHONY BYRNES
               ✓ T: 213.305.3132
               ✓ E: anthonybyrnes@mac.com

Date:          November 11, 2025

Recipient:     UCLA School of Theater, Film and Television

RE:            Associate Dean and Chief Administrative Officer [CAO]

Salutation:    Dear Search Committee,

Looks correct? (yes/modify/[field name])

Configuration:

  • Defaults: ~/.claude/skills/format-cover-letter/defaults.yaml
  • Job descriptions: Auto-searched in career-applications/

Workflow

Step 1: Analyze Content

I'll parse your content and create JSON structure:

{
  "document_metadata": {
    "type": "cover-letter",
    "author_name": "Anthony Byrnes",
    "document_title": "Position Title Cover Letter"
  },
  "content": [
    {"text": "ANTHONY BYRNES", "style": "Contact Name", "type": "paragraph"},
    {"text": "RE: Position Title", "style": "RE Line", "type": "paragraph"},
    {"text": "Body with play title...", "style": "Body Text", "type": "paragraph"}
  ]
}

Step 2: Generate Document

I'll call the formatter to create your .docx:

import json
import subprocess
from pathlib import Path

# Save content mapping
mapping_file = "/tmp/cover_letter_mapping.json"
with open(mapping_file, 'w') as f:
    json.dump(data, f, indent=2)

# Format document
result = subprocess.run([
    "python3",
    "format_cv.py",
    mapping_file,
    output_path,
    "--document-type", "cover-letter",
    "--preview"
], capture_output=True, text=True, cwd=str(Path.home() / "PycharmProjects/career-lexicon-builder"))

Step 3: Visual Preview

I'll convert to PDF and show you what it looks like using the open command.

Step 4: Review

You can request changes: "That venue should be italic" or "Don't emphasize that number"

Step 5: Learn (if corrections made)

If you made corrections, I'll update learned-preferences.yaml and add new plays to play-titles-dictionary.yaml.

Hybrid Inline Styling

The Problem: Manually marking up every play title is tedious:

{
  "text": "For Louis & Keely: Live at the Sahara, I...",
  "runs": [
    {"text": "For ", "style": null},
    {"text": "Louis & Keely: Live at the Sahara", "style": "Play Title"},
    {"text": ", I...", "style": null}
  ]
}

The Solution: Dictionary auto-styling (95% of cases):

{
  "text": "For Louis & Keely: Live at the Sahara, I...",
  "style": "Body Text"
}

→ "Louis & Keely: Live at the Sahara" automatically italicized from dictionary!

Dictionary Location:

~/.claude/skills/format-cover-letter/play-titles-dictionary.yaml

Example dictionary:

productions:
  - "Louis & Keely: Live at the Sahara"
  - "Romeo & Juliet"
  - "Hamlet"

programs:
  - "Experience LA!"

Manual Override (for new/unknown plays):

{
  "text": "For My New Play, I generated...",
  "style": "Body Text",
  "inline_styles": [
    {"text": "My New Play", "style": "Play Title"}
  ]
}

Exclusion (when dictionary shouldn't apply):

{
  "text": "We decided NOT to produce Romeo & Juliet.",
  "inline_styles": [
    {"text": "Romeo & Juliet", "exclude": true}
  ]
}

Learning System

You: "Add 'The Tempest' to the dictionary"

Me: ✓ Added to play-titles-dictionary.yaml

Next cover letter: Automatically italicizes "The Tempest" without asking.

Signature Images

Setup signature:

  1. Create PNG of your signature (~1.5 inches wide, transparent background)
  2. Save to: ~/.claude/skills/format-cover-letter/signatures/signature.png
  3. Reference in JSON: {"text": "signature", "style": "Signature Image", "type": "image"}

If signature missing: System logs warning and continues without image.

Template Location

Shared template path:

cv_formatting/templates/career-documents-template.docx

Why shared? Same template as format-resume ensures visual consistency across CV and cover letter.

Key Differences from CV Formatting

Aspect CV (format-resume) Cover Letter (this skill)
Organization Timeline-based sections Narrative paragraphs
Section Headers Orange, 11pt Orange, 13pt (bug fixed!)
Main Content Timeline entries, bullets Body text paragraphs
Special Elements Hanging indent timelines Contact block, RE line, signature
Inline Styling Manual only Hybrid (dictionary + manual)

IMPORTANT: Section headers are ALWAYS ORANGE for both CVs and cover letters. Earlier versions incorrectly made cover letter headers black.

Error Handling

Template not found:

Run: python generate_cv_template.py

PDF preview not available:

Install: brew install libreoffice

Image generation skipped:

Install: brew install poppler

Files

  • career-documents-template.docx - Shared template with 19 semantic styles
  • format_cv.py - Main formatting script
  • play-titles-dictionary.yaml - Known plays for auto-italicization
  • learned-preferences.yaml - Your accumulated corrections
  • signatures/ - Directory for signature images

JSON Export for Wrapper Application

After formatting the cover letter, export structured formatting metadata to enable wrapper application integration.

Phase 6: JSON Export

Write to: cover-letter-formatted-v1.json (increment version if exists)

Implementation:

  1. Check if cover-letter-formatted-v1.json already exists
  2. If exists, increment version: cover-letter-formatted-v2.json, cover-letter-formatted-v3.json, etc.
  3. Extract formatting metadata from the document generation process
  4. Write JSON file with proper formatting (2-space indentation)
  5. Save to same directory as output files

Structure:

{
  "metadata": {
    "created_at": "YYYY-MM-DDTHH:MM:SSZ",
    "version": 1,
    "skill": "format-cover-letter",
    "input_file": "cover-letter-draft.md",
    "output_file": "cover-letter-formatted.pdf"
  },
  "formatting_metadata": {
    "template": "career-documents-template.docx",
    "template_path": "cv_formatting/templates/career-documents-template.docx",
    "font": "Helvetica",
    "font_size": 11,
    "margins": {
      "top": 0.75,
      "bottom": 0.75,
      "left": 1.0,
      "right": 1.0
    },
    "line_spacing": 1.15,
    "paragraph_spacing": 0.15,
    "letterhead": true,
    "signature": "included"
  },
  "content_structure": {
    "header": {
      "name": "ANTHONY BYRNES",
      "contact": {
        "phone": "213.305.3132",
        "email": "anthonybyrnes@mac.com"
      },
      "validation": "passed"
    },
    "date": {
      "text": "November 12, 2025",
      "format": "MMMM DD, YYYY",
      "validation": "passed"
    },
    "recipient": {
      "organization": "UCLA School of Theater, Film and Television",
      "address_lines": [
        "UCLA School of Theater, Film and Television",
        "102 East Melnitz Hall",
        "Los Angeles, CA 90095"
      ],
      "validation": "passed"
    },
    "re_line": {
      "text": "RE: Associate Dean and Chief Administrative Officer [CAO]",
      "style": "RE Line",
      "validation": "passed"
    },
    "salutation": {
      "text": "Dear Search Committee,",
      "validation": "passed"
    },
    "body": [
      {
        "paragraph": 1,
        "purpose": "opening",
        "word_count": 85,
        "has_play_titles": true,
        "inline_styles_applied": 2,
        "validation": "passed"
      },
      {
        "paragraph": 2,
        "purpose": "body",
        "word_count": 120,
        "has_play_titles": true,
        "inline_styles_applied": 3,
        "validation": "passed"
      },
      {
        "paragraph": 3,
        "purpose": "body",
        "word_count": 95,
        "has_play_titles": false,
        "inline_styles_applied": 1,
        "validation": "passed"
      },
      {
        "paragraph": 4,
        "purpose": "closing",
        "word_count": 42,
        "has_play_titles": false,
        "inline_styles_applied": 0,
        "validation": "passed"
      }
    ],
    "closing": {
      "salutation": "Sincerely,",
      "signature_space": true,
      "signature_image": true,
      "name": "Anthony Byrnes",
      "validation": "passed"
    }
  },
  "validation_results": {
    "total_checks": 12,
    "passed": 12,
    "failed": 0,
    "warnings": 0,
    "checks": [
      {"check": "header_present", "status": "passed"},
      {"check": "date_format_correct", "status": "passed"},
      {"check": "recipient_complete", "status": "passed"},
      {"check": "re_line_formatted", "status": "passed"},
      {"check": "salutation_professional", "status": "passed"},
      {"check": "body_paragraphs_present", "status": "passed"},
      {"check": "play_titles_italicized", "status": "passed"},
      {"check": "inline_styles_applied", "status": "passed"},
      {"check": "closing_complete", "status": "passed"},
      {"check": "signature_included", "status": "passed"},
      {"check": "page_count_valid", "status": "passed"},
      {"check": "professional_tone", "status": "passed"}
    ],
    "issues": []
  },
  "styling_metadata": {
    "play_titles_dictionary_used": true,
    "dictionary_matches": [
      "Louis & Keely: Live at the Sahara",
      "Romeo & Juliet"
    ],
    "manual_inline_styles": [
      {"text": "The New Play", "style": "Play Title", "reason": "not in dictionary"}
    ],
    "exclusions": [],
    "styles_applied": {
      "Contact Name": 1,
      "Contact Info": 2,
      "Date Line": 1,
      "Recipient Address": 3,
      "RE Line": 1,
      "Body Text": 4,
      "Play Title": 5,
      "Institution": 3,
      "Job Title": 2
    }
  },
  "metrics": {
    "page_count": 1,
    "word_count": 342,
    "paragraph_count": 4,
    "sentence_count": 18,
    "estimated_read_time_seconds": 80,
    "average_paragraph_length": 85,
    "readability_score": 0.90,
    "professionalism_score": 0.93,
    "visual_appeal_score": 0.91
  },
  "output_files": [
    {
      "type": "docx",
      "path": "cover-letter-formatted.docx",
      "size_bytes": 87654,
      "created_at": "YYYY-MM-DDTHH:MM:SSZ"
    },
    {
      "type": "pdf",
      "path": "cover-letter-formatted.pdf",
      "size_bytes": 156432,
      "created_at": "YYYY-MM-DDTHH:MM:SSZ"
    }
  ],
  "learned_preferences": {
    "new_plays_added": ["The New Play"],
    "style_corrections": [],
    "user_feedback": ""
  }
}

Present to user:

Formatting complete! Saved to:
- cover-letter-formatted.docx (formatted document)
- cover-letter-formatted.pdf (visual preview)
- cover-letter-formatted-v1.json (structured metadata)

Document metrics:
- Pages: 1
- Word count: 342
- Paragraphs: 4
- Validation: 12/12 checks passed
- Readability score: 0.90

All play titles automatically italicized from dictionary. Ready for review!

Related

  • Format Resume Skill: ~/.claude/skills/format-resume/skill.md
  • Implementation Handoff: docs/handoffs/2025-11-11-cover-letter-formatting-implementation-complete.md
  • Template generation: python generate_cv_template.py

Ready to format your cover letter?

Just say: "Format this cover letter: [your content]"