listener-creator
The listener-creator skill generates TypeScript event listeners that monitor email activity and automatically trigger custom actions based on specified conditions. Use it when you need to set up email automation workflows, receive notifications for specific email patterns, or automatically process emails that match criteria like sender, subject keywords, or time-based triggers.
git clone --depth 1 https://github.com/anthropics/claude-agent-sdk-demos /tmp/listener-creator && cp -r /tmp/listener-creator/email-agent/agent/.claude/skills/listener-creator ~/.claude/skills/listener-creatorSKILL.md
# Listener Creator
Creates TypeScript listener files that monitor email events and execute custom logic when conditions are met.
## When to Use This Skill
Use this skill when the user wants to:
- Get notifications about specific emails ("notify me when boss sends urgent emails")
- Automatically handle certain emails ("auto-archive newsletters")
- Monitor for patterns ("watch for package tracking emails")
- Set up scheduled actions ("daily email summary at 9am")
- Create custom email workflows
## How Listeners Work
Listeners are TypeScript files in `agent/custom_scripts/listeners/` that:
1. Export a `config` object defining the event type and metadata
2. Export a `handler` function that filters and processes events
3. Use `ListenerContext` methods to perform actions (notify, archive, star, etc.)
The system automatically loads enabled listeners and executes them when matching events occur.
## Creating a Listener
### 1. Understand the User's Intent
Parse the user's request to identify:
- **Event type**: What triggers this listener? (email_received, email_sent, email_starred, email_archived, email_labeled, scheduled_time)
- **Filter conditions**: What specific emails/events to match? (sender, subject keywords, time-based)
- **Actions**: What should happen? (notify, archive, star, mark as read, add label)
- **Priority**: How urgent is this? (high/normal/low)
### 2. Choose an Event Type
```typescript
// Available event types:
- "email_received" // Most common - new email arrives
- "email_sent" // User sends an email
- "email_starred" // Email is starred
- "email_archived" // Email is archived
- "email_labeled" // Label added to email
- "scheduled_time" // Time-based (cron) - requires scheduler setup
```
### 3. Write the Listener File
Create a file in `agent/custom_scripts/listeners/` with this structure:
```typescript
import type { ListenerConfig, Email, ListenerContext } from "../types";
export const config: ListenerConfig = {
id: "unique_listener_id", // kebab-case, descriptive
name: "Human Readable Name", // For UI display
description: "What this does", // Optional but helpful
enabled: true, // Start enabled
event: "email_received" // Event type
};
export async function handler(email: Email, context: ListenerContext): Promise<void> {
// 1. Basic filter (identity/sender only)
if (!email.from.includes("example@email.com")) return;
// 2. Use AI for intelligent classification (PREFERRED over keyword matching)
const analysis = await context.callAgent<{ isUrgent: boolean; reason: string }>({
prompt: `Is this email urgent?\nSubject: ${email.subject}\nBody: ${email.body.substring(0, 500)}`,
schema: {
type: "object",
properties: {
isUrgent: { type: "boolean" },
reason: { type: "string" }
},
required: ["isUrgent", "reason"]
},
model: "haiku"
});
if (!analysis.isUrgent) return;
// 3. Perform actions via context methods
await context.notify(`Urgent email: ${email.subject}\n${analysis.reason}`, {
priority: "high"
});
await context.starEmail(email.messageId);
}
```
### 4. File Naming Convention
Use kebab-case matching the listener's purpose:
- `boss-urgent-watcher.ts`
- `auto-archive-newsletters.ts`
- `package-tracking.ts`
- `daily-summary.ts`
### 5. Available Context Methods
The `ListenerContext` provides these methods:
```typescript
// Notifications
await context.notify(message, { priority: "high" | "normal" | "low" });
// Email actions
await context.archiveEmail(emailId);
await context.starEmail(emailId);
await context.unstarEmail(emailId);
await context.markAsRead(emailId);
await context.markAsUnread(emailId);
await context.addLabel(emailId, "label-name");
await context.removeLabel(emailId, "label-name");
// AI-powered analysis
const result = await context.callAgent<ResultType>({
prompt: "Your prompt with email content",
schema: {
type: "object",
properties: { field: { type: "string" } },
required: ["field"]
},
model: "haiku" // or "sonnet" or "opus"
});
```
## Recommended Approach: AI-Powered Classification
**Default to using `context.callAgent()` for intelligent decision-making** instead of hard-coded keyword lists. This provides better accuracy and adaptability.
```typescript
// PREFERRED: AI-based urgency detection
const analysis = await context.callAgent<{ isUrgent: boolean; reason: string }>({
prompt: `Analyze if this email is urgent:
Subject: ${email.subject}
Body: ${email.body.substring(0, 500)}
Is this email urgent or time-sensitive? Consider context, not just keywords.`,
schema: {
type: "object",
properties: {
isUrgent: { type: "boolean" },
reason: { type: "string" }
},
required: ["isUrgent", "reason"]
},
model: "haiku" // Fast and cost-effective
});
if (analysis.isUrgent) {
await context.notify(`Urgent: ${email.subject}\n${analysis.reason}`);
}
// AVOID: Hard-coded keyword lists (brittle and prone to false positives)
// const isUrgent = subject.includes("urgent") || subject.includes("asap");
```
## Examples and Templates
Reference the template files for common patterns:
- **[ai-classifier.ts](templates/ai-classifier.ts)**: ⭐ AI-powered email classification (RECOMMENDED)
- **[urgent-watcher.ts](templates/urgent-watcher.ts)**: AI-based urgent email detection
- **[auto-archive.ts](templates/auto-archive.ts)**: Automatically archives newsletters
- **[package-tracker.ts](templates/package-tracker.ts)**: Package tracking with status extraction
## Best Practices
1. **Prefer AI Classification**: Use `context.callAgent()` instead of hard-coded keyword lists for intelligent decision-making
2. **Filter Early**: Return early if email doesn't match basic criteria (like sender)
3. **Clear IDs**: Use descriptive, unique listener IDs
4. **Error Handling**: Wrap context method calls in try-catch when appropriate
5. **Performance**: Use "haiku" model foEmail inbox search specialist, takes in appropriate context for the email and a goal of what to search for. Return the answer to the question.
Creates user-specific one-click action templates that execute email operations when clicked in the chat interface. Use when user wants reusable actions for their specific workflows (send payment reminder to ACME Corp, forward bugs to engineering, archive old newsletters from specific sources).
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
Perform competitive analysis on companies or products
Fact-check claims or verify information
Research current market trends in a specific industry or domain
Start a focused research session on any topic
Summarize all current research findings