Borrowing it
Nothing to install: this file belongs to FranRom/pupila. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/FranRom/pupila/main/.claude/skills/pupila-fetchers/SKILL.mdgit clone --depth 1 https://github.com/FranRom/pupilaWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/franrom/pupila/pupila-fetchers)<a href="https://agentmods.dev/skills/franrom/pupila/pupila-fetchers"><img src="https://agentmods.dev/badge/skills/franrom/pupila/pupila-fetchers/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/franrom/pupila/pupila-fetchers"><img src="https://agentmods.dev/badge/skills/franrom/pupila/pupila-fetchers.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00075 | $0.02349 |
| Opus 5 | $0.00037 | $0.01175 |
| Sonnet 5 | $0.00015 | $0.00470 |
| Haiku 4.5 | $0.00007 | $0.00235 |
Grade A, and why
pupila-fetchers scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 12d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Makes network callslowCapability
Not a fault in itself. Listed so you know the mod talks to something, and to what.
curl -sI "https://api.ashbyhq.com/posting-api/job-board/<slug>?includeCompensation=true" How it starts
The opening of the file, as written. The whole thing — 95 lines — stays where its author put it; the contents beside it link to each section on GitHub.
The pipeline ingests from 19 public sources (5 ATS APIs — Ashby, Greenhouse, Lever, Recruitee, Personio (XML) — plus RSS, JSON boards, HN, HTML scrapers, an Aave Next.js scraper, ashby-private for orgs whose public posting-API is disabled, jobicy and himalayas — no-key remote-jobs feeds, and bluedoor — a free cross-ATS aggregator queried by region from profile.location). Adding a source means: a fetcher, a normalizer, a Source literal, a slot in the orchestrator, and dedup/render wiring.
Companion invariants: src/fetchers/CLAUDE.md (auto-loaded when working in that dir) — security checklist + must-obey rules. Read those rules; this skill covers the procedural side.
Add a new fetcher (mechanical checklist)
- Raw shape in
src/types.ts—interface Raw<Name> { ... }. - Fetcher at
src/fetchers/<name>.ts, exportingfetch<Name>(): Promise<FetcherResult<Raw>>→{ items, errors }. Never throw — catch internally, push toerrors.- Use
fetchWithTimeout/fetchJson/fetchTextfromsrc/utils.ts(30s timeout, 1 retry on 5xx/network). - Pass
JSON_HEADERSorRSS_HEADERS. - For multi-slug fetchers, use
fetchMultiSlugfromsrc/fetchers/_shared.ts— it owns thePromise.all+ per-slug try/catch + flatMap. The fetcher only owns per-slug extraction. Canonical examples:ashby.ts,greenhouse.ts,lever.ts.
- Use
- Canonical source name — add the literal to the
SOURCESconst tuple insrc/types.ts(single source of truth;type Sourcederives from it). This one edit cascades: the MCPsourceEnum,KNOWN_SOURCESinsrc/lib/fetch-runner.ts, and the UI fetch-progress panel (ui/plugins/fetchJobs.ts) all derive from it automatically — don't hand-edit those. - Normalize — add
normalize<Name>(items, fetchedAt): Job[]tosrc/normalize.ts. UsewithSalary()spread to populatesalary*fields. - Wire orchestrator —
src/index.ts: import + add a line in thePromise.allblock viaprocessFetcher(...). - Dedup priority — add to
SOURCE_PRIORITYinsrc/dedup.ts(ordered most → least trusted). Compile-enforced:Record<Source, …>fails to build if you skip it. - Render — add to the display-ordered
SOURCESinsrc/render.tsso by-source counts appear inJOBS.md. Compile-enforced: thesatisfies+ exhaustiveness guard below the array fails to build if you skip it. - UI client mirror — add the literal to the
Sourceunion inui/src/types.ts(a deliberate mirror that must NOT import fromsrc/*). Guarded bytests/source-lists.test.ts, which fails if it drifts from the canonical tuple. - Tests — at least one parser test in
tests/for HTML scrapers. Use existing files (aave.test.ts,ashby-private.test.ts,normalize-hn.test.ts,bluedoor.test.ts) as templates.
Source lists are guarded, not duplicated. After step 3, steps 6–8 are the only other places that need a manual entry, and every one fails the build or a test if you forget — see
tests/source-lists.test.tsand the guards insrc/render.ts/src/dedup.ts. You can't silently half-wire a source anymore.
What ships with it
1 file beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 12d ago First seen · 95 lines · 75 tokens per session scan A ddac45d0af35
pupila-fetchers is a skill published in the GitHub repository FranRom/pupila (37 stars, last pushed 2mo ago), licensed MIT. It adds 75 tokens to every session and 2,349 once invoked, about $0.0004 per session on Opus 5. A static security scan graded it A with 1 finding (makes network calls). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
sprite-gen
A pipeline for turning generated 2D game-character images into transparent sprite sheets, which store animation frames for a game.
redteam-cors-miscfg-detail-pack
Domain routing and boundary guidance for authorized CORS misconfiguration testing, including reflected origins, null origins, subdomain trust, and credential exposure. Use when a task belongs to the CORS testing domain and needs scope, evidence, pivot, or exit criteria.
readable-measure
Set line length and measure for comfortable reading across type sizes and breakpoints. Use when tuning body text. Covers measure only — for the full size and weight scale, use typography-scale.
animation-principles
Apply animation principles — easing, staging, follow-through — to one specific UI motion. Use when tuning how an animation feels. For product-wide duration and easing tokens use motion-system (design-systems); for a full interaction spec use micro-interaction-spec.
pinme-share
A tool for packaging a result as a static web page and publishing it through PinMe. A static page is a self-contained page that does not need a server to generate its content.
spacing-system
Create a spacing scale from a base unit with rules for when each step applies. Use when standardising padding and margins. For page-level columns and gutters, use layout-grid.