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 +6 -0
- package/package.json +1 -1
- package/src/cli.js +25 -0
- package/src/index.js +1 -0
- package/src/llms-txt.js +76 -0
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
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";
|
package/src/llms-txt.js
ADDED
|
@@ -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
|
+
}
|