llmstxt-cli 0.2.0 → 0.4.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/dist/index.js +399 -847
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23,23 +23,23 @@ function error(message) {
|
|
|
23
23
|
function spinner2(_text) {
|
|
24
24
|
const s = p.spinner();
|
|
25
25
|
return {
|
|
26
|
-
start(
|
|
27
|
-
s.start(
|
|
26
|
+
start(text2) {
|
|
27
|
+
s.start(text2 || _text || "");
|
|
28
28
|
},
|
|
29
|
-
stop(
|
|
30
|
-
s.stop(
|
|
29
|
+
stop(text2) {
|
|
30
|
+
s.stop(text2 || "");
|
|
31
31
|
},
|
|
32
|
-
succeed(
|
|
33
|
-
s.stop(`${pc.green("\u2713")} ${
|
|
32
|
+
succeed(text2) {
|
|
33
|
+
s.stop(`${pc.green("\u2713")} ${text2}`);
|
|
34
34
|
},
|
|
35
|
-
fail(
|
|
36
|
-
s.stop(`${pc.red("\u2717")} ${
|
|
35
|
+
fail(text2) {
|
|
36
|
+
s.stop(`${pc.red("\u2717")} ${text2}`);
|
|
37
37
|
},
|
|
38
|
-
info(
|
|
39
|
-
s.stop(`${pc.blue("\u2139")} ${
|
|
38
|
+
info(text2) {
|
|
39
|
+
s.stop(`${pc.blue("\u2139")} ${text2}`);
|
|
40
40
|
},
|
|
41
|
-
warn(
|
|
42
|
-
s.stop(`${pc.yellow("\u26A0")} ${
|
|
41
|
+
warn(text2) {
|
|
42
|
+
s.stop(`${pc.yellow("\u26A0")} ${text2}`);
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
}
|
|
@@ -6390,6 +6390,9 @@ function searchRegistry(query, categories) {
|
|
|
6390
6390
|
function getEntry2(slug) {
|
|
6391
6391
|
return entries.find((e) => e.slug === slug);
|
|
6392
6392
|
}
|
|
6393
|
+
function getAllEntries(categories) {
|
|
6394
|
+
return categories ? filterByCategories(entries, categories) : entries;
|
|
6395
|
+
}
|
|
6393
6396
|
function resolveSlug(nameOrSlug) {
|
|
6394
6397
|
const exact = entries.find((e) => e.slug === nameOrSlug);
|
|
6395
6398
|
if (exact) return exact;
|
|
@@ -6401,7 +6404,7 @@ function resolveSlug(nameOrSlug) {
|
|
|
6401
6404
|
|
|
6402
6405
|
// src/lib/storage.ts
|
|
6403
6406
|
import { createHash } from "crypto";
|
|
6404
|
-
import {
|
|
6407
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
6405
6408
|
import { join as join4 } from "path";
|
|
6406
6409
|
|
|
6407
6410
|
// src/lib/agents.ts
|
|
@@ -6457,7 +6460,7 @@ var agents = [
|
|
|
6457
6460
|
displayName: "Antigravity",
|
|
6458
6461
|
skillsDir: ".agent/skills",
|
|
6459
6462
|
isUniversal: false,
|
|
6460
|
-
detectInstalled: () => existsSync2(join3(
|
|
6463
|
+
detectInstalled: () => existsSync2(join3(home, ".gemini/antigravity"))
|
|
6461
6464
|
},
|
|
6462
6465
|
{
|
|
6463
6466
|
name: "augment",
|
|
@@ -6485,7 +6488,7 @@ var agents = [
|
|
|
6485
6488
|
displayName: "CodeBuddy",
|
|
6486
6489
|
skillsDir: ".codebuddy/skills",
|
|
6487
6490
|
isUniversal: false,
|
|
6488
|
-
detectInstalled: () => existsSync2(join3(
|
|
6491
|
+
detectInstalled: () => existsSync2(join3(home, ".codebuddy"))
|
|
6489
6492
|
},
|
|
6490
6493
|
{
|
|
6491
6494
|
name: "codex",
|
|
@@ -6506,7 +6509,7 @@ var agents = [
|
|
|
6506
6509
|
displayName: "Continue",
|
|
6507
6510
|
skillsDir: ".continue/skills",
|
|
6508
6511
|
isUniversal: false,
|
|
6509
|
-
detectInstalled: () => existsSync2(join3(
|
|
6512
|
+
detectInstalled: () => existsSync2(join3(home, ".continue"))
|
|
6510
6513
|
},
|
|
6511
6514
|
{
|
|
6512
6515
|
name: "crush",
|
|
@@ -6541,7 +6544,7 @@ var agents = [
|
|
|
6541
6544
|
displayName: "GitHub Copilot",
|
|
6542
6545
|
skillsDir: ".agents/skills",
|
|
6543
6546
|
isUniversal: true,
|
|
6544
|
-
detectInstalled: () => existsSync2(join3(
|
|
6547
|
+
detectInstalled: () => existsSync2(join3(home, ".copilot"))
|
|
6545
6548
|
},
|
|
6546
6549
|
{
|
|
6547
6550
|
name: "goose",
|
|
@@ -6632,7 +6635,7 @@ var agents = [
|
|
|
6632
6635
|
displayName: "OpenCode",
|
|
6633
6636
|
skillsDir: ".agents/skills",
|
|
6634
6637
|
isUniversal: true,
|
|
6635
|
-
detectInstalled: () => existsSync2(join3(configHome, "opencode"))
|
|
6638
|
+
detectInstalled: () => existsSync2(join3(configHome, "opencode"))
|
|
6636
6639
|
},
|
|
6637
6640
|
{
|
|
6638
6641
|
name: "openhands",
|
|
@@ -6753,15 +6756,6 @@ function removeAgentSkill({ projectDir, slug, agent }) {
|
|
|
6753
6756
|
} catch {
|
|
6754
6757
|
}
|
|
6755
6758
|
}
|
|
6756
|
-
function getGitignoreEntries() {
|
|
6757
|
-
const dirs = /* @__PURE__ */ new Set([`${CANONICAL_DIR}/`]);
|
|
6758
|
-
for (const agent of agents) {
|
|
6759
|
-
if (!agent.isUniversal) {
|
|
6760
|
-
dirs.add(`${agent.skillsDir}/`);
|
|
6761
|
-
}
|
|
6762
|
-
}
|
|
6763
|
-
return [...dirs].sort();
|
|
6764
|
-
}
|
|
6765
6759
|
|
|
6766
6760
|
// src/lib/storage.ts
|
|
6767
6761
|
var LLMS_DIR = ".llms";
|
|
@@ -6812,7 +6806,8 @@ function installToAgents({
|
|
|
6812
6806
|
slug,
|
|
6813
6807
|
entry,
|
|
6814
6808
|
content,
|
|
6815
|
-
format
|
|
6809
|
+
format,
|
|
6810
|
+
targetAgents
|
|
6816
6811
|
}) {
|
|
6817
6812
|
const checksum = createHash("sha256").update(content).digest("hex");
|
|
6818
6813
|
const size = Buffer.byteLength(content, "utf-8");
|
|
@@ -6827,8 +6822,8 @@ function installToAgents({
|
|
|
6827
6822
|
writeFileSync3(join4(canonicalDir, "reference.md"), referenceMd, "utf-8");
|
|
6828
6823
|
}
|
|
6829
6824
|
installedAgents.push("universal");
|
|
6830
|
-
const
|
|
6831
|
-
for (const agent of
|
|
6825
|
+
const agentsToLink = targetAgents ?? detectInstalledAgents();
|
|
6826
|
+
for (const agent of agentsToLink) {
|
|
6832
6827
|
if (agent.isUniversal) {
|
|
6833
6828
|
if (!installedAgents.includes(agent.name)) {
|
|
6834
6829
|
installedAgents.push(agent.name);
|
|
@@ -6858,30 +6853,6 @@ function isInstalled({ projectDir, slug }) {
|
|
|
6858
6853
|
sanitizeSlug(slug);
|
|
6859
6854
|
return existsSync3(join4(projectDir, CANONICAL_DIR, slug, "SKILL.md"));
|
|
6860
6855
|
}
|
|
6861
|
-
function addToGitignore(projectDir) {
|
|
6862
|
-
try {
|
|
6863
|
-
const gitignorePath = join4(projectDir, ".gitignore");
|
|
6864
|
-
const gitignoreEntries = [".llms/", ...getGitignoreEntries()];
|
|
6865
|
-
if (existsSync3(gitignorePath)) {
|
|
6866
|
-
const content = readFileSync3(gitignorePath, "utf-8");
|
|
6867
|
-
const missing = gitignoreEntries.filter((e) => !content.includes(e));
|
|
6868
|
-
if (missing.length === 0) return false;
|
|
6869
|
-
appendFileSync(gitignorePath, `
|
|
6870
|
-
# llms.txt documentation
|
|
6871
|
-
${missing.join("\n")}
|
|
6872
|
-
`);
|
|
6873
|
-
} else {
|
|
6874
|
-
writeFileSync3(gitignorePath, `# llms.txt documentation
|
|
6875
|
-
${gitignoreEntries.join("\n")}
|
|
6876
|
-
`);
|
|
6877
|
-
}
|
|
6878
|
-
return true;
|
|
6879
|
-
} catch (err) {
|
|
6880
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
6881
|
-
console.warn(`Could not update .gitignore: ${msg}`);
|
|
6882
|
-
return false;
|
|
6883
|
-
}
|
|
6884
|
-
}
|
|
6885
6856
|
|
|
6886
6857
|
// src/commands/info.ts
|
|
6887
6858
|
async function info(name) {
|
|
@@ -6934,6 +6905,68 @@ ${pc2.dim("Full:")} ${entry.llmsFullTxtUrl}` : ""}`
|
|
|
6934
6905
|
import * as p3 from "@clack/prompts";
|
|
6935
6906
|
import pc4 from "picocolors";
|
|
6936
6907
|
|
|
6908
|
+
// src/lib/agent-selection.ts
|
|
6909
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
6910
|
+
import { join as join5 } from "path";
|
|
6911
|
+
var PREFS_DIR = ".llms";
|
|
6912
|
+
var PREFS_FILE = "agent-prefs.json";
|
|
6913
|
+
var DEFAULT_AGENTS = ["claude-code", "cursor", "codex"];
|
|
6914
|
+
function detectProjectAgents(opts) {
|
|
6915
|
+
const detected = [];
|
|
6916
|
+
for (const agent of opts.allAgents) {
|
|
6917
|
+
if (agent.isUniversal) continue;
|
|
6918
|
+
const configDir = agent.skillsDir.split("/")[0];
|
|
6919
|
+
if (configDir && configDir !== "skills" && existsSync4(join5(opts.projectDir, configDir))) {
|
|
6920
|
+
detected.push(agent.name);
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
return detected;
|
|
6924
|
+
}
|
|
6925
|
+
function getInitialAgents(opts) {
|
|
6926
|
+
const validNames = new Set(opts.allAgents.map((a) => a.name));
|
|
6927
|
+
if (opts.savedPrefs && opts.savedPrefs.length > 0) {
|
|
6928
|
+
const filtered = opts.savedPrefs.filter((name) => validNames.has(name));
|
|
6929
|
+
if (filtered.length > 0) return filtered;
|
|
6930
|
+
}
|
|
6931
|
+
if (opts.projectDir) {
|
|
6932
|
+
const detected = detectProjectAgents({ projectDir: opts.projectDir, allAgents: opts.allAgents });
|
|
6933
|
+
if (detected.length > 0) return detected;
|
|
6934
|
+
}
|
|
6935
|
+
return DEFAULT_AGENTS.filter((name) => validNames.has(name));
|
|
6936
|
+
}
|
|
6937
|
+
function ensureUniversalAgents(opts) {
|
|
6938
|
+
const result = [...opts.selected];
|
|
6939
|
+
for (const agent of opts.allAgents) {
|
|
6940
|
+
if (agent.isUniversal && !result.includes(agent.name)) {
|
|
6941
|
+
result.push(agent.name);
|
|
6942
|
+
}
|
|
6943
|
+
}
|
|
6944
|
+
return result;
|
|
6945
|
+
}
|
|
6946
|
+
function loadSavedAgentPrefs(projectDir) {
|
|
6947
|
+
try {
|
|
6948
|
+
const filePath = join5(projectDir, PREFS_DIR, PREFS_FILE);
|
|
6949
|
+
if (!existsSync4(filePath)) return null;
|
|
6950
|
+
const data = JSON.parse(readFileSync4(filePath, "utf-8"));
|
|
6951
|
+
if (Array.isArray(data.agents)) return data.agents;
|
|
6952
|
+
return null;
|
|
6953
|
+
} catch {
|
|
6954
|
+
return null;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
function saveAgentPrefs(projectDir, agentNames) {
|
|
6958
|
+
try {
|
|
6959
|
+
const dir = join5(projectDir, PREFS_DIR);
|
|
6960
|
+
mkdirSync5(dir, { recursive: true });
|
|
6961
|
+
writeFileSync4(
|
|
6962
|
+
join5(dir, PREFS_FILE),
|
|
6963
|
+
JSON.stringify({ agents: agentNames }, null, 2) + "\n",
|
|
6964
|
+
"utf-8"
|
|
6965
|
+
);
|
|
6966
|
+
} catch {
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
|
|
6937
6970
|
// src/lib/banner.ts
|
|
6938
6971
|
import pc3 from "picocolors";
|
|
6939
6972
|
var BANNER_LINES = [
|
|
@@ -6959,18 +6992,18 @@ ${pc3.dim(` v${version} \xB7 Install llms.txt documentation for AI coding tools
|
|
|
6959
6992
|
}
|
|
6960
6993
|
|
|
6961
6994
|
// src/lib/context.ts
|
|
6962
|
-
import { existsSync as
|
|
6963
|
-
import { join as
|
|
6995
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
6996
|
+
import { join as join6 } from "path";
|
|
6964
6997
|
var START_MARKER = "<!-- llmstxt:start -->";
|
|
6965
6998
|
var END_MARKER = "<!-- llmstxt:end -->";
|
|
6966
6999
|
function syncClaudeMd(projectDir) {
|
|
6967
7000
|
try {
|
|
6968
7001
|
const lockfile = readLockfile(projectDir);
|
|
6969
7002
|
const entries2 = Object.values(lockfile.entries);
|
|
6970
|
-
const claudeMdPath =
|
|
7003
|
+
const claudeMdPath = join6(projectDir, "CLAUDE.md");
|
|
6971
7004
|
let content = "";
|
|
6972
|
-
if (
|
|
6973
|
-
content =
|
|
7005
|
+
if (existsSync5(claudeMdPath)) {
|
|
7006
|
+
content = readFileSync5(claudeMdPath, "utf-8");
|
|
6974
7007
|
}
|
|
6975
7008
|
const section = buildSection(entries2);
|
|
6976
7009
|
if (content.includes(START_MARKER)) {
|
|
@@ -6993,12 +7026,12 @@ function syncClaudeMd(projectDir) {
|
|
|
6993
7026
|
new RegExp(`\\n?${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`),
|
|
6994
7027
|
""
|
|
6995
7028
|
).trim();
|
|
6996
|
-
if (content.length === 0 && !
|
|
7029
|
+
if (content.length === 0 && !existsSync5(claudeMdPath)) {
|
|
6997
7030
|
return;
|
|
6998
7031
|
}
|
|
6999
7032
|
}
|
|
7000
|
-
if (content.length > 0 ||
|
|
7001
|
-
|
|
7033
|
+
if (content.length > 0 || existsSync5(claudeMdPath)) {
|
|
7034
|
+
writeFileSync5(claudeMdPath, content.endsWith("\n") ? content : `${content}
|
|
7002
7035
|
`, "utf-8");
|
|
7003
7036
|
}
|
|
7004
7037
|
} catch (err) {
|
|
@@ -7026,701 +7059,76 @@ function escapeRegex(s) {
|
|
|
7026
7059
|
}
|
|
7027
7060
|
|
|
7028
7061
|
// src/lib/detector.ts
|
|
7029
|
-
import { existsSync as
|
|
7030
|
-
import { join as
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
adx: "adx",
|
|
7045
|
-
"affordable-nvme-ssd-web-hosting-pakistan": "affordable-nvme-ssd-web-hosting-pakistan",
|
|
7046
|
-
aftermath: "aftermath",
|
|
7047
|
-
agentai: "agentai",
|
|
7048
|
-
agentlayer: "agentlayer",
|
|
7049
|
-
agentql: "agentql",
|
|
7050
|
-
agno: "agno",
|
|
7051
|
-
"ai-consulting": "ai-consulting",
|
|
7052
|
-
"ai-dream-scope": "ai-dream-scope",
|
|
7053
|
-
"ai-predict-stock": "ai-predict-stock",
|
|
7054
|
-
"ai-sdk": "ai-sdk",
|
|
7055
|
-
"ai-squared": "ai-squared",
|
|
7056
|
-
aicryptocore: "aicryptocore",
|
|
7057
|
-
akool: "akool",
|
|
7058
|
-
alexopdev: "alexopdev",
|
|
7059
|
-
"all-in": "all-in",
|
|
7060
|
-
"alpha-fi": "alpha-fi",
|
|
7061
|
-
alphagate: "alphagate",
|
|
7062
|
-
altostrat: "altostrat",
|
|
7063
|
-
alva: "alva",
|
|
7064
|
-
amema: "amema",
|
|
7065
|
-
amplemarket: "amplemarket",
|
|
7066
|
-
analog: "analog",
|
|
7067
|
-
annoto: "annoto",
|
|
7068
|
-
answerai: "answerai",
|
|
7069
|
-
"ant-design": "ant-design",
|
|
7070
|
-
anthropic: "anthropic",
|
|
7071
|
-
anytrack: "anytrack",
|
|
7072
|
-
anytype: "anytype",
|
|
7073
|
-
"apex-protocol": "apex-protocol",
|
|
7074
|
-
apibara: "apibara",
|
|
7075
|
-
apify: "apify",
|
|
7076
|
-
aporia: "aporia",
|
|
7077
|
-
appointo: "appointo",
|
|
7078
|
-
appzung: "appzung",
|
|
7079
|
-
"aps-sdks-openapi-specification-aps": "aps-sdks-openapi-specification-aps",
|
|
7080
|
-
aptible: "aptible",
|
|
7081
|
-
arbiscan: "arbiscan",
|
|
7082
|
-
arcade: "arcade",
|
|
7083
|
-
"argil-ai": "argil-ai",
|
|
7084
|
-
"ark-ui": "ark-ui",
|
|
7085
|
-
arpeggi: "arpeggi",
|
|
7086
|
-
artzero: "artzero",
|
|
7087
|
-
asapp: "asapp",
|
|
7088
|
-
"asposewords-product-family": "asposewords-product-family",
|
|
7089
|
-
"ast-grep": "ast-grep",
|
|
7090
|
-
astro: "astro",
|
|
7091
|
-
"augment-code": "augment-code",
|
|
7092
|
-
autentique: "autentique",
|
|
7093
|
-
avaamo: "avaamo",
|
|
7094
|
-
avacloud: "avacloud",
|
|
7095
|
-
"avada-seo-suite": "avada-seo-suite",
|
|
7096
|
-
"avalanche-hvac-services-heating-air": "avalanche-hvac-services-heating-air",
|
|
7097
|
-
avo: "avo",
|
|
7098
|
-
awesomeapi: "awesomeapi",
|
|
7099
|
-
axiom: "axiom",
|
|
7100
|
-
axle: "axle",
|
|
7101
|
-
azumuta: "azumuta",
|
|
7102
|
-
basehub: "basehub",
|
|
7103
|
-
beacon: "beacon",
|
|
7104
|
-
"best-app-development-company": "best-app-development-company",
|
|
7105
|
-
"best-boat-lifts": "best-boat-lifts",
|
|
7106
|
-
"beta-three-professional-audio": "beta-three-professional-audio",
|
|
7107
|
-
"better-auth": "better-auth",
|
|
7108
|
-
beyondwords: "beyondwords",
|
|
7109
|
-
bika: "bika",
|
|
7110
|
-
birdie: "birdie",
|
|
7111
|
-
"bitcoin-cold-storage-tools": "bitcoin-cold-storage-tools",
|
|
7112
|
-
bito: "bito",
|
|
7113
|
-
"bits-ui": "bits-ui",
|
|
7114
|
-
bixgrow: "bixgrow",
|
|
7115
|
-
blacknet: "blacknet",
|
|
7116
|
-
"blue-media-services": "blue-media-services",
|
|
7117
|
-
blueshift: "blueshift",
|
|
7118
|
-
booqable: "booqable",
|
|
7119
|
-
bottalk: "bottalk",
|
|
7120
|
-
braintrust: "braintrust",
|
|
7121
|
-
brandfetch: "brandfetch",
|
|
7122
|
-
"bright-data": "bright-data",
|
|
7123
|
-
browsee: "browsee",
|
|
7124
|
-
bucket: "bucket",
|
|
7125
|
-
bugsplat: "bugsplat",
|
|
7126
|
-
builtwith: "builtwith",
|
|
7127
|
-
bun: "bun",
|
|
7128
|
-
bunny: "bunny",
|
|
7129
|
-
butlr: "butlr",
|
|
7130
|
-
caf: "caf",
|
|
7131
|
-
calcom: "calcom",
|
|
7132
|
-
calendarscripts: "calendarscripts",
|
|
7133
|
-
"callback-technologies": "callback-technologies",
|
|
7134
|
-
campsite: "campsite",
|
|
7135
|
-
captivaterecipes: "captivaterecipes",
|
|
7136
|
-
"car-rental-in-airports-ofgeorgia": "car-rental-in-airports-ofgeorgia",
|
|
7137
|
-
cardknox: "cardknox",
|
|
7138
|
-
carto: "carto",
|
|
7139
|
-
carv: "carv",
|
|
7140
|
-
catizen: "catizen",
|
|
7141
|
-
"cdata-software": "cdata-software",
|
|
7142
|
-
"chakra-ui": "chakra-ui",
|
|
7143
|
-
chargeblast: "chargeblast",
|
|
7144
|
-
chartbeat: "chartbeat",
|
|
7145
|
-
chatbase: "chatbase",
|
|
7146
|
-
chatknow: "chatknow",
|
|
7147
|
-
chatling: "chatling",
|
|
7148
|
-
"checkmate-live": "checkmate-live",
|
|
7149
|
-
"chic-room": "chic-room",
|
|
7150
|
-
"chirp-wireless": "chirp-wireless",
|
|
7151
|
-
"cid-contact": "cid-contact",
|
|
7152
|
-
cipherstash: "cipherstash",
|
|
7153
|
-
circleci: "circleci",
|
|
7154
|
-
citizenshipper: "citizenshipper",
|
|
7155
|
-
citrusad: "citrusad",
|
|
7156
|
-
civic: "civic",
|
|
7157
|
-
"claude-mcp-community": "claude-mcp-community",
|
|
7158
|
-
clerk: "clerk",
|
|
7159
|
-
"clever-cloud": "clever-cloud",
|
|
7160
|
-
cloreai: "cloreai",
|
|
7161
|
-
cloudfix: "cloudfix",
|
|
7162
|
-
cloudflare: "cloudflare",
|
|
7163
|
-
clouve: "clouve",
|
|
7164
|
-
cloverspace: "cloverspace",
|
|
7165
|
-
"cnpjws-api": "cnpjws-api",
|
|
7166
|
-
cobo: "cobo",
|
|
7167
|
-
cobrowse: "cobrowse",
|
|
7168
|
-
codecrafters: "codecrafters",
|
|
7169
|
-
codeium: "codeium",
|
|
7170
|
-
coefont: "coefont",
|
|
7171
|
-
coframe: "coframe",
|
|
7172
|
-
cog: "cog",
|
|
7173
|
-
cohere: "cohere",
|
|
7174
|
-
comforterp: "comforterp",
|
|
7175
|
-
comforthrm: "comforthrm",
|
|
7176
|
-
comfy: "comfy",
|
|
7177
|
-
"commerce-layer": "commerce-layer",
|
|
7178
|
-
"common-ninja": "common-ninja",
|
|
7179
|
-
"community-helm-charts": "community-helm-charts",
|
|
7180
|
-
comparisonator: "comparisonator",
|
|
7181
|
-
"concept-designs-marketing": "concept-designs-marketing",
|
|
7182
|
-
conductor: "conductor",
|
|
7183
|
-
configcat: "configcat",
|
|
7184
|
-
consentik: "consentik",
|
|
7185
|
-
contentsquare: "contentsquare",
|
|
7186
|
-
"contractor-marketing-agency": "contractor-marketing-agency",
|
|
7187
|
-
contravault: "contravault",
|
|
7188
|
-
convex: "convex",
|
|
7189
|
-
coolify: "coolify",
|
|
7190
|
-
coollabs: "coollabs",
|
|
7191
|
-
"copenhagen-art-and-photography": "copenhagen-art-and-photography",
|
|
7192
|
-
"corso-seo-online-certificato": "corso-seo-online-certificato",
|
|
7193
|
-
cosmic: "cosmic",
|
|
7194
|
-
couchdrop: "couchdrop",
|
|
7195
|
-
count: "count",
|
|
7196
|
-
courier: "courier",
|
|
7197
|
-
craftco: "craftco",
|
|
7198
|
-
"cre-data-and-location-intelligence-app": "cre-data-and-location-intelligence-app",
|
|
7199
|
-
"creative-handbook-production-resource-directory": "creative-handbook-production-resource-directory",
|
|
7200
|
-
creatopy: "creatopy",
|
|
7201
|
-
crewai: "crewai",
|
|
7202
|
-
"cross-browser-mobile-app-testing": "cross-browser-mobile-app-testing",
|
|
7203
|
-
cryptlex: "cryptlex",
|
|
7204
|
-
"curling-io": "curling-io",
|
|
7205
|
-
cursor: "cursor",
|
|
7206
|
-
"customer-service-ai-platform": "customer-service-ai-platform",
|
|
7207
|
-
"cyber-security-news": "cyber-security-news",
|
|
7208
|
-
daisyui: "daisyui",
|
|
7209
|
-
dappier: "dappier",
|
|
7210
|
-
dat1co: "dat1co",
|
|
7211
|
-
"data-surfer": "data-surfer",
|
|
7212
|
-
"databuddy-analytics": "databuddy-analytics",
|
|
7213
|
-
datacamp: "datacamp",
|
|
7214
|
-
datafold: "datafold",
|
|
7215
|
-
dataimpulse: "dataimpulse",
|
|
7216
|
-
"datastax-astra-db": "datastax-astra-db",
|
|
7217
|
-
daytona: "daytona",
|
|
7218
|
-
decocx: "decocx",
|
|
7219
|
-
deepconverse: "deepconverse",
|
|
7220
|
-
"demo-time": "demo-time",
|
|
7221
|
-
"deno-documentation": "deno-documentation",
|
|
7222
|
-
deployhq: "deployhq",
|
|
7223
|
-
designmodo: "designmodo",
|
|
7224
|
-
devhub: "devhub",
|
|
7225
|
-
devunus: "devunus",
|
|
7226
|
-
"dexpaprika-api-live-crypto-pool-data": "dexpaprika-api-live-crypto-pool-data",
|
|
7227
|
-
dns0eu: "dns0eu",
|
|
7228
|
-
docetl: "docetl",
|
|
7229
|
-
"docker-docs": "docker-docs",
|
|
7230
|
-
docspring: "docspring",
|
|
7231
|
-
"document-file-translation-powered-by-ai": "document-file-translation-powered-by-ai",
|
|
7232
|
-
donobu: "donobu",
|
|
7233
|
-
"dopp-finance": "dopp-finance",
|
|
7234
|
-
dotenvx: "dotenvx",
|
|
7235
|
-
"drizzle-orm": "drizzle-orm",
|
|
7236
|
-
dub: "dub",
|
|
7237
|
-
duckdb: "duckdb",
|
|
7238
|
-
"duende-software": "duende-software",
|
|
7239
|
-
dynamic: "dynamic",
|
|
7240
|
-
e6data: "e6data",
|
|
7241
|
-
effect: "effect",
|
|
7242
|
-
elevenlabs: "elevenlabs",
|
|
7243
|
-
elysia: "elysia",
|
|
7244
|
-
emailgic: "emailgic",
|
|
7245
|
-
"embed-notion-pages-into-your-website": "embed-notion-pages-into-your-website",
|
|
7246
|
-
embedchain: "embedchain",
|
|
7247
|
-
envoyer: "envoyer",
|
|
7248
|
-
equipment: "equipment",
|
|
7249
|
-
essio: "essio",
|
|
7250
|
-
"expo-documentation": "expo-documentation",
|
|
7251
|
-
fabric: "fabric",
|
|
7252
|
-
facets: "facets",
|
|
7253
|
-
"fantasy-sports-app-development-company": "fantasy-sports-app-development-company",
|
|
7254
|
-
"farcaster-miniapps": "farcaster-miniapps",
|
|
7255
|
-
"feedback-sync": "feedback-sync",
|
|
7256
|
-
fern: "fern",
|
|
7257
|
-
fibery: "fibery",
|
|
7258
|
-
"film-and-screenwriter-school": "film-and-screenwriter-school",
|
|
7259
|
-
finch: "finch",
|
|
7260
|
-
fireproof: "fireproof",
|
|
7261
|
-
"fireworks-ai": "fireworks-ai",
|
|
7262
|
-
firmly: "firmly",
|
|
7263
|
-
flatfile: "flatfile",
|
|
7264
|
-
flipto: "flipto",
|
|
7265
|
-
flows: "flows",
|
|
7266
|
-
flowx: "flowx",
|
|
7267
|
-
"fork-force-australia": "fork-force-australia",
|
|
7268
|
-
formo: "formo",
|
|
7269
|
-
formwerk: "formwerk",
|
|
7270
|
-
fractalpay: "fractalpay",
|
|
7271
|
-
"fraction-ai": "fraction-ai",
|
|
7272
|
-
fragbin: "fragbin",
|
|
7273
|
-
"frank-krav-maga-self-defense-bengaluru": "frank-krav-maga-self-defense-bengaluru",
|
|
7274
|
-
"free-ai-image-generator-maker": "free-ai-image-generator-maker",
|
|
7275
|
-
frigade: "frigade",
|
|
7276
|
-
"front-matter-cms-a-cms-in-your-vs-code-editor": "front-matter-cms-a-cms-in-your-vs-code-editor",
|
|
7277
|
-
"funny-stories-of-horrible-stories": "funny-stories-of-horrible-stories",
|
|
7278
|
-
galileo: "galileo",
|
|
7279
|
-
"game-development-hub": "game-development-hub",
|
|
7280
|
-
gaminator: "gaminator",
|
|
7281
|
-
"gaslighting-check": "gaslighting-check",
|
|
7282
|
-
genaiscript: "genaiscript",
|
|
7283
|
-
"generate-ai-ugc-videos-for-ads": "generate-ai-ugc-videos-for-ads",
|
|
7284
|
-
getinbox: "getinbox",
|
|
7285
|
-
getmarked: "getmarked",
|
|
7286
|
-
giselle: "giselle",
|
|
7287
|
-
glama: "glama",
|
|
7288
|
-
gloodai: "gloodai",
|
|
7289
|
-
glucncom: "glucncom",
|
|
7290
|
-
"gnosis-chain": "gnosis-chain",
|
|
7291
|
-
goody: "goody",
|
|
7292
|
-
gradio: "gradio",
|
|
7293
|
-
"graphite-note": "graphite-note",
|
|
7294
|
-
"greece-vacation-search": "greece-vacation-search",
|
|
7295
|
-
"green-apple-travel-tourism": "green-apple-travel-tourism",
|
|
7296
|
-
groqcloud: "groqcloud",
|
|
7297
|
-
gumlet: "gumlet",
|
|
7298
|
-
helicone: "helicone",
|
|
7299
|
-
"help-for-erectile-dysfunction": "help-for-erectile-dysfunction",
|
|
7300
|
-
"henan-pengfei-pvp-k30-povidone": "henan-pengfei-pvp-k30-povidone",
|
|
7301
|
-
herd: "herd",
|
|
7302
|
-
"heritage-collection": "heritage-collection",
|
|
7303
|
-
heyflow: "heyflow",
|
|
7304
|
-
hola: "hola",
|
|
7305
|
-
home: "home",
|
|
7306
|
-
"home-llms-txt": "home-llms-txt",
|
|
7307
|
-
"home-tz": "home-tz",
|
|
7308
|
-
"home-angular": "home-angular",
|
|
7309
|
-
hono: "hono",
|
|
7310
|
-
hub88: "hub88",
|
|
7311
|
-
hubspot: "hubspot",
|
|
7312
|
-
"hugging-face-accelerate": "hugging-face-accelerate",
|
|
7313
|
-
"hugging-face-diffusers": "hugging-face-diffusers",
|
|
7314
|
-
"hugging-face-hub": "hugging-face-hub",
|
|
7315
|
-
"hugging-face-hub-python-library": "hugging-face-hub-python-library",
|
|
7316
|
-
"hugging-face-transformers": "hugging-face-transformers",
|
|
7317
|
-
"humanity-protocol": "humanity-protocol",
|
|
7318
|
-
hybridai: "hybridai",
|
|
7319
|
-
hyperbeam: "hyperbeam",
|
|
7320
|
-
hyperline: "hyperline",
|
|
7321
|
-
hypermode: "hypermode",
|
|
7322
|
-
hypertune: "hypertune",
|
|
7323
|
-
i3dnet: "i3dnet",
|
|
7324
|
-
"iagent-protocol": "iagent-protocol",
|
|
7325
|
-
icepanel: "icepanel",
|
|
7326
|
-
id21: "id21",
|
|
7327
|
-
ideogram: "ideogram",
|
|
7328
|
-
"ig-exporter": "ig-exporter",
|
|
7329
|
-
illuvium: "illuvium",
|
|
7330
|
-
imaginstudio: "imaginstudio",
|
|
7331
|
-
imagineart: "imagineart",
|
|
7332
|
-
"img-arena": "img-arena",
|
|
7333
|
-
"immortal-rising-2": "immortal-rising-2",
|
|
7334
|
-
infera: "infera",
|
|
7335
|
-
infisical: "infisical",
|
|
7336
|
-
inkeep: "inkeep",
|
|
7337
|
-
inngest: "inngest",
|
|
7338
|
-
inspector: "inspector",
|
|
7339
|
-
"inspira-ui-build-beautiful-websites-using-vue-nuxt": "inspira-ui-build-beautiful-websites-using-vue-nuxt",
|
|
7340
|
-
instant: "instant",
|
|
7341
|
-
instruqt: "instruqt",
|
|
7342
|
-
intelligems: "intelligems",
|
|
7343
|
-
intract: "intract",
|
|
7344
|
-
intuned: "intuned",
|
|
7345
|
-
ionos: "ionos",
|
|
7346
|
-
ionq: "ionq",
|
|
7347
|
-
ipaper: "ipaper",
|
|
7348
|
-
iproyalcom: "iproyalcom",
|
|
7349
|
-
irev: "irev",
|
|
7350
|
-
"island-router": "island-router",
|
|
7351
|
-
jam: "jam",
|
|
7352
|
-
jazztools: "jazztools",
|
|
7353
|
-
journeyapps: "journeyapps",
|
|
7354
|
-
journify: "journify",
|
|
7355
|
-
jsfiddle: "jsfiddle",
|
|
7356
|
-
jumptask: "jumptask",
|
|
7357
|
-
"juniper-creates": "juniper-creates",
|
|
7358
|
-
juno: "juno",
|
|
7359
|
-
"kaisar-network": "kaisar-network",
|
|
7360
|
-
"karrier-one": "karrier-one",
|
|
7361
|
-
keeper: "keeper",
|
|
7362
|
-
ketch: "ketch",
|
|
7363
|
-
kick: "kick",
|
|
7364
|
-
koala: "koala",
|
|
7365
|
-
kruzty: "kruzty",
|
|
7366
|
-
lacremeai: "lacremeai",
|
|
7367
|
-
lago: "lago",
|
|
7368
|
-
lambdatest: "lambdatest",
|
|
7369
|
-
"langchain-javascript-docs": "langchain-javascript-docs",
|
|
7370
|
-
"langchain-python-docs": "langchain-python-docs",
|
|
7371
|
-
langflow: "langflow",
|
|
7372
|
-
langfuse: "langfuse",
|
|
7373
|
-
"langgraph-javascript-docs": "langgraph-javascript-docs",
|
|
7374
|
-
"langgraph-python-docs": "langgraph-python-docs",
|
|
7375
|
-
launchfast: "launchfast",
|
|
7376
|
-
lavita: "lavita",
|
|
7377
|
-
"law-firm-digital-marketing-agency": "law-firm-digital-marketing-agency",
|
|
7378
|
-
layouthub: "layouthub",
|
|
7379
|
-
"leather-jackets-coats-for-men-women": "leather-jackets-coats-for-men-women",
|
|
7380
|
-
legend: "legend",
|
|
7381
|
-
"legend-state": "legend-state",
|
|
7382
|
-
"legends-of-learning": "legends-of-learning",
|
|
7383
|
-
legitt: "legitt",
|
|
7384
|
-
lettermint: "lettermint",
|
|
7385
|
-
"liam-erd": "liam-erd",
|
|
7386
|
-
liblab: "liblab",
|
|
7387
|
-
libmodulor: "libmodulor",
|
|
7388
|
-
likec4: "likec4",
|
|
7389
|
-
linktree: "linktree",
|
|
7390
|
-
litdb: "litdb",
|
|
7391
|
-
liveblocks: "liveblocks",
|
|
7392
|
-
livecaller: "livecaller",
|
|
7393
|
-
livecodes: "livecodes",
|
|
7394
|
-
livespotting: "livespotting",
|
|
7395
|
-
"llms-txtio": "llms-txtio",
|
|
7396
|
-
llmstxt: "llmstxt",
|
|
7397
|
-
llmvo: "llmvo",
|
|
7398
|
-
"lm-studio": "lm-studio",
|
|
7399
|
-
lobehub: "lobehub",
|
|
7400
|
-
loglayer: "loglayer",
|
|
7401
|
-
loops: "loops",
|
|
7402
|
-
"lots-of-csvs": "lots-of-csvs",
|
|
7403
|
-
lottielab: "lottielab",
|
|
7404
|
-
lunacy: "lunacy",
|
|
7405
|
-
luxalgo: "luxalgo",
|
|
7406
|
-
luxid: "luxid",
|
|
7407
|
-
lynx: "lynx",
|
|
7408
|
-
mailmodo: "mailmodo",
|
|
7409
|
-
mako: "mako",
|
|
7410
|
-
mangopay: "mangopay",
|
|
7411
|
-
"manifestly-checklists": "manifestly-checklists",
|
|
7412
|
-
"marco-ronco-seo-specialist": "marco-ronco-seo-specialist",
|
|
7413
|
-
marimo: "marimo",
|
|
7414
|
-
"marketing-doctors": "marketing-doctors",
|
|
7415
|
-
"marketing-integration-and-automation": "marketing-integration-and-automation",
|
|
7416
|
-
massive: "massive",
|
|
7417
|
-
mastory: "mastory",
|
|
7418
|
-
mastra: "mastra",
|
|
7419
|
-
"material-ui-aka-mui": "material-ui-aka-mui",
|
|
7420
|
-
"maxim-ai": "maxim-ai",
|
|
7421
|
-
"mdutil-free-markdown-tools": "mdutil-free-markdown-tools",
|
|
7422
|
-
mealbymeal: "mealbymeal",
|
|
7423
|
-
"meds-canada": "meds-canada",
|
|
7424
|
-
medusa: "medusa",
|
|
7425
|
-
meilisearch: "meilisearch",
|
|
7426
|
-
"mekalite-cnc-machining-services": "mekalite-cnc-machining-services",
|
|
7427
|
-
meshconnect: "meshconnect",
|
|
7428
|
-
"method-financial": "method-financial",
|
|
7429
|
-
micro1: "micro1",
|
|
7430
|
-
mintlify: "mintlify",
|
|
7431
|
-
mixo: "mixo",
|
|
7432
|
-
"model-context-protocol-mcp": "model-context-protocol-mcp",
|
|
7433
|
-
"monster-ui": "monster-ui",
|
|
7434
|
-
moondream: "moondream",
|
|
7435
|
-
"morphic-solutions": "morphic-solutions",
|
|
7436
|
-
movehealth: "movehealth",
|
|
7437
|
-
"mubashir-hassan": "mubashir-hassan",
|
|
7438
|
-
"mui-x-advanced-react-components-for-complex-use-cases": "mui-x-advanced-react-components-for-complex-use-cases",
|
|
7439
|
-
multiplier: "multiplier",
|
|
7440
|
-
multisynq: "multisynq",
|
|
7441
|
-
mux: "mux",
|
|
7442
|
-
"mystery-o-matic": "mystery-o-matic",
|
|
7443
|
-
nash: "nash",
|
|
7444
|
-
nativescript: "nativescript",
|
|
7445
|
-
navi: "navi",
|
|
7446
|
-
"naviga-global": "naviga-global",
|
|
7447
|
-
"needle-cloud": "needle-cloud",
|
|
7448
|
-
netlify: "netlify",
|
|
7449
|
-
nextevo: "nextevo",
|
|
7450
|
-
nextevogroup: "nextevogroup",
|
|
7451
|
-
"nile-postgres": "nile-postgres",
|
|
7452
|
-
nomadhelperai: "nomadhelperai",
|
|
7453
|
-
"nonprofit-management-consulting": "nonprofit-management-consulting",
|
|
7454
|
-
"novi-labs": "novi-labs",
|
|
7455
|
-
nsoftware: "nsoftware",
|
|
7456
|
-
nuxt: "nuxt",
|
|
7457
|
-
"omnimind-docs-oss-mcp-client": "omnimind-docs-oss-mcp-client",
|
|
7458
|
-
onagentsorg: "onagentsorg",
|
|
7459
|
-
"once-ui": "once-ui",
|
|
7460
|
-
onetrust: "onetrust",
|
|
7461
|
-
openfort: "openfort",
|
|
7462
|
-
openphone: "openphone",
|
|
7463
|
-
openpipe: "openpipe",
|
|
7464
|
-
openrouter: "openrouter",
|
|
7465
|
-
"openvpn-zero-trust-vpn": "openvpn-zero-trust-vpn",
|
|
7466
|
-
"opik-by-comet": "opik-by-comet",
|
|
7467
|
-
"optimajet-form-builder": "optimajet-form-builder",
|
|
7468
|
-
oxla: "oxla",
|
|
7469
|
-
papergraderpro: "papergraderpro",
|
|
7470
|
-
paragon: "paragon",
|
|
7471
|
-
"parcelcube-static-dimensioning-systems": "parcelcube-static-dimensioning-systems",
|
|
7472
|
-
parseable: "parseable",
|
|
7473
|
-
pastaclean: "pastaclean",
|
|
7474
|
-
payperfax: "payperfax",
|
|
7475
|
-
payrollrabbit: "payrollrabbit",
|
|
7476
|
-
"pentesting-red-teaming-company": "pentesting-red-teaming-company",
|
|
7477
|
-
perplexity: "perplexity",
|
|
7478
|
-
"personal-page": "personal-page",
|
|
7479
|
-
"petite-box": "petite-box",
|
|
7480
|
-
pgflow: "pgflow",
|
|
7481
|
-
phare: "phare",
|
|
7482
|
-
pikaicons: "pikaicons",
|
|
7483
|
-
pinata: "pinata",
|
|
7484
|
-
pinecone: "pinecone",
|
|
7485
|
-
plain: "plain",
|
|
7486
|
-
"plan-harmony-travel-planning": "plan-harmony-travel-planning",
|
|
7487
|
-
platformsh: "platformsh",
|
|
7488
|
-
playai: "playai",
|
|
7489
|
-
popsmash: "popsmash",
|
|
7490
|
-
postfast: "postfast",
|
|
7491
|
-
preact: "preact",
|
|
7492
|
-
prettier: "prettier",
|
|
7493
|
-
primev: "primev",
|
|
7494
|
-
prisma: "prisma",
|
|
7495
|
-
profound: "profound",
|
|
7496
|
-
progressrocks: "progressrocks",
|
|
7497
|
-
"proguard-pest-control": "proguard-pest-control",
|
|
7498
|
-
projectdiscovery: "projectdiscovery",
|
|
7499
|
-
"prompt-kit": "prompt-kit",
|
|
7500
|
-
promptfoo: "promptfoo",
|
|
7501
|
-
pydantic: "pydantic",
|
|
7502
|
-
pydanticai: "pydanticai",
|
|
7503
|
-
qrcoau: "qrcoau",
|
|
7504
|
-
quill: "quill",
|
|
7505
|
-
qwikrank: "qwikrank",
|
|
7506
|
-
rainbowkit: "rainbowkit",
|
|
7507
|
-
raincamp: "raincamp",
|
|
7508
|
-
rankscaleai: "rankscaleai",
|
|
7509
|
-
rapidtextai: "rapidtextai",
|
|
7510
|
-
raycast: "raycast",
|
|
7511
|
-
rcponline: "rcponline",
|
|
7512
|
-
redpanda: "redpanda",
|
|
7513
|
-
rememberizer: "rememberizer",
|
|
7514
|
-
remotion: "remotion",
|
|
7515
|
-
remult: "remult",
|
|
7516
|
-
render: "render",
|
|
7517
|
-
reown: "reown",
|
|
7518
|
-
replit: "replit",
|
|
7519
|
-
resend: "resend",
|
|
7520
|
-
respondio: "respondio",
|
|
7521
|
-
retainful: "retainful",
|
|
7522
|
-
"ri-xu-online": "ri-xu-online",
|
|
7523
|
-
"rims-tires-for-cars-and-trucks": "rims-tires-for-cars-and-trucks",
|
|
7524
|
-
roc: "roc",
|
|
7525
|
-
rsbuild: "rsbuild",
|
|
7526
|
-
rsdoctor: "rsdoctor",
|
|
7527
|
-
rslib: "rslib",
|
|
7528
|
-
rspack: "rspack",
|
|
7529
|
-
rubric: "rubric",
|
|
7530
|
-
"ruleta-aleatoria-online-gratis": "ruleta-aleatoria-online-gratis",
|
|
7531
|
-
rushdb: "rushdb",
|
|
7532
|
-
saev: "saev",
|
|
7533
|
-
salesbricks: "salesbricks",
|
|
7534
|
-
"salesforce-marketing-cloud-consultants": "salesforce-marketing-cloud-consultants",
|
|
7535
|
-
"samsung-food": "samsung-food",
|
|
7536
|
-
sandisk: "sandisk",
|
|
7537
|
-
sardine: "sardine",
|
|
7538
|
-
"scottish-art-prints-by-carol-mcewan": "scottish-art-prints-by-carol-mcewan",
|
|
7539
|
-
"scraping-proxies": "scraping-proxies",
|
|
7540
|
-
screenshotone: "screenshotone",
|
|
7541
|
-
sealos: "sealos",
|
|
7542
|
-
"secure-fast-online-money-transfers": "secure-fast-online-money-transfers",
|
|
7543
|
-
sekhlopk: "sekhlopk",
|
|
7544
|
-
self: "self",
|
|
7545
|
-
sellersprite: "sellersprite",
|
|
7546
|
-
semgrep: "semgrep",
|
|
7547
|
-
seo2llm: "seo2llm",
|
|
7548
|
-
servicestack: "servicestack",
|
|
7549
|
-
sgnlai: "sgnlai",
|
|
7550
|
-
sherlock: "sherlock",
|
|
7551
|
-
"shop-positioner-llc": "shop-positioner-llc",
|
|
7552
|
-
"side-space": "side-space",
|
|
7553
|
-
simplepdf: "simplepdf",
|
|
7554
|
-
sinch: "sinch",
|
|
7555
|
-
"singing-carrots": "singing-carrots",
|
|
7556
|
-
sitespeakai: "sitespeakai",
|
|
7557
|
-
skipgo: "skipgo",
|
|
7558
|
-
"sky-follower-bridge": "sky-follower-bridge",
|
|
7559
|
-
skydeckai: "skydeckai",
|
|
7560
|
-
"skyworkthe-ai-workspace-agents": "skyworkthe-ai-workspace-agents",
|
|
7561
|
-
smartcar: "smartcar",
|
|
7562
|
-
social: "social",
|
|
7563
|
-
socialityio: "socialityio",
|
|
7564
|
-
solid: "solid",
|
|
7565
|
-
sourcegraph: "sourcegraph",
|
|
7566
|
-
spacetimedb: "spacetimedb",
|
|
7567
|
-
speakeasy: "speakeasy",
|
|
7568
|
-
starwind: "starwind",
|
|
7569
|
-
statusfield: "statusfield",
|
|
7570
|
-
stedi: "stedi",
|
|
7571
|
-
"stephanie-kabi": "stephanie-kabi",
|
|
7572
|
-
"stock-trading-investment-app": "stock-trading-investment-app",
|
|
7573
|
-
stripe: "stripe",
|
|
7574
|
-
"study-fetch": "study-fetch",
|
|
7575
|
-
"sunra-ai": "sunra-ai",
|
|
7576
|
-
supabase: "supabase",
|
|
7577
|
-
supadata: "supadata",
|
|
7578
|
-
superwall: "superwall",
|
|
7579
|
-
svelte: "svelte",
|
|
7580
|
-
"svg-viewer": "svg-viewer",
|
|
7581
|
-
"swipe-simple-invoicing-and-payments-app": "swipe-simple-invoicing-and-payments-app",
|
|
7582
|
-
tamagui: "tamagui",
|
|
7583
|
-
"taskade-ai": "taskade-ai",
|
|
7584
|
-
tavus: "tavus",
|
|
7585
|
-
"tlassistance-snior": "tlassistance-snior",
|
|
7586
|
-
televisionai: "televisionai",
|
|
7587
|
-
tensorzero: "tensorzero",
|
|
7588
|
-
"the-ai-engineers-handbook": "the-ai-engineers-handbook",
|
|
7589
|
-
"the-bucket-hat": "the-bucket-hat",
|
|
7590
|
-
"the-crawl-tool": "the-crawl-tool",
|
|
7591
|
-
"the-data-driven-marketer": "the-data-driven-marketer",
|
|
7592
|
-
"the-dinner-detective-murder-mystery-show": "the-dinner-detective-murder-mystery-show",
|
|
7593
|
-
theirstack: "theirstack",
|
|
7594
|
-
"therapydave-dave-lechnyr-lcsw": "therapydave-dave-lechnyr-lcsw",
|
|
7595
|
-
tidb: "tidb",
|
|
7596
|
-
tidio: "tidio",
|
|
7597
|
-
tinybird: "tinybird",
|
|
7598
|
-
tiptap: "tiptap",
|
|
7599
|
-
toriut: "toriut",
|
|
7600
|
-
trackingplan: "trackingplan",
|
|
7601
|
-
trackvia: "trackvia",
|
|
7602
|
-
"trail-of-bits": "trail-of-bits",
|
|
7603
|
-
transloadit: "transloadit",
|
|
7604
|
-
"travel-nepal": "travel-nepal",
|
|
7605
|
-
triggerdev: "triggerdev",
|
|
7606
|
-
triplit: "triplit",
|
|
7607
|
-
trueprofit: "trueprofit",
|
|
7608
|
-
truffle: "truffle",
|
|
7609
|
-
turbo: "turbo",
|
|
7610
|
-
turbodocx: "turbodocx",
|
|
7611
|
-
turso: "turso",
|
|
7612
|
-
"twicpics-by-frontify": "twicpics-by-frontify",
|
|
7613
|
-
twoshoes: "twoshoes",
|
|
7614
|
-
"ufc-velvet": "ufc-velvet",
|
|
7615
|
-
"uminai-mcp": "uminai-mcp",
|
|
7616
|
-
underrunio: "underrunio",
|
|
7617
|
-
unifygtm: "unifygtm",
|
|
7618
|
-
unistyles: "unistyles",
|
|
7619
|
-
uniwebview: "uniwebview",
|
|
7620
|
-
unkey: "unkey",
|
|
7621
|
-
unstructured: "unstructured",
|
|
7622
|
-
upstash: "upstash",
|
|
7623
|
-
"upstreet-ai": "upstreet-ai",
|
|
7624
|
-
upsun: "upsun",
|
|
7625
|
-
useapinet: "useapinet",
|
|
7626
|
-
"utrecht-golf-instructor-marina-romanik": "utrecht-golf-instructor-marina-romanik",
|
|
7627
|
-
"ux-patterns-for-devs": "ux-patterns-for-devs",
|
|
7628
|
-
vald: "vald",
|
|
7629
|
-
"vald-health": "vald-health",
|
|
7630
|
-
vapi: "vapi",
|
|
7631
|
-
vdoninja: "vdoninja",
|
|
7632
|
-
velt: "velt",
|
|
7633
|
-
vendure: "vendure",
|
|
7634
|
-
veniceai: "veniceai",
|
|
7635
|
-
ventrata: "ventrata",
|
|
7636
|
-
"vercel-ai-sdk": "vercel-ai-sdk",
|
|
7637
|
-
verdn: "verdn",
|
|
7638
|
-
"video-and-audio-frameworks-for-net": "video-and-audio-frameworks-for-net",
|
|
7639
|
-
videosdklive: "videosdklive",
|
|
7640
|
-
videowise: "videowise",
|
|
7641
|
-
viem: "viem",
|
|
7642
|
-
"vignette-id": "vignette-id",
|
|
7643
|
-
vital: "vital",
|
|
7644
|
-
"voxel-busters": "voxel-busters",
|
|
7645
|
-
"voyager-shuffle": "voyager-shuffle",
|
|
7646
|
-
vplayed: "vplayed",
|
|
7647
|
-
"vue-macros": "vue-macros",
|
|
7648
|
-
vuejs: "vuejs",
|
|
7649
|
-
wandio: "wandio",
|
|
7650
|
-
warp: "warp",
|
|
7651
|
-
weathercom: "weathercom",
|
|
7652
|
-
"web-design-company-qatar": "web-design-company-qatar",
|
|
7653
|
-
"web-development-wordpress-maintenance": "web-development-wordpress-maintenance",
|
|
7654
|
-
webrecorder: "webrecorder",
|
|
7655
|
-
"wedgwood-insurance": "wedgwood-insurance",
|
|
7656
|
-
weka: "weka",
|
|
7657
|
-
"welcome-to-bunny": "welcome-to-bunny",
|
|
7658
|
-
"welcome-to-htmlhint": "welcome-to-htmlhint",
|
|
7659
|
-
"wf-content-creator-platform": "wf-content-creator-platform",
|
|
7660
|
-
whereby: "whereby",
|
|
7661
|
-
"wild-in-africa": "wild-in-africa",
|
|
7662
|
-
wized: "wized",
|
|
7663
|
-
wonderchat: "wonderchat",
|
|
7664
|
-
woowup: "woowup",
|
|
7665
|
-
wordlift: "wordlift",
|
|
7666
|
-
workbookly: "workbookly",
|
|
7667
|
-
workflow: "workflow",
|
|
7668
|
-
"wot-design-uni": "wot-design-uni",
|
|
7669
|
-
writer: "writer",
|
|
7670
|
-
wxt: "wxt",
|
|
7671
|
-
x: "x",
|
|
7672
|
-
"x-cmd": "x-cmd",
|
|
7673
|
-
xmcp: "xmcp",
|
|
7674
|
-
xomatic: "xomatic",
|
|
7675
|
-
yamlresume: "yamlresume",
|
|
7676
|
-
youform: "youform",
|
|
7677
|
-
zag: "zag",
|
|
7678
|
-
zapts: "zapts",
|
|
7679
|
-
"zaphyr-php-framework": "zaphyr-php-framework",
|
|
7680
|
-
zapier: "zapier",
|
|
7681
|
-
zeffy: "zeffy",
|
|
7682
|
-
zenml: "zenml",
|
|
7683
|
-
zep: "zep",
|
|
7684
|
-
zigpoll: "zigpoll",
|
|
7685
|
-
zipchat: "zipchat",
|
|
7686
|
-
zipy: "zipy",
|
|
7687
|
-
zodori: "zodori",
|
|
7688
|
-
zoko: "zoko",
|
|
7689
|
-
"zoomryconveyorshiploader-manufacturer": "zoomryconveyorshiploader-manufacturer"
|
|
7062
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
7063
|
+
import { join as join7 } from "path";
|
|
7064
|
+
function normalize(name) {
|
|
7065
|
+
return name.toLowerCase().replace(/[-_./]/g, "");
|
|
7066
|
+
}
|
|
7067
|
+
function extractTokens(dep) {
|
|
7068
|
+
const tokens = [];
|
|
7069
|
+
const unscoped = dep.startsWith("@") ? dep.slice(1) : dep;
|
|
7070
|
+
tokens.push(unscoped);
|
|
7071
|
+
if (dep.startsWith("@") && unscoped.includes("/")) {
|
|
7072
|
+
const [scope, pkg] = unscoped.split("/");
|
|
7073
|
+
tokens.push(pkg);
|
|
7074
|
+
tokens.push(scope);
|
|
7075
|
+
const cleanScope = scope.replace(/js$/, "").replace(/-ai$/, "");
|
|
7076
|
+
if (cleanScope !== scope) tokens.push(cleanScope);
|
|
7690
7077
|
}
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7078
|
+
for (const suffix of ["-js", "-sdk", "-client", "-core", "-cli", "-types"]) {
|
|
7079
|
+
if (dep.endsWith(suffix)) {
|
|
7080
|
+
tokens.push(dep.slice(0, -suffix.length));
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
return tokens;
|
|
7084
|
+
}
|
|
7085
|
+
function matchesEntry(dep, entry) {
|
|
7086
|
+
const tokens = extractTokens(dep);
|
|
7087
|
+
const entrySlug = entry.slug.toLowerCase();
|
|
7088
|
+
const entryName = normalize(entry.name);
|
|
7089
|
+
for (const token of tokens) {
|
|
7090
|
+
const norm = normalize(token);
|
|
7091
|
+
if (norm === entrySlug) return true;
|
|
7092
|
+
if (norm === entryName) return true;
|
|
7093
|
+
if (entrySlug === norm) return true;
|
|
7094
|
+
if (entryName.startsWith(norm) && norm.length >= 3) return true;
|
|
7095
|
+
}
|
|
7096
|
+
return false;
|
|
7097
|
+
}
|
|
7694
7098
|
function detectFromPackageJson(projectDir) {
|
|
7695
|
-
const pkgPath =
|
|
7696
|
-
if (!
|
|
7099
|
+
const pkgPath = join7(projectDir, "package.json");
|
|
7100
|
+
if (!existsSync6(pkgPath)) return [];
|
|
7697
7101
|
let pkg;
|
|
7698
7102
|
try {
|
|
7699
|
-
pkg = JSON.parse(
|
|
7103
|
+
pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
|
|
7700
7104
|
} catch {
|
|
7701
7105
|
return [];
|
|
7702
7106
|
}
|
|
7703
|
-
const
|
|
7107
|
+
const depNames = Object.keys({
|
|
7704
7108
|
...pkg.dependencies,
|
|
7705
7109
|
...pkg.devDependencies
|
|
7706
|
-
};
|
|
7707
|
-
|
|
7110
|
+
});
|
|
7111
|
+
if (depNames.length === 0) return [];
|
|
7112
|
+
const entries2 = getAllEntries();
|
|
7708
7113
|
const matchesBySlug = /* @__PURE__ */ new Map();
|
|
7709
|
-
for (const
|
|
7710
|
-
const
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
results.push({ slug, matchedPackages, registryEntry });
|
|
7114
|
+
for (const dep of depNames) {
|
|
7115
|
+
for (const entry of entries2) {
|
|
7116
|
+
if (matchesEntry(dep, entry)) {
|
|
7117
|
+
const existing = matchesBySlug.get(entry.slug);
|
|
7118
|
+
if (existing) {
|
|
7119
|
+
existing.deps.push(dep);
|
|
7120
|
+
} else {
|
|
7121
|
+
matchesBySlug.set(entry.slug, { deps: [dep], entry });
|
|
7122
|
+
}
|
|
7123
|
+
break;
|
|
7124
|
+
}
|
|
7721
7125
|
}
|
|
7722
7126
|
}
|
|
7723
|
-
return
|
|
7127
|
+
return [...matchesBySlug.values()].map(({ deps, entry }) => ({
|
|
7128
|
+
slug: entry.slug,
|
|
7129
|
+
matchedPackages: deps,
|
|
7130
|
+
registryEntry: entry
|
|
7131
|
+
}));
|
|
7724
7132
|
}
|
|
7725
7133
|
function filterMatchesByCategories(matches, categories) {
|
|
7726
7134
|
if (categories.length === 0) return matches;
|
|
@@ -7832,12 +7240,12 @@ async function fetchLlmsTxt({ url, existingEtag }) {
|
|
|
7832
7240
|
if (contentLength && Number.parseInt(contentLength, 10) > MAX_SIZE) {
|
|
7833
7241
|
throw new Error(`Response too large (${contentLength} bytes, max ${MAX_SIZE})`);
|
|
7834
7242
|
}
|
|
7835
|
-
const
|
|
7836
|
-
if (
|
|
7837
|
-
throw new Error(`Response too large (${
|
|
7243
|
+
const text2 = await response.text();
|
|
7244
|
+
if (text2.length > MAX_SIZE) {
|
|
7245
|
+
throw new Error(`Response too large (${text2.length} bytes, max ${MAX_SIZE})`);
|
|
7838
7246
|
}
|
|
7839
7247
|
return {
|
|
7840
|
-
content:
|
|
7248
|
+
content: text2,
|
|
7841
7249
|
etag: response.headers.get("etag"),
|
|
7842
7250
|
lastModified: response.headers.get("last-modified"),
|
|
7843
7251
|
notModified: false
|
|
@@ -7849,7 +7257,7 @@ async function fetchLlmsTxt({ url, existingEtag }) {
|
|
|
7849
7257
|
|
|
7850
7258
|
// src/lib/telemetry.ts
|
|
7851
7259
|
var TELEMETRY_ENDPOINT = "https://llmstxt.directory/api/cli/telemetry";
|
|
7852
|
-
var CLI_VERSION = "0.
|
|
7260
|
+
var CLI_VERSION = "0.4.0";
|
|
7853
7261
|
var CI_ENV_VARS = ["CI", "GITHUB_ACTIONS", "GITLAB_CI", "CIRCLECI", "TRAVIS"];
|
|
7854
7262
|
function isDisabled() {
|
|
7855
7263
|
return process.env.DO_NOT_TRACK === "1" || process.env.LLMSTXT_TELEMETRY_DISABLED === "1";
|
|
@@ -7876,27 +7284,13 @@ function track(params) {
|
|
|
7876
7284
|
async function init(options) {
|
|
7877
7285
|
const projectDir = process.cwd();
|
|
7878
7286
|
const isInteractive = process.stdin.isTTY && !options.yes;
|
|
7879
|
-
printBanner("0.
|
|
7287
|
+
printBanner("0.4.0");
|
|
7880
7288
|
p3.intro("Install llms.txt documentation for your project");
|
|
7881
7289
|
const spin = spinner2("Loading registry...");
|
|
7882
7290
|
spin.start();
|
|
7883
7291
|
await loadRegistry();
|
|
7884
7292
|
spin.succeed("Registry loaded");
|
|
7885
7293
|
const agents2 = detectInstalledAgents();
|
|
7886
|
-
if (agents2.length > 0) {
|
|
7887
|
-
p3.log.info(`Detected agents: ${agents2.map((a) => pc4.cyan(a.displayName)).join(", ")}`);
|
|
7888
|
-
} else {
|
|
7889
|
-
p3.log.warn("No AI coding tools detected \u2014 files will be installed to .agents/skills/ only");
|
|
7890
|
-
}
|
|
7891
|
-
const spin2 = spinner2("Detecting project dependencies...");
|
|
7892
|
-
spin2.start();
|
|
7893
|
-
let matches = detectFromPackageJson(projectDir);
|
|
7894
|
-
if (matches.length === 0) {
|
|
7895
|
-
spin2.info("No matching llms.txt entries found for your dependencies");
|
|
7896
|
-
p3.log.message(pc4.dim("Try `llmstxt search <query>` to find entries manually"));
|
|
7897
|
-
p3.outro("No skills to install.");
|
|
7898
|
-
return;
|
|
7899
|
-
}
|
|
7900
7294
|
let activeCategories;
|
|
7901
7295
|
if (options.allCategories) {
|
|
7902
7296
|
activeCategories = [];
|
|
@@ -7905,95 +7299,223 @@ async function init(options) {
|
|
|
7905
7299
|
} else {
|
|
7906
7300
|
activeCategories = [...PRIMARY_CATEGORIES];
|
|
7907
7301
|
}
|
|
7302
|
+
let depMatches = detectFromPackageJson(projectDir);
|
|
7908
7303
|
if (activeCategories.length > 0) {
|
|
7909
|
-
|
|
7304
|
+
depMatches = filterMatchesByCategories(depMatches, activeCategories);
|
|
7305
|
+
}
|
|
7306
|
+
const depSlugs = new Set(depMatches.map((m) => m.slug));
|
|
7307
|
+
if (depMatches.length > 0) {
|
|
7308
|
+
p3.log.info(
|
|
7309
|
+
`Found ${depMatches.length} matching your dependencies: ${depMatches.map((m) => pc4.cyan(m.registryEntry.name)).join(", ")}`
|
|
7310
|
+
);
|
|
7910
7311
|
}
|
|
7911
|
-
if (
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7312
|
+
if (!isInteractive) {
|
|
7313
|
+
return installEntries({
|
|
7314
|
+
projectDir,
|
|
7315
|
+
entries: depMatches.map((m) => m.registryEntry),
|
|
7316
|
+
options,
|
|
7317
|
+
agents: agents2,
|
|
7318
|
+
targetAgents: agents2
|
|
7319
|
+
});
|
|
7320
|
+
}
|
|
7321
|
+
const selectedEntries = await browseAndSelect({ projectDir, depMatches, depSlugs });
|
|
7322
|
+
if (selectedEntries.length === 0) {
|
|
7323
|
+
p3.outro("No skills selected.");
|
|
7915
7324
|
return;
|
|
7916
7325
|
}
|
|
7917
|
-
|
|
7918
|
-
if (
|
|
7919
|
-
|
|
7920
|
-
const already = isInstalled({ projectDir, slug: match.slug });
|
|
7921
|
-
const status = already ? pc4.dim(" (already installed)") : "";
|
|
7922
|
-
p3.log.message(` ${pc4.cyan(match.registryEntry.name)}${status}`);
|
|
7923
|
-
}
|
|
7924
|
-
p3.outro("Dry run \u2014 no files were written");
|
|
7326
|
+
const targetAgents = await pickAgents(projectDir);
|
|
7327
|
+
if (!targetAgents) {
|
|
7328
|
+
p3.cancel("Installation cancelled.");
|
|
7925
7329
|
return;
|
|
7926
7330
|
}
|
|
7927
|
-
|
|
7928
|
-
if (
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
}
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
const
|
|
7948
|
-
message: "
|
|
7949
|
-
options:
|
|
7950
|
-
|
|
7951
|
-
|
|
7331
|
+
const format = await pickFormat(selectedEntries, options);
|
|
7332
|
+
if (!format) {
|
|
7333
|
+
p3.cancel("Installation cancelled.");
|
|
7334
|
+
return;
|
|
7335
|
+
}
|
|
7336
|
+
return installEntries({
|
|
7337
|
+
projectDir,
|
|
7338
|
+
entries: selectedEntries,
|
|
7339
|
+
options: { ...options, full: format === "llms-full.txt" },
|
|
7340
|
+
agents: agents2,
|
|
7341
|
+
targetAgents
|
|
7342
|
+
});
|
|
7343
|
+
}
|
|
7344
|
+
async function browseAndSelect({
|
|
7345
|
+
projectDir,
|
|
7346
|
+
depMatches,
|
|
7347
|
+
depSlugs
|
|
7348
|
+
}) {
|
|
7349
|
+
const selectedEntries = [];
|
|
7350
|
+
while (true) {
|
|
7351
|
+
const action = await p3.select({
|
|
7352
|
+
message: selectedEntries.length === 0 ? "How would you like to find llms.txt documentation?" : `${selectedEntries.length} selected. Add more or install?`,
|
|
7353
|
+
options: [
|
|
7354
|
+
...depMatches.length > 0 && selectedEntries.length === 0 ? [
|
|
7355
|
+
{
|
|
7356
|
+
value: "suggestions",
|
|
7357
|
+
label: `Suggested from dependencies (${depMatches.length} found)`,
|
|
7358
|
+
hint: depMatches.map((m) => m.registryEntry.name).join(", ")
|
|
7359
|
+
}
|
|
7360
|
+
] : [],
|
|
7361
|
+
{ value: "browse", label: "Browse by category" },
|
|
7362
|
+
{ value: "search", label: "Search by name" },
|
|
7363
|
+
...selectedEntries.length > 0 ? [{ value: "install", label: `Install ${selectedEntries.length} selected` }] : [],
|
|
7364
|
+
{ value: "done", label: selectedEntries.length > 0 ? "Cancel" : "Exit" }
|
|
7365
|
+
]
|
|
7952
7366
|
});
|
|
7953
|
-
if (p3.isCancel(
|
|
7954
|
-
p3.cancel("Installation cancelled.");
|
|
7955
|
-
|
|
7956
|
-
return;
|
|
7367
|
+
if (p3.isCancel(action) || action === "done") {
|
|
7368
|
+
if (selectedEntries.length > 0) p3.cancel("Installation cancelled.");
|
|
7369
|
+
else p3.outro("No skills selected.");
|
|
7370
|
+
return [];
|
|
7957
7371
|
}
|
|
7958
|
-
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7372
|
+
if (action === "install") break;
|
|
7373
|
+
let picked = [];
|
|
7374
|
+
if (action === "suggestions") {
|
|
7375
|
+
picked = await pickFromList(
|
|
7376
|
+
depMatches.map((m) => m.registryEntry),
|
|
7377
|
+
projectDir,
|
|
7378
|
+
depSlugs
|
|
7379
|
+
);
|
|
7380
|
+
} else if (action === "browse") {
|
|
7381
|
+
picked = await browseByCategory(projectDir, depSlugs);
|
|
7382
|
+
} else if (action === "search") {
|
|
7383
|
+
picked = await searchByName(projectDir, depSlugs);
|
|
7962
7384
|
}
|
|
7963
|
-
const
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
p3.cancel("Installation cancelled.");
|
|
7968
|
-
process.exitCode = 0;
|
|
7969
|
-
return;
|
|
7385
|
+
for (const entry of picked) {
|
|
7386
|
+
if (!selectedEntries.some((e) => e.slug === entry.slug)) {
|
|
7387
|
+
selectedEntries.push(entry);
|
|
7388
|
+
}
|
|
7970
7389
|
}
|
|
7971
|
-
}
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7390
|
+
}
|
|
7391
|
+
return selectedEntries;
|
|
7392
|
+
}
|
|
7393
|
+
async function browseByCategory(projectDir, depSlugs) {
|
|
7394
|
+
const allEntries = getAllEntries();
|
|
7395
|
+
const categoryMap = /* @__PURE__ */ new Map();
|
|
7396
|
+
for (const entry of allEntries) {
|
|
7397
|
+
categoryMap.set(entry.category, (categoryMap.get(entry.category) || 0) + 1);
|
|
7398
|
+
}
|
|
7399
|
+
const categoryChoice = await p3.select({
|
|
7400
|
+
message: "Select a category:",
|
|
7401
|
+
options: [...categoryMap.entries()].sort((a, b) => b[1] - a[1]).map(([cat, count]) => ({
|
|
7402
|
+
value: cat,
|
|
7403
|
+
label: cat,
|
|
7404
|
+
hint: `${count} entries`
|
|
7405
|
+
}))
|
|
7406
|
+
});
|
|
7407
|
+
if (p3.isCancel(categoryChoice)) return [];
|
|
7408
|
+
const categoryEntries = allEntries.filter((e) => e.category === categoryChoice);
|
|
7409
|
+
return pickFromList(categoryEntries, projectDir, depSlugs);
|
|
7410
|
+
}
|
|
7411
|
+
async function searchByName(projectDir, depSlugs) {
|
|
7412
|
+
const query = await p3.text({
|
|
7413
|
+
message: "Search for:",
|
|
7414
|
+
placeholder: "e.g. react, stripe, prisma..."
|
|
7415
|
+
});
|
|
7416
|
+
if (p3.isCancel(query) || !query) return [];
|
|
7417
|
+
const results = searchRegistry(query).slice(0, 20);
|
|
7418
|
+
if (results.length === 0) {
|
|
7419
|
+
p3.log.warn(`No results for "${query}"`);
|
|
7420
|
+
return [];
|
|
7421
|
+
}
|
|
7422
|
+
return pickFromList(results, projectDir, depSlugs);
|
|
7423
|
+
}
|
|
7424
|
+
async function pickFromList(entries2, projectDir, depSlugs) {
|
|
7425
|
+
const optionsList = entries2.map((entry) => {
|
|
7426
|
+
const already = isInstalled({ projectDir, slug: entry.slug });
|
|
7427
|
+
const isDep = depSlugs.has(entry.slug);
|
|
7428
|
+
const hints = [];
|
|
7429
|
+
if (already) hints.push("installed");
|
|
7430
|
+
if (isDep) hints.push("in your deps");
|
|
7431
|
+
hints.push(entry.category);
|
|
7432
|
+
return {
|
|
7433
|
+
value: entry.slug,
|
|
7434
|
+
label: entry.name,
|
|
7435
|
+
hint: hints.join(" \xB7 ")
|
|
7436
|
+
};
|
|
7437
|
+
});
|
|
7438
|
+
const selected = await p3.multiselect({
|
|
7439
|
+
message: `Select entries (${entries2.length} available):`,
|
|
7440
|
+
options: optionsList,
|
|
7441
|
+
required: false
|
|
7442
|
+
});
|
|
7443
|
+
if (p3.isCancel(selected)) return [];
|
|
7444
|
+
const slugSet = new Set(selected);
|
|
7445
|
+
return entries2.filter((e) => slugSet.has(e.slug));
|
|
7446
|
+
}
|
|
7447
|
+
async function pickFormat(entries2, options) {
|
|
7448
|
+
if (options.full) return "llms-full.txt";
|
|
7449
|
+
const hasFullAvailable = entries2.some((e) => e.llmsFullTxtUrl);
|
|
7450
|
+
if (!hasFullAvailable) return "llms.txt";
|
|
7451
|
+
const fullCount = entries2.filter((e) => e.llmsFullTxtUrl).length;
|
|
7452
|
+
const choice = await p3.select({
|
|
7453
|
+
message: "Which documentation format?",
|
|
7454
|
+
options: [
|
|
7455
|
+
{
|
|
7456
|
+
value: "llms.txt",
|
|
7457
|
+
label: "llms.txt",
|
|
7458
|
+
hint: "concise \u2014 smaller, faster to load"
|
|
7459
|
+
},
|
|
7460
|
+
{
|
|
7461
|
+
value: "llms-full.txt",
|
|
7462
|
+
label: "llms-full.txt",
|
|
7463
|
+
hint: `comprehensive \u2014 ${fullCount}/${entries2.length} selected have full version`
|
|
7464
|
+
}
|
|
7465
|
+
]
|
|
7466
|
+
});
|
|
7467
|
+
if (p3.isCancel(choice)) return null;
|
|
7468
|
+
return choice;
|
|
7469
|
+
}
|
|
7470
|
+
async function pickAgents(projectDir) {
|
|
7471
|
+
const savedPrefs = loadSavedAgentPrefs(projectDir);
|
|
7472
|
+
const initialValues = getInitialAgents({ allAgents: agents, savedPrefs, projectDir });
|
|
7473
|
+
const selected = await p3.multiselect({
|
|
7474
|
+
message: "Which agents should receive the skills?",
|
|
7475
|
+
options: agents.map((a) => ({
|
|
7476
|
+
value: a.name,
|
|
7477
|
+
label: a.displayName,
|
|
7478
|
+
hint: a.isUniversal ? "always included" : a.skillsDir
|
|
7479
|
+
})),
|
|
7480
|
+
initialValues,
|
|
7481
|
+
required: true
|
|
7482
|
+
});
|
|
7483
|
+
if (p3.isCancel(selected)) return null;
|
|
7484
|
+
const finalNames = ensureUniversalAgents({ selected, allAgents: agents });
|
|
7485
|
+
saveAgentPrefs(projectDir, selected);
|
|
7486
|
+
const nameSet = new Set(finalNames);
|
|
7487
|
+
return agents.filter((a) => nameSet.has(a.name));
|
|
7488
|
+
}
|
|
7489
|
+
async function installEntries({
|
|
7490
|
+
projectDir,
|
|
7491
|
+
entries: entries2,
|
|
7492
|
+
options,
|
|
7493
|
+
agents: agents2,
|
|
7494
|
+
targetAgents
|
|
7495
|
+
}) {
|
|
7496
|
+
if (options.dryRun) {
|
|
7497
|
+
for (const entry of entries2) {
|
|
7498
|
+
const already = isInstalled({ projectDir, slug: entry.slug });
|
|
7499
|
+
const status = already ? pc4.dim(" (already installed)") : "";
|
|
7500
|
+
p3.log.message(` ${pc4.cyan(entry.name)}${status}`);
|
|
7977
7501
|
}
|
|
7502
|
+
p3.outro("Dry run \u2014 no files were written");
|
|
7503
|
+
return;
|
|
7978
7504
|
}
|
|
7979
7505
|
const format = options.full ? "llms-full.txt" : "llms.txt";
|
|
7980
7506
|
let installed = 0;
|
|
7981
7507
|
let skipped = 0;
|
|
7982
7508
|
let failed = 0;
|
|
7983
7509
|
const installedSlugs = [];
|
|
7984
|
-
for (const
|
|
7985
|
-
if (!selectedSlugs.has(match.slug)) {
|
|
7986
|
-
continue;
|
|
7987
|
-
}
|
|
7988
|
-
const entry = match.registryEntry;
|
|
7510
|
+
for (const entry of entries2) {
|
|
7989
7511
|
const actualFormat = format === "llms-full.txt" && entry.llmsFullTxtUrl ? "llms-full.txt" : "llms.txt";
|
|
7990
7512
|
const url = actualFormat === "llms-full.txt" ? entry.llmsFullTxtUrl : entry.llmsTxtUrl;
|
|
7991
|
-
if (isInstalled({ projectDir, slug:
|
|
7513
|
+
if (isInstalled({ projectDir, slug: entry.slug })) {
|
|
7992
7514
|
skipped++;
|
|
7993
7515
|
continue;
|
|
7994
7516
|
}
|
|
7995
|
-
const
|
|
7996
|
-
|
|
7517
|
+
const spin = spinner2(`Fetching ${entry.name}...`);
|
|
7518
|
+
spin.start();
|
|
7997
7519
|
try {
|
|
7998
7520
|
const result = await fetchLlmsTxt({ url });
|
|
7999
7521
|
const {
|
|
@@ -8002,15 +7524,16 @@ async function init(options) {
|
|
|
8002
7524
|
agents: installedTo
|
|
8003
7525
|
} = installToAgents({
|
|
8004
7526
|
projectDir,
|
|
8005
|
-
slug:
|
|
7527
|
+
slug: entry.slug,
|
|
8006
7528
|
entry,
|
|
8007
7529
|
content: result.content,
|
|
8008
|
-
format: actualFormat
|
|
7530
|
+
format: actualFormat,
|
|
7531
|
+
targetAgents
|
|
8009
7532
|
});
|
|
8010
7533
|
addEntry({
|
|
8011
7534
|
projectDir,
|
|
8012
7535
|
entry: {
|
|
8013
|
-
slug:
|
|
7536
|
+
slug: entry.slug,
|
|
8014
7537
|
format: actualFormat,
|
|
8015
7538
|
sourceUrl: url,
|
|
8016
7539
|
etag: result.etag,
|
|
@@ -8021,12 +7544,12 @@ async function init(options) {
|
|
|
8021
7544
|
name: entry.name
|
|
8022
7545
|
}
|
|
8023
7546
|
});
|
|
8024
|
-
|
|
7547
|
+
spin.succeed(`${entry.name} ${pc4.dim(`\u2192 ${installedTo.join(", ")}`)}`);
|
|
8025
7548
|
installed++;
|
|
8026
|
-
installedSlugs.push(
|
|
7549
|
+
installedSlugs.push(entry.slug);
|
|
8027
7550
|
} catch (err) {
|
|
8028
7551
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8029
|
-
|
|
7552
|
+
spin.fail(`${entry.name}: ${msg}`);
|
|
8030
7553
|
failed++;
|
|
8031
7554
|
}
|
|
8032
7555
|
}
|
|
@@ -8037,9 +7560,6 @@ async function init(options) {
|
|
|
8037
7560
|
if (summaryLines.length > 0) {
|
|
8038
7561
|
p3.note(summaryLines.join("\n"), "Summary");
|
|
8039
7562
|
}
|
|
8040
|
-
if (addToGitignore(projectDir)) {
|
|
8041
|
-
p3.log.success("Added .llms/ and .agents/skills/ to .gitignore");
|
|
8042
|
-
}
|
|
8043
7563
|
if (installed > 0) {
|
|
8044
7564
|
syncClaudeMd(projectDir);
|
|
8045
7565
|
}
|
|
@@ -8068,8 +7588,34 @@ async function install({ names, options }) {
|
|
|
8068
7588
|
await loadRegistry();
|
|
8069
7589
|
spin.succeed("Registry loaded");
|
|
8070
7590
|
const agents2 = detectInstalledAgents();
|
|
8071
|
-
|
|
8072
|
-
|
|
7591
|
+
let targetAgents;
|
|
7592
|
+
if (!process.stdin.isTTY) {
|
|
7593
|
+
targetAgents = agents2;
|
|
7594
|
+
if (agents2.length > 0) {
|
|
7595
|
+
const display = agents2.map((a) => a.displayName).join(", ");
|
|
7596
|
+
p4.log.message(pc5.dim(`Installing to: ${display}`));
|
|
7597
|
+
}
|
|
7598
|
+
} else {
|
|
7599
|
+
const savedPrefs = loadSavedAgentPrefs(projectDir);
|
|
7600
|
+
const initialValues = getInitialAgents({ allAgents: agents, savedPrefs, projectDir });
|
|
7601
|
+
const selected = await p4.multiselect({
|
|
7602
|
+
message: "Which agents should receive the skills?",
|
|
7603
|
+
options: agents.map((a) => ({
|
|
7604
|
+
value: a.name,
|
|
7605
|
+
label: a.displayName,
|
|
7606
|
+
hint: a.isUniversal ? "always included" : a.skillsDir
|
|
7607
|
+
})),
|
|
7608
|
+
initialValues,
|
|
7609
|
+
required: true
|
|
7610
|
+
});
|
|
7611
|
+
if (p4.isCancel(selected)) {
|
|
7612
|
+
p4.cancel("Installation cancelled.");
|
|
7613
|
+
return;
|
|
7614
|
+
}
|
|
7615
|
+
const finalNames = ensureUniversalAgents({ selected, allAgents: agents });
|
|
7616
|
+
saveAgentPrefs(projectDir, selected);
|
|
7617
|
+
const nameSet = new Set(finalNames);
|
|
7618
|
+
targetAgents = agents.filter((a) => nameSet.has(a.name));
|
|
8073
7619
|
}
|
|
8074
7620
|
let installed = 0;
|
|
8075
7621
|
let failed = 0;
|
|
@@ -8122,7 +7668,14 @@ async function install({ names, options }) {
|
|
|
8122
7668
|
checksum,
|
|
8123
7669
|
size,
|
|
8124
7670
|
agents: installedTo
|
|
8125
|
-
} = installToAgents({
|
|
7671
|
+
} = installToAgents({
|
|
7672
|
+
projectDir,
|
|
7673
|
+
slug: entry.slug,
|
|
7674
|
+
entry,
|
|
7675
|
+
content: result.content,
|
|
7676
|
+
format,
|
|
7677
|
+
targetAgents
|
|
7678
|
+
});
|
|
8126
7679
|
addEntry({
|
|
8127
7680
|
projectDir,
|
|
8128
7681
|
entry: {
|
|
@@ -8154,7 +7707,6 @@ async function install({ names, options }) {
|
|
|
8154
7707
|
p4.note(lines.join("\n"), "Summary");
|
|
8155
7708
|
}
|
|
8156
7709
|
if (installed > 0) {
|
|
8157
|
-
addToGitignore(projectDir);
|
|
8158
7710
|
syncClaudeMd(projectDir);
|
|
8159
7711
|
}
|
|
8160
7712
|
if (failed > 0) {
|
|
@@ -8378,8 +7930,8 @@ async function update(name, options) {
|
|
|
8378
7930
|
|
|
8379
7931
|
// src/index.ts
|
|
8380
7932
|
var program = new Command();
|
|
8381
|
-
program.name("llmstxt").description("Install llms.txt files from the llms-txt-hub registry into your AI coding tools").version("0.
|
|
8382
|
-
printBanner("0.
|
|
7933
|
+
program.name("llmstxt").description("Install llms.txt files from the llms-txt-hub registry into your AI coding tools").version("0.4.0").action(() => {
|
|
7934
|
+
printBanner("0.4.0");
|
|
8383
7935
|
program.outputHelp();
|
|
8384
7936
|
});
|
|
8385
7937
|
program.command("init").description("Auto-detect dependencies and install matching llms.txt files").option("--category <categories>", "Filter by categories (comma-separated)").option("--all-categories", "Include all categories").option("--dry-run", "Preview without installing").option("--full", "Prefer llms-full.txt when available").option("-y, --yes", "Skip confirmation prompts").action(init);
|