اسکیل answer-me-with-html مدل را از نوشتن HTML خلاص می‌کند: شما فقط یک稿件 Markdown کوتاه می‌دهید و ابزار به آن am.mjs با ۳۰۱ هزار بایت، قالب، تم، چیدمان SVG و یک بررسی نگارش را اضافه می‌کند. در این نوشته همان اسکیل را روی همین سرور نصب کردم، یک稿件 سه‌پنلی را رندر کردم و خروجی واقعی را سنجیدم: ۸۹۵ بایت稿件 در برابر ۲۷۴۸۸ بایت صفحه، یعنی 30.7 برابر. لحظه‌ی خواندن داده: ۱۲ مهر ۱۴۰۵، برابر با ۴ اکتبر ۲۰۲۶.

ایده: مدل محتوا می‌نویسد، ابزار صفحه می‌سازد

ریپوی QingYunA/answer-me-with-html در ۲ اکتبر ۲۰۲۶ ساخته شده و تا لحظه‌ی خواندن این نوشته ۵۳۵ ستاره و ۴۵ فورک گرفته است. نسبت فورک به ستاره 0.084 درمی‌آید؛ یعنی بیشتر ستاره‌ها از کسانی است که فقط نگاه کرده‌اند، نه کسانی که مخزن را برداشته‌اند.

سازوکارش ساده است. به جای اینکه مدل هزاران توکن HTML بنویسد، یک متن کوتاه با چند عنوان می‌نویسد و یک ابزار خط فرمان به نام am آن متن را می‌گیرد و خودش صفحه را می‌سازد.

نکته‌ای که در README هست و در نصب خودتان می‌بینید: فرمان npx skills add فقط پوشه‌ی اسکیل را می‌گذارد و فرمان am را روی PATH شما نمی‌سازد. باید مسیر فایل را صدا بزنید. فایل am.mjs یک فایل تکی است و پوشه‌ی node_modules کنارش وجود ندارد، پس بدون npm install هم کار می‌کند. تنها شرط آن Node.js نسخه‌ی ۲۰ به بالا است که package.json در بخش engines اعلام می‌کند.

# نصب اسکیل به‌صورت سراسری؛ -a نام ایجنت خودتان را می‌گیرد
$ npx -y skills add QingYunA/answer-me-with-html -g -y
│
●  Installing to: Claude Code, Codex, Hermes Agent
│
◇  ~/.agents/skills/answer-me-with-html
│    universal: Codex, Amp, Cline +15 more
│    symlink → Claude Code, Hermes Agent
│
└ ✓ Installed 1 skill

# دو فایل نصب‌شده: اسکیل ۱۲۳۶۲ بایت، ابزار ۳۰۱۶۱۶ بایت، بدون node_modules
$ ls -la /root/.agents/skills/answer-me-with-html/
-rw-r--r-- 1 root root 12362 SKILL.md
drwxr-xr-x 2 root root  4096 scripts
-rw-r--r-- 1 root root 301616 scripts/am.mjs
$ node --version
v26.7.0

خروجی نصب یک نکته‌ی دیگر هم دارد: تلاش برای نصب روی PromptScript شکست خورد، چون آن ابزار نصب سراسری را پشتیبانی نمی‌کند. بقیه‌ی ایجنت‌ها با یک پوشه‌ی مشترک در /root/.agents/skills تغذیه می‌شوند و هر کدام با یک پیوند نمادین به آن اشاره می‌کنند.

اولین صفحه: یک稿件، یک فرمان، خروجی واقعی

ورودی یک فایل Markdown با سرآیند است و بقیه‌اش عنوان هر پنل با علامت ##. در فرمان پایین، اول محتوای稿件 و بعد خروجی واقعی رندر را می‌بینید.

# محتوای فایل稿件؛ سه پنل: نمودار پیام، درخت وضعیت، و دلیل سه‌بار بودن
$ cat tcp.draft.md
---
template: sheet
theme: blueprint
title: سه‌بار handshake در TCP
cols: 3
---
دو طرف برای شروع ارتباط باید هم‌زمان آماده باشند.

## A سه پیام {span=2}
```sequence
Client -> Server: SYN
Server -> Client: SYN-ACK
Client -> Server: ACK
```

## B وضعیت‌ها
```tree
list
Client: CLOSED → SYN-SENT
Server: LISTEN → SYN-RECEIVED
```

# رندر و خروجی واقعی همان اجرا
$ node /root/.agents/skills/answer-me-with-html/scripts/am.mjs render tcp.draft.md --no-open
✓ /root/.answer-me-with-html/pages/سه-بار-handshake-در-TCP-20261004-055853.html
  sheet · blueprint · 3 面板 · sequence×1 tree×1
  STE ✓ 0 条警告

خط اول مسیر فایل خروجی است و دو خط بعد شمارش پنل‌ها و کامپوننت‌ها. عدد ۳ یعنی سه پنل و sequence×1 tree×1 یعنی یک نمودار پیام و یک درخت. اگر شمارش با稿件 شما نخواند، یعنی یک بلوک کد را درست بسته نکرده‌اید.

اندازه‌ی فایل‌ها را خودم اندازه گرفتم، نه از README:

اندازه‌ی稿件 در برابر صفحه‌ی ساخته‌شده، اندازه‌گیری روی همین اجرا
فایلاندازهنسبت به稿件
稿件 tcp.draft.md۸۹۵ بایت۱ برابر
صفحه‌ی sheet سه‌پنلی۲۷۴۸۸ بایت30.7 برابر
صفحه‌ی آزمایشی یک‌پنلی۲۴۳۸۶ بایت27.2 برابر

نسبت از تقسیم ۲۷۴۸۸ بر ۸۹۵ به دست می‌آید و می‌شود 30.7 برابر. یعنی شما حدود ۳۰ بایت متن می‌نویسید و ابزار حدود ۲۷ هزار بایت HTML، CSS و مختصات SVG می‌سازد. توکن خروجی مدل همین‌قدر کم می‌شود چون مدل دیگر آن ۲۷ هزار بایت را تولید نمی‌کند.

صفحه یک فایل تکی است. در آن هیچ ارجاعی به بیرون ندارد: تنها نشانی بیرونی خودش http://www.w3.org/2000/svg است که فضای‌نام SVG است نه یک درخواست شبکه. هیچ برگه‌ی link به شیوه‌نامه وجود ندارد و هیچ برگه‌ی script با src هم نیست.

قوی‌ترین بخش: patch یک پنل، بدون بازنویسی کل صفحه

اگر از صفحه‌ای که ساخته شده خوشتان نیامد، لازم نیست کل صفحه را دوباره بنویسید. هر صفحه‌ی ساخته‌شده یک عنصر مخفی به نام #am-source دارد که همان稿件 اصلی را نگه می‌دارد.

# فقط پنل C را عوض می‌کنیم، بقیه‌ی صفحه دست‌نخورده می‌ماند
$ node /root/.agents/skills/answer-me-with-html/scripts/am.mjs patch صفحه.html --panel "C" panelC.md --no-open
✓ /root/.answer-me-with-html/pages/سه-بار-handshake-در-TCP-20261004-055853.html
  sheet · blueprint · 3 面板 · sequence×1 tree×1
  STE ✓ 0 条警告

قبل از این فرمان، جمله‌ی قدیمی دو بار در صفحه بود. بعد از آن، جمله‌ی جدید دو بار بود و جمله‌ی قدیمی صفر بار. شمارش پنل‌ها هم همان ۳ ماند. یعنی ابزار فقط همان یک بخش را نوشت و بقیه‌ی HTML را دست نزد.

این روش برای ویرایش‌های چرخشی ارزش عملی دارد. وقتی یک اسکیل هر بار کل صفحه را بازنویسی می‌کند، شما در هر دور باید تمام توکن‌های پنل‌های دیگر را دوباره تولید کنید. اینجا فقط پنلی را می‌دهید که عوض شده است.

بررسی نگارش: کجا کار می‌کند و کجا کار نمی‌کند

پیش از تحویل صفحه، متن با یک قاعده به نام STE سنجیده می‌شود. فرمان جداگانه‌ی am lint فقط همین بررسی را می‌کند و صفحه نمی‌سازد.

# متن انگلیسیِ عمدا بد: ۹ هشدار، هر کدام با شماره خط و جایگزین
$ node .../am.mjs lint ste-en.md
  STE 9 条警告(修正稿件后重新执行):
  L8 [sentence-length] 句子 31 words(上限 25):"In order to facilitate t…"
  L8 [passive] 疑似被动语态:"be noted" → 改为主动语态
  L8 [word] 不推荐 "In order to" → to
  L8 [word] 不推荐 "utilization" → use
  L12 [word] 不推荐 "utilization" → use
  L13 [word] 不推荐 "utilization" → use

# همان متن کافی‌سازی، با اعلام زبان چینی: ۷ هشدار
$ node .../am.mjs lint ste-zh.md
  STE 7 条警告(修正稿件后重新执行):
  L8 [word] 虚动词 "加以说明"(加以/予以) → 直接用「说明」
  L8 [cliche] 套话 "赋能" → 删除,或换成具体事实
  L8 [cliche] 套话 "闭环" → 删除,或换成具体事实

# متن فارسی: صفر هشدار، چون قاعده‌ای برای فارسی وجود ندارد
$ node .../am.mjs lint lang-fa.md
  STE ✓ 0 条警告

هر هشدار شماره‌ی خط، نوع قاعده و یک جایگزین پیشنهادی دارد. سطح پیش‌فرض style: 80 فقط هشدار می‌دهد و صفحه را تحویل می‌دهد. اگر style: strict بگذارید، صفحه ساخته نمی‌شود تا متن را اصلاح کنید.

اینجا یک محدودیت واقعی پیدا کردم که در README نیامده. بررسی نگارش برای انگلیسی و چینی نوشته شده است، نه فارسی. همان متن بد، وقتی سرآیندش lang: zh باشد هشدار می‌گیرد و وقتی lang: fa باشد ساکت می‌ماند.

نتیجه‌ی عملی: اگر فارسی می‌نویسید، این بررسی به شما سکوت می‌دهد و کیفیت متن را تضمین نمی‌کند. برای متن فارسی باید خودتان نقش داور را بازی کنید.

محدودیت دوم در همان مسیر دیده می‌شود. حتی وقتی در سرآیند lang: fa می‌نویسید، برچسب lang در صفحه‌ی خروجی باز هم en می‌ماند و هیچ dir="rtl" هم ساخته نمی‌شود.

نتیجه‌ی واقعی رندر روی زبان، روی همین اجرا اندازه‌گیری شد
ورودیبرچسب lang خروجیجهت
متن فارسی، بدون کلید langenندارد
متن فارسی، با lang: faenندارد
متن انگلیسیenندارد

پس اگر صفحه‌ی فارسی می‌خواهید، باید خودتان جهت را جای دیگری درست کنید. این ابزار برای بازار انگلیسی و چینی نوشته شده است.

پیکربندی و پاک‌سازی: چیزهایی که روزانه به کار می‌آید

فرمان am config هفت کلید را نشان می‌دهد. روی یک سرور بدون میزکار، open باید خاموش باشد وگرنه هر رندر یک فرایند مرورگر باز می‌کند. برای همین در همه‌ی فرمان‌های بالا --no-open داده‌ام که فقط همان یک بار را خاموش می‌کند.

کلید always حالت پرتکرار است: به‌جای منتظر ماندن برای پرسش شما، به هر نتیجه‌گیری یک صفحه پیوست می‌کند. برای کار دسته‌ای مناسب است و برای ترمینال روزمره حواس‌پرتی می‌سازد.

کار am clean را با --dry-run پیش از اجرا ببینید. این فرمان روی همین سرور دو صفحه و ۵۱ کیلوبایت گزارش داد و گفت بدون پرچم حذف، چیزی در بیش از ۳۰ روز را پاک نمی‌کند.

$ node .../am.mjs config
配置文件:/root/.answer-me-with-html/config.json
  open         on        生成后自动用浏览器打开页面(on | off)
  always       on        高频模式:给结论时都附一页(on | off)
  theme        blueprint 默认主题(blueprint | shadcn)
  mode         auto      默认明暗模式(auto | light | dark)
  style        80        STE 写作检查严格度(off | 80 | strict)
  update_check on        每周在后台检查一次新版本(on | off)
  voice        auto      视频旁白配音(auto | elevenlabs | system | off)

$ node .../am.mjs clean --dry-run
数据目录:/root/.answer-me-with-html(共 51 KB:页面 2 个,视频 0 个,配音缓存 0 KB)
将删除 0 个文件,释放 0 KB(30 天前的页面和视频 + 配音缓存)

جمع‌بندی: چه کسی سراغش برود

این ابزار برای وقتی است که جواب شما ماهیت گراف دارد: یک پروتکل، یک معماری، یک مقایسه‌ی چندبعدی. برای پرسش کوتاه یا دستوری که باید همان لحظه کپی شود، سربار ساخت صفحه بی‌فایده است.

مزیت اصلی، کم شدن توکن خروجی مدل است، چون مدل دیگر HTML نمی‌نویسد. بنچمارک خود ریپو ادعا می‌کند توکن خروجی از ۶۸۷۳ به ۹۲۳ رسیده، یعنی 7.4 برابر کمتر. خود ریپو هم در همان صفحه صادقانه می‌گوید هزینه‌ی هر پاسخ تقریبا ثابت می‌ماند، چون هر دور دوباره کانتکست را می‌خواند.

آنچه را نتوانستم تایید کنم: بخش ویدیوی am video و خروجی MP4 را اجرا نکردم، چون به ffmpeg و یک مرورگر محلی نیاز دارد. همچنین ادعای بنچمارک را بازتولید نکردم؛ اعداد بالا از خود صفحه‌ی بنچمارک ریپو نقل شده و روش خودش claude -p --output-format json را اعلام می‌کند.

برای مطالعه‌ی بیشتر، یادداشت تغییرات کلاد کد و RFC 9293 منابع اصلی‌اند. رپوی مثال‌های کامل هم یک稿件 نمونه برای هر نوع شکل اطلاعات دارند.

اگر اسکیل‌های مبتنی بر MCP خواستی، در نوشته‌ی ساخت سرور MCP با SDK پایتون سرور را از صفر ساختیم و در تبدیل ماده به صفحه‌ی آموزشی دیدیم یک اسکیل چطور خروجی قابل استفاده تولید می‌کند. اینجا تفاوت در این است که آن اسکیل‌ها یک فایل تولید می‌کردند و این یکی یک صفحه‌ی کامل با چیدمان.

منابع

  1. مخزن answer-me-with-html روی گیت‌هاب — ساخته‌شده در ۲ اکتبر ۲۰۲۶، ۵۳۵ ستاره در لحظه‌ی خواندن
  2. همان مخزن از رابط برنامه‌نویسی گیت‌هاب — تاریخ ساخت، ستاره، فورک و مجوز MIT
  3. package.json — نسخه‌ی 0.4.3، نیازمند Node.js نسخه‌ی ۲۰ به بالا، دو وابستگی
  4. صفحه‌ی بنچمارک ریپو — اعداد توکن و زمان با روش claude -p
  5. مثال دست‌نویس TCP در رپو — نمونه‌ی کامل یک稿件 چهارپنلی
  6. صفحه‌ی ارزیابی امنیتی اسکیل در skills.sh
  7. مجوز MIT ریپو
  8. یادداشت تغییرات کلاد کد — منبع اصلی نسخه‌ها
  9. RFC 9293 — مشخصات لایه‌ی انتقال TCP
  10. اسکریپت ساخت ویدیوی نمایشی در رپو