From teamclco-harness
회의록 산출물(PDF 첨부 + Google Docs 링크)을 검정 프리미엄 HTML 레터헤드로 포장해 이메일 발송한다. 기본 수신자는 [email protected](외부 Naver 주소). "회의록 보내", "회의록 발송", "회의록 이메일", "미팅 결과 공유", "sesilao에게 발송", "외부 공유" 같은 회의록/문서 발송 요청이면 이 스킬을 사용하라. 외부 주소 발송이므로 반드시 (1) 본문 미리보기를 사용자에게 보여주고 (2) "보내"/"발송"/"OK" 같은 명시 승인을 받은 뒤에만 실제 발송한다 — 승인 전에는 절대 발송하지 않는다. meeting-minutes 스킬이 회의록을 만든 뒤 이어서 호출하거나, 사용자가 직접 단독으로 호출할 수 있다.
How this skill is triggered — by the user, by Claude, or both
Slash command
/teamclco-harness:meeting-mailThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> 비유: 완성된 회의록을 고급 레터헤드 봉투에 담아 보내는 비서. 단, 봉투를 봉하기 전에 반드시 대표에게 "이대로 보낼까요?"를 보여주고, "보내"라는 답을 들은 뒤에만 우체통에 넣는다.
비유: 완성된 회의록을 고급 레터헤드 봉투에 담아 보내는 비서. 단, 봉투를 봉하기 전에 반드시 대표에게 "이대로 보낼까요?"를 보여주고, "보내"라는 답을 들은 뒤에만 우체통에 넣는다.
회의록 PDF + Google Docs 링크를 검정 프리미엄 HTML(정본: .claude/rules/email-design.md)로 포장해 발송한다. 외부(naver) 주소 발송이라 미리보기 → 사용자 승인 게이트가 핵심 안전장치다.
pdf_path: 첨부할 회의록 PDF 절대경로 (필수)gdocs_url: Google Docs 공유 링크 (선택)title/date: 제목·날짜 (제목 줄에 사용)recipient: 수신자. 미지정 시 기본값 [email protected]meeting-minutes 스킬에서 이어서 호출된 경우, 직전 산출물 경로(minutes-final.pdf/minutes.pdf, Docs URL)가 메인 세션 컨텍스트에 그대로 있으므로 그 값을 사용한다.
이 스킬의 base directory를 $SKILL_DIR이라 하자 (= $HOME/팀클코/.claude/skills/meeting-mail).
$SKILL_DIR/scripts/send_meeting_mail.py — MIME multipart 빌드 + 발송. 기본 dry-run, --send가 있을 때만 실제 발송. Step 5에서 사용.PDF="<pdf_path>"
if [ ! -f "$PDF" ]; then echo "중단: PDF 없음 — $PDF"; exit 1; fi
file "$PDF" | grep -qi pdf || { echo "중단: PDF 형식 아님"; exit 1; }
SIZE=$(stat -f%z "$PDF"); echo "PDF 크기: $((SIZE/1024)) KB"
[ "$SIZE" -gt 0 ] || { echo "중단: 0바이트"; exit 1; }
[ "$SIZE" -gt 26214400 ] && echo "경고: 25MB 초과 — 첨부 대신 Drive 링크 권장"
pdftotext "$PDF" /dev/null 2>/dev/null && echo "텍스트 추출 OK" || echo "경고: 텍스트 추출 실패(이미지 PDF일 수 있음 — 정상)"
.claude/rules/email-design.md §5 완성형 골격을 정본으로 사용한다. 골격을 그대로 쓰되 { } 자리만 회의 내용으로 치환해 /tmp/email.html에 Write로 저장한다 (인라인 스타일만, <style> 블록 0개).
<!DOCTYPE html>
<html lang="ko"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="dark light">
</head>
<body style="margin:0;padding:0;background:#0A0A0A;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#0A0A0A;">
<tr><td align="center" style="padding:24px 12px;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="width:100%;max-width:600px;background:#141414;border-radius:12px;overflow:hidden;border:1px solid #2A2A2A;">
<tr><td style="padding:28px 32px 20px;background:#0A0A0A;border-bottom:1px solid #2A2A2A;">
<img src="https://qjc.app/logo-white.png" width="132" alt="QJC 퀀텀점프클럽" style="display:block;border:0;height:auto;">
<div style="margin-top:8px;height:2px;width:40px;background:#2563EB;font-size:0;line-height:0;"> </div>
</td></tr>
<tr><td style="padding:32px;font-family:-apple-system,'Apple SD Gothic Neo','Noto Sans KR','맑은 고딕',sans-serif;color:#F2F2F2;font-size:16px;line-height:1.7;">
<p style="margin:0 0 16px;">안녕하세요,</p>
<p style="margin:0 0 16px;">{회의 제목·날짜 회의록을 전달드립니다. 핵심 결론 한 줄}</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:24px 0;background:#1C1C1C;border-left:3px solid #2563EB;border-radius:6px;">
<tr><td style="padding:16px 20px;color:#E0E0E0;font-size:15px;line-height:1.6;">{결정사항·액션아이템 요약 2~4줄}</td></tr>
</table>
<table role="presentation" cellpadding="0" cellspacing="0" style="margin:8px 0 4px;">
<tr><td style="background:#2563EB;border-radius:6px;">
<a href="{GOOGLE_DOCS_URL}" style="display:inline-block;padding:13px 28px;color:#FFFFFF;font-family:-apple-system,'Apple SD Gothic Neo',sans-serif;font-size:15px;font-weight:600;text-decoration:none;">회의록 원문 보기</a>
</td></tr>
</table>
<p style="margin:16px 0 0;color:#9A9A9A;font-size:13px;">PDF 회의록을 첨부드립니다.</p>
</td></tr>
<tr><td style="padding:24px 32px 28px;background:#0A0A0A;border-top:1px solid #2A2A2A;font-family:-apple-system,'Apple SD Gothic Neo','Noto Sans KR',sans-serif;">
<p style="margin:0 0 4px;color:#F2F2F2;font-size:14px;font-weight:600;">정상록 <span style="color:#9A9A9A;font-weight:400;">| 대표</span></p>
<p style="margin:0 0 10px;color:#9A9A9A;font-size:13px;line-height:1.6;">퀀텀점프클럽 (QJC)</p>
<p style="margin:0;color:#9A9A9A;font-size:13px;line-height:1.7;">
010-0000-0000 ·
<a href="mailto:[email protected]" style="color:#5B8DEF;text-decoration:none;">[email protected]</a><br>
<a href="https://qjc.app" style="color:#5B8DEF;text-decoration:none;">https://qjc.app</a>
</p>
</td></tr>
</table>
</td></tr>
</table>
</body></html>
Google Docs 링크가 없으면 CTA 블록 전체를 제거한다(빈 링크 금지). CTA는 1개만.
multipart/alternative용 plain part를 /tmp/email.txt에 만든다. 마크다운 마커(#/**/|...|) 금지, 순수 줄글 + 하이픈 리스트 + URL 직접 노출만.
안녕하세요,
{회의 제목} {날짜} 회의록을 전달드립니다.
핵심:
- {결정/액션 1}
- {결정/액션 2}
회의록 원문: {GOOGLE_DOCS_URL}
PDF 회의록을 첨부드립니다.
정상록 | 대표
퀀텀점프클럽 (QJC)
010-0000-0000 · [email protected]
https://qjc.app
H=/tmp/email.html
echo -n "② 인라인만(<style> 0): "; grep -c "<style" "$H" # 0 이어야 통과
echo -n "③ 로고 헤더 존재: "; grep -c "logo-white.png" "$H" # 1 이상
echo -n "③ 푸터 서명 존재: "; grep -c "정상록" "$H" # 1 이상
echo -n "⑤ fluid 600px: "; grep -c "max-width:600px" "$H" # 1 이상
echo -n "⑥ 링크 수: "; grep -oE "<a [^>]*href" "$H" | wc -l # 본문 CTA 1 + 푸터 2 = 정상, 본문 CTA는 1개만
test -f /tmp/email.txt && echo "① plain 폴백 존재: OK" || echo "① plain 폴백 없음: ✗"
④(다크 대비)·⑦(실제 다크 렌더링)은 모든 색이 hex로 명시됐는지 확인(골격이 이미 충족) + 미리보기 육안 확인. 본문 CTA(#2563EB 버튼)는 1개만 유지.
발송 전 반드시 아래 미리보기를 결론 먼저로 사용자에게 보여준다.
## 이메일 미리보기 (발송 대기 — 승인 필요)
- 수신자: [email protected] (외부 Naver 주소)
- 제목: [회의록] {날짜} {제목}
- 본문: 검정 프리미엄 HTML (헤더 로고 + 결정/액션 요약 박스 + Docs 링크 CTA + 서명)
- 첨부: {PDF 파일명} ({크기} KB)
- 자가검증: <style> 0 / 로고 1 / 서명 1 / fluid 600px / CTA 1 → 통과
이대로 발송할까요? ("보내"/"발송"/"OK" 시 발송)
외부 메일 무인 발송 금지(work-agreements.md §3 + signature-stamping.md). 승인 신호 판정:
승인이 없으면 발송하지 않는다. 필요 시 발송 여부를 한 번 더 명시적으로 묻는다.
번들 스크립트로 발송한다. 기본은 dry-run이라, 먼저 dry-run으로 최종 검증한 뒤 --send로 실제 발송한다 (drafts send는 bash-pre-guard 차단 — 스크립트는 messages send 경로 사용).
SK="$SKILL_DIR/scripts/send_meeting_mail.py"
# 5-1) dry-run 최종 검증
python3 "$SK" --to "[email protected]" --subject "[회의록] $DATE $TITLE" \
--html /tmp/email.html --txt /tmp/email.txt --pdf "<pdf_path>"
# 5-2) 실제 발송 (사용자 승인 후에만 --send 추가)
python3 "$SK" --to "[email protected]" --subject "[회의록] $DATE $TITLE" \
--html /tmp/email.html --txt /tmp/email.txt --pdf "<pdf_path>" --send
첨부가 필요 없는 단순 발송이거나 위가 실패하면, 실재 헬퍼
~/.claude/scripts/gmail-send-markdown.py(QJC 디자인 인라인 + plain 자동)를--dry-run→ 승인 후 발송 순으로 폴백한다. 단 PDF 첨부 보장이 필요하면 번들 스크립트를 우선한다.
발송 직후 Sent에서 메시지를 확인해 수신자·첨부·라벨을 재검증한다(signature-stamping.md §3).
gws gmail users messages get --params '{"userId":"me","id":"<MESSAGE_ID>","format":"metadata"}' \
| python3 -c "import json,sys; m=json.load(sys.stdin); print('labels:', m.get('labelIds')); print('snippet:', m.get('snippet','')[:80])"
SENT 라벨 확인 + 수신자([email protected]) 일치 확인. 오기 발견 시 즉시 사용자에게 alert.--send는 승인 후에만.drafts send 경로 (bash-pre-guard 차단 — messages send/+reply 사용)<style> 블록 / 마크다운 raw를 본문에 (인라인 HTML + plain 폴백만)Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub sangrokjung/samsung-gen-ai-260624 --plugin teamclco-harness