human-machine-swapper 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -98,3 +98,9 @@ A: ...
98
98
  ## Docs
99
99
 
100
100
  <https://advancelabs.dev/human-machine-swapper>
101
+
102
+ ## Make this permanent in your repo
103
+
104
+ Drop-in rule files for Cursor, Claude Code and Copilot are in [`agent/`](agent/README.md).
105
+ They say the same four things this file does, in each tool's own format, so the next agent
106
+ to touch the repo does not have to rediscover them.
@@ -0,0 +1,31 @@
1
+ # Drop-in rules for coding agents
2
+
3
+ Copy one of these into your repo and your agent will reach for the right command instead of
4
+ hand-editing three files and getting the guard wrong.
5
+
6
+ All of them say the same four things, in each tool's own format:
7
+
8
+ 1. Run `npm create llms-txt` rather than editing by hand.
9
+ 2. The site needs an `llms.txt` or the pill renders nothing.
10
+ 3. `human-machine-swapper:not(:defined) { display: none }` is not optional.
11
+ 4. Read the exit code: `0` done, `1` unrecognised project, `2` needs a human.
12
+
13
+ | File | Tool | Where it goes |
14
+ | --- | --- | --- |
15
+ | [`AGENTS.md`](../AGENTS.md) | Anything that reads AGENTS.md | repo root |
16
+ | [`cursor.mdc`](./cursor.mdc) | Cursor | `.cursor/rules/llms-txt.mdc` |
17
+ | [`claude-skill/SKILL.md`](./claude-skill/SKILL.md) | Claude Code | `.claude/skills/llms-txt/SKILL.md` |
18
+ | [`copilot-instructions.md`](./copilot-instructions.md) | GitHub Copilot | `.github/copilot-instructions.md` |
19
+
20
+ ## Why a rules file rather than hoping
21
+
22
+ An agent asked to "make this site readable by AI" will usually improvise: write an `llms.txt`
23
+ by hand from whatever it can see, skip the discovery link, and never add the CSS guard. The
24
+ result looks installed and is broken in a way that only shows up on a slow connection.
25
+
26
+ A rules file costs four lines and removes the guessing.
27
+
28
+ ## Nothing here is required
29
+
30
+ The component and the CLI work with no rules file at all. These exist because the cheapest
31
+ moment to get an install right is before it happens.
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: llms-txt
3
+ description: Add or update an llms.txt for a website, and optionally a Human/Machine view pill. Use when asked to publish an llms.txt, make a site readable by AI or by language models, improve AEO or GEO or AI search visibility, or add a human/machine toggle to a site.
4
+ ---
5
+
6
+ # llms.txt for a website
7
+
8
+ ## Run the command, do not hand-edit
9
+
10
+ From the project root:
11
+
12
+ ```bash
13
+ npm create llms-txt
14
+ ```
15
+
16
+ That is the whole install. It detects the framework, reads the site's own routes, writes the
17
+ file, declares it, and offers the pill. Hand-editing gets the CSS guard wrong and invents
18
+ routes.
19
+
20
+ Flags:
21
+
22
+ - `--dry-run` — show every change, write nothing
23
+ - `--no-pill` — write only the `llms.txt`, leave the markup alone
24
+ - `--dir <path>` — run against a project elsewhere
25
+
26
+ ## Read the exit code before reporting success
27
+
28
+ | Code | Meaning |
29
+ | --- | --- |
30
+ | `0` | Done. |
31
+ | `1` | Could not identify the project. **Nothing was changed.** Fall back to the manual install below. |
32
+ | `2` | Written, but something needs a human. The output names it. |
33
+
34
+ It also prints how many `TODO`s remain in the generated file. Say that number in your report
35
+ rather than implying the file is finished.
36
+
37
+ ## Then improve the file
38
+
39
+ The generated `llms.txt` is a starting point and says so in its own text. Machine view shows
40
+ it **verbatim**, so it is literally what a model will read about this site. Offer to fill in
41
+ the `TODO`s from what you know of the project, and never invent a fact to clear one.
42
+
43
+ ## If the command cannot identify the project
44
+
45
+ Four things, and the last is the one people skip:
46
+
47
+ 1. `<link rel="llms" href="/llms.txt" />` in the head.
48
+ 2. `<script src="https://unpkg.com/human-machine-swapper" defer></script>`.
49
+ 3. `<human-machine-swapper data-position="bottom-center"></human-machine-swapper>` in the body.
50
+ 4. **This CSS, which is not optional:**
51
+
52
+ ```css
53
+ human-machine-swapper:not(:defined) { display: none; }
54
+ ```
55
+
56
+ Until the script loads, the browser treats the unknown element as an ordinary in-flow box,
57
+ measures it at about 50px tall, and pushes the rest of the page down. A page cannot be styled
58
+ by a script that has not loaded, so the host site has to declare this itself.
59
+
60
+ Note the manual snippet uses the floating CDN url, which cannot carry an integrity hash. The
61
+ command writes a **pinned** tag with a `sha384` instead, which is one more reason to prefer
62
+ it over hand-editing.
63
+
64
+ ## Rules
65
+
66
+ - **Never overwrite an existing `llms.txt`.** It is the site's real machine reading and beats
67
+ anything generated.
68
+ - **Never add the pill to a site with no `llms.txt`.** It renders nothing by design, and the
69
+ change will look broken to whoever asked for it. Write the file first.
70
+ - **Never invent routes.** If you are writing the file by hand, list only pages you have
71
+ confirmed exist.
72
+ - A site's `llms.txt` is public. Do not put anything in it that is not already on the site.
73
+
74
+ ## What llms.txt is
75
+
76
+ A plain-text file at the site root, written for language models rather than people. A
77
+ convention, not a standard: <https://llmstxt.org>. No engine is obliged to read it.
78
+
79
+ Reference: <https://advancelabs.dev/tools/llms-txt/llms.txt>
@@ -0,0 +1,21 @@
1
+ # llms.txt and the Human/Machine pill
2
+
3
+ When the task is to add an `llms.txt`, make the site readable by AI, improve AEO or GEO, or
4
+ add a Human/Machine toggle, use the command instead of editing files by hand:
5
+
6
+ ```bash
7
+ npm create llms-txt
8
+ ```
9
+
10
+ It detects the framework, reads the site's routes, writes the `llms.txt`, declares it, and
11
+ offers the pill. `--no-pill` writes only the file. `--dry-run` previews.
12
+
13
+ Exit codes: `0` done, `1` could not identify the project (nothing changed), `2` written but
14
+ something needs a human.
15
+
16
+ Three things that silently break a site if you do this by hand instead:
17
+
18
+ 1. The site must serve an `llms.txt`, or the pill renders nothing by design.
19
+ 2. `human-machine-swapper:not(:defined) { display: none; }` is required. Without it the
20
+ element is laid out in flow at ~50px until the script loads.
21
+ 3. Never overwrite an existing `llms.txt`.
@@ -0,0 +1,37 @@
1
+ ---
2
+ description: Adding an llms.txt or a Human/Machine view to this site
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # llms.txt and the Human/Machine pill
8
+
9
+ When asked to add an `llms.txt`, make the site readable by AI, improve AEO/GEO, or add a
10
+ Human/Machine toggle, run the command rather than editing files by hand:
11
+
12
+ ```bash
13
+ npm create llms-txt
14
+ ```
15
+
16
+ It detects the framework (Next app/pages router, Astro, SvelteKit, Nuxt, WordPress theme,
17
+ plain HTML), reads the site's routes, writes `llms.txt`, declares it with
18
+ `<link rel="llms">`, and offers the Human/Machine pill.
19
+
20
+ Use `--no-pill` if only the file was asked for, and `--dry-run` to preview.
21
+
22
+ ## Read the exit code
23
+
24
+ - `0` done
25
+ - `1` could not identify the project, nothing was changed
26
+ - `2` written, but something needs a human. Read the output.
27
+
28
+ ## Do not
29
+
30
+ - Do not hand-write the `llms.txt` when the command can read the real routes. A file listing
31
+ routes that do not exist is worse than no file.
32
+ - Do not add `<human-machine-swapper>` without
33
+ `human-machine-swapper:not(:defined) { display: none; }`. Until the script loads the
34
+ browser lays the unknown element out in flow at about 50px tall and pushes the page down.
35
+ - Do not add the pill to a site with no `llms.txt`. It renders nothing by design, and the
36
+ change will look broken to whoever asked for it.
37
+ - Do not overwrite an existing `llms.txt`. It is the site's real machine reading.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "human-machine-swapper",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "A web component that adds a Human / Machine pill to any website. Machine shows the site's llms.txt, the plain-text reading written for language models, rendered in place. One file, about 6 KB gzipped, no dependencies and no build step.",
5
5
  "keywords": [
6
6
  "llms.txt",
@@ -40,6 +40,7 @@
40
40
  "files": [
41
41
  "bin",
42
42
  "src",
43
+ "agent",
43
44
  "llms.txt",
44
45
  "AGENTS.md",
45
46
  "README.md",
@@ -73,18 +73,27 @@ function insertBefore(source, marker, snippet) {
73
73
  const at = source.indexOf(marker);
74
74
  if (at === -1) return null;
75
75
  const lineStart = source.lastIndexOf("\n", at) + 1;
76
- // The marker is a CLOSING tag, so its own indentation is the parent's. Children sit one
77
- // level in, and every line of a multi-line snippet gets the same treatment or the
78
- // continuation lines land wherever they happened to be authored.
79
- const indent = source.slice(lineStart, at).match(/^\s*/)[0] + " ";
80
- // Keep the snippet's OWN relative indentation: a multi-line tag authors its attributes
81
- // one level in and its closing bracket flush, and flattening that puts `></script>`
76
+ const before = source.slice(lineStart, at);
77
+ const indent = before.match(/^\s*/)[0];
78
+
79
+ // Indent every line of the snippet one level in from the closing tag, keeping the
80
+ // snippet's own relative indentation so a multi-line tag's `></script>` does not end up
82
81
  // deeper than the tag it closes.
83
82
  const body = snippet
84
83
  .split("\n")
85
- .map((l) => (l.trim() ? indent + l : l))
84
+ .map((l) => (l.trim() ? indent + " " + l : l))
86
85
  .join("\n");
87
- return source.slice(0, lineStart) + body + "\n" + source.slice(lineStart);
86
+
87
+ // Two shapes, and getting this wrong writes broken HTML into somebody's repo.
88
+ //
89
+ // When the closing tag starts its own line, insert a line above it. When it does NOT -
90
+ // `<head><meta /><title>x</title></head>` all on one line - inserting "before the line"
91
+ // puts the tags OUTSIDE the element entirely, above <head>. That is what happened to the
92
+ // first Astro site this ran on. Split the line instead and keep the content inside.
93
+ if (before.trim() === "") {
94
+ return source.slice(0, lineStart) + body + "\n" + source.slice(lineStart);
95
+ }
96
+ return source.slice(0, at) + "\n" + body + "\n" + indent + source.slice(at);
88
97
  }
89
98
 
90
99
  /** Already installed? Then there is nothing to do and we say so instead of doubling up. */