Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
readme
sandermuller/boost-skills
claude-code
php
sandermuller
boost-skills

Author and maintain a concise, high-quality README for a Composer package. Covers stub, comprehensive, and docs-site shapes (thin README + a docs/ site, for example VitePress on GitHub Pages), length budgets, curated coverage, voice, the agent-facing surface (llms.txt, llms-full.txt, per-page markdown, robots.txt), staleness audits, and docs index/link sync. Activates when: writing or auditing a README or a docs page, or when the user says the docs are too long, too verbose, over-explained, read like a feature list, or asks to shorten or trim them.

Install
php artisan boost:add-skill sandermuller/boost-skills

Save this content to: .claude/skills/readme/SKILL.md

# README authoring

## When to apply

- Bootstrapping a new package's README
- Asked to "audit", "refresh", "improve", "shorten", or "trim" an existing README or docs page
- Reviewing a PR that touches README
- The package moves its documentation to a `docs/` site (for example VitePress, published on GitHub Pages)

## The opening names a problem, not a feature set

Every shape below starts with a description. Its job is the same in all three: name the situation the reader is in without the package, then what the package does about it. One or two sentences, then the first code block: the install command, or the teaser example in the docs-site shape. A critical-tier prerequisite or warning that governs that block stays beside it, as the coverage tiers below require. A reader who recognises the situation keeps reading. One who does not will not install the package, whatever the capability list says.

```markdown
❌ Provides queue middleware, retry policies, a dashboard, and Slack notifications for Laravel jobs.

✅ A job that fails at 3am retries until the queue gives up, and nobody finds out until a customer does.
   This package tells you the first time, with the payload that failed.
```

Start from the problem the reader already has. Capabilities that do not follow from it go in usage, in a table, or nowhere. The `Why <package>` docs page (below) carries the long form. The README opening stays at one or two sentences.

## Three valid shapes

**Stub README** (for early-stage packages, <500 stars):
- One-paragraph description — the problem-first opening above
- Install command
- Minimal usage example that resolves the opening's problem
- License + author

**Comprehensive README** (for established packages or ones with substantial API):
- Description (problem-first) + status badges
- Install + requirements
- Usage examples for the **common** cases only — see the coverage tiers below, which decide what gets an example, a table row, or nothing. The first example resolves the problem the opening named; it is the before/after, not a tour of the API
- Configuration reference (link to dedicated docs if long)
- Testing/development section
- Contributing pointer
- Changelog pointer
- License + credits

**Docs-site README** (for packages whose documentation lives in a `docs/` site):
- Description (problem-first) + status badges
- A copy-pasteable teaser example that resolves the opening's problem
- Install + requirements
- One minimal usage example
- Documentation section: the published site root URL stated once in prose, plus links to every page or to section entry points (pick one policy — see the index-sync rules below — and the link mechanics). Page links are navigation and do not count against the once rule
- Standard footer: contributing, changelog, security, credits, license

Pick one shape consistently. Don't mix tiers in the same README.

### Detecting the docs-site shape

A repo is docs-site shaped when `docs/` exists AND any of these signals identifies it as a generated site's source (in precedence order):

1. A generator config inside `docs/` (for example `docs/.vitepress/`, or a `docs/package.json` with a `build` script)
2. A root-level generator config or package script that names `docs/` as its source directory
3. A deploy workflow that builds from `docs/`

A plain-markdown `docs/` matching none of these is the comprehensive shape with linked docs, not the docs-site shape.

## Length is a constraint, not an outcome

A reader skims a README to install the package and get one thing working. Every sentence past that costs them. Write to a budget and cut to fit it — **the budget is not a target to fill**.

Counted the same way everywhere: **`wc -w` on the whole file** — code fences, tables and frontmatter included. One command, no judgement about what counts.

| Surface | Budget (`wc -w`) | Over it? |
|---|---|---|
| Stub README | ~350 words | Cut, or move to the comprehensive shape |
| Comprehensive README | ~900 words, hard ceiling ~1,200 | Move detail to a `docs/` site |
| Docs-site README | ~700 words | The README is restating a docs page — link instead |
| One docs page | ~800 words | Split it, turn prose into a table, or cut the low-value half |

Well-regarded packages in this ecosystem land inside those numbers, and they get there structurally, not by writing shorter sentences: the page is mostly code fences, tables, and one-line bullets, with prose only where it frames the next example.

**The count is whole-file; the cut is prose.** A page over budget because it carries several necessary examples is fine — cut the paragraphs around them first, and only then ask whether an example is redundant. Over budget is a signal to look, not an instruction to delete.

**The budget has a floor.** Never cut a security caveat, a data-loss or irreversibility warning, a required prerequisite or version constraint, an accessibility note, or a breaking-change pointer to hit a number. If a page is over budget and only load-bearing content remains, it is not too long — it is two pages. Trim rationale, motivation, and restated code before touching anything a reader can be harmed by missing.

Two structural rules do most of the work:

- **Reach a code block in under ~80 words** — on a README or a task page (install, usage, configuration). A reader who has to scroll past motivation to find the install line is being made to pay for the author's enthusiasm. A page with no task in it — a concept explainer, a security or accessibility note, a troubleshooting page — is exempt from this rule and from the prose-majority one below: prose is the right form there, and the word budget plus the paragraph cap still apply.
- **Cap a paragraph at ~100 words.** Count words between blank lines, not lines — a soft-wrapped file puts a 250-word wall on one line, so any line-based measure reads it as short. Healthy pages peak around 40–80 words per paragraph; a paragraph past ~100, or a section where paragraph words exceed the words in its code fences, tables and lists combined, is a defect. The content is skimmable as a list or table, or it is explaining something that does not need documenting at all.

## Coverage is curated — completeness is not the goal

Documenting every command, endpoint, option, and event is how a page becomes unreadable. Most of them are discoverable from the tool itself (`--help`, an IDE, a config file with comments), and a reader who needs the rare one will look there. **Reference material the tool already publishes does not need a prose copy.**

Sort every command / endpoint / option into three tiers and write to the tier:

Judge the tier from the repository, never from a guess about how many users need something:

| Tier | Repository evidence | Treatment |
|---|---|---|
| **Common** | On the critical path: named in the quickstart, the first example, or the default config | Prose + a runnable example |
| **Occasional** | Part of the documented public API or shipped config, but no example uses it | One table row: name, one-line effect. No example, no rationale |
| **Rare** | Not referenced by any example or default, and self-describing from `--help`, a typed signature, or a commented config key | Collapse it, or leave it out entirely |

**One tier overrides the other three: critical.** A prerequisite without which the package does not work, a security caveat, a destructive or irreversible operation, a data-loss risk, an accessibility requirement, and a compatibility limit are documented **in full and in place**, next to the action they govern — never collapsed, never demoted for being rare, never cut to meet a budget. Frequency does not apply to them: the reader who hits a data-loss case once is the reader who needed the sentence. Everything below is about the *rest* of the surface.

**"Undocumented" is a legitimate tier.** A rarely-used flag that behaves the way its name suggests needs no entry. Leaving it out is not an omission to apologise for in a "not documented here" note — say nothing.

### Collapse the long tail

Low-value material that has to exist — an exhaustive option table, a driver matrix, a long output sample, low-impact troubleshooting — goes inside `<details>`. Recovery steps stay visible: a failed upgrade, a restore, anything touching data loss or security is critical-tier and is never collapsed. It renders on GitHub and in the common static-site generators, and it keeps the page's skimmable line count low:

```markdown
<details>
<summary>All formatting options</summary>

| Option | Effect |
|---|---|
| `--format=json` | machine-readable output |
| `--format=table` | aligned columns |

</details>
```

Leave a blank line after `</summary>`, or the markdown inside renders as source.

### Explain "why" only where its absence causes a mistake

Rationale is the single biggest source of bloat, because every decision has one and each feels worth a sentence. It earns its place in exactly two cases:

- **A gotcha with a cost** — the reader will otherwise misuse the feature, lose data, or hit a failure they cannot diagnose.
- **A choice that looks wrong** — the surprising default, the one argument order that is not the obvious one.

This rule does not cut the opening. *Why the package exists* is the opening sentence and stays: it is the reader's problem, not a rationale. *Why a feature works the way it does* is rationale and goes.

Everything else gets the *what* and stops. "`--format=json` prints machine-readable output" is complete. Why JSON was chosen, how it is serialised, and which internal fields it omits are the author's context, not the reader's — and a paragraph defending a design decision belongs in an ADR or a release note, never in a usage section.

## Docs-site conventions

**Three pages open every site, in this order.** A reader arrives knowing nothing and leaves able to use the package:

| Page | Answers |
|---|---|
| **Why \<package\>** | What problem it solves, what it refuses to do, and when a different tool is the right one. |
| **Installation** | Install command, requirements, and any publish or config step. Nothing else. |
| **Getting started** | The single most common use case, end to end, in code the reader can paste and run. |

**Getting started is not a tour.** One scenario, the one most people arrive for, carried from nothing to a working result. No option tables, no alternatives, no "you could also". Every branch belongs on a later page, and a link is how the reader gets there. If the page cannot be followed start to finish without a decision, it is a topic page wearing the wrong title.

A topic page that happens to come third is not this page. "Checkpoints", "Payload capture" and "Basic usage" each teach a feature; a reader who has just installed the package still does not know what to type first.

**No duplication.** Deep content lives in `docs/`; the README links to it, never restates it. If a section grows past a teaser, move it to a docs page and link.

**A docs site is not a licence to write more.** Moving content out of the README does not exempt it from the budgets above — the page limit, the ~100-word paragraph cap, the coverage tiers, and the why-rule all apply per docs page, and a site makes them matter more: a reader lands on one page from a search result and needs their answer on it. One page, one job. A page past ~800 words is usually two pages, or one page plus a collapsed reference table.

**Link mechanics.** README → docs links use absolute published-site URLs (for example `https://acme.github.io/example-package/installation`), not repo-relative paths to `docs/*.md`. This is the ecosystem convention — spatie/laravel-permission, spatie/laravel-medialibrary, livewire/livewire, inertiajs/inertia, and laravel/framework all link their READMEs to the published site. Absolute URLs render everywhere the README lands: GitHub, Packagist, IDE package viewers, forks, and the installed vendor copy — where `docs/` is export-ignored and a repo-relative link is dead.

Keep at most one repo-relative pointer to `docs/` as the source location (for example `[docs/](docs/README.md)`). Repo-relative links to individual pages are the non-recommended form — flag them in the audit.

The recommended `docs/` layout — a numeric `NN-` filename prefix so GitHub lists `docs/` in reading order, with generator rewrites stripping the prefix so published URLs stay stable when pages are reordered — is this skill's recommended layout (implemented with VitePress rewrites). It is about filenames, not link form.

**URL stability.** Prefix-stripping rewrites keep a published URL stable when only the `NN-` prefix changes (a reorder). They do NOT keep it stable when the slug itself changes — a slug rename needs an explicit legacy rewrite/redirect for the old route, or an accepted URL break. Because README links are absolute site URLs, a slug rename breaks them too, not only external inbound links.

**Index sync.** Every index/navigation surface the repo actually has must agree on the page inventory:

- The **canonical inventory** is the markdown pages in `docs/`, minus the index page itself and any files the generator config excludes from the site. Compare by source page after route normalization — a rewrite renames the published URL, it never drops a page.
- The **docs index** (`docs/README.md` or `docs/index.md`, when present) and an explicit **sidebar config** (when the generator uses one) must each cover the full inventory.
- A **top nav bar** lists sections/entry points by design — check it only for dead entries, never for full coverage.
- **`llms.txt`** covers the full inventory too. Generated from the page list it cannot drift, so the check is that it is generated rather than hand-maintained; a hand-written link list is the finding.
- The **root README Documentation section** links every page, or only section entry points when the page count makes a full list unreadable — be consistent about which.

The full triple-index layout (README section + docs index + sidebar) is the recommended VitePress shape; a generator that auto-generates navigation or has no docs index page is checked only on the surfaces it has.

**Link audit.** Three link classes resolve differently — don't conflate them:

- **README → docs links** are absolute site URLs. They cannot be validated on disk — check each one against a route the generator actually produces (the source page after slug and rewrite normalization). On-disk resolution still applies to the single repo-relative `docs/` source pointer and to non-docs repo links (`UPGRADING.md`, `CONTRIBUTING.md`, `LICENSE.md`). Flag repo-relative links to individual docs pages as the non-recommended form.
- **Site-internal links inside `docs/`** resolve through the generator's routing. Under active rewrites a valid link may name the rewritten route, not an existing file — the docs build is authoritative for these; manually flag only links that match neither a source file nor a configured route.
- **Asset references** follow the generator's asset rules.

In-page anchors are best-effort. Dead external URLs belong to the staleness audit below.

## The agent-facing surface

A docs site is read by agents as well as people, and they need different files. Three artifacts, all published at the site root:

| File | Built how | Holds |
|---|---|---|
| `llms.txt` | link list generated, preamble optional and hand-written | the index: what the package is, the rules an agent must not get wrong, then one line per page |
| `llms-full.txt` | generated | every page in reading order, so an agent takes the documentation in one fetch instead of crawling nav chrome |
| `<slug>.md` | generated, one per page | the single page an agent actually wants, without the HTML around it |

**Generate the link list; hand-write only the preamble.** The list of pages is exactly what drifts (add a page, forget the index), so build it from the same page list that drives the sidebar. What a generator cannot write is the paragraph an agent needs first: the constraints that make it use the package wrongly if it misses them.

Write that preamble when the package has semantics an agent will misread. The test is whether a wrong reading produces confident bad advice:

- A result that means "not determined" but reads like "nothing found".
- A default that is off, opt-in, or environment-gated, where assuming it is on gives wrong instructions.
- A feature with a blast radius: one that exposes data, deletes, or changes runtime behaviour.
- A platform limit: unsupported under a runtime, framework-only, one framework version.

A package with none of these is fine with the generated header alone: an H1 and the description as a blockquote.

**A page's index line is not its sidebar line.** A sidebar blurb sells the next page to a reader who is already browsing; an index line helps an agent decide whether this page answers the question it holds. Keep a separate agent-facing description where the two differ, and fall back to the blurb where they do not.

**Ship `robots.txt` with a `Sitemap:` line.** Both crawlers and agents use it to enumerate rather than guess.

**Document the agent surface the package itself ships.** A package that installs agent skills, or exposes an MCP server, has a capability a reader cannot discover from its API. It needs its own page, or at least a section: what gets installed, how it is invoked, what it does. A skill nobody knows about is a skill nobody runs.

## Voice

- Second-person ("Install with Composer", not "Users install via Composer")
- Present tense for current behavior, future tense only for genuinely unshipped work
- Avoid marketing language ("blazing fast", "powerful") — show, don't tell
- Beat the **curse of knowledge on the critical path**: install, first working example, and the one gotcha that breaks people. Spell out the prerequisite you have internalised *there*. This is not a mandate to explain every flag — applied page-wide it is the main cause of bloat, and it is bounded by the coverage tiers and the why-rule above.

## Anti-patterns

- Padding the README with motivation prose — **omit needless words**; after the problem-first opening, every sentence should help a reader install or use the package
- Burying the install command below ten paragraphs of motivation
- Examples that don't actually run (always copy-pasteable)
- Stale "TODO" sections — delete them before publishing
- Duplicating CHANGELOG content in README
- Documenting every command, endpoint, or option because it exists — coverage is curated, and "undocumented" is a tier
- A paragraph explaining why a low-importance detail works the way it does
- Restating in prose what the code block below already shows
- An opening that lists what the package provides instead of the problem it removes — and a "Features" list that renames the table of contents
- Announcing what a section will cover before covering it
- (Docs-site shape) Restating a docs page's content in the README, or stating the site root URL more than once in prose (page links to the site don't count)

## Staleness audit

**At every release** (`pre-release` runs it), and quarterly when releases are less frequent: search for old version numbers, deprecated APIs, dead links, and "coming soon" callouts. Either ship them or remove them.

### Verbosity audit

Run this with the staleness scan — docs rot by growing, not only by aging. Every release adds a paragraph, and nothing ever removes one.

- **A missing opening page** — no Why, no Installation, or no Getting started, or a topic page sitting in the Getting-started slot.
- **A feature-list description** — the README opening enumerates capabilities and never names the problem the reader has without the package. Rewrite it from the reader's situation.
- **Over budget** — a README or docs page past its word budget. Cut or split; do not leave it because "it is all true".
- **Prose-majority sections** — paragraph words exceeding the section's code, table and list words. Convert or cut. Exempt: a page with no task in it (concept, security, accessibility, troubleshooting), where prose is the right form.
- **Paragraphs past ~100 words** — count words between blank lines; a line-based check misses a soft-wrapped wall entirely.
- **Rationale on low-importance detail** — a why that does not prevent a mistake. Delete the sentence, keep the what.
- **A long tail written out in full** — an exhaustive option or driver table sitting inline. Collapse it.
- **Detail written above its tier** — an option given prose and an example while the code shows it is not on the critical path: not referenced by the package's own quickstart or examples, not part of the documented public API, and discoverable from `--help`, a typed signature, or a commented config file. Demote it a tier. Judge this from the repository, never from a guess about what users have asked — and never demote anything in the critical tier.

Deleting text is the deliverable here. A page that only ever grows is a page people stop reading.

### Agent-surface audit

For a docs-site repo, check the published site rather than the sources. These are build outputs, and a config change can silently drop one:

- `llms.txt`, `llms-full.txt` and one `<slug>.md` all return 200.
- `llms.txt` lists every current page.
- The preamble still matches the package: a caveat that no longer applies is worse than none, because an agent will act on it.
- A package shipping agent skills or an MCP server still documents them, and the commands it names still exist.

For the docs-site shape, the audit also covers `docs/`:

- The same staleness scan over every docs page
- The index-sync check (all existing surfaces agree on the inventory)
- The link audit (README site links match generator routes; repo-relative pointers and asset references resolve; site-internal links per the generator's routing)

## See also

- [llmstxt.org](https://llmstxt.org) for the `llms.txt` format itself
- `humanizer` skill for the prose-level AI tells (inflated significance, hedging, rule-of-three) this skill's budgets don't catch
- `release-notes` skill for GitHub release body writing
- `upgrading` skill for UPGRADING.md structure
- `pre-release` skill runs this skill's staleness + docs-site audits at every release

README authoring

When to apply

  • Bootstrapping a new package's README
  • Asked to "audit", "refresh", "improve", "shorten", or "trim" an existing README or docs page
  • Reviewing a PR that touches README
  • The package moves its documentation to a docs/ site (for example VitePress, published on GitHub Pages)

The opening names a problem, not a feature set

Every shape below starts with a description. Its job is the same in all three: name the situation the reader is in without the package, then what the package does about it. One or two sentences, then the first code block: the install command, or the teaser example in the docs-site shape. A critical-tier prerequisite or warning that governs that block stays beside it, as the coverage tiers below require. A reader who recognises the situation keeps reading. One who does not will not install the package, whatever the capability list says.

❌ Provides queue middleware, retry policies, a dashboard, and Slack notifications for Laravel jobs.

✅ A job that fails at 3am retries until the queue gives up, and nobody finds out until a customer does.
   This package tells you the first time, with the payload that failed.

Start from the problem the reader already has. Capabilities that do not follow from it go in usage, in a table, or nowhere. The Why <package> docs page (below) carries the long form. The README opening stays at one or two sentences.

Three valid shapes

Stub README (for early-stage packages, <500 stars):

  • One-paragraph description — the problem-first opening above
  • Install command
  • Minimal usage example that resolves the opening's problem
  • License + author

Comprehensive README (for established packages or ones with substantial API):

  • Description (problem-first) + status badges
  • Install + requirements
  • Usage examples for the common cases only — see the coverage tiers below, which decide what gets an example, a table row, or nothing. The first example resolves the problem the opening named; it is the before/after, not a tour of the API
  • Configuration reference (link to dedicated docs if long)
  • Testing/development section
  • Contributing pointer
  • Changelog pointer
  • License + credits

Docs-site README (for packages whose documentation lives in a docs/ site):

  • Description (problem-first) + status badges
  • A copy-pasteable teaser example that resolves the opening's problem
  • Install + requirements
  • One minimal usage example
  • Documentation section: the published site root URL stated once in prose, plus links to every page or to section entry points (pick one policy — see the index-sync rules below — and the link mechanics). Page links are navigation and do not count against the once rule
  • Standard footer: contributing, changelog, security, credits, license

Pick one shape consistently. Don't mix tiers in the same README.

Detecting the docs-site shape

A repo is docs-site shaped when docs/ exists AND any of these signals identifies it as a generated site's source (in precedence order):

  1. A generator config inside docs/ (for example docs/.vitepress/, or a docs/package.json with a build script)
  2. A root-level generator config or package script that names docs/ as its source directory
  3. A deploy workflow that builds from docs/

A plain-markdown docs/ matching none of these is the comprehensive shape with linked docs, not the docs-site shape.

Length is a constraint, not an outcome

A reader skims a README to install the package and get one thing working. Every sentence past that costs them. Write to a budget and cut to fit it — the budget is not a target to fill.

Counted the same way everywhere: wc -w on the whole file — code fences, tables and frontmatter included. One command, no judgement about what counts.

Surface Budget (wc -w) Over it?
Stub README ~350 words Cut, or move to the comprehensive shape
Comprehensive README ~900 words, hard ceiling ~1,200 Move detail to a docs/ site
Docs-site README ~700 words The README is restating a docs page — link instead
One docs page ~800 words Split it, turn prose into a table, or cut the low-value half

Well-regarded packages in this ecosystem land inside those numbers, and they get there structurally, not by writing shorter sentences: the page is mostly code fences, tables, and one-line bullets, with prose only where it frames the next example.

The count is whole-file; the cut is prose. A page over budget because it carries several necessary examples is fine — cut the paragraphs around them first, and only then ask whether an example is redundant. Over budget is a signal to look, not an instruction to delete.

The budget has a floor. Never cut a security caveat, a data-loss or irreversibility warning, a required prerequisite or version constraint, an accessibility note, or a breaking-change pointer to hit a number. If a page is over budget and only load-bearing content remains, it is not too long — it is two pages. Trim rationale, motivation, and restated code before touching anything a reader can be harmed by missing.

Two structural rules do most of the work:

  • Reach a code block in under ~80 words — on a README or a task page (install, usage, configuration). A reader who has to scroll past motivation to find the install line is being made to pay for the author's enthusiasm. A page with no task in it — a concept explainer, a security or accessibility note, a troubleshooting page — is exempt from this rule and from the prose-majority one below: prose is the right form there, and the word budget plus the paragraph cap still apply.
  • Cap a paragraph at ~100 words. Count words between blank lines, not lines — a soft-wrapped file puts a 250-word wall on one line, so any line-based measure reads it as short. Healthy pages peak around 40–80 words per paragraph; a paragraph past ~100, or a section where paragraph words exceed the words in its code fences, tables and lists combined, is a defect. The content is skimmable as a list or table, or it is explaining something that does not need documenting at all.

Coverage is curated — completeness is not the goal

Documenting every command, endpoint, option, and event is how a page becomes unreadable. Most of them are discoverable from the tool itself (--help, an IDE, a config file with comments), and a reader who needs the rare one will look there. Reference material the tool already publishes does not need a prose copy.

Sort every command / endpoint / option into three tiers and write to the tier:

Judge the tier from the repository, never from a guess about how many users need something:

Tier Repository evidence Treatment
Common On the critical path: named in the quickstart, the first example, or the default config Prose + a runnable example
Occasional Part of the documented public API or shipped config, but no example uses it One table row: name, one-line effect. No example, no rationale
Rare Not referenced by any example or default, and self-describing from --help, a typed signature, or a commented config key Collapse it, or leave it out entirely

One tier overrides the other three: critical. A prerequisite without which the package does not work, a security caveat, a destructive or irreversible operation, a data-loss risk, an accessibility requirement, and a compatibility limit are documented in full and in place, next to the action they govern — never collapsed, never demoted for being rare, never cut to meet a budget. Frequency does not apply to them: the reader who hits a data-loss case once is the reader who needed the sentence. Everything below is about the rest of the surface.

"Undocumented" is a legitimate tier. A rarely-used flag that behaves the way its name suggests needs no entry. Leaving it out is not an omission to apologise for in a "not documented here" note — say nothing.

Collapse the long tail

Low-value material that has to exist — an exhaustive option table, a driver matrix, a long output sample, low-impact troubleshooting — goes inside <details>. Recovery steps stay visible: a failed upgrade, a restore, anything touching data loss or security is critical-tier and is never collapsed. It renders on GitHub and in the common static-site generators, and it keeps the page's skimmable line count low:

<details>
<summary>All formatting options</summary>

| Option | Effect |
|---|---|
| `--format=json` | machine-readable output |
| `--format=table` | aligned columns |

</details>

Leave a blank line after </summary>, or the markdown inside renders as source.

Explain "why" only where its absence causes a mistake

Rationale is the single biggest source of bloat, because every decision has one and each feels worth a sentence. It earns its place in exactly two cases:

  • A gotcha with a cost — the reader will otherwise misuse the feature, lose data, or hit a failure they cannot diagnose.
  • A choice that looks wrong — the surprising default, the one argument order that is not the obvious one.

This rule does not cut the opening. Why the package exists is the opening sentence and stays: it is the reader's problem, not a rationale. Why a feature works the way it does is rationale and goes.

Everything else gets the what and stops. "--format=json prints machine-readable output" is complete. Why JSON was chosen, how it is serialised, and which internal fields it omits are the author's context, not the reader's — and a paragraph defending a design decision belongs in an ADR or a release note, never in a usage section.

Docs-site conventions

Three pages open every site, in this order. A reader arrives knowing nothing and leaves able to use the package:

Page Answers
Why <package> What problem it solves, what it refuses to do, and when a different tool is the right one.
Installation Install command, requirements, and any publish or config step. Nothing else.
Getting started The single most common use case, end to end, in code the reader can paste and run.

Getting started is not a tour. One scenario, the one most people arrive for, carried from nothing to a working result. No option tables, no alternatives, no "you could also". Every branch belongs on a later page, and a link is how the reader gets there. If the page cannot be followed start to finish without a decision, it is a topic page wearing the wrong title.

A topic page that happens to come third is not this page. "Checkpoints", "Payload capture" and "Basic usage" each teach a feature; a reader who has just installed the package still does not know what to type first.

No duplication. Deep content lives in docs/; the README links to it, never restates it. If a section grows past a teaser, move it to a docs page and link.

A docs site is not a licence to write more. Moving content out of the README does not exempt it from the budgets above — the page limit, the ~100-word paragraph cap, the coverage tiers, and the why-rule all apply per docs page, and a site makes them matter more: a reader lands on one page from a search result and needs their answer on it. One page, one job. A page past ~800 words is usually two pages, or one page plus a collapsed reference table.

Link mechanics. README → docs links use absolute published-site URLs (for example https://acme.github.io/example-package/installation), not repo-relative paths to docs/*.md. This is the ecosystem convention — spatie/laravel-permission, spatie/laravel-medialibrary, livewire/livewire, inertiajs/inertia, and laravel/framework all link their READMEs to the published site. Absolute URLs render everywhere the README lands: GitHub, Packagist, IDE package viewers, forks, and the installed vendor copy — where docs/ is export-ignored and a repo-relative link is dead.

Keep at most one repo-relative pointer to docs/ as the source location (for example [docs/](docs/README.md)). Repo-relative links to individual pages are the non-recommended form — flag them in the audit.

The recommended docs/ layout — a numeric NN- filename prefix so GitHub lists docs/ in reading order, with generator rewrites stripping the prefix so published URLs stay stable when pages are reordered — is this skill's recommended layout (implemented with VitePress rewrites). It is about filenames, not link form.

URL stability. Prefix-stripping rewrites keep a published URL stable when only the NN- prefix changes (a reorder). They do NOT keep it stable when the slug itself changes — a slug rename needs an explicit legacy rewrite/redirect for the old route, or an accepted URL break. Because README links are absolute site URLs, a slug rename breaks them too, not only external inbound links.

Index sync. Every index/navigation surface the repo actually has must agree on the page inventory:

  • The canonical inventory is the markdown pages in docs/, minus the index page itself and any files the generator config excludes from the site. Compare by source page after route normalization — a rewrite renames the published URL, it never drops a page.
  • The docs index (docs/README.md or docs/index.md, when present) and an explicit sidebar config (when the generator uses one) must each cover the full inventory.
  • A top nav bar lists sections/entry points by design — check it only for dead entries, never for full coverage.
  • llms.txt covers the full inventory too. Generated from the page list it cannot drift, so the check is that it is generated rather than hand-maintained; a hand-written link list is the finding.
  • The root README Documentation section links every page, or only section entry points when the page count makes a full list unreadable — be consistent about which.

The full triple-index layout (README section + docs index + sidebar) is the recommended VitePress shape; a generator that auto-generates navigation or has no docs index page is checked only on the surfaces it has.

Link audit. Three link classes resolve differently — don't conflate them:

  • README → docs links are absolute site URLs. They cannot be validated on disk — check each one against a route the generator actually produces (the source page after slug and rewrite normalization). On-disk resolution still applies to the single repo-relative docs/ source pointer and to non-docs repo links (UPGRADING.md, CONTRIBUTING.md, LICENSE.md). Flag repo-relative links to individual docs pages as the non-recommended form.
  • Site-internal links inside docs/ resolve through the generator's routing. Under active rewrites a valid link may name the rewritten route, not an existing file — the docs build is authoritative for these; manually flag only links that match neither a source file nor a configured route.
  • Asset references follow the generator's asset rules.

In-page anchors are best-effort. Dead external URLs belong to the staleness audit below.

The agent-facing surface

A docs site is read by agents as well as people, and they need different files. Three artifacts, all published at the site root:

File Built how Holds
llms.txt link list generated, preamble optional and hand-written the index: what the package is, the rules an agent must not get wrong, then one line per page
llms-full.txt generated every page in reading order, so an agent takes the documentation in one fetch instead of crawling nav chrome
<slug>.md generated, one per page the single page an agent actually wants, without the HTML around it

Generate the link list; hand-write only the preamble. The list of pages is exactly what drifts (add a page, forget the index), so build it from the same page list that drives the sidebar. What a generator cannot write is the paragraph an agent needs first: the constraints that make it use the package wrongly if it misses them.

Write that preamble when the package has semantics an agent will misread. The test is whether a wrong reading produces confident bad advice:

  • A result that means "not determined" but reads like "nothing found".
  • A default that is off, opt-in, or environment-gated, where assuming it is on gives wrong instructions.
  • A feature with a blast radius: one that exposes data, deletes, or changes runtime behaviour.
  • A platform limit: unsupported under a runtime, framework-only, one framework version.

A package with none of these is fine with the generated header alone: an H1 and the description as a blockquote.

A page's index line is not its sidebar line. A sidebar blurb sells the next page to a reader who is already browsing; an index line helps an agent decide whether this page answers the question it holds. Keep a separate agent-facing description where the two differ, and fall back to the blurb where they do not.

Ship robots.txt with a Sitemap: line. Both crawlers and agents use it to enumerate rather than guess.

Document the agent surface the package itself ships. A package that installs agent skills, or exposes an MCP server, has a capability a reader cannot discover from its API. It needs its own page, or at least a section: what gets installed, how it is invoked, what it does. A skill nobody knows about is a skill nobody runs.

Voice

  • Second-person ("Install with Composer", not "Users install via Composer")
  • Present tense for current behavior, future tense only for genuinely unshipped work
  • Avoid marketing language ("blazing fast", "powerful") — show, don't tell
  • Beat the curse of knowledge on the critical path: install, first working example, and the one gotcha that breaks people. Spell out the prerequisite you have internalised there. This is not a mandate to explain every flag — applied page-wide it is the main cause of bloat, and it is bounded by the coverage tiers and the why-rule above.

Anti-patterns

  • Padding the README with motivation prose — omit needless words; after the problem-first opening, every sentence should help a reader install or use the package
  • Burying the install command below ten paragraphs of motivation
  • Examples that don't actually run (always copy-pasteable)
  • Stale "TODO" sections — delete them before publishing
  • Duplicating CHANGELOG content in README
  • Documenting every command, endpoint, or option because it exists — coverage is curated, and "undocumented" is a tier
  • A paragraph explaining why a low-importance detail works the way it does
  • Restating in prose what the code block below already shows
  • An opening that lists what the package provides instead of the problem it removes — and a "Features" list that renames the table of contents
  • Announcing what a section will cover before covering it
  • (Docs-site shape) Restating a docs page's content in the README, or stating the site root URL more than once in prose (page links to the site don't count)

Staleness audit

At every release (pre-release runs it), and quarterly when releases are less frequent: search for old version numbers, deprecated APIs, dead links, and "coming soon" callouts. Either ship them or remove them.

Verbosity audit

Run this with the staleness scan — docs rot by growing, not only by aging. Every release adds a paragraph, and nothing ever removes one.

  • A missing opening page — no Why, no Installation, or no Getting started, or a topic page sitting in the Getting-started slot.
  • A feature-list description — the README opening enumerates capabilities and never names the problem the reader has without the package. Rewrite it from the reader's situation.
  • Over budget — a README or docs page past its word budget. Cut or split; do not leave it because "it is all true".
  • Prose-majority sections — paragraph words exceeding the section's code, table and list words. Convert or cut. Exempt: a page with no task in it (concept, security, accessibility, troubleshooting), where prose is the right form.
  • Paragraphs past ~100 words — count words between blank lines; a line-based check misses a soft-wrapped wall entirely.
  • Rationale on low-importance detail — a why that does not prevent a mistake. Delete the sentence, keep the what.
  • A long tail written out in full — an exhaustive option or driver table sitting inline. Collapse it.
  • Detail written above its tier — an option given prose and an example while the code shows it is not on the critical path: not referenced by the package's own quickstart or examples, not part of the documented public API, and discoverable from --help, a typed signature, or a commented config file. Demote it a tier. Judge this from the repository, never from a guess about what users have asked — and never demote anything in the critical tier.

Deleting text is the deliverable here. A page that only ever grows is a page people stop reading.

Agent-surface audit

For a docs-site repo, check the published site rather than the sources. These are build outputs, and a config change can silently drop one:

  • llms.txt, llms-full.txt and one <slug>.md all return 200.
  • llms.txt lists every current page.
  • The preamble still matches the package: a caveat that no longer applies is worse than none, because an agent will act on it.
  • A package shipping agent skills or an MCP server still documents them, and the commands it names still exist.

For the docs-site shape, the audit also covers docs/:

  • The same staleness scan over every docs page
  • The index-sync check (all existing surfaces agree on the inventory)
  • The link audit (README site links match generator routes; repo-relative pointers and asset references resolve; site-internal links per the generator's routing)

See also

  • llmstxt.org for the llms.txt format itself
  • humanizer skill for the prose-level AI tells (inflated significance, hedging, rule-of-three) this skill's budgets don't catch
  • release-notes skill for GitHub release body writing
  • upgrading skill for UPGRADING.md structure
  • pre-release skill runs this skill's staleness + docs-site audits at every release
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support