=== AMI LLMS file ===
Contributors: amidev
Requires at least: 6.2
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.9.8
License: GPLv2 or later

Supercharge your AI SEO with AMI LLMS. Editable llms.txt + llms-full.txt, robots.txt advertising, Yoast/Rank Math/AIOSEO support, crawler stats.

== Description ==

Supercharge your AI SEO with AMI LLMS. Generates and serves an editable llms.txt file at yoursite.com/llms.txt and a full-content llms-full.txt version, and advertises them in robots.txt. Works with all major SEO plugins. Auto-updates when you publish, edit, or delete content, and can be edited manually from the WordPress admin. With crawler stats.

**Features:**

* Auto-generated llms.txt with structured sections (Company, Services, Resources, Contact, Policies), page descriptions, and last-updated dates
* Ecommerce ready: include WooCommerce Products, Product Categories, Brands, and any other public taxonomy as their own sections
* Full-content llms-full.txt built from your pages as they actually render — works with page builders and block themes
* Reads meta descriptions from Yoast SEO, Rank Math, All in One SEO, SEOPress, and any other SEO plugin via the rendered page
* robots.txt lines so AI crawlers discover the files
* Manual override with Replace and Hybrid modes, plus a version History page with diffs
* Per-page controls: exclude any page, or hand-write its description, right in the editor
* Crawler Analytics: see which AI crawlers (GPTBot, ClaudeBot, PerplexityBot and more) are reading your files
* Rebuilds automatically whenever content, titles, or meta descriptions change

== Installation ==

1. Upload the whole "ami-llms" folder to /wp-content/plugins/
   (or upload the .zip via Plugins > Add New > Upload Plugin)
2. Activate the plugin through the "Plugins" menu in WordPress
3. Go to the "AMI LLMS file" menu item in your WordPress admin sidebar (or
   click "Edit LLMS file" next to the plugin on the Plugins page) to configure it
4. Visit yoursite.com/llms.txt to see the live file

If the file returns a 404 immediately after activating, go to
Settings > Permalinks and click "Save Changes" once — this refreshes
WordPress's URL rewrite rules.

== How it works ==

Auto-generated mode (default):
- Lists your published pages/posts (you choose which post types)
- Pages are organised into meaningful sections automatically: parent pages
  with sub-pages become their own section (e.g. "Capabilities" or
  "Services"), privacy/terms pages go under "Policies", contact pages under
  "Contact", and remaining top-level pages under "Company" with the
  homepage listed first
- Each link carries a description of up to ~300 characters, taken from the
  page's SEO meta description (Yoast, Rank Math, AIOSEO or SEOPress), its
  excerpt, or the start of its content
- Includes an intro paragraph: your custom text, or automatically the
  homepage's meta description or the site tagline
- Rebuilds automatically whenever you publish, edit, or delete content
- Cached for up to 1 hour for performance, but any content change clears
  the cache immediately so the next visitor always sees the latest version

Full-content file (llms-full.txt):
- Served at yoursite.com/llms-full.txt alongside llms.txt
- Contains the complete plain-text content of every included page/post,
  so AI crawlers can read your site without visiting each URL
- Uses the same post-type selections and intro text as llms.txt
- Can be switched off from the settings page if you only want the index file

robots.txt integration:
- Reference lines pointing at llms.txt (and llms-full.txt, if enabled) are
  appended automatically to WordPress's robots.txt, so AI crawlers can
  discover the files
- Can be switched off from the settings page
- Only works with WordPress's built-in (virtual) robots.txt — if a physical
  robots.txt file exists on your server it takes priority over WordPress,
  and the settings page will show you the lines to paste into it manually

Manual override mode:
- Go to the "AMI LLMS file" menu in your WordPress admin sidebar
- Type your own llms.txt content into the "Manual Override" box
- Choose how it's used:
  * Replace — your text is the entire file, served exactly as written.
    It does not update when you publish new content.
  * Hybrid — your text appears at the top and the auto-generated page
    listing is appended below it. The listing keeps updating automatically
    as content changes; your text is never modified.
- Clear the box to switch back to fully auto-generated mode
- Applies to llms.txt only; llms-full.txt is always auto-generated

== Notes ==

- The files are served dynamically (not written to disk), so the plugin works
  on hosts where it doesn't have file-write permissions.
- Deleting the plugin removes all of its settings and cached data from the
  database automatically.
- No Google Search Console integration is included in this version —
  llms.txt is not currently a file type that Search Console reads or
  reports on, so there's nothing for it to connect to yet. If Google
  or another provider introduces official support in future, this
  plugin can be extended to hook into that API.

== Upgrade Notice ==

= 1.9.4 =
Ecommerce support (Product Categories, Brands, product descriptions from the Description field), cleaner sentence-complete descriptions with no ellipses or placeholder text, detection and one-click removal of a physical llms.txt blocking the plugin, and instant rebuilds on updates.

== Changelog ==

= What's new since 1.8.7 =

**Ecommerce support (1.9.0–1.9.2)**
* New "Shop & category listings" setting: include archive pages as their own llms.txt sections — WooCommerce Product Categories and Brands (including Perfect WooCommerce Brands and YITH), Easy Digital Downloads categories, blog Categories/Tags, and any other public taxonomy. Each section links every non-empty term's archive page with its description.
* Product entries are described from the product's long Description field, trimmed at a sentence boundary — not from template-generated meta descriptions built on the terse short description. Hand-written per-product SEO descriptions still take priority.
* Products themselves already appear via the "Content to include" list when WooCommerce is active.
* Files also rebuild automatically when taxonomy terms are added, edited, or deleted.

**Cleaner, more reliable descriptions (1.8.10–1.9.3)**
* When a page has no meta description, a description is auto-generated from the page's rendered content, within the recommended 160-character limit; if no usable text exists, the entry shows just the page name and URL.
* Descriptions never end with an ellipsis: truncation ends at a complete sentence, a first sentence slightly over the limit is allowed to finish, and when no complete sentence can be produced the description is left blank.
* Placeholder text (e.g. leftover Lorem ipsum in hidden editor fields) can no longer appear in the file, from any source.
* Heading text (h1–h6) is stripped from auto-generated content, so descriptions and llms-full.txt read as clean prose.

**Physical file detection (1.9.4)**
* If a real llms.txt file exists in the site root (uploaded manually, or created by another plugin such as Yoast SEO's llms.txt feature), it is served by the web server and shadows this plugin. The settings page now warns when this happens and offers a one-click "Remove the physical file" button, with guidance to disable the other plugin's feature so the file is not re-created.

**Behaviour and defaults**
* Plugin updates now rebuild the files immediately instead of serving the previous version's output for up to an hour.
* New-install defaults simplified: robots.txt advertising on; llms-full.txt and last-updated dates off (both can be enabled in settings); Manual Override starts in Hybrid mode.

**Housekeeping (1.8.8–1.8.9)**
* Updated author information.

= 1.9.8 =
- Updated the developer website link

= 1.9.7 =
- Final Plugin Check pass: annotated the History page's read-only view
  selector

= 1.9.6 =
- Updated the plugin description

= 1.9.5 =
- Code-quality pass for the WordPress.org Plugin Check: all output escaped,
  database queries use identifier placeholders, input reads sanitised, and
  the text domain aligned with the plugin slug. Minimum WordPress version
  is now 6.2.

= 1.9.4 =
- New: physical-file detection — if a real llms.txt or llms-full.txt file
  exists in the site root (uploaded manually, or created by another
  plugin such as Yoast SEO's llms.txt feature), it is served by the web
  server directly and shadows this plugin. The settings page now warns
  when this is the case and offers a one-click "Remove the physical file"
  button, with guidance to disable the other plugin's feature so the file
  is not re-created.

= 1.9.3 =
- Improved: descriptions never end with an ellipsis. A first sentence
  slightly longer than the length limit is now allowed to complete (up to
  twice the limit), and when no complete sentence can be produced the
  description is left blank — the entry shows just the name and URL

= 1.9.2 =
- Improved: product entries (WooCommerce and Easy Digital Downloads) now
  use the product's long Description field for their llms.txt description,
  trimmed to 160 characters at a sentence boundary — instead of
  template-generated meta descriptions built from the terse short
  description. A hand-written per-product SEO meta description still takes
  priority, and the short description remains as a fallback.

= 1.9.1 =
- Improved: truncated descriptions now end at the last complete sentence
  that fits the length limit, instead of stopping mid-sentence with an
  ellipsis

= 1.9.0 =
- New: ecommerce support — a "Shop & category listings" setting lists
  archive pages as their own llms.txt sections: WooCommerce Product
  Categories and Brands (including Perfect WooCommerce Brands and YITH),
  Easy Digital Downloads categories, blog Categories/Tags, and any other
  public taxonomy. Each section links every non-empty term's archive page
  with its description. Products themselves already appear via the
  existing "Content to include" post-type list.
- The files also rebuild automatically when taxonomy terms are added,
  edited, or deleted

= 1.8.14 =
- Improved: heading text (h1–h6) is now removed from auto-generated
  content — descriptions no longer start with the page's own headings,
  and llms-full.txt body text reads as clean prose

= 1.8.13 =
- Fixed: placeholder text (Lorem ipsum) can no longer appear as a page
  description from any source — every description candidate is validated,
  and placeholder copy is rejected wherever it is found
- Changed: when no meta description exists, the description is
  auto-generated from the page's rendered text within the recommended
  meta description length (160 characters); when no usable text exists,
  the entry shows just the page name and URL. The excerpt fallback was
  removed.
- Fixed: the files are now rebuilt immediately when the plugin is
  updated, instead of serving the previous version's output for up to an
  hour

= 1.8.12 =
- Changed default: the Manual Override mode now starts on Hybrid (your
  text on top, live auto-updating page listing below) on new installs

= 1.8.11 =
- Changed defaults: the full-content llms-full.txt file and last-updated
  dates now start switched off on new installs (both can still be enabled
  in settings; existing installs keep their saved settings)

= 1.8.10 =
- Fixed: stale placeholder text (e.g. Lorem ipsum left in the editor
  field) can no longer appear as a page description. When a page has no
  meta description or excerpt, a short description (max 170 characters)
  is auto-generated from the page's rendered text; when no usable text
  exists, the description is left blank and the entry shows just the
  page name and URL

= 1.8.9 =
- Updated author information

= 1.8.7 =
- Updated "Tested up to" to WordPress 7.0 and declared the minimum PHP
  version for the WordPress.org directory

= 1.8.6 =
- Restructured readme.txt for the WordPress.org format: short description
  within the 150-character limit, full description and feature list in a
  dedicated Description section

= 1.8.5 =
- Updated the plugin description

= 1.8.4 =
- Fixed: settings changes (e.g. unticking last-updated dates) not showing
  in the live files. The llms.txt and llms-full.txt responses are now
  served with no-cache headers and the DONOTCACHEPAGE flag, so browsers,
  page-cache plugins, and CDNs stop holding stale copies

= 1.8.3 =
- Fixed: meta descriptions generated by SEO plugin templates (rather than
  typed per page) were not picked up. The lookup is now layered: the
  per-page AMI description, then Yoast's API (resolves templates and
  %%variables%%), then the per-page fields of Yoast / Rank Math / All in
  One SEO / SEOPress (with template-variable resolution), then the meta
  description tag in the rendered page itself — which works with every
  SEO plugin — and finally the excerpt and page-text fallbacks

= 1.8.2 =
- Fixed: llms-full.txt showing little or no content (or stale placeholder
  text) on sites built with page builders or block themes, where the real
  content doesn't live in the WordPress editor field. The plugin now reads
  each page's rendered HTML — fetching the page itself, extracting the
  main content area, and stripping navigation, scripts, and page furniture
  — so the file always matches what visitors actually see. Extracted text
  is cached per page and refreshed only when that page changes.
- Fixed: the same stale editor content leaking into llms.txt descriptions
  when a page has no SEO meta description or excerpt — the rendered page
  text is now used for that fallback too

= 1.8.1 =
- Removed: per-bot AI crawler blocking. The robots.txt integration that
  advertises llms.txt and llms-full.txt is unchanged.

= 1.8.0 =
- Removed: the experimental AI content-generation features (the API key
  setting, generation button, scheduled regeneration, editorial
  observations, and stale-file warning). Any scheduled regeneration event
  and stored data are cleaned up automatically on update.
- Everything else is unchanged: auto-generated house-style llms.txt and
  llms-full.txt, manual override (Replace/Hybrid), robots.txt integration,
  AI crawler blocking, per-page exclude/description controls, last-updated
  dates, Crawler Analytics, and the History page (manual edits)

= 1.7.0 =
- New: AI crawler access control — per-crawler Block checkboxes (GPTBot,
  ClaudeBot, PerplexityBot, Google-Extended, CCBot, Bytespider and more)
  that write Disallow rules into robots.txt
- New: scheduled AI regeneration — regenerate llms.txt with AI weekly or
  monthly via WP-Cron, applied automatically, with last-run status shown
  in settings
- New: History page — the last 10 saved versions of the file (manual edits
  and AI generations), each comparable against the current file with a
  colour-coded diff
- New: stale-file warning — when site content changes after an AI
  generation, the settings page flags that the saved file may be out of
  date

= 1.6.0 =
- New: Crawler Analytics — every request to llms.txt and llms-full.txt is
  logged with the requesting crawler identified (GPTBot, ClaudeBot,
  PerplexityBot, Google-Extended, CCBot and more). A new "Crawler
  Analytics" page under the AMI LLMS file menu shows 30-day totals per
  crawler, per file, and the most recent hits. Data is kept for 90 days.
- New: per-page controls — an "AMI LLMS file" box in the page/post editor
  sidebar with an "Exclude from llms.txt" checkbox and a custom
  description field that overrides the meta description in the file
- New: last-updated dates on each entry (and in llms-full.txt), so
  crawlers can prioritise fresh content — can be switched off in settings
- Note: excluded pages are also left out of llms-full.txt and of the
  inventory sent to the AI generator

= 1.5.1 =
- Improved: the file now also rebuilds when SEO titles or meta descriptions
  (Yoast, Rank Math, AIOSEO, SEOPress) are changed outside the post editor —
  e.g. via bulk editors, quick edit, or imports

= 1.5.0 =
- New: experimental AI content generation (removed again in 1.8.0)
- Improved: link labels now come from each page's on-page H1 where one
  exists in the content, falling back to the page title
- Improved: URLs are now the canonical URLs, not raw permalinks
- Improved: house section order — Company, parent-page groups
  (Services/Capabilities), Resources, Contact, Policies; the blog/posts
  section is now titled "Resources"

= 1.4.0 =
- New: hybrid override mode — keep your hand-written text at the top of
  llms.txt while the auto-generated page listing below it stays live,
  updating automatically as you publish, edit, or delete content

= 1.3.0 =
- Improved: llms.txt structure — pages are grouped into named sections from
  the page hierarchy (parent pages with children become their own section),
  with dedicated "Policies" and "Contact" sections and a "Company" section
  for remaining top-level pages, homepage first
- Improved: richer link descriptions — up to ~300 characters (was 200),
  truncated on word boundaries instead of mid-word, with a longer fallback
  taken from page content when no SEO description or excerpt exists
- Improved: the intro paragraph now falls back to the homepage's SEO meta
  description before the site tagline
- Improved: pages are ordered by menu order (matching your site structure)
  rather than alphabetically

= 1.2.0 =
- New: robots.txt integration — llms.txt and llms-full.txt are advertised
  automatically in WordPress's robots.txt (can be disabled in settings)
- New: the settings page warns when a physical robots.txt file would block
  the integration, and shows the lines to add manually

= 1.1.0 =
- New: llms-full.txt companion file with the complete plain-text content of
  every included page/post (can be disabled in settings)
- New: uninstall cleanup — options and cached data are removed when the
  plugin is deleted
- Fixed: settings saved under the old internal option name are migrated
  automatically
- Fixed: rewrite rules refresh automatically after plugin updates (no need
  to re-save permalinks)
- Internal: renamed all internal prefixes from the legacy "slm" naming to
  "ami_llms" for consistency

= 1.0.0 =
- Initial release
