Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add moonlight-lupin/agent-skills --skill fill-templategit clone --depth 1 https://github.com/moonlight-lupin/agent-skillsWrote 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/moonlight-lupin/agent-skills/fill-template)<a href="https://agentmods.dev/skills/moonlight-lupin/agent-skills/fill-template"><img src="https://agentmods.dev/badge/skills/moonlight-lupin/agent-skills/fill-template/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/moonlight-lupin/agent-skills/fill-template"><img src="https://agentmods.dev/badge/skills/moonlight-lupin/agent-skills/fill-template.svg" alt="Reviewed on agentmods" width="80" height="20"></a>- NVIDIA SkillSpector pass
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.00215 | $0.02314 |
| Opus 5 | $0.00108 | $0.01157 |
| Sonnet 5 | $0.00043 | $0.00463 |
| Haiku 4.5 | $0.00021 | $0.00231 |
Grade A, and why
fill-template scanned grade A with 0 findings 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 11d 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.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 169 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Fill Template (mail-merge)
Turn one master template + a data table into many filled copies — one per row — swapping only the parts that vary and leaving the master's layout and styling untouched. Document generation only: nothing is sent, posted or signed.
Scope and routing
Use this skill when the user has one template and a list, and wants a filled copy per row. Do not use it to get data out of documents (that's an extraction task), to produce a single bespoke letter (just edit one document), or where the host environment mandates a different document pipeline.
Inputs the user provides
- The master template — a
.docxletter or form, or a.xlsxform. One master per run. This is the source of truth for layout and styling. - The data table — a
.xlsxor.csv, one row per output, with a header row. Columns supply the values that vary (names, amounts, dates, references…). - (Optional) a naming pattern — how each output file is named, e.g.
Letter_{Name}. Defaults to<template>_<row-number>.
Workflow (do this, in order)
- Analyse the master. Read it with
read_content(path)and identify the parts that vary row to row — names, salutations, amounts, dates, reference numbers — versus the boilerplate that stays fixed.read_contentshows repeated paragraph text once with a(×N)count — that's how many placestokenisewill replace it (e.g. a name in both the body and the header). Seereferences/tokenising-guide.mdfor what to tokenise and how to name tokens well. - Propose a tokenised template. Build a
mappingof each varying phrase → a token name, and present it to the user as a plain list ("Ms Jordan Lee→{{Name}},$1,000,000→{{Amount}}, …"). Token names should match the data file's column headers where possible — that makes the mapping automatic. - Confirm with the user. Show the proposed tokens (and, if helpful, save the tokenised template
and show its text) and wait for explicit confirmation before generating anything. This is the
review gate — get the template right once, then fan it out.
from fill_template import read_content, tokenise, tokens_in, load_rows, generate print(read_content("Letter_master.docx")) # step 1 rep = tokenise("Letter_master.docx", # step 2 "Letter_tokenised.docx", [{"find": "Ms Jordan Lee", "token": "Name"}, {"find": "$1,000,000", "token": "Amount"}, {"find": "01 Jul 2026", "token": "EffectiveDate"}, {"find": "REF-0001", "token": "Reference"}]) # rep["not_found"] lists any phrase that wasn't located — fix those before generating. print(tokens_in("Letter_tokenised.docx"))tokenisefinds each exact phrase and replaces it with{{Token}}, preserving the formatting of the run/cell it sits in (a bold figure stays bold). It reports a hit count per token and flags any phrase it could not find, so a typo in thefindtext is caught before you generate 200 letters. - Load the data and check the mapping.
headers, rows = load_rows("recipients.xlsx"). The token→column map defaults to token name == column header (case-insensitive); override any that differ. Any template token with no column, or a mapped column blank for a given row, becomes a visible«MISSING: Token»flag — never a guess. - Generate one file per row.
report = generate( "Letter_tokenised.docx", rows, token_to_column={"Name": "Recipient"}, # only the ones whose token != column outdir="out", name_pattern="Letter_{Recipient}", )reportlists every file written, the rows skipped (e.g. a name-pattern column missing from the data), anyunmapped_tokens, and per-filemissingtokens. - Report back honestly. Tell the user how many files were produced and where, and surface
every
missingflag andunmapped_tokensentry so blanks are dealt with before the batch is used. Outputs are drafts for a person to review before they go out.
What ships with it
7 files 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.
- 11d ago First seen · 169 lines · 215 tokens per session scan A 3e95648319a9
fill-template is a skill published in the GitHub repository moonlight-lupin/agent-skills (62 stars, last pushed 4d ago), licensed MIT. It adds 215 tokens to every session and 2,314 once invoked, about $0.0011 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
document-converter-suite
Convert local PDF, Office, Markdown, HTML, text, CSV, TSV, and JSON files; batch-convert folders, extract tables, fill templates, and edit PDF pages.
xlsx
Create, inspect, edit, and verify Excel XLSX workbooks with openpyxl, including CSV import, formulas, styling, error checks, and optional LibreOffice rendering.
gws-sheets
Google Sheets: Read and write spreadsheets.
gws-sheets-append
Google Sheets: Append a row to a spreadsheet.
gws-sheets-read
Google Sheets: Read values from a spreadsheet.
recipe-copy-sheet-for-new-month
Duplicate a Google Sheets template tab for a new month of tracking.