asciidoctor-llms

An AsciidoctorJ extension that turns a single-page AsciiDoc manual into llms.txt, one Markdown file per section, and a section-level search index.

The problem

The Keycloak Server Administration Guide is one HTML page of about 1.79 MB (measured). On keycloak.org it is not in the site’s Pagefind index: for every term below, none of the hits is under /docs/. And an AI assistant cannot read a 2 MB page in one go.

(b) AI answers

Same question in three conditions, one run each, run 2026-10-22 with Claude Code 2.1.296 (claude -p --output-format json). Details: evidence/README.md.

In Keycloak, how do I enable Google reCAPTCHA on the user registration page? Give the exact steps in the Admin Console, including which flow, which execution and which settings to change. Be concise. If you are not sure about a detail, say so.

A · No material

Tools disabled; no documents given.

Model(s)
claude-sonnet-5-5 ($0.0330)
Duration
10765 ms (API 10492 ms), 1 turn(s)
Tokens (sonnet)
2 in / 1252 out (cache read 6902, cache write 4951)
Total cost
$0.0330
These steps are from memory of the Keycloak admin console (v20+ UI). Exact labels may differ slightly between versions.

**1. Get keys from Google**
- In the Google reCAPTCHA admin console, create a site using **reCAPTCHA v2 ("I'm not a robot" checkbox)**.
- Add your Keycloak hostname as a domain.
- Copy the **site key** and **secret key**.
- Keycloak's built-in action is the v2 one. I'm not sure about v3 support, so check your version's docs if you want v3.

**2. Copy the registration flow**
- In the Admin Console, select your realm and go to **Authentication → Flows**.
- Built-in flows can't be edited, so open the **registration** flow's kebab menu and choose **Duplicate**. Name it, for example, `registration-captcha`.

…

View full raw output

  • mentions “Security defenses”: yes
  • mentions “Use recaptcha.net”: yes
  • mentions “reCAPTCHA v3” setting: no

B · Official entry URL only

Given https://www.keycloak.org/docs/latest/server_admin/index.html; only WebFetch allowed.

Model(s)
claude-sonnet-5-5 ($0.0430), claude-haiku-5-5 ($0.0120)
Duration
27701 ms (API 30363 ms), 5 turn(s)
Tokens (sonnet)
8 in / 1535 out (cache read 45909, cache write 5768)
Total cost
$0.0551
**Steps** (from the "Setting up Google reCAPTCHA" procedure in the Server Administration Guide):

1. **At Google:** open the Google reCAPTCHA admin page and create a site. Choose v2 (checkbox) or v3 (score-based). Copy the **site key** and **secret key**.
2. **In the Admin Console:** select your realm, then go to **Authentication → Flows**. Open the **Registration** flow. If you need a custom copy, duplicate it first and bind the copy to the Registration flow.
3. Find the **reCAPTCHA** execution. It sits in the registration form sub-flow. Set its requirement to **Required**.
4. Click the **gear icon** on that row and enter the **Site key** and **Secret**. Turn on **reCAPTCHA v3** only if your key is a v3 key. Optionally turn on **Use recaptcha.net**, which is for regions where google.com is blocked.
5. Go to **Realm settings → Security defenses**. Add the Google domain (`https://www.google.com`, or the recaptcha.net domain if you enabled that option) to the **X-Frame-Options** and **Content-Security-Policy** headers. Without this, the widget can't load in the registration page.
6. Make sure **User registration** is on under **Realm settings → Login**, so the registration page exists.

**What I'm not sure about:**
- The documentation fetch went through a summarizer, and I didn't read the page text directly. I'm unsure of the exact label and value of the header changes in step 5, so check them against the guide (anchor `#procedure_recaptcha`).
- The doc also has a separate "Setting up Google reCAPTCHA Enterprise" procedure. I didn't read it. Use it if your key is an Enterprise one.
…

View full raw output

  • mentions “Security defenses”: yes
  • mentions “Use recaptcha.net”: yes
  • mentions “reCAPTCHA v3” setting: yes

C · llms.txt + section .md

Given our llms.txt and md/proc-enabling-recaptcha_server_administration_guide.md; tools disabled.

Model(s)
claude-sonnet-5-5 ($0.0807)
Duration
6909 ms (API 6699 ms), 1 turn(s)
Tokens (sonnet)
2 in / 642 out (cache read 8470, cache write 18365)
Total cost
$0.0807
**Steps (Google reCAPTCHA, v2 or v3):**

1. In Google's reCAPTCHA admin (`https://www.google.com/recaptcha/admin/create`), create a key (Challenge v2 or Score-based v3) and note the site key and secret. Localhost domains aren't supported by default, so add them to the key's domain list if you need them for development.
2. In the Keycloak Admin Console, go to **Authentication** → **Flows** tab → select the **Registration** flow.
3. Find the **reCAPTCHA** execution and set its requirement to **Required**.
4. Click the **gear icon** on the **reCAPTCHA** row and set:
   - **reCAPTCHA Site Key**
   - **reCAPTCHA Secret**
   - **reCAPTCHA v3**: on for a v3 key, off for a v2 key.
   - **Use recaptcha.net** (optional): uses `www.recaptcha.net` instead of `www.google.com`.
5. Allow Google to frame the registration page. Go to **Realm Settings** → **Security Defenses** tab. Enter `https://www.google.com` in both the **X-Frame-Options** and **Content-Security-Policy** header fields. If you enabled **Use recaptcha.net**, use the recaptcha.net URL instead.

…

View full raw output

  • mentions “Security defenses”: yes
  • mentions “Use recaptcha.net”: yes
  • mentions “reCAPTCHA v3” setting: yes

Excerpts are the first lines of each result field, unedited; “…” marks truncation. The fact lists are plain string checks on the full text.

Measured on the Keycloak docs

Server Administration Guide, llms-split-level=2: 1.79 MB HTML converted in about 5 seconds with 0 Asciidoctor warnings, producing 208 Markdown files, a 37.1 KB llms.txt and a 332 KB search-index.json (current build of the same source, Keycloak main @ 461809bf; see notes/e2e-results.md).

Quick start

asciidoctor-maven-plugin

Install the jar locally (mvn install), then add it as a plugin dependency:

<plugin>
  <groupId>org.asciidoctor</groupId>
  <artifactId>asciidoctor-maven-plugin</artifactId>
  <version>3.0.0</version>
  <dependencies>
    <dependency>
      <groupId>dev.asciidocsearch</groupId>
      <artifactId>asciidoctor-llms</artifactId>
      <version>0.1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
  <executions>
    <execution>
      <id>html</id>
      <phase>generate-resources</phase>
      <goals><goal>process-asciidoc</goal></goals>
      <configuration>
        <backend>html5</backend>
        <attributes>
          <llms-split-level>2</llms-split-level>
          <llms-base-url>https://example.com/docs/</llms-base-url>
          <llms-search-shard-size>100000</llms-search-shard-size>
        </attributes>
      </configuration>
    </execution>
  </executions>
</plugin>

CLI

mvn -q clean package
java -jar target/asciidoctor-llms-0.1.0-SNAPSHOT-all.jar in.adoc outdir -a llms-split-level=2 -a llms-base-url=https://example.com/docs/