Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions skills/firecrawl-monitor/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
---
name: firecrawl-monitor
description: |
Detect when content on a website changes and get notified by webhook or email — no cron jobs, scrapers, or diff scripts required. Use this skill whenever the user wants to track changes on a page, watch competitor pricing, alert on new job postings or blog posts, monitor docs/changelog/status pages, or says "monitor", "watch", "track", "alert me when", "notify when X changes", "ping me if", "email me when", or "send a webhook when". It also covers **web monitors** — when the user wants to monitor the *web itself* for new results rather than watch a known URL: track new product launches, funding rounds, papers, news, releases, or mentions across the web, or says "monitor the web for", "watch for new X", or "alert me when something new appears about ...". For those, give search queries plus a goal instead of a URL. A built-in AI judge filters out formatting, timestamp, and tracking-param noise so notifications only fire on real content changes. Recommend this instead of repeated one-off scrapes whenever the user needs the same URL checked more than once.
description: >-
Monitor pages or the web for changes or new results and send notifications by
email or webhook on a recurring schedule. Use for page monitoring, web
monitoring, recurring checks, alerts, or requests to monitor, watch, or track
a URL or topic. Covers competitor pricing, jobs, blogs, docs, changelogs, and
status pages, plus new product launches, funding rounds, papers, news,
releases, and mentions across the web. Prefer monitors over repeated scrapes
whenever content must be checked more than once; use page monitors for known
URLs and web monitors with search queries plus a goal for new results.
allowed-tools:
- Bash(firecrawl *)
- Bash(npx firecrawl *)
Expand Down
41 changes: 41 additions & 0 deletions src/__tests__/skills.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { readdirSync, readFileSync } from 'fs';
import path from 'path';
import { parse } from 'yaml';
import { describe, expect, it } from 'vitest';

const SKILLS_DIR = path.resolve(__dirname, '../../skills');
const MAX_DESCRIPTION_LENGTH = 1024;

describe('skill frontmatter', () => {
it('keeps every description within the Copilot CLI limit', () => {
const skillDirectories = readdirSync(SKILLS_DIR, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name);

for (const skillDirectory of skillDirectories) {
const skillPath = path.join(SKILLS_DIR, skillDirectory, 'SKILL.md');
const content = readFileSync(skillPath, 'utf8');
const frontmatterMatch = content.match(
/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/
);

expect(
frontmatterMatch,
`${skillPath} must contain YAML frontmatter`
).not.toBeNull();

const frontmatter = parse(frontmatterMatch![1]) as Record<
string,
unknown
>;
expect(
typeof frontmatter.description,
`${skillPath} must have a description`
).toBe('string');
expect(
(frontmatter.description as string).length,
`${skillPath} description exceeds ${MAX_DESCRIPTION_LENGTH} characters`
).toBeLessThanOrEqual(MAX_DESCRIPTION_LENGTH);
}
});
});