🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Heleni Meetings

by @netanel-abergel

All-in-one meetings skill. Section 1: Schedule a meeting by coordinating with another PA, finding free slots, and sending a calendar invite. Section 2: Paste...

Versionv1.0.0
Downloads389
TERMINAL
clawhub install heleni-meetings

πŸ“– About This Skill


name: meetings description: "All-in-one meetings skill. Section 1: Schedule a meeting by coordinating with another PA, finding free slots, and sending a calendar invite. Section 2: Paste meeting notes or transcript β†’ get summary, action items with owners and deadlines."

Meetings Skill

Minimum Model

Any model. For timezone reasoning or complex scheduling constraints, use a medium model.

Trigger Phrases

  • "schedule a meeting" / "set up a meeting with X" / "book a call with Y"
  • "summarize meeting notes" / "take notes" / "action items from meeting" / "extract tasks from this transcript"

  • Section 1 β€” Schedule a Meeting

    End-to-end meeting coordination: find availability, contact the other PA, book the calendar invite.

    Step 1 β€” Understand the Request

    Before acting, confirm:

  • Who to meet with
  • Duration (default: 30 min if not specified)
  • Timeframe ("this week", "next week", "mornings only", etc.)
  • Meeting type (video, in-person, phone)
  • If the request is vague (e.g. "set up a call with Jane") β†’ ask one clarifying question before proceeding.


    Step 2 β€” Find the Other PA

    Check data/pa-directory.json:

    python3 -c "
    import json, sys
    try:
        with open('data/pa-directory.json') as f:
            d = json.load(f)
    except FileNotFoundError:
        print('ERROR: data/pa-directory.json not found')
        sys.exit(1)

    name = 'PERSON_NAME' # replace with actual name matches = [p for p in d.get('pas', []) if name.lower() in p['owner'].lower()]

    if not matches: print('No PA found for:', name) else: for p in matches: print('PA:', p['name'], '| Phone:', p['phone']) "

    If no PA found β†’ skip to Step 4 and contact the person directly by email.


    Step 3 β€” Check Owner's Availability

    #!/bin/bash
    TODAY=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    NEXT_WEEK=$(date -u -d '+7 days' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
      || date -u -v+7d +%Y-%m-%dT%H:%M:%SZ)

    GOG_ACCOUNT=owner@company.com gog calendar events primary \ --from "$TODAY" \ --to "$NEXT_WEEK" \ 2>/dev/null \ | python3 -c " import sys, json try: events = json.load(sys.stdin) except: events = []

    print('Upcoming events:') for e in sorted(events, key=lambda x: x.get('start', {}).get('dateTime', '')): start = e.get('start', {}).get('dateTime', '')[:16].replace('T', ' ') print(' ', start, 'β€”', e.get('summary', 'Untitled')) "

    Find free slots automatically:

    #!/usr/bin/env python3
    import subprocess, json, sys
    from datetime import datetime, timedelta, timezone

    OWNER_EMAIL = "owner@company.com" # replace DURATION_MIN = 30 DAYS_AHEAD = 7 WORK_START_HOUR = 9 WORK_END_HOUR = 18

    try: result = subprocess.run( ['gog', 'calendar', 'events', 'primary', '--from', datetime.now(timezone.utc).isoformat(), '--to', (datetime.now(timezone.utc) + timedelta(days=DAYS_AHEAD)).isoformat()], env={'GOG_ACCOUNT': OWNER_EMAIL, 'PATH': '/usr/bin:/usr/local/bin:/bin'}, capture_output=True, text=True, timeout=30 ) events = json.loads(result.stdout) if result.stdout.strip() else [] except Exception as e: print("Could not fetch calendar:", e) sys.exit(1)

    busy = [] for e in events: start = e.get('start', {}).get('dateTime') end = e.get('end', {}).get('dateTime') if start and end: busy.append((start, end))

    suggestions = [] for day_offset in range(1, DAYS_AHEAD + 1): day = datetime.now(timezone.utc) + timedelta(days=day_offset) if day.weekday() >= 5: continue for hour in range(WORK_START_HOUR, WORK_END_HOUR): slot_start = day.replace(hour=hour, minute=0, second=0, microsecond=0) slot_end = slot_start + timedelta(minutes=DURATION_MIN) if slot_end.hour > WORK_END_HOUR: continue conflict = any( slot_start.isoformat() < b[1] and slot_end.isoformat() > b[0] for b in busy ) if not conflict: suggestions.append(slot_start) if len(suggestions) >= 5: break if len(suggestions) >= 5: break

    if not suggestions: print("No slots found in the next 7 days during working hours.") else: print(f"Available {DURATION_MIN}-min slots:") for s in suggestions: print(" β€’", s.strftime('%A %b %d'), "at", s.strftime('%H:%M'), "UTC")


    Step 4 β€” Contact the Other PA

    Propose 3–5 specific slots:

    "Hey [PA Name], [your owner] would like to meet [their owner] for [duration].
    Slots that work:
    β€’ [Day Date] at [HH:MM TZ]
    β€’ [Day Date] at [HH:MM TZ]
    β€’ [Day Date] at [HH:MM TZ]
    Do any work? Or what times work best?"
    

    If no response within 2 hours on a business day β†’ follow up once. If still no response after 4 hours β†’ tell owner and suggest direct contact.


    Step 5 β€” Book the Meeting

    Once both sides agree:

    GOG_ACCOUNT=owner@company.com gog calendar create primary \
      --summary "Meeting: [Owner A] + [Owner B]" \
      --start "YYYY-MM-DDTHH:MM:SS+00:00" \
      --end "YYYY-MM-DDTHH:MM:SS+00:00" \
      --attendees "other-owner@company.com" \
      --description "Scheduled via PA coordination"
    

    For video calls, add:

      --description "Video call: https://meet.google.com/xxx-xxxx-xxx"
    


    Step 6 β€” Confirm Both Sides

    To your owner:
    "βœ… Done β€” [Date] at [Time] with [Person]. Calendar invite sent."

    To the other PA: "βœ… Invite sent to [Their Owner] for [Date] [Time]. Let me know if anything changes."

    Quick Templates

    | Situation | Template | |---|---| | Initial request | "Hey [PA], [Owner A] wants to connect with [Owner B] for ~30 min [this/next] week. What works?" | | Propose slots | "Here are 3 options: [A], [B], [C]. Any work?" | | Confirm | "βœ… Booked for [time]. Invite sent to [email]." | | Reschedule | "[Owner] can't make [time]. Can we try [alternative]?" | | Cancel | "[Owner] needs to cancel [time]. Apologies." |

    Rescheduling

    # Find the event
    GOG_ACCOUNT=owner@company.com gog calendar events primary \
      --from "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
      --to "$(date -u -d '+14 days' +%Y-%m-%dT%H:%M:%SZ)"

    Delete old event (use ID from above)

    GOG_ACCOUNT=owner@company.com gog calendar delete primary EVENT_ID

    Re-coordinate and create new event


    Section 2 β€” Meeting Notes & Action Items

    Paste any meeting notes, transcript, or text β†’ get a clean summary with action items, owners, and deadlines.

    Response Format (MANDATORY β€” One Message Only)

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    πŸ“‹ [MEETING TITLE] β€” [YYYY-MM-DD]
    Duration: [X min] | Attendees: [Names]
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    SUMMARY [2-3 sentence overview]

    ⚑ ACTION ITEMS ([X] of [Total]) 1. [ ] @Owner: Task β€” Deadline 2. [ ] @Owner: Task β€” Deadline 3. [ ] @Owner: Task β€” Deadline

    βœ… KEY DECISIONS β€’ Decision 1 β€’ Decision 2

    πŸ“Ž Saved: meeting-notes/YYYY-MM-DD_topic-name.md

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Add to your to-do list? β€’ "all" β€” Add all [X] items β€’ "1,2,4" β€” Add specific items β€’ "none" β€” Skip

    Rules:

  • ONE message only β€” never split into multiple
  • Filename format: YYYY-MM-DD_topic.md (date first, always)
  • Always show numbered action items
  • Always include the to-do prompt if action items exist
  • What to Extract

    | Section | Description | |---------|-------------| | Summary | 2-3 sentence overview | | Action Items | - [ ] @Owner: Task β€” Deadline | | Decisions | What was agreed upon | | Open Questions | Unresolved items | | Next Steps | What happens after this meeting |

    File Storage

    Save all meeting notes to meeting-notes/YYYY-MM-DD_topic.md:

    ---
    date: YYYY-MM-DD
    title: Meeting Title
    attendees: [Name1, Name2]
    source: pasted notes | transcript | email
    

    Meeting Title

    Summary

    [2-3 sentences]

    Action Items

  • [ ] @Owner: Task description β€” *Deadline*
  • Decisions

  • Decision 1
  • Open Questions

  • Question 1
  • πŸ“ Raw Notes [Original input preserved]

    To-Do List Integration

    After extracting action items:

  • "all" β†’ Add all items to todo.md
  • "1,3,5" β†’ Add specific items
  • "none" β†’ Skip
  • File: todo.md in workspace root. Organized by: Overdue β†’ Due Today β†’ This Week β†’ No Deadline β†’ Completed.

    Referencing Previous Meetings

    Ask things like:

  • "What did we decide about the budget?" β†’ search meeting-notes/ Decisions sections
  • "What action items does @Sarah have?" β†’ search for @Sarah across all files
  • "Show me last week's meetings" β†’ list files from date range
  • Edge Cases

    | Situation | Action | |---|---| | Very short notes | Still extract what's there | | No clear topic | Ask: "What should I call this meeting?" | | Multiple meetings in one paste | Ask if they should be separated into files | | Not meeting notes | Still extract actionable items; adjust filename |


    Cost Tips

  • Scheduling: Cheap β€” any small model works for slot-finding and coordination.
  • Notes extraction: Medium model recommended for complex transcripts with many action items.
  • Batch: Propose 3–5 slots at once instead of one at a time.
  • Don't re-fetch calendar repeatedly β€” fetch once, extract 5 slots, propose them all.