geo-ai-search-optimization 1.0.1 → 1.0.2

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/README.md CHANGED
@@ -28,12 +28,18 @@ geo-ai-search-optimization install
28
28
  geo-ai-search-optimization install --target ./tmp/custom-skills --json
29
29
  geo-ai-search-optimization where
30
30
  geo-ai-search-optimization doctor
31
+ geo-ai-search-optimization init-llms ./site --site-name "Acme Docs" --site-url "https://example.com"
31
32
  geo-ai-search-optimization scan ./my-site --max-file-size 500000 --max-examples 3
32
33
  geo-ai-search-optimization scan ./my-site --json --out ./reports/geo-scan.json
33
34
  geo-ai-search-optimization version
34
35
  geo-ai-search-optimization help
35
36
  ```
36
37
 
38
+ ## New in 1.0.2
39
+
40
+ - `init-llms` command for generating an `llms.txt` starter template
41
+ - keeps the `1.0.1` CLI upgrades: `doctor`, custom `install --target`, and richer `scan` output controls
42
+
37
43
  ## New in 1.0.1
38
44
 
39
45
  - `doctor` command for installation and environment checks
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geo-ai-search-optimization",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Install and run a GEO-first, SEO-supported Codex skill for AI search optimization.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -5,6 +5,7 @@ import { installSkill } from "./install-skill.js";
5
5
  import { getBundledSkillPath, getInstalledSkillPath, getSkillName, getSkillsDir } from "./paths.js";
6
6
  import { renderScanMarkdown, scanProject, writeScanOutput } from "./scan.js";
7
7
  import { renderDoctorMarkdown, runDoctor } from "./doctor.js";
8
+ import { createLlmsTxt } from "./llms-txt.js";
8
9
 
9
10
  let cachedVersion;
10
11
 
@@ -29,6 +30,7 @@ function printHelp() {
29
30
  " geo-ai-search-optimization install [--target <dir>] [--json]",
30
31
  " geo-ai-search-optimization where",
31
32
  " geo-ai-search-optimization doctor [--json]",
33
+ " geo-ai-search-optimization init-llms [target-dir] [--site-name <name>] [--site-url <url>] [--overwrite] [--json]",
32
34
  " geo-ai-search-optimization scan <project-path> [--json] [--out <file>] [--max-file-size <bytes>] [--max-examples <count>]",
33
35
  " geo-ai-search-optimization version",
34
36
  " geo-ai-search-optimization help",
@@ -123,6 +125,24 @@ async function handleScan(args) {
123
125
  process.stdout.write(renderedOutput);
124
126
  }
125
127
 
128
+ async function handleInitLlms(args) {
129
+ const targetDir = args.find((value) => !value.startsWith("-")) || ".";
130
+ const outputJson = hasFlag(args, "--json");
131
+ const result = await createLlmsTxt({
132
+ targetDir,
133
+ siteName: getFlagValue(args, "--site-name"),
134
+ siteUrl: getFlagValue(args, "--site-url"),
135
+ overwrite: hasFlag(args, "--overwrite")
136
+ });
137
+
138
+ if (outputJson) {
139
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
140
+ return;
141
+ }
142
+
143
+ process.stdout.write(`Created llms.txt at ${result.outputPath}\n`);
144
+ }
145
+
126
146
  export async function runCli(args = []) {
127
147
  const [command = "install", ...rest] = args;
128
148
 
@@ -151,6 +171,11 @@ export async function runCli(args = []) {
151
171
  return;
152
172
  }
153
173
 
174
+ if (command === "init-llms") {
175
+ await handleInitLlms(rest);
176
+ return;
177
+ }
178
+
154
179
  if (command === "scan") {
155
180
  await handleScan(rest);
156
181
  return;
package/src/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { installSkill } from "./install-skill.js";
2
2
  export { runCli } from "./cli.js";
3
3
  export { runDoctor, renderDoctorMarkdown } from "./doctor.js";
4
+ export { createLlmsTxt } from "./llms-txt.js";
4
5
  export { scanProject, renderScanMarkdown, writeScanOutput } from "./scan.js";
@@ -0,0 +1,76 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ async function pathExists(targetPath) {
5
+ try {
6
+ await fs.access(targetPath);
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+
13
+ function buildLlmsTxtContent({ siteName, siteUrl }) {
14
+ const resolvedSiteName = siteName || "Your Site Name";
15
+ const resolvedSiteUrl = siteUrl || "https://example.com";
16
+
17
+ return [
18
+ `# ${resolvedSiteName}`,
19
+ "",
20
+ `> GEO-first site profile for AI assistants and answer engines.`,
21
+ "",
22
+ `Canonical: ${resolvedSiteUrl}`,
23
+ "",
24
+ "## About",
25
+ "",
26
+ "- Summarize what this site does in 1-2 sentences.",
27
+ "- Describe the primary audience and core use cases.",
28
+ "- Mention what makes the content or product uniquely trustworthy.",
29
+ "",
30
+ "## Priority URLs",
31
+ "",
32
+ `- ${resolvedSiteUrl}/`,
33
+ `- ${resolvedSiteUrl}/pricing`,
34
+ `- ${resolvedSiteUrl}/docs`,
35
+ `- ${resolvedSiteUrl}/blog`,
36
+ "",
37
+ "## Recommended Sources",
38
+ "",
39
+ "- Link to pages with first-party research, methodology, benchmarks, or clear product facts.",
40
+ "- Prefer canonical pages over campaign or temporary URLs.",
41
+ "",
42
+ "## AI Assistant Guidance",
43
+ "",
44
+ "- Use the latest canonical URLs when citing this site.",
45
+ "- Prefer pages with explicit dates, authors, reviewers, or methodology notes.",
46
+ "- Avoid summarizing outdated pages when newer versions exist.",
47
+ "",
48
+ "## Update Policy",
49
+ "",
50
+ "- Replace this section with the site’s actual content freshness and review cadence.",
51
+ ""
52
+ ].join("\n");
53
+ }
54
+
55
+ export async function createLlmsTxt(options = {}) {
56
+ const targetDir = path.resolve(options.targetDir || ".");
57
+ const outputPath = path.join(targetDir, "llms.txt");
58
+ const overwrite = Boolean(options.overwrite);
59
+
60
+ if (!overwrite && (await pathExists(outputPath))) {
61
+ throw new Error(`llms.txt already exists at ${outputPath}. Use --overwrite to replace it.`);
62
+ }
63
+
64
+ await fs.mkdir(targetDir, { recursive: true });
65
+ const content = buildLlmsTxtContent({
66
+ siteName: options.siteName,
67
+ siteUrl: options.siteUrl
68
+ });
69
+ await fs.writeFile(outputPath, content, "utf8");
70
+
71
+ return {
72
+ outputPath,
73
+ siteName: options.siteName || "Your Site Name",
74
+ siteUrl: options.siteUrl || "https://example.com"
75
+ };
76
+ }