Add hooks and refactor skills to use resources pattern
Phase 1 of plugin-structure refactor: - Add hooks/hooks.json for SessionStart automation - Refactor gmail skill: - Extract inline scripts to scripts/check_unread.py, check_urgent.py, search.py - Add references/query-patterns.md for query documentation - Simplify SKILL.md to reference scripts instead of inline code - Add gcal/scripts/agenda.py for direct calendar access - Make all scripts executable This follows the "Skill with Bundled Resources" pattern from developing-claude-code-plugins best practices. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
48
skills/gmail/scripts/check_unread.py
Executable file
48
skills/gmail/scripts/check_unread.py
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check unread emails, grouped by sender."""
|
||||
import os
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
# Set credentials path
|
||||
os.environ.setdefault('GMAIL_CREDENTIALS_PATH', os.path.expanduser('~/.gmail-mcp/credentials.json'))
|
||||
|
||||
from gmail_mcp.utils.GCP.gmail_auth import get_gmail_service
|
||||
|
||||
def main():
|
||||
days = int(sys.argv[1]) if len(sys.argv) > 1 else 7
|
||||
max_results = int(sys.argv[2]) if len(sys.argv) > 2 else 25
|
||||
|
||||
service = get_gmail_service()
|
||||
results = service.users().messages().list(
|
||||
userId='me',
|
||||
q=f'is:unread newer_than:{days}d',
|
||||
maxResults=max_results
|
||||
).execute()
|
||||
|
||||
by_sender = defaultdict(list)
|
||||
for msg in results.get('messages', []):
|
||||
detail = service.users().messages().get(
|
||||
userId='me',
|
||||
id=msg['id'],
|
||||
format='metadata',
|
||||
metadataHeaders=['From', 'Subject']
|
||||
).execute()
|
||||
headers = {h['name']: h['value'] for h in detail['payload']['headers']}
|
||||
sender = headers.get('From', 'Unknown').split('<')[0].strip().strip('"')
|
||||
by_sender[sender].append(headers.get('Subject', '(no subject)')[:50])
|
||||
|
||||
if not by_sender:
|
||||
print("No unread emails in the last", days, "days")
|
||||
return
|
||||
|
||||
print(f"Unread emails (last {days} days):\n")
|
||||
for sender, subjects in sorted(by_sender.items(), key=lambda x: -len(x[1])):
|
||||
print(f"* {sender} ({len(subjects)})")
|
||||
for s in subjects[:2]:
|
||||
print(f" - {s}")
|
||||
if len(subjects) > 2:
|
||||
print(f" - ...+{len(subjects)-2} more")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
38
skills/gmail/scripts/check_urgent.py
Executable file
38
skills/gmail/scripts/check_urgent.py
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check for urgent unread emails."""
|
||||
import os
|
||||
|
||||
# Set credentials path
|
||||
os.environ.setdefault('GMAIL_CREDENTIALS_PATH', os.path.expanduser('~/.gmail-mcp/credentials.json'))
|
||||
|
||||
from gmail_mcp.utils.GCP.gmail_auth import get_gmail_service
|
||||
|
||||
def main():
|
||||
service = get_gmail_service()
|
||||
results = service.users().messages().list(
|
||||
userId='me',
|
||||
q='is:unread newer_than:3d (subject:urgent OR subject:asap OR subject:"action required" OR is:important)',
|
||||
maxResults=15
|
||||
).execute()
|
||||
|
||||
messages = results.get('messages', [])
|
||||
if not messages:
|
||||
print("No urgent emails found")
|
||||
return
|
||||
|
||||
print(f"Found {len(messages)} urgent email(s):\n")
|
||||
for msg in messages:
|
||||
detail = service.users().messages().get(
|
||||
userId='me',
|
||||
id=msg['id'],
|
||||
format='metadata',
|
||||
metadataHeaders=['From', 'Subject', 'Date']
|
||||
).execute()
|
||||
headers = {h['name']: h['value'] for h in detail['payload']['headers']}
|
||||
print(f"From: {headers.get('From', 'Unknown')}")
|
||||
print(f"Subject: {headers.get('Subject', '(no subject)')}")
|
||||
print(f"Date: {headers.get('Date', 'Unknown')}")
|
||||
print("---")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
47
skills/gmail/scripts/search.py
Executable file
47
skills/gmail/scripts/search.py
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Search emails with a custom query."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Set credentials path
|
||||
os.environ.setdefault('GMAIL_CREDENTIALS_PATH', os.path.expanduser('~/.gmail-mcp/credentials.json'))
|
||||
|
||||
from gmail_mcp.utils.GCP.gmail_auth import get_gmail_service
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: search.py <query> [max_results]")
|
||||
print("Example: search.py 'from:github.com' 10")
|
||||
sys.exit(1)
|
||||
|
||||
query = sys.argv[1]
|
||||
max_results = int(sys.argv[2]) if len(sys.argv) > 2 else 20
|
||||
|
||||
service = get_gmail_service()
|
||||
results = service.users().messages().list(
|
||||
userId='me',
|
||||
q=query,
|
||||
maxResults=max_results
|
||||
).execute()
|
||||
|
||||
messages = results.get('messages', [])
|
||||
if not messages:
|
||||
print(f"No emails found for query: {query}")
|
||||
return
|
||||
|
||||
print(f"Found {len(messages)} email(s) for query: {query}\n")
|
||||
for msg in messages:
|
||||
detail = service.users().messages().get(
|
||||
userId='me',
|
||||
id=msg['id'],
|
||||
format='metadata',
|
||||
metadataHeaders=['From', 'Subject', 'Date']
|
||||
).execute()
|
||||
headers = {h['name']: h['value'] for h in detail['payload']['headers']}
|
||||
print(f"From: {headers.get('From', 'Unknown')}")
|
||||
print(f"Subject: {headers.get('Subject', '(no subject)')}")
|
||||
print(f"Date: {headers.get('Date', 'Unknown')}")
|
||||
print("---")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user