Part of The Static Agent Web — the verified, serverless agent ecosystem
CI license

Teach any agent how to use your site. No server required.

llms.txt already tells agents WHAT your site is. This adds a standard way to say HOW to use it: a `## Skills` section pointing at your SKILL.md files — discovered, verified, and used with explicit opt-in.

llms.txt
## Skills

- [placeholder](/skills/placeholder/SKILL.md): generate SVG placeholder image URLs for UI mockups. <!-- skill: {"version":"1.0.0","license":"MIT"} -->

Two ecosystems that don't talk to each other

llms.txt tells an agent what your site is. Agent Skills (SKILL.md) tell it how to use it. Today there is no standard way for a site to say "here is the skill for working with me" — so an agent that reads your llms.txt has no signal a skill even exists.

Without this standard

  • Agent reads llms.txt, sees prose about your API
  • No signal that a SKILL.md exists or where
  • Agent invents a generic call and gets it wrong

## Skills in llms.txt

  • One `## Skills` section, same llms.txt fetch
  • Agent discovers title, description, and URL
  • Verified by sha256 (and ed25519 if signed), then used

How it works

Four steps. The user's opt-in is never skipped.

A publisher's llms.txt lists ## Skills; the agent shows them to the user, the user opts in, and the agent fetches and verifies the SKILL.md before using it. Publisher site static: GitHub Pages, R2, any host serves /llms.txt + /skills/*/SKILL.md Agent Claude, Cursor, any MCP-aware runtime parses ## Skills, verifies sha256 User sees the skill list opt-in is mandatory, never automatic 1 llms.txt + ## Skills 2 list skills, ask opt-in 3 approve 4 fetch + verify SKILL.md
  1. A publisher adds a ## Skills section to the llms.txt it already serves — one line of markdown per skill.
  2. An agent that reads llms.txt now sees the skills available and lists them to the user.
  3. The user opts in explicitly. Agents MUST NOT auto-install a skill.
  4. The agent fetches the SKILL.md, verifies its sha256 (and ed25519 signature if declared), then loads it as context.

Three ways to consume it today

All three are real and working, not roadmap.

Claude Code plugin recommended

Install the llms-txt-aware consumer skill as a Claude Code plugin. It activates automatically whenever you're about to touch a web domain.

claude code
/plugin marketplace add MauricioPerera/llms-txt-skills
/plugin install llms-txt-aware@llms-txt-skills

MCP server any MCP runtime

A standalone MCP server exposing discover/fetch/verify as tools — for Cline, Continue, Cursor, Windsurf, or any MCP client.

json
{
  "mcpServers": {
    "llmstxt": {
      "command": "python",
      "args": ["integrations/mcp/llms_txt_skills_mcp.py"]
    }
  }
}

System prompt any agent

Copy the 6-step procedure into your agent's system prompt. No plugin system required, works with any model that follows instructions.

skill
cat skills/llms-txt-aware/SKILL.md

Three rings of trust

sha256 alone proves integrity, not authenticity — the same document that points to a skill also asserts its hash. Signing closes that gap. And neither says whether the content is still true — signed freshness covers that.

01

Integrity — sha256

Declared inline in ## Skills and in /.well-known/agent-skills/index.json. Agents MUST verify it and refuse to load on mismatch.

02

Authenticity — ed25519 + key pinning

The publisher signs each SKILL.md with a key kept offline. Agents pin the key per origin (TOFU) and flag a silent change across sessions.

03

Freshness — signed “still true”

Hashes freeze bytes, not truth. A registered reviewer signs a freshness attestation bound to the exact content sha — voided by any edit, expiring on a date — and llms-skills freshness turns stale knowledge into a failing CI build.

Does publishing a skill change what an agent does?

Measured, not asserted — 6 local models, 7 scenarios, 3 reference sites.

0%
baseline: uses the real endpoint
given only the task, models mostly invent a local fallback
0%
discovery: uses the real endpoint
given the site's llms.txt + SKILL.md, most get it right
0
models tested locally
0.5B to 9B parameters, via LM Studio
0
scenarios × sites
image API, storefront, wireframe validator

Small-N proof of mechanism, not a benchmark — all 3 sites are first-party. Full methodology, caveats, and raw data in evals/results.md.

Live publishers you can consume right now

Seven first-party origins dogfood the full stack — ## Skills, hash-pinned BM25 knowledge, executable tools, SKILL.md recipes, signed index. The root origin is directly consumable (npx -y @rckflr/mcpwasm https://mauricioperera.github.io) and now aggregates a second project on the same llms.txt: KDD under the kdd scope — kdd__search_knowledge, with its own verified memory (scopes, Executable Skills v0.5 §2.5; live in mcpwasm 0.6.0, llms-skills memory --scope in 0.3.0). Other project pages are consumed via clone + --serve.

  • mauricioperera.github.ioroot origin: site_facts + the standard's own skills + KDD aggregated under the kdd scope, live-consumable
  • /llms-txt-skills/this spec: 4 skills incl. a custom validator + 6-concept knowledge bundle
  • /KDD/a real pre-existing OKF bundle, 40 concepts — also served from the root as kdd__*
  • /ccdd/, /taskmd/, /ccdd-gate/, /game-protocol/the KDD methodology family, each publishing its own specs as searchable skills

Where this fits

This does not replace MCP or A2A — it fills the gap below them: publishing a skill for a simple API or static site, with no server to run.

MCP A2A /.well-known/skills/ ## Skills in llms.txt
Requires a running server Yes Yes No No
Works on static sites No No Yes Yes
Multiple skills per domain Yes Yes No (one only) Yes
Co-located with llms.txt No No No Yes
Implementation complexity High High Low Low

Adopt it in 3 steps

Fastest path: the GitHub template — a working publisher out of the box (example knowledge bundle, generated skills, validation CI). Click Use this template, replace knowledge/, run two commands.

The one-command way (CLI)

bash
npx @rckflr/llms-skills init mi-skill    # scaffold SKILL.md + manifest
npx @rckflr/llms-skills memory ./docs     # opcional: bundle OKF → RAG sin servidor
npx @rckflr/llms-skills publish           # hash + ## Skills + index.json (+ firma)
npx @rckflr/llms-skills attest ./docs --concept faq.md --by human:tu --until 2027-07-10 --key tu.key
npx @rckflr/llms-skills freshness ./docs  # gate CI: vence/edición sin re-atestar = build rojo

1. Or add the section to your llms.txt by hand

markdown
## Skills

- [mi-skill](/skills/mi-skill/SKILL.md): qué hace esta skill y cuándo usarla. <!-- skill: {"version":"1.0.0","license":"MIT"} -->

2. Write the SKILL.md

yaml
---
name: mi-skill
description: Qué hace esta skill y cuándo usarla.
version: 1.0.0
license: MIT
---

Instrucciones detalladas para el agente.

3. Or install the consumer skill (Claude Code)

claude code
/plugin marketplace add MauricioPerera/llms-txt-skills
/plugin install llms-txt-aware@llms-txt-skills

The CLI (@rckflr/llms-skills) computes the sha256, syncs .well-known/agent-skills/index.json, and signs — so none of it is done by hand. In CI, a reusable GitHub Action (uses: MauricioPerera/llms-txt-skills@master) fails the build if what you serve drifts from your sources. Full guide in the README.

From a static site to a live MCP server

llms-txt-skills is the format; mcpwasm is a runtime for it. A publisher serves hash-pinned, attested skills once, the standard way — the runtime discovers, verifies, and runs each as an MCP tool. The whole contract between them is one tool_sha256 and its attestation.

A static publisher site serves llms.txt skills and tool.js; mcpwasm fetches and verifies them, then exposes each as an MCP tool that a client can call, running the tool.js sandboxed. Static site llms.txt · ## Skills · tool.js index.json · attestations.json mcpwasm runtime gateway (Workers) or npx local verify + QuickJS sandbox MCP client Claude, Cursor, any MCP host lists and calls the tools 1 fetch + verify 2 serve as MCP tools 3 call tool(args) 4 sandboxed tool.js
  1. A publisher serves an llms.txt whose ## Skills section lists each executable skill with its tool.js and tool_sha256 — mirrored in /.well-known/agent-skills/index.json and signed in attestations.json. Optionally, a hash-pinned BM25 snapshot (one llms-skills memory command over an OKF bundle) adds serverless search over the site's own knowledge. This is exactly what this spec defines.
  2. A runtime like mcpwasm points at that origin, fetches the llms.txt, and verifies every tool.js against its tool_sha256 and its attestation — rejecting any mismatch before loading it.
  3. Each verified skill becomes an MCP tool, and its SKILL.md recipe is served alongside as an MCP resource (with a get_skill_guide fallback) — the agent gets the manual, not just the hammer. Claude, Cursor, any MCP host list and call it like any other tool.
  4. On a call, the runtime executes that tool.js verbatim inside a QuickJS-wasm sandbox — no network or filesystem except the host capabilities it grants (a scoped fetchOrigin back to the site, and search over the site's own content). The result returns to the client.

Neither side has to trust the other's prose: the runtime re-derives the hash and checks the signature itself. Static hosting + a verifying runtime = an MCP server with no server to run.

Part of a growing spec

This RFC (v0.10) has two provisional extensions: Executable Skills, sandboxed tool.js a runtime executes verbatim instead of asking a model to improvise, and Skill Attestations, signed human review with an expiry window. Both are field-tested end-to-end in mcpwasm, their reference implementation.