llmstxt-cli 0.1.0 → 0.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.
Files changed (3) hide show
  1. package/LICENCE +24 -0
  2. package/dist/index.js +643 -825
  3. package/package.json +10 -10
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(text) {
27
- s.start(text || _text || "");
26
+ start(text2) {
27
+ s.start(text2 || _text || "");
28
28
  },
29
- stop(text) {
30
- s.stop(text || "");
29
+ stop(text2) {
30
+ s.stop(text2 || "");
31
31
  },
32
- succeed(text) {
33
- s.stop(`${pc.green("\u2713")} ${text}`);
32
+ succeed(text2) {
33
+ s.stop(`${pc.green("\u2713")} ${text2}`);
34
34
  },
35
- fail(text) {
36
- s.stop(`${pc.red("\u2717")} ${text}`);
35
+ fail(text2) {
36
+ s.stop(`${pc.red("\u2717")} ${text2}`);
37
37
  },
38
- info(text) {
39
- s.stop(`${pc.blue("\u2139")} ${text}`);
38
+ info(text2) {
39
+ s.stop(`${pc.blue("\u2139")} ${text2}`);
40
40
  },
41
- warn(text) {
42
- s.stop(`${pc.yellow("\u26A0")} ${text}`);
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;
@@ -6417,6 +6420,9 @@ import {
6417
6420
  import { homedir as homedir2 } from "os";
6418
6421
  import { dirname as dirname2, join as join3, relative, resolve } from "path";
6419
6422
  var home = homedir2();
6423
+ var configHome = process.env.XDG_CONFIG_HOME?.trim() || join3(home, ".config");
6424
+ var codexHome = process.env.CODEX_HOME?.trim() || join3(home, ".codex");
6425
+ var claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join3(home, ".claude");
6420
6426
  var CANONICAL_DIR = ".agents/skills";
6421
6427
  function sanitizeSlug(slug) {
6422
6428
  if (!slug || typeof slug !== "string") {
@@ -6435,12 +6441,82 @@ function assertPathContainment(fullPath, parentDir) {
6435
6441
  }
6436
6442
  }
6437
6443
  var agents = [
6444
+ {
6445
+ name: "adal",
6446
+ displayName: "AdaL",
6447
+ skillsDir: ".adal/skills",
6448
+ isUniversal: false,
6449
+ detectInstalled: () => existsSync2(join3(home, ".adal"))
6450
+ },
6451
+ {
6452
+ name: "amp",
6453
+ displayName: "Amp",
6454
+ skillsDir: ".agents/skills",
6455
+ isUniversal: true,
6456
+ detectInstalled: () => existsSync2(join3(configHome, "amp"))
6457
+ },
6458
+ {
6459
+ name: "antigravity",
6460
+ displayName: "Antigravity",
6461
+ skillsDir: ".agent/skills",
6462
+ isUniversal: false,
6463
+ detectInstalled: () => existsSync2(join3(home, ".gemini/antigravity"))
6464
+ },
6465
+ {
6466
+ name: "augment",
6467
+ displayName: "Augment",
6468
+ skillsDir: ".augment/skills",
6469
+ isUniversal: false,
6470
+ detectInstalled: () => existsSync2(join3(home, ".augment"))
6471
+ },
6438
6472
  {
6439
6473
  name: "claude-code",
6440
6474
  displayName: "Claude Code",
6441
6475
  skillsDir: ".claude/skills",
6442
6476
  isUniversal: false,
6443
- detectInstalled: () => existsSync2(join3(home, ".claude"))
6477
+ detectInstalled: () => existsSync2(claudeHome)
6478
+ },
6479
+ {
6480
+ name: "cline",
6481
+ displayName: "Cline",
6482
+ skillsDir: ".cline/skills",
6483
+ isUniversal: false,
6484
+ detectInstalled: () => existsSync2(join3(home, ".cline"))
6485
+ },
6486
+ {
6487
+ name: "codebuddy",
6488
+ displayName: "CodeBuddy",
6489
+ skillsDir: ".codebuddy/skills",
6490
+ isUniversal: false,
6491
+ detectInstalled: () => existsSync2(join3(home, ".codebuddy"))
6492
+ },
6493
+ {
6494
+ name: "codex",
6495
+ displayName: "Codex",
6496
+ skillsDir: ".agents/skills",
6497
+ isUniversal: true,
6498
+ detectInstalled: () => existsSync2(codexHome) || existsSync2("/etc/codex")
6499
+ },
6500
+ {
6501
+ name: "command-code",
6502
+ displayName: "Command Code",
6503
+ skillsDir: ".commandcode/skills",
6504
+ isUniversal: false,
6505
+ detectInstalled: () => existsSync2(join3(home, ".commandcode"))
6506
+ },
6507
+ {
6508
+ name: "continue",
6509
+ displayName: "Continue",
6510
+ skillsDir: ".continue/skills",
6511
+ isUniversal: false,
6512
+ detectInstalled: () => existsSync2(join3(home, ".continue"))
6513
+ },
6514
+ {
6515
+ name: "crush",
6516
+ displayName: "Crush",
6517
+ skillsDir: ".crush/skills",
6518
+ isUniversal: false,
6519
+ detectInstalled: () => existsSync2(join3(configHome, "crush"))
6444
6520
  },
6445
6521
  {
6446
6522
  name: "cursor",
@@ -6450,32 +6526,186 @@ var agents = [
6450
6526
  detectInstalled: () => existsSync2(join3(home, ".cursor"))
6451
6527
  },
6452
6528
  {
6453
- name: "opencode",
6454
- displayName: "OpenCode",
6529
+ name: "droid",
6530
+ displayName: "Droid",
6531
+ skillsDir: ".factory/skills",
6532
+ isUniversal: false,
6533
+ detectInstalled: () => existsSync2(join3(home, ".factory"))
6534
+ },
6535
+ {
6536
+ name: "gemini-cli",
6537
+ displayName: "Gemini CLI",
6455
6538
  skillsDir: ".agents/skills",
6456
6539
  isUniversal: true,
6457
- detectInstalled: () => existsSync2(join3(home, ".config", "opencode")) || existsSync2(join3(home, ".agents"))
6540
+ detectInstalled: () => existsSync2(join3(home, ".gemini"))
6458
6541
  },
6459
6542
  {
6460
- name: "codex",
6461
- displayName: "Codex",
6543
+ name: "github-copilot",
6544
+ displayName: "GitHub Copilot",
6545
+ skillsDir: ".agents/skills",
6546
+ isUniversal: true,
6547
+ detectInstalled: () => existsSync2(join3(home, ".copilot"))
6548
+ },
6549
+ {
6550
+ name: "goose",
6551
+ displayName: "Goose",
6552
+ skillsDir: ".goose/skills",
6553
+ isUniversal: false,
6554
+ detectInstalled: () => existsSync2(join3(configHome, "goose"))
6555
+ },
6556
+ {
6557
+ name: "iflow-cli",
6558
+ displayName: "iFlow CLI",
6559
+ skillsDir: ".iflow/skills",
6560
+ isUniversal: false,
6561
+ detectInstalled: () => existsSync2(join3(home, ".iflow"))
6562
+ },
6563
+ {
6564
+ name: "junie",
6565
+ displayName: "Junie",
6566
+ skillsDir: ".junie/skills",
6567
+ isUniversal: false,
6568
+ detectInstalled: () => existsSync2(join3(home, ".junie"))
6569
+ },
6570
+ {
6571
+ name: "kilo",
6572
+ displayName: "Kilo Code",
6573
+ skillsDir: ".kilocode/skills",
6574
+ isUniversal: false,
6575
+ detectInstalled: () => existsSync2(join3(home, ".kilocode"))
6576
+ },
6577
+ {
6578
+ name: "kimi-cli",
6579
+ displayName: "Kimi Code CLI",
6580
+ skillsDir: ".agents/skills",
6581
+ isUniversal: true,
6582
+ detectInstalled: () => existsSync2(join3(home, ".kimi"))
6583
+ },
6584
+ {
6585
+ name: "kiro-cli",
6586
+ displayName: "Kiro CLI",
6587
+ skillsDir: ".kiro/skills",
6588
+ isUniversal: false,
6589
+ detectInstalled: () => existsSync2(join3(home, ".kiro"))
6590
+ },
6591
+ {
6592
+ name: "kode",
6593
+ displayName: "Kode",
6594
+ skillsDir: ".kode/skills",
6595
+ isUniversal: false,
6596
+ detectInstalled: () => existsSync2(join3(home, ".kode"))
6597
+ },
6598
+ {
6599
+ name: "mcpjam",
6600
+ displayName: "MCPJam",
6601
+ skillsDir: ".mcpjam/skills",
6602
+ isUniversal: false,
6603
+ detectInstalled: () => existsSync2(join3(home, ".mcpjam"))
6604
+ },
6605
+ {
6606
+ name: "mistral-vibe",
6607
+ displayName: "Mistral Vibe",
6608
+ skillsDir: ".vibe/skills",
6609
+ isUniversal: false,
6610
+ detectInstalled: () => existsSync2(join3(home, ".vibe"))
6611
+ },
6612
+ {
6613
+ name: "mux",
6614
+ displayName: "Mux",
6615
+ skillsDir: ".mux/skills",
6616
+ isUniversal: false,
6617
+ detectInstalled: () => existsSync2(join3(home, ".mux"))
6618
+ },
6619
+ {
6620
+ name: "neovate",
6621
+ displayName: "Neovate",
6622
+ skillsDir: ".neovate/skills",
6623
+ isUniversal: false,
6624
+ detectInstalled: () => existsSync2(join3(home, ".neovate"))
6625
+ },
6626
+ {
6627
+ name: "openclaw",
6628
+ displayName: "OpenClaw",
6629
+ skillsDir: "skills",
6630
+ isUniversal: false,
6631
+ detectInstalled: () => existsSync2(join3(home, ".openclaw")) || existsSync2(join3(home, ".clawdbot")) || existsSync2(join3(home, ".moltbot"))
6632
+ },
6633
+ {
6634
+ name: "opencode",
6635
+ displayName: "OpenCode",
6462
6636
  skillsDir: ".agents/skills",
6463
6637
  isUniversal: true,
6464
- detectInstalled: () => existsSync2(join3(home, ".codex"))
6638
+ detectInstalled: () => existsSync2(join3(configHome, "opencode"))
6639
+ },
6640
+ {
6641
+ name: "openhands",
6642
+ displayName: "OpenHands",
6643
+ skillsDir: ".openhands/skills",
6644
+ isUniversal: false,
6645
+ detectInstalled: () => existsSync2(join3(home, ".openhands"))
6646
+ },
6647
+ {
6648
+ name: "pi",
6649
+ displayName: "Pi",
6650
+ skillsDir: ".pi/skills",
6651
+ isUniversal: false,
6652
+ detectInstalled: () => existsSync2(join3(home, ".pi/agent"))
6653
+ },
6654
+ {
6655
+ name: "pochi",
6656
+ displayName: "Pochi",
6657
+ skillsDir: ".pochi/skills",
6658
+ isUniversal: false,
6659
+ detectInstalled: () => existsSync2(join3(home, ".pochi"))
6660
+ },
6661
+ {
6662
+ name: "qoder",
6663
+ displayName: "Qoder",
6664
+ skillsDir: ".qoder/skills",
6665
+ isUniversal: false,
6666
+ detectInstalled: () => existsSync2(join3(home, ".qoder"))
6667
+ },
6668
+ {
6669
+ name: "qwen-code",
6670
+ displayName: "Qwen Code",
6671
+ skillsDir: ".qwen/skills",
6672
+ isUniversal: false,
6673
+ detectInstalled: () => existsSync2(join3(home, ".qwen"))
6674
+ },
6675
+ {
6676
+ name: "roo",
6677
+ displayName: "Roo Code",
6678
+ skillsDir: ".roo/skills",
6679
+ isUniversal: false,
6680
+ detectInstalled: () => existsSync2(join3(home, ".roo"))
6681
+ },
6682
+ {
6683
+ name: "trae",
6684
+ displayName: "Trae",
6685
+ skillsDir: ".trae/skills",
6686
+ isUniversal: false,
6687
+ detectInstalled: () => existsSync2(join3(home, ".trae"))
6688
+ },
6689
+ {
6690
+ name: "trae-cn",
6691
+ displayName: "Trae CN",
6692
+ skillsDir: ".trae/skills",
6693
+ isUniversal: false,
6694
+ detectInstalled: () => existsSync2(join3(home, ".trae-cn"))
6465
6695
  },
6466
6696
  {
6467
6697
  name: "windsurf",
6468
6698
  displayName: "Windsurf",
6469
6699
  skillsDir: ".windsurf/skills",
6470
6700
  isUniversal: false,
6471
- detectInstalled: () => existsSync2(join3(home, ".codeium", "windsurf"))
6701
+ detectInstalled: () => existsSync2(join3(home, ".codeium/windsurf"))
6472
6702
  },
6473
6703
  {
6474
- name: "cline",
6475
- displayName: "Cline",
6476
- skillsDir: ".cline/skills",
6704
+ name: "zencoder",
6705
+ displayName: "Zencoder",
6706
+ skillsDir: ".zencoder/skills",
6477
6707
  isUniversal: false,
6478
- detectInstalled: () => existsSync2(join3(home, ".cline"))
6708
+ detectInstalled: () => existsSync2(join3(home, ".zencoder"))
6479
6709
  }
6480
6710
  ];
6481
6711
  function detectInstalledAgents() {
@@ -6526,6 +6756,15 @@ function removeAgentSkill({ projectDir, slug, agent }) {
6526
6756
  } catch {
6527
6757
  }
6528
6758
  }
6759
+ function getGitignoreEntries() {
6760
+ const dirs = /* @__PURE__ */ new Set([`${CANONICAL_DIR}/`]);
6761
+ for (const agent of agents) {
6762
+ if (!agent.isUniversal) {
6763
+ dirs.add(`${agent.skillsDir}/`);
6764
+ }
6765
+ }
6766
+ return [...dirs].sort();
6767
+ }
6529
6768
 
6530
6769
  // src/lib/storage.ts
6531
6770
  var LLMS_DIR = ".llms";
@@ -6576,7 +6815,8 @@ function installToAgents({
6576
6815
  slug,
6577
6816
  entry,
6578
6817
  content,
6579
- format
6818
+ format,
6819
+ targetAgents
6580
6820
  }) {
6581
6821
  const checksum = createHash("sha256").update(content).digest("hex");
6582
6822
  const size = Buffer.byteLength(content, "utf-8");
@@ -6591,8 +6831,8 @@ function installToAgents({
6591
6831
  writeFileSync3(join4(canonicalDir, "reference.md"), referenceMd, "utf-8");
6592
6832
  }
6593
6833
  installedAgents.push("universal");
6594
- const detectedAgents = detectInstalledAgents();
6595
- for (const agent of detectedAgents) {
6834
+ const agentsToLink = targetAgents ?? detectInstalledAgents();
6835
+ for (const agent of agentsToLink) {
6596
6836
  if (agent.isUniversal) {
6597
6837
  if (!installedAgents.includes(agent.name)) {
6598
6838
  installedAgents.push(agent.name);
@@ -6625,14 +6865,7 @@ function isInstalled({ projectDir, slug }) {
6625
6865
  function addToGitignore(projectDir) {
6626
6866
  try {
6627
6867
  const gitignorePath = join4(projectDir, ".gitignore");
6628
- const gitignoreEntries = [
6629
- ".llms/",
6630
- ".agents/skills/",
6631
- ".claude/skills/",
6632
- ".cursor/skills/",
6633
- ".windsurf/skills/",
6634
- ".cline/skills/"
6635
- ];
6868
+ const gitignoreEntries = [".llms/", ...getGitignoreEntries()];
6636
6869
  if (existsSync3(gitignorePath)) {
6637
6870
  const content = readFileSync3(gitignorePath, "utf-8");
6638
6871
  const missing = gitignoreEntries.filter((e) => !content.includes(e));
@@ -6705,6 +6938,68 @@ ${pc2.dim("Full:")} ${entry.llmsFullTxtUrl}` : ""}`
6705
6938
  import * as p3 from "@clack/prompts";
6706
6939
  import pc4 from "picocolors";
6707
6940
 
6941
+ // src/lib/agent-selection.ts
6942
+ import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
6943
+ import { join as join5 } from "path";
6944
+ var PREFS_DIR = ".llms";
6945
+ var PREFS_FILE = "agent-prefs.json";
6946
+ var DEFAULT_AGENTS = ["claude-code", "cursor", "codex"];
6947
+ function detectProjectAgents(opts) {
6948
+ const detected = [];
6949
+ for (const agent of opts.allAgents) {
6950
+ if (agent.isUniversal) continue;
6951
+ const configDir = agent.skillsDir.split("/")[0];
6952
+ if (configDir && configDir !== "skills" && existsSync4(join5(opts.projectDir, configDir))) {
6953
+ detected.push(agent.name);
6954
+ }
6955
+ }
6956
+ return detected;
6957
+ }
6958
+ function getInitialAgents(opts) {
6959
+ const validNames = new Set(opts.allAgents.map((a) => a.name));
6960
+ if (opts.savedPrefs && opts.savedPrefs.length > 0) {
6961
+ const filtered = opts.savedPrefs.filter((name) => validNames.has(name));
6962
+ if (filtered.length > 0) return filtered;
6963
+ }
6964
+ if (opts.projectDir) {
6965
+ const detected = detectProjectAgents({ projectDir: opts.projectDir, allAgents: opts.allAgents });
6966
+ if (detected.length > 0) return detected;
6967
+ }
6968
+ return DEFAULT_AGENTS.filter((name) => validNames.has(name));
6969
+ }
6970
+ function ensureUniversalAgents(opts) {
6971
+ const result = [...opts.selected];
6972
+ for (const agent of opts.allAgents) {
6973
+ if (agent.isUniversal && !result.includes(agent.name)) {
6974
+ result.push(agent.name);
6975
+ }
6976
+ }
6977
+ return result;
6978
+ }
6979
+ function loadSavedAgentPrefs(projectDir) {
6980
+ try {
6981
+ const filePath = join5(projectDir, PREFS_DIR, PREFS_FILE);
6982
+ if (!existsSync4(filePath)) return null;
6983
+ const data = JSON.parse(readFileSync4(filePath, "utf-8"));
6984
+ if (Array.isArray(data.agents)) return data.agents;
6985
+ return null;
6986
+ } catch {
6987
+ return null;
6988
+ }
6989
+ }
6990
+ function saveAgentPrefs(projectDir, agentNames) {
6991
+ try {
6992
+ const dir = join5(projectDir, PREFS_DIR);
6993
+ mkdirSync5(dir, { recursive: true });
6994
+ writeFileSync4(
6995
+ join5(dir, PREFS_FILE),
6996
+ JSON.stringify({ agents: agentNames }, null, 2) + "\n",
6997
+ "utf-8"
6998
+ );
6999
+ } catch {
7000
+ }
7001
+ }
7002
+
6708
7003
  // src/lib/banner.ts
6709
7004
  import pc3 from "picocolors";
6710
7005
  var BANNER_LINES = [
@@ -6730,18 +7025,18 @@ ${pc3.dim(` v${version} \xB7 Install llms.txt documentation for AI coding tools
6730
7025
  }
6731
7026
 
6732
7027
  // src/lib/context.ts
6733
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
6734
- import { join as join5 } from "path";
7028
+ import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
7029
+ import { join as join6 } from "path";
6735
7030
  var START_MARKER = "<!-- llmstxt:start -->";
6736
7031
  var END_MARKER = "<!-- llmstxt:end -->";
6737
7032
  function syncClaudeMd(projectDir) {
6738
7033
  try {
6739
7034
  const lockfile = readLockfile(projectDir);
6740
7035
  const entries2 = Object.values(lockfile.entries);
6741
- const claudeMdPath = join5(projectDir, "CLAUDE.md");
7036
+ const claudeMdPath = join6(projectDir, "CLAUDE.md");
6742
7037
  let content = "";
6743
- if (existsSync4(claudeMdPath)) {
6744
- content = readFileSync4(claudeMdPath, "utf-8");
7038
+ if (existsSync5(claudeMdPath)) {
7039
+ content = readFileSync5(claudeMdPath, "utf-8");
6745
7040
  }
6746
7041
  const section = buildSection(entries2);
6747
7042
  if (content.includes(START_MARKER)) {
@@ -6764,12 +7059,12 @@ function syncClaudeMd(projectDir) {
6764
7059
  new RegExp(`\\n?${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`),
6765
7060
  ""
6766
7061
  ).trim();
6767
- if (content.length === 0 && !existsSync4(claudeMdPath)) {
7062
+ if (content.length === 0 && !existsSync5(claudeMdPath)) {
6768
7063
  return;
6769
7064
  }
6770
7065
  }
6771
- if (content.length > 0 || existsSync4(claudeMdPath)) {
6772
- writeFileSync4(claudeMdPath, content.endsWith("\n") ? content : `${content}
7066
+ if (content.length > 0 || existsSync5(claudeMdPath)) {
7067
+ writeFileSync5(claudeMdPath, content.endsWith("\n") ? content : `${content}
6773
7068
  `, "utf-8");
6774
7069
  }
6775
7070
  } catch (err) {
@@ -6797,701 +7092,76 @@ function escapeRegex(s) {
6797
7092
  }
6798
7093
 
6799
7094
  // src/lib/detector.ts
6800
- import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
6801
- import { join as join6 } from "path";
6802
-
6803
- // data/package-mappings.json
6804
- var package_mappings_default = {
6805
- version: 1,
6806
- npm: {
6807
- agent: "agent",
6808
- "02aidev": "02aidev",
6809
- "abstract-api": "abstract-api",
6810
- aceessayai: "aceessayai",
6811
- acrcloud: "acrcloud",
6812
- activepieces: "activepieces",
6813
- adiacent: "adiacent",
6814
- "advin-servers": "advin-servers",
6815
- adx: "adx",
6816
- "affordable-nvme-ssd-web-hosting-pakistan": "affordable-nvme-ssd-web-hosting-pakistan",
6817
- aftermath: "aftermath",
6818
- agentai: "agentai",
6819
- agentlayer: "agentlayer",
6820
- agentql: "agentql",
6821
- agno: "agno",
6822
- "ai-consulting": "ai-consulting",
6823
- "ai-dream-scope": "ai-dream-scope",
6824
- "ai-predict-stock": "ai-predict-stock",
6825
- "ai-sdk": "ai-sdk",
6826
- "ai-squared": "ai-squared",
6827
- aicryptocore: "aicryptocore",
6828
- akool: "akool",
6829
- alexopdev: "alexopdev",
6830
- "all-in": "all-in",
6831
- "alpha-fi": "alpha-fi",
6832
- alphagate: "alphagate",
6833
- altostrat: "altostrat",
6834
- alva: "alva",
6835
- amema: "amema",
6836
- amplemarket: "amplemarket",
6837
- analog: "analog",
6838
- annoto: "annoto",
6839
- answerai: "answerai",
6840
- "ant-design": "ant-design",
6841
- anthropic: "anthropic",
6842
- anytrack: "anytrack",
6843
- anytype: "anytype",
6844
- "apex-protocol": "apex-protocol",
6845
- apibara: "apibara",
6846
- apify: "apify",
6847
- aporia: "aporia",
6848
- appointo: "appointo",
6849
- appzung: "appzung",
6850
- "aps-sdks-openapi-specification-aps": "aps-sdks-openapi-specification-aps",
6851
- aptible: "aptible",
6852
- arbiscan: "arbiscan",
6853
- arcade: "arcade",
6854
- "argil-ai": "argil-ai",
6855
- "ark-ui": "ark-ui",
6856
- arpeggi: "arpeggi",
6857
- artzero: "artzero",
6858
- asapp: "asapp",
6859
- "asposewords-product-family": "asposewords-product-family",
6860
- "ast-grep": "ast-grep",
6861
- astro: "astro",
6862
- "augment-code": "augment-code",
6863
- autentique: "autentique",
6864
- avaamo: "avaamo",
6865
- avacloud: "avacloud",
6866
- "avada-seo-suite": "avada-seo-suite",
6867
- "avalanche-hvac-services-heating-air": "avalanche-hvac-services-heating-air",
6868
- avo: "avo",
6869
- awesomeapi: "awesomeapi",
6870
- axiom: "axiom",
6871
- axle: "axle",
6872
- azumuta: "azumuta",
6873
- basehub: "basehub",
6874
- beacon: "beacon",
6875
- "best-app-development-company": "best-app-development-company",
6876
- "best-boat-lifts": "best-boat-lifts",
6877
- "beta-three-professional-audio": "beta-three-professional-audio",
6878
- "better-auth": "better-auth",
6879
- beyondwords: "beyondwords",
6880
- bika: "bika",
6881
- birdie: "birdie",
6882
- "bitcoin-cold-storage-tools": "bitcoin-cold-storage-tools",
6883
- bito: "bito",
6884
- "bits-ui": "bits-ui",
6885
- bixgrow: "bixgrow",
6886
- blacknet: "blacknet",
6887
- "blue-media-services": "blue-media-services",
6888
- blueshift: "blueshift",
6889
- booqable: "booqable",
6890
- bottalk: "bottalk",
6891
- braintrust: "braintrust",
6892
- brandfetch: "brandfetch",
6893
- "bright-data": "bright-data",
6894
- browsee: "browsee",
6895
- bucket: "bucket",
6896
- bugsplat: "bugsplat",
6897
- builtwith: "builtwith",
6898
- bun: "bun",
6899
- bunny: "bunny",
6900
- butlr: "butlr",
6901
- caf: "caf",
6902
- calcom: "calcom",
6903
- calendarscripts: "calendarscripts",
6904
- "callback-technologies": "callback-technologies",
6905
- campsite: "campsite",
6906
- captivaterecipes: "captivaterecipes",
6907
- "car-rental-in-airports-ofgeorgia": "car-rental-in-airports-ofgeorgia",
6908
- cardknox: "cardknox",
6909
- carto: "carto",
6910
- carv: "carv",
6911
- catizen: "catizen",
6912
- "cdata-software": "cdata-software",
6913
- "chakra-ui": "chakra-ui",
6914
- chargeblast: "chargeblast",
6915
- chartbeat: "chartbeat",
6916
- chatbase: "chatbase",
6917
- chatknow: "chatknow",
6918
- chatling: "chatling",
6919
- "checkmate-live": "checkmate-live",
6920
- "chic-room": "chic-room",
6921
- "chirp-wireless": "chirp-wireless",
6922
- "cid-contact": "cid-contact",
6923
- cipherstash: "cipherstash",
6924
- circleci: "circleci",
6925
- citizenshipper: "citizenshipper",
6926
- citrusad: "citrusad",
6927
- civic: "civic",
6928
- "claude-mcp-community": "claude-mcp-community",
6929
- clerk: "clerk",
6930
- "clever-cloud": "clever-cloud",
6931
- cloreai: "cloreai",
6932
- cloudfix: "cloudfix",
6933
- cloudflare: "cloudflare",
6934
- clouve: "clouve",
6935
- cloverspace: "cloverspace",
6936
- "cnpjws-api": "cnpjws-api",
6937
- cobo: "cobo",
6938
- cobrowse: "cobrowse",
6939
- codecrafters: "codecrafters",
6940
- codeium: "codeium",
6941
- coefont: "coefont",
6942
- coframe: "coframe",
6943
- cog: "cog",
6944
- cohere: "cohere",
6945
- comforterp: "comforterp",
6946
- comforthrm: "comforthrm",
6947
- comfy: "comfy",
6948
- "commerce-layer": "commerce-layer",
6949
- "common-ninja": "common-ninja",
6950
- "community-helm-charts": "community-helm-charts",
6951
- comparisonator: "comparisonator",
6952
- "concept-designs-marketing": "concept-designs-marketing",
6953
- conductor: "conductor",
6954
- configcat: "configcat",
6955
- consentik: "consentik",
6956
- contentsquare: "contentsquare",
6957
- "contractor-marketing-agency": "contractor-marketing-agency",
6958
- contravault: "contravault",
6959
- convex: "convex",
6960
- coolify: "coolify",
6961
- coollabs: "coollabs",
6962
- "copenhagen-art-and-photography": "copenhagen-art-and-photography",
6963
- "corso-seo-online-certificato": "corso-seo-online-certificato",
6964
- cosmic: "cosmic",
6965
- couchdrop: "couchdrop",
6966
- count: "count",
6967
- courier: "courier",
6968
- craftco: "craftco",
6969
- "cre-data-and-location-intelligence-app": "cre-data-and-location-intelligence-app",
6970
- "creative-handbook-production-resource-directory": "creative-handbook-production-resource-directory",
6971
- creatopy: "creatopy",
6972
- crewai: "crewai",
6973
- "cross-browser-mobile-app-testing": "cross-browser-mobile-app-testing",
6974
- cryptlex: "cryptlex",
6975
- "curling-io": "curling-io",
6976
- cursor: "cursor",
6977
- "customer-service-ai-platform": "customer-service-ai-platform",
6978
- "cyber-security-news": "cyber-security-news",
6979
- daisyui: "daisyui",
6980
- dappier: "dappier",
6981
- dat1co: "dat1co",
6982
- "data-surfer": "data-surfer",
6983
- "databuddy-analytics": "databuddy-analytics",
6984
- datacamp: "datacamp",
6985
- datafold: "datafold",
6986
- dataimpulse: "dataimpulse",
6987
- "datastax-astra-db": "datastax-astra-db",
6988
- daytona: "daytona",
6989
- decocx: "decocx",
6990
- deepconverse: "deepconverse",
6991
- "demo-time": "demo-time",
6992
- "deno-documentation": "deno-documentation",
6993
- deployhq: "deployhq",
6994
- designmodo: "designmodo",
6995
- devhub: "devhub",
6996
- devunus: "devunus",
6997
- "dexpaprika-api-live-crypto-pool-data": "dexpaprika-api-live-crypto-pool-data",
6998
- dns0eu: "dns0eu",
6999
- docetl: "docetl",
7000
- "docker-docs": "docker-docs",
7001
- docspring: "docspring",
7002
- "document-file-translation-powered-by-ai": "document-file-translation-powered-by-ai",
7003
- donobu: "donobu",
7004
- "dopp-finance": "dopp-finance",
7005
- dotenvx: "dotenvx",
7006
- "drizzle-orm": "drizzle-orm",
7007
- dub: "dub",
7008
- duckdb: "duckdb",
7009
- "duende-software": "duende-software",
7010
- dynamic: "dynamic",
7011
- e6data: "e6data",
7012
- effect: "effect",
7013
- elevenlabs: "elevenlabs",
7014
- elysia: "elysia",
7015
- emailgic: "emailgic",
7016
- "embed-notion-pages-into-your-website": "embed-notion-pages-into-your-website",
7017
- embedchain: "embedchain",
7018
- envoyer: "envoyer",
7019
- equipment: "equipment",
7020
- essio: "essio",
7021
- "expo-documentation": "expo-documentation",
7022
- fabric: "fabric",
7023
- facets: "facets",
7024
- "fantasy-sports-app-development-company": "fantasy-sports-app-development-company",
7025
- "farcaster-miniapps": "farcaster-miniapps",
7026
- "feedback-sync": "feedback-sync",
7027
- fern: "fern",
7028
- fibery: "fibery",
7029
- "film-and-screenwriter-school": "film-and-screenwriter-school",
7030
- finch: "finch",
7031
- fireproof: "fireproof",
7032
- "fireworks-ai": "fireworks-ai",
7033
- firmly: "firmly",
7034
- flatfile: "flatfile",
7035
- flipto: "flipto",
7036
- flows: "flows",
7037
- flowx: "flowx",
7038
- "fork-force-australia": "fork-force-australia",
7039
- formo: "formo",
7040
- formwerk: "formwerk",
7041
- fractalpay: "fractalpay",
7042
- "fraction-ai": "fraction-ai",
7043
- fragbin: "fragbin",
7044
- "frank-krav-maga-self-defense-bengaluru": "frank-krav-maga-self-defense-bengaluru",
7045
- "free-ai-image-generator-maker": "free-ai-image-generator-maker",
7046
- frigade: "frigade",
7047
- "front-matter-cms-a-cms-in-your-vs-code-editor": "front-matter-cms-a-cms-in-your-vs-code-editor",
7048
- "funny-stories-of-horrible-stories": "funny-stories-of-horrible-stories",
7049
- galileo: "galileo",
7050
- "game-development-hub": "game-development-hub",
7051
- gaminator: "gaminator",
7052
- "gaslighting-check": "gaslighting-check",
7053
- genaiscript: "genaiscript",
7054
- "generate-ai-ugc-videos-for-ads": "generate-ai-ugc-videos-for-ads",
7055
- getinbox: "getinbox",
7056
- getmarked: "getmarked",
7057
- giselle: "giselle",
7058
- glama: "glama",
7059
- gloodai: "gloodai",
7060
- glucncom: "glucncom",
7061
- "gnosis-chain": "gnosis-chain",
7062
- goody: "goody",
7063
- gradio: "gradio",
7064
- "graphite-note": "graphite-note",
7065
- "greece-vacation-search": "greece-vacation-search",
7066
- "green-apple-travel-tourism": "green-apple-travel-tourism",
7067
- groqcloud: "groqcloud",
7068
- gumlet: "gumlet",
7069
- helicone: "helicone",
7070
- "help-for-erectile-dysfunction": "help-for-erectile-dysfunction",
7071
- "henan-pengfei-pvp-k30-povidone": "henan-pengfei-pvp-k30-povidone",
7072
- herd: "herd",
7073
- "heritage-collection": "heritage-collection",
7074
- heyflow: "heyflow",
7075
- hola: "hola",
7076
- home: "home",
7077
- "home-llms-txt": "home-llms-txt",
7078
- "home-tz": "home-tz",
7079
- "home-angular": "home-angular",
7080
- hono: "hono",
7081
- hub88: "hub88",
7082
- hubspot: "hubspot",
7083
- "hugging-face-accelerate": "hugging-face-accelerate",
7084
- "hugging-face-diffusers": "hugging-face-diffusers",
7085
- "hugging-face-hub": "hugging-face-hub",
7086
- "hugging-face-hub-python-library": "hugging-face-hub-python-library",
7087
- "hugging-face-transformers": "hugging-face-transformers",
7088
- "humanity-protocol": "humanity-protocol",
7089
- hybridai: "hybridai",
7090
- hyperbeam: "hyperbeam",
7091
- hyperline: "hyperline",
7092
- hypermode: "hypermode",
7093
- hypertune: "hypertune",
7094
- i3dnet: "i3dnet",
7095
- "iagent-protocol": "iagent-protocol",
7096
- icepanel: "icepanel",
7097
- id21: "id21",
7098
- ideogram: "ideogram",
7099
- "ig-exporter": "ig-exporter",
7100
- illuvium: "illuvium",
7101
- imaginstudio: "imaginstudio",
7102
- imagineart: "imagineart",
7103
- "img-arena": "img-arena",
7104
- "immortal-rising-2": "immortal-rising-2",
7105
- infera: "infera",
7106
- infisical: "infisical",
7107
- inkeep: "inkeep",
7108
- inngest: "inngest",
7109
- inspector: "inspector",
7110
- "inspira-ui-build-beautiful-websites-using-vue-nuxt": "inspira-ui-build-beautiful-websites-using-vue-nuxt",
7111
- instant: "instant",
7112
- instruqt: "instruqt",
7113
- intelligems: "intelligems",
7114
- intract: "intract",
7115
- intuned: "intuned",
7116
- ionos: "ionos",
7117
- ionq: "ionq",
7118
- ipaper: "ipaper",
7119
- iproyalcom: "iproyalcom",
7120
- irev: "irev",
7121
- "island-router": "island-router",
7122
- jam: "jam",
7123
- jazztools: "jazztools",
7124
- journeyapps: "journeyapps",
7125
- journify: "journify",
7126
- jsfiddle: "jsfiddle",
7127
- jumptask: "jumptask",
7128
- "juniper-creates": "juniper-creates",
7129
- juno: "juno",
7130
- "kaisar-network": "kaisar-network",
7131
- "karrier-one": "karrier-one",
7132
- keeper: "keeper",
7133
- ketch: "ketch",
7134
- kick: "kick",
7135
- koala: "koala",
7136
- kruzty: "kruzty",
7137
- lacremeai: "lacremeai",
7138
- lago: "lago",
7139
- lambdatest: "lambdatest",
7140
- "langchain-javascript-docs": "langchain-javascript-docs",
7141
- "langchain-python-docs": "langchain-python-docs",
7142
- langflow: "langflow",
7143
- langfuse: "langfuse",
7144
- "langgraph-javascript-docs": "langgraph-javascript-docs",
7145
- "langgraph-python-docs": "langgraph-python-docs",
7146
- launchfast: "launchfast",
7147
- lavita: "lavita",
7148
- "law-firm-digital-marketing-agency": "law-firm-digital-marketing-agency",
7149
- layouthub: "layouthub",
7150
- "leather-jackets-coats-for-men-women": "leather-jackets-coats-for-men-women",
7151
- legend: "legend",
7152
- "legend-state": "legend-state",
7153
- "legends-of-learning": "legends-of-learning",
7154
- legitt: "legitt",
7155
- lettermint: "lettermint",
7156
- "liam-erd": "liam-erd",
7157
- liblab: "liblab",
7158
- libmodulor: "libmodulor",
7159
- likec4: "likec4",
7160
- linktree: "linktree",
7161
- litdb: "litdb",
7162
- liveblocks: "liveblocks",
7163
- livecaller: "livecaller",
7164
- livecodes: "livecodes",
7165
- livespotting: "livespotting",
7166
- "llms-txtio": "llms-txtio",
7167
- llmstxt: "llmstxt",
7168
- llmvo: "llmvo",
7169
- "lm-studio": "lm-studio",
7170
- lobehub: "lobehub",
7171
- loglayer: "loglayer",
7172
- loops: "loops",
7173
- "lots-of-csvs": "lots-of-csvs",
7174
- lottielab: "lottielab",
7175
- lunacy: "lunacy",
7176
- luxalgo: "luxalgo",
7177
- luxid: "luxid",
7178
- lynx: "lynx",
7179
- mailmodo: "mailmodo",
7180
- mako: "mako",
7181
- mangopay: "mangopay",
7182
- "manifestly-checklists": "manifestly-checklists",
7183
- "marco-ronco-seo-specialist": "marco-ronco-seo-specialist",
7184
- marimo: "marimo",
7185
- "marketing-doctors": "marketing-doctors",
7186
- "marketing-integration-and-automation": "marketing-integration-and-automation",
7187
- massive: "massive",
7188
- mastory: "mastory",
7189
- mastra: "mastra",
7190
- "material-ui-aka-mui": "material-ui-aka-mui",
7191
- "maxim-ai": "maxim-ai",
7192
- "mdutil-free-markdown-tools": "mdutil-free-markdown-tools",
7193
- mealbymeal: "mealbymeal",
7194
- "meds-canada": "meds-canada",
7195
- medusa: "medusa",
7196
- meilisearch: "meilisearch",
7197
- "mekalite-cnc-machining-services": "mekalite-cnc-machining-services",
7198
- meshconnect: "meshconnect",
7199
- "method-financial": "method-financial",
7200
- micro1: "micro1",
7201
- mintlify: "mintlify",
7202
- mixo: "mixo",
7203
- "model-context-protocol-mcp": "model-context-protocol-mcp",
7204
- "monster-ui": "monster-ui",
7205
- moondream: "moondream",
7206
- "morphic-solutions": "morphic-solutions",
7207
- movehealth: "movehealth",
7208
- "mubashir-hassan": "mubashir-hassan",
7209
- "mui-x-advanced-react-components-for-complex-use-cases": "mui-x-advanced-react-components-for-complex-use-cases",
7210
- multiplier: "multiplier",
7211
- multisynq: "multisynq",
7212
- mux: "mux",
7213
- "mystery-o-matic": "mystery-o-matic",
7214
- nash: "nash",
7215
- nativescript: "nativescript",
7216
- navi: "navi",
7217
- "naviga-global": "naviga-global",
7218
- "needle-cloud": "needle-cloud",
7219
- netlify: "netlify",
7220
- nextevo: "nextevo",
7221
- nextevogroup: "nextevogroup",
7222
- "nile-postgres": "nile-postgres",
7223
- nomadhelperai: "nomadhelperai",
7224
- "nonprofit-management-consulting": "nonprofit-management-consulting",
7225
- "novi-labs": "novi-labs",
7226
- nsoftware: "nsoftware",
7227
- nuxt: "nuxt",
7228
- "omnimind-docs-oss-mcp-client": "omnimind-docs-oss-mcp-client",
7229
- onagentsorg: "onagentsorg",
7230
- "once-ui": "once-ui",
7231
- onetrust: "onetrust",
7232
- openfort: "openfort",
7233
- openphone: "openphone",
7234
- openpipe: "openpipe",
7235
- openrouter: "openrouter",
7236
- "openvpn-zero-trust-vpn": "openvpn-zero-trust-vpn",
7237
- "opik-by-comet": "opik-by-comet",
7238
- "optimajet-form-builder": "optimajet-form-builder",
7239
- oxla: "oxla",
7240
- papergraderpro: "papergraderpro",
7241
- paragon: "paragon",
7242
- "parcelcube-static-dimensioning-systems": "parcelcube-static-dimensioning-systems",
7243
- parseable: "parseable",
7244
- pastaclean: "pastaclean",
7245
- payperfax: "payperfax",
7246
- payrollrabbit: "payrollrabbit",
7247
- "pentesting-red-teaming-company": "pentesting-red-teaming-company",
7248
- perplexity: "perplexity",
7249
- "personal-page": "personal-page",
7250
- "petite-box": "petite-box",
7251
- pgflow: "pgflow",
7252
- phare: "phare",
7253
- pikaicons: "pikaicons",
7254
- pinata: "pinata",
7255
- pinecone: "pinecone",
7256
- plain: "plain",
7257
- "plan-harmony-travel-planning": "plan-harmony-travel-planning",
7258
- platformsh: "platformsh",
7259
- playai: "playai",
7260
- popsmash: "popsmash",
7261
- postfast: "postfast",
7262
- preact: "preact",
7263
- prettier: "prettier",
7264
- primev: "primev",
7265
- prisma: "prisma",
7266
- profound: "profound",
7267
- progressrocks: "progressrocks",
7268
- "proguard-pest-control": "proguard-pest-control",
7269
- projectdiscovery: "projectdiscovery",
7270
- "prompt-kit": "prompt-kit",
7271
- promptfoo: "promptfoo",
7272
- pydantic: "pydantic",
7273
- pydanticai: "pydanticai",
7274
- qrcoau: "qrcoau",
7275
- quill: "quill",
7276
- qwikrank: "qwikrank",
7277
- rainbowkit: "rainbowkit",
7278
- raincamp: "raincamp",
7279
- rankscaleai: "rankscaleai",
7280
- rapidtextai: "rapidtextai",
7281
- raycast: "raycast",
7282
- rcponline: "rcponline",
7283
- redpanda: "redpanda",
7284
- rememberizer: "rememberizer",
7285
- remotion: "remotion",
7286
- remult: "remult",
7287
- render: "render",
7288
- reown: "reown",
7289
- replit: "replit",
7290
- resend: "resend",
7291
- respondio: "respondio",
7292
- retainful: "retainful",
7293
- "ri-xu-online": "ri-xu-online",
7294
- "rims-tires-for-cars-and-trucks": "rims-tires-for-cars-and-trucks",
7295
- roc: "roc",
7296
- rsbuild: "rsbuild",
7297
- rsdoctor: "rsdoctor",
7298
- rslib: "rslib",
7299
- rspack: "rspack",
7300
- rubric: "rubric",
7301
- "ruleta-aleatoria-online-gratis": "ruleta-aleatoria-online-gratis",
7302
- rushdb: "rushdb",
7303
- saev: "saev",
7304
- salesbricks: "salesbricks",
7305
- "salesforce-marketing-cloud-consultants": "salesforce-marketing-cloud-consultants",
7306
- "samsung-food": "samsung-food",
7307
- sandisk: "sandisk",
7308
- sardine: "sardine",
7309
- "scottish-art-prints-by-carol-mcewan": "scottish-art-prints-by-carol-mcewan",
7310
- "scraping-proxies": "scraping-proxies",
7311
- screenshotone: "screenshotone",
7312
- sealos: "sealos",
7313
- "secure-fast-online-money-transfers": "secure-fast-online-money-transfers",
7314
- sekhlopk: "sekhlopk",
7315
- self: "self",
7316
- sellersprite: "sellersprite",
7317
- semgrep: "semgrep",
7318
- seo2llm: "seo2llm",
7319
- servicestack: "servicestack",
7320
- sgnlai: "sgnlai",
7321
- sherlock: "sherlock",
7322
- "shop-positioner-llc": "shop-positioner-llc",
7323
- "side-space": "side-space",
7324
- simplepdf: "simplepdf",
7325
- sinch: "sinch",
7326
- "singing-carrots": "singing-carrots",
7327
- sitespeakai: "sitespeakai",
7328
- skipgo: "skipgo",
7329
- "sky-follower-bridge": "sky-follower-bridge",
7330
- skydeckai: "skydeckai",
7331
- "skyworkthe-ai-workspace-agents": "skyworkthe-ai-workspace-agents",
7332
- smartcar: "smartcar",
7333
- social: "social",
7334
- socialityio: "socialityio",
7335
- solid: "solid",
7336
- sourcegraph: "sourcegraph",
7337
- spacetimedb: "spacetimedb",
7338
- speakeasy: "speakeasy",
7339
- starwind: "starwind",
7340
- statusfield: "statusfield",
7341
- stedi: "stedi",
7342
- "stephanie-kabi": "stephanie-kabi",
7343
- "stock-trading-investment-app": "stock-trading-investment-app",
7344
- stripe: "stripe",
7345
- "study-fetch": "study-fetch",
7346
- "sunra-ai": "sunra-ai",
7347
- supabase: "supabase",
7348
- supadata: "supadata",
7349
- superwall: "superwall",
7350
- svelte: "svelte",
7351
- "svg-viewer": "svg-viewer",
7352
- "swipe-simple-invoicing-and-payments-app": "swipe-simple-invoicing-and-payments-app",
7353
- tamagui: "tamagui",
7354
- "taskade-ai": "taskade-ai",
7355
- tavus: "tavus",
7356
- "tlassistance-snior": "tlassistance-snior",
7357
- televisionai: "televisionai",
7358
- tensorzero: "tensorzero",
7359
- "the-ai-engineers-handbook": "the-ai-engineers-handbook",
7360
- "the-bucket-hat": "the-bucket-hat",
7361
- "the-crawl-tool": "the-crawl-tool",
7362
- "the-data-driven-marketer": "the-data-driven-marketer",
7363
- "the-dinner-detective-murder-mystery-show": "the-dinner-detective-murder-mystery-show",
7364
- theirstack: "theirstack",
7365
- "therapydave-dave-lechnyr-lcsw": "therapydave-dave-lechnyr-lcsw",
7366
- tidb: "tidb",
7367
- tidio: "tidio",
7368
- tinybird: "tinybird",
7369
- tiptap: "tiptap",
7370
- toriut: "toriut",
7371
- trackingplan: "trackingplan",
7372
- trackvia: "trackvia",
7373
- "trail-of-bits": "trail-of-bits",
7374
- transloadit: "transloadit",
7375
- "travel-nepal": "travel-nepal",
7376
- triggerdev: "triggerdev",
7377
- triplit: "triplit",
7378
- trueprofit: "trueprofit",
7379
- truffle: "truffle",
7380
- turbo: "turbo",
7381
- turbodocx: "turbodocx",
7382
- turso: "turso",
7383
- "twicpics-by-frontify": "twicpics-by-frontify",
7384
- twoshoes: "twoshoes",
7385
- "ufc-velvet": "ufc-velvet",
7386
- "uminai-mcp": "uminai-mcp",
7387
- underrunio: "underrunio",
7388
- unifygtm: "unifygtm",
7389
- unistyles: "unistyles",
7390
- uniwebview: "uniwebview",
7391
- unkey: "unkey",
7392
- unstructured: "unstructured",
7393
- upstash: "upstash",
7394
- "upstreet-ai": "upstreet-ai",
7395
- upsun: "upsun",
7396
- useapinet: "useapinet",
7397
- "utrecht-golf-instructor-marina-romanik": "utrecht-golf-instructor-marina-romanik",
7398
- "ux-patterns-for-devs": "ux-patterns-for-devs",
7399
- vald: "vald",
7400
- "vald-health": "vald-health",
7401
- vapi: "vapi",
7402
- vdoninja: "vdoninja",
7403
- velt: "velt",
7404
- vendure: "vendure",
7405
- veniceai: "veniceai",
7406
- ventrata: "ventrata",
7407
- "vercel-ai-sdk": "vercel-ai-sdk",
7408
- verdn: "verdn",
7409
- "video-and-audio-frameworks-for-net": "video-and-audio-frameworks-for-net",
7410
- videosdklive: "videosdklive",
7411
- videowise: "videowise",
7412
- viem: "viem",
7413
- "vignette-id": "vignette-id",
7414
- vital: "vital",
7415
- "voxel-busters": "voxel-busters",
7416
- "voyager-shuffle": "voyager-shuffle",
7417
- vplayed: "vplayed",
7418
- "vue-macros": "vue-macros",
7419
- vuejs: "vuejs",
7420
- wandio: "wandio",
7421
- warp: "warp",
7422
- weathercom: "weathercom",
7423
- "web-design-company-qatar": "web-design-company-qatar",
7424
- "web-development-wordpress-maintenance": "web-development-wordpress-maintenance",
7425
- webrecorder: "webrecorder",
7426
- "wedgwood-insurance": "wedgwood-insurance",
7427
- weka: "weka",
7428
- "welcome-to-bunny": "welcome-to-bunny",
7429
- "welcome-to-htmlhint": "welcome-to-htmlhint",
7430
- "wf-content-creator-platform": "wf-content-creator-platform",
7431
- whereby: "whereby",
7432
- "wild-in-africa": "wild-in-africa",
7433
- wized: "wized",
7434
- wonderchat: "wonderchat",
7435
- woowup: "woowup",
7436
- wordlift: "wordlift",
7437
- workbookly: "workbookly",
7438
- workflow: "workflow",
7439
- "wot-design-uni": "wot-design-uni",
7440
- writer: "writer",
7441
- wxt: "wxt",
7442
- x: "x",
7443
- "x-cmd": "x-cmd",
7444
- xmcp: "xmcp",
7445
- xomatic: "xomatic",
7446
- yamlresume: "yamlresume",
7447
- youform: "youform",
7448
- zag: "zag",
7449
- zapts: "zapts",
7450
- "zaphyr-php-framework": "zaphyr-php-framework",
7451
- zapier: "zapier",
7452
- zeffy: "zeffy",
7453
- zenml: "zenml",
7454
- zep: "zep",
7455
- zigpoll: "zigpoll",
7456
- zipchat: "zipchat",
7457
- zipy: "zipy",
7458
- zodori: "zodori",
7459
- zoko: "zoko",
7460
- "zoomryconveyorshiploader-manufacturer": "zoomryconveyorshiploader-manufacturer"
7095
+ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
7096
+ import { join as join7 } from "path";
7097
+ function normalize(name) {
7098
+ return name.toLowerCase().replace(/[-_./]/g, "");
7099
+ }
7100
+ function extractTokens(dep) {
7101
+ const tokens = [];
7102
+ const unscoped = dep.startsWith("@") ? dep.slice(1) : dep;
7103
+ tokens.push(unscoped);
7104
+ if (dep.startsWith("@") && unscoped.includes("/")) {
7105
+ const [scope, pkg] = unscoped.split("/");
7106
+ tokens.push(pkg);
7107
+ tokens.push(scope);
7108
+ const cleanScope = scope.replace(/js$/, "").replace(/-ai$/, "");
7109
+ if (cleanScope !== scope) tokens.push(cleanScope);
7461
7110
  }
7462
- };
7463
-
7464
- // src/lib/detector.ts
7111
+ for (const suffix of ["-js", "-sdk", "-client", "-core", "-cli", "-types"]) {
7112
+ if (dep.endsWith(suffix)) {
7113
+ tokens.push(dep.slice(0, -suffix.length));
7114
+ }
7115
+ }
7116
+ return tokens;
7117
+ }
7118
+ function matchesEntry(dep, entry) {
7119
+ const tokens = extractTokens(dep);
7120
+ const entrySlug = entry.slug.toLowerCase();
7121
+ const entryName = normalize(entry.name);
7122
+ for (const token of tokens) {
7123
+ const norm = normalize(token);
7124
+ if (norm === entrySlug) return true;
7125
+ if (norm === entryName) return true;
7126
+ if (entrySlug === norm) return true;
7127
+ if (entryName.startsWith(norm) && norm.length >= 3) return true;
7128
+ }
7129
+ return false;
7130
+ }
7465
7131
  function detectFromPackageJson(projectDir) {
7466
- const pkgPath = join6(projectDir, "package.json");
7467
- if (!existsSync5(pkgPath)) return [];
7132
+ const pkgPath = join7(projectDir, "package.json");
7133
+ if (!existsSync6(pkgPath)) return [];
7468
7134
  let pkg;
7469
7135
  try {
7470
- pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
7136
+ pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
7471
7137
  } catch {
7472
7138
  return [];
7473
7139
  }
7474
- const allDeps = {
7140
+ const depNames = Object.keys({
7475
7141
  ...pkg.dependencies,
7476
7142
  ...pkg.devDependencies
7477
- };
7478
- const mappings = package_mappings_default;
7143
+ });
7144
+ if (depNames.length === 0) return [];
7145
+ const entries2 = getAllEntries();
7479
7146
  const matchesBySlug = /* @__PURE__ */ new Map();
7480
- for (const depName of Object.keys(allDeps)) {
7481
- const slug = mappings.npm[depName];
7482
- if (!slug) continue;
7483
- const existing = matchesBySlug.get(slug) || [];
7484
- existing.push(depName);
7485
- matchesBySlug.set(slug, existing);
7486
- }
7487
- const results = [];
7488
- for (const [slug, matchedPackages] of matchesBySlug) {
7489
- const registryEntry = getEntry2(slug);
7490
- if (registryEntry) {
7491
- results.push({ slug, matchedPackages, registryEntry });
7147
+ for (const dep of depNames) {
7148
+ for (const entry of entries2) {
7149
+ if (matchesEntry(dep, entry)) {
7150
+ const existing = matchesBySlug.get(entry.slug);
7151
+ if (existing) {
7152
+ existing.deps.push(dep);
7153
+ } else {
7154
+ matchesBySlug.set(entry.slug, { deps: [dep], entry });
7155
+ }
7156
+ break;
7157
+ }
7492
7158
  }
7493
7159
  }
7494
- return results;
7160
+ return [...matchesBySlug.values()].map(({ deps, entry }) => ({
7161
+ slug: entry.slug,
7162
+ matchedPackages: deps,
7163
+ registryEntry: entry
7164
+ }));
7495
7165
  }
7496
7166
  function filterMatchesByCategories(matches, categories) {
7497
7167
  if (categories.length === 0) return matches;
@@ -7603,12 +7273,12 @@ async function fetchLlmsTxt({ url, existingEtag }) {
7603
7273
  if (contentLength && Number.parseInt(contentLength, 10) > MAX_SIZE) {
7604
7274
  throw new Error(`Response too large (${contentLength} bytes, max ${MAX_SIZE})`);
7605
7275
  }
7606
- const text = await response.text();
7607
- if (text.length > MAX_SIZE) {
7608
- throw new Error(`Response too large (${text.length} bytes, max ${MAX_SIZE})`);
7276
+ const text2 = await response.text();
7277
+ if (text2.length > MAX_SIZE) {
7278
+ throw new Error(`Response too large (${text2.length} bytes, max ${MAX_SIZE})`);
7609
7279
  }
7610
7280
  return {
7611
- content: text,
7281
+ content: text2,
7612
7282
  etag: response.headers.get("etag"),
7613
7283
  lastModified: response.headers.get("last-modified"),
7614
7284
  notModified: false
@@ -7620,7 +7290,7 @@ async function fetchLlmsTxt({ url, existingEtag }) {
7620
7290
 
7621
7291
  // src/lib/telemetry.ts
7622
7292
  var TELEMETRY_ENDPOINT = "https://llmstxt.directory/api/cli/telemetry";
7623
- var CLI_VERSION = "0.1.0";
7293
+ var CLI_VERSION = "0.3.0";
7624
7294
  var CI_ENV_VARS = ["CI", "GITHUB_ACTIONS", "GITLAB_CI", "CIRCLECI", "TRAVIS"];
7625
7295
  function isDisabled() {
7626
7296
  return process.env.DO_NOT_TRACK === "1" || process.env.LLMSTXT_TELEMETRY_DISABLED === "1";
@@ -7647,27 +7317,13 @@ function track(params) {
7647
7317
  async function init(options) {
7648
7318
  const projectDir = process.cwd();
7649
7319
  const isInteractive = process.stdin.isTTY && !options.yes;
7650
- printBanner("0.1.0");
7320
+ printBanner("0.3.0");
7651
7321
  p3.intro("Install llms.txt documentation for your project");
7652
7322
  const spin = spinner2("Loading registry...");
7653
7323
  spin.start();
7654
7324
  await loadRegistry();
7655
7325
  spin.succeed("Registry loaded");
7656
7326
  const agents2 = detectInstalledAgents();
7657
- if (agents2.length > 0) {
7658
- p3.log.info(`Detected agents: ${agents2.map((a) => pc4.cyan(a.displayName)).join(", ")}`);
7659
- } else {
7660
- p3.log.warn("No AI coding tools detected \u2014 files will be installed to .agents/skills/ only");
7661
- }
7662
- const spin2 = spinner2("Detecting project dependencies...");
7663
- spin2.start();
7664
- let matches = detectFromPackageJson(projectDir);
7665
- if (matches.length === 0) {
7666
- spin2.info("No matching llms.txt entries found for your dependencies");
7667
- p3.log.message(pc4.dim("Try `llmstxt search <query>` to find entries manually"));
7668
- p3.outro("No skills to install.");
7669
- return;
7670
- }
7671
7327
  let activeCategories;
7672
7328
  if (options.allCategories) {
7673
7329
  activeCategories = [];
@@ -7676,95 +7332,223 @@ async function init(options) {
7676
7332
  } else {
7677
7333
  activeCategories = [...PRIMARY_CATEGORIES];
7678
7334
  }
7335
+ let depMatches = detectFromPackageJson(projectDir);
7679
7336
  if (activeCategories.length > 0) {
7680
- matches = filterMatchesByCategories(matches, activeCategories);
7337
+ depMatches = filterMatchesByCategories(depMatches, activeCategories);
7338
+ }
7339
+ const depSlugs = new Set(depMatches.map((m) => m.slug));
7340
+ if (depMatches.length > 0) {
7341
+ p3.log.info(
7342
+ `Found ${depMatches.length} matching your dependencies: ${depMatches.map((m) => pc4.cyan(m.registryEntry.name)).join(", ")}`
7343
+ );
7344
+ }
7345
+ if (!isInteractive) {
7346
+ return installEntries({
7347
+ projectDir,
7348
+ entries: depMatches.map((m) => m.registryEntry),
7349
+ options,
7350
+ agents: agents2,
7351
+ targetAgents: agents2
7352
+ });
7681
7353
  }
7682
- if (matches.length === 0) {
7683
- spin2.info("No matching entries in selected categories");
7684
- p3.log.message(pc4.dim("Try `llmstxt init --all-categories` to include all categories"));
7685
- p3.outro("No skills to install.");
7354
+ const selectedEntries = await browseAndSelect({ projectDir, depMatches, depSlugs });
7355
+ if (selectedEntries.length === 0) {
7356
+ p3.outro("No skills selected.");
7686
7357
  return;
7687
7358
  }
7688
- spin2.succeed(`Found ${matches.length} matching entries`);
7689
- if (options.dryRun) {
7690
- for (const match of matches) {
7691
- const already = isInstalled({ projectDir, slug: match.slug });
7692
- const status = already ? pc4.dim(" (already installed)") : "";
7693
- p3.log.message(` ${pc4.cyan(match.registryEntry.name)}${status}`);
7694
- }
7695
- p3.outro("Dry run \u2014 no files were written");
7359
+ const targetAgents = await pickAgents(projectDir);
7360
+ if (!targetAgents) {
7361
+ p3.cancel("Installation cancelled.");
7696
7362
  return;
7697
7363
  }
7698
- let selectedSlugs;
7699
- if (isInteractive) {
7700
- const byCategory = /* @__PURE__ */ new Map();
7701
- for (const match of matches) {
7702
- const cat = match.registryEntry.category;
7703
- const group = byCategory.get(cat) || [];
7704
- group.push(match);
7705
- byCategory.set(cat, group);
7706
- }
7707
- const options_list = [];
7708
- for (const [category, group] of byCategory) {
7709
- for (const match of group) {
7710
- const already = isInstalled({ projectDir, slug: match.slug });
7711
- options_list.push({
7712
- value: match.slug,
7713
- label: match.registryEntry.name,
7714
- hint: already ? "already installed" : `${category} \xB7 matched: ${match.matchedPackages.join(", ")}`
7715
- });
7716
- }
7717
- }
7718
- const selected = await p3.multiselect({
7719
- message: "Select skills to install:",
7720
- options: options_list,
7721
- initialValues: matches.filter((m) => !isInstalled({ projectDir, slug: m.slug })).map((m) => m.slug),
7722
- required: false
7364
+ const format = await pickFormat(selectedEntries, options);
7365
+ if (!format) {
7366
+ p3.cancel("Installation cancelled.");
7367
+ return;
7368
+ }
7369
+ return installEntries({
7370
+ projectDir,
7371
+ entries: selectedEntries,
7372
+ options: { ...options, full: format === "llms-full.txt" },
7373
+ agents: agents2,
7374
+ targetAgents
7375
+ });
7376
+ }
7377
+ async function browseAndSelect({
7378
+ projectDir,
7379
+ depMatches,
7380
+ depSlugs
7381
+ }) {
7382
+ const selectedEntries = [];
7383
+ while (true) {
7384
+ const action = await p3.select({
7385
+ message: selectedEntries.length === 0 ? "How would you like to find llms.txt documentation?" : `${selectedEntries.length} selected. Add more or install?`,
7386
+ options: [
7387
+ ...depMatches.length > 0 && selectedEntries.length === 0 ? [
7388
+ {
7389
+ value: "suggestions",
7390
+ label: `Suggested from dependencies (${depMatches.length} found)`,
7391
+ hint: depMatches.map((m) => m.registryEntry.name).join(", ")
7392
+ }
7393
+ ] : [],
7394
+ { value: "browse", label: "Browse by category" },
7395
+ { value: "search", label: "Search by name" },
7396
+ ...selectedEntries.length > 0 ? [{ value: "install", label: `Install ${selectedEntries.length} selected` }] : [],
7397
+ { value: "done", label: selectedEntries.length > 0 ? "Cancel" : "Exit" }
7398
+ ]
7723
7399
  });
7724
- if (p3.isCancel(selected)) {
7725
- p3.cancel("Installation cancelled.");
7726
- process.exitCode = 0;
7727
- return;
7400
+ if (p3.isCancel(action) || action === "done") {
7401
+ if (selectedEntries.length > 0) p3.cancel("Installation cancelled.");
7402
+ else p3.outro("No skills selected.");
7403
+ return [];
7728
7404
  }
7729
- selectedSlugs = new Set(selected);
7730
- if (selectedSlugs.size === 0) {
7731
- p3.outro("No skills selected.");
7732
- return;
7405
+ if (action === "install") break;
7406
+ let picked = [];
7407
+ if (action === "suggestions") {
7408
+ picked = await pickFromList(
7409
+ depMatches.map((m) => m.registryEntry),
7410
+ projectDir,
7411
+ depSlugs
7412
+ );
7413
+ } else if (action === "browse") {
7414
+ picked = await browseByCategory(projectDir, depSlugs);
7415
+ } else if (action === "search") {
7416
+ picked = await searchByName(projectDir, depSlugs);
7733
7417
  }
7734
- const shouldContinue = await p3.confirm({
7735
- message: `Install ${selectedSlugs.size} skill(s)?`
7736
- });
7737
- if (p3.isCancel(shouldContinue) || !shouldContinue) {
7738
- p3.cancel("Installation cancelled.");
7739
- process.exitCode = 0;
7740
- return;
7418
+ for (const entry of picked) {
7419
+ if (!selectedEntries.some((e) => e.slug === entry.slug)) {
7420
+ selectedEntries.push(entry);
7421
+ }
7741
7422
  }
7742
- } else {
7743
- selectedSlugs = new Set(
7744
- matches.filter((m) => !isInstalled({ projectDir, slug: m.slug })).map((m) => m.slug)
7745
- );
7746
- if (!process.stdin.isTTY) {
7747
- p3.log.message(pc4.dim("Non-interactive mode. Use -y to skip prompts."));
7423
+ }
7424
+ return selectedEntries;
7425
+ }
7426
+ async function browseByCategory(projectDir, depSlugs) {
7427
+ const allEntries = getAllEntries();
7428
+ const categoryMap = /* @__PURE__ */ new Map();
7429
+ for (const entry of allEntries) {
7430
+ categoryMap.set(entry.category, (categoryMap.get(entry.category) || 0) + 1);
7431
+ }
7432
+ const categoryChoice = await p3.select({
7433
+ message: "Select a category:",
7434
+ options: [...categoryMap.entries()].sort((a, b) => b[1] - a[1]).map(([cat, count]) => ({
7435
+ value: cat,
7436
+ label: cat,
7437
+ hint: `${count} entries`
7438
+ }))
7439
+ });
7440
+ if (p3.isCancel(categoryChoice)) return [];
7441
+ const categoryEntries = allEntries.filter((e) => e.category === categoryChoice);
7442
+ return pickFromList(categoryEntries, projectDir, depSlugs);
7443
+ }
7444
+ async function searchByName(projectDir, depSlugs) {
7445
+ const query = await p3.text({
7446
+ message: "Search for:",
7447
+ placeholder: "e.g. react, stripe, prisma..."
7448
+ });
7449
+ if (p3.isCancel(query) || !query) return [];
7450
+ const results = searchRegistry(query).slice(0, 20);
7451
+ if (results.length === 0) {
7452
+ p3.log.warn(`No results for "${query}"`);
7453
+ return [];
7454
+ }
7455
+ return pickFromList(results, projectDir, depSlugs);
7456
+ }
7457
+ async function pickFromList(entries2, projectDir, depSlugs) {
7458
+ const optionsList = entries2.map((entry) => {
7459
+ const already = isInstalled({ projectDir, slug: entry.slug });
7460
+ const isDep = depSlugs.has(entry.slug);
7461
+ const hints = [];
7462
+ if (already) hints.push("installed");
7463
+ if (isDep) hints.push("in your deps");
7464
+ hints.push(entry.category);
7465
+ return {
7466
+ value: entry.slug,
7467
+ label: entry.name,
7468
+ hint: hints.join(" \xB7 ")
7469
+ };
7470
+ });
7471
+ const selected = await p3.multiselect({
7472
+ message: `Select entries (${entries2.length} available):`,
7473
+ options: optionsList,
7474
+ required: false
7475
+ });
7476
+ if (p3.isCancel(selected)) return [];
7477
+ const slugSet = new Set(selected);
7478
+ return entries2.filter((e) => slugSet.has(e.slug));
7479
+ }
7480
+ async function pickFormat(entries2, options) {
7481
+ if (options.full) return "llms-full.txt";
7482
+ const hasFullAvailable = entries2.some((e) => e.llmsFullTxtUrl);
7483
+ if (!hasFullAvailable) return "llms.txt";
7484
+ const fullCount = entries2.filter((e) => e.llmsFullTxtUrl).length;
7485
+ const choice = await p3.select({
7486
+ message: "Which documentation format?",
7487
+ options: [
7488
+ {
7489
+ value: "llms.txt",
7490
+ label: "llms.txt",
7491
+ hint: "concise \u2014 smaller, faster to load"
7492
+ },
7493
+ {
7494
+ value: "llms-full.txt",
7495
+ label: "llms-full.txt",
7496
+ hint: `comprehensive \u2014 ${fullCount}/${entries2.length} selected have full version`
7497
+ }
7498
+ ]
7499
+ });
7500
+ if (p3.isCancel(choice)) return null;
7501
+ return choice;
7502
+ }
7503
+ async function pickAgents(projectDir) {
7504
+ const savedPrefs = loadSavedAgentPrefs(projectDir);
7505
+ const initialValues = getInitialAgents({ allAgents: agents, savedPrefs, projectDir });
7506
+ const selected = await p3.multiselect({
7507
+ message: "Which agents should receive the skills?",
7508
+ options: agents.map((a) => ({
7509
+ value: a.name,
7510
+ label: a.displayName,
7511
+ hint: a.isUniversal ? "always included" : a.skillsDir
7512
+ })),
7513
+ initialValues,
7514
+ required: true
7515
+ });
7516
+ if (p3.isCancel(selected)) return null;
7517
+ const finalNames = ensureUniversalAgents({ selected, allAgents: agents });
7518
+ saveAgentPrefs(projectDir, selected);
7519
+ const nameSet = new Set(finalNames);
7520
+ return agents.filter((a) => nameSet.has(a.name));
7521
+ }
7522
+ async function installEntries({
7523
+ projectDir,
7524
+ entries: entries2,
7525
+ options,
7526
+ agents: agents2,
7527
+ targetAgents
7528
+ }) {
7529
+ if (options.dryRun) {
7530
+ for (const entry of entries2) {
7531
+ const already = isInstalled({ projectDir, slug: entry.slug });
7532
+ const status = already ? pc4.dim(" (already installed)") : "";
7533
+ p3.log.message(` ${pc4.cyan(entry.name)}${status}`);
7748
7534
  }
7535
+ p3.outro("Dry run \u2014 no files were written");
7536
+ return;
7749
7537
  }
7750
7538
  const format = options.full ? "llms-full.txt" : "llms.txt";
7751
7539
  let installed = 0;
7752
7540
  let skipped = 0;
7753
7541
  let failed = 0;
7754
7542
  const installedSlugs = [];
7755
- for (const match of matches) {
7756
- if (!selectedSlugs.has(match.slug)) {
7757
- continue;
7758
- }
7759
- const entry = match.registryEntry;
7543
+ for (const entry of entries2) {
7760
7544
  const actualFormat = format === "llms-full.txt" && entry.llmsFullTxtUrl ? "llms-full.txt" : "llms.txt";
7761
7545
  const url = actualFormat === "llms-full.txt" ? entry.llmsFullTxtUrl : entry.llmsTxtUrl;
7762
- if (isInstalled({ projectDir, slug: match.slug })) {
7546
+ if (isInstalled({ projectDir, slug: entry.slug })) {
7763
7547
  skipped++;
7764
7548
  continue;
7765
7549
  }
7766
- const spin3 = spinner2(`Fetching ${entry.name}...`);
7767
- spin3.start();
7550
+ const spin = spinner2(`Fetching ${entry.name}...`);
7551
+ spin.start();
7768
7552
  try {
7769
7553
  const result = await fetchLlmsTxt({ url });
7770
7554
  const {
@@ -7773,15 +7557,16 @@ async function init(options) {
7773
7557
  agents: installedTo
7774
7558
  } = installToAgents({
7775
7559
  projectDir,
7776
- slug: match.slug,
7560
+ slug: entry.slug,
7777
7561
  entry,
7778
7562
  content: result.content,
7779
- format: actualFormat
7563
+ format: actualFormat,
7564
+ targetAgents
7780
7565
  });
7781
7566
  addEntry({
7782
7567
  projectDir,
7783
7568
  entry: {
7784
- slug: match.slug,
7569
+ slug: entry.slug,
7785
7570
  format: actualFormat,
7786
7571
  sourceUrl: url,
7787
7572
  etag: result.etag,
@@ -7792,12 +7577,12 @@ async function init(options) {
7792
7577
  name: entry.name
7793
7578
  }
7794
7579
  });
7795
- spin3.succeed(`${entry.name} ${pc4.dim(`\u2192 ${installedTo.join(", ")}`)}`);
7580
+ spin.succeed(`${entry.name} ${pc4.dim(`\u2192 ${installedTo.join(", ")}`)}`);
7796
7581
  installed++;
7797
- installedSlugs.push(match.slug);
7582
+ installedSlugs.push(entry.slug);
7798
7583
  } catch (err) {
7799
7584
  const msg = err instanceof Error ? err.message : String(err);
7800
- spin3.fail(`${entry.name}: ${msg}`);
7585
+ spin.fail(`${entry.name}: ${msg}`);
7801
7586
  failed++;
7802
7587
  }
7803
7588
  }
@@ -7809,7 +7594,7 @@ async function init(options) {
7809
7594
  p3.note(summaryLines.join("\n"), "Summary");
7810
7595
  }
7811
7596
  if (addToGitignore(projectDir)) {
7812
- p3.log.success("Added .llms/ and .agents/skills/ to .gitignore");
7597
+ p3.log.success("Added skill directories to .gitignore");
7813
7598
  }
7814
7599
  if (installed > 0) {
7815
7600
  syncClaudeMd(projectDir);
@@ -7839,8 +7624,34 @@ async function install({ names, options }) {
7839
7624
  await loadRegistry();
7840
7625
  spin.succeed("Registry loaded");
7841
7626
  const agents2 = detectInstalledAgents();
7842
- if (agents2.length > 0) {
7843
- p4.log.message(pc5.dim(`Detected: ${agents2.map((a) => a.displayName).join(", ")}`));
7627
+ let targetAgents;
7628
+ if (!process.stdin.isTTY) {
7629
+ targetAgents = agents2;
7630
+ if (agents2.length > 0) {
7631
+ const display = agents2.map((a) => a.displayName).join(", ");
7632
+ p4.log.message(pc5.dim(`Installing to: ${display}`));
7633
+ }
7634
+ } else {
7635
+ const savedPrefs = loadSavedAgentPrefs(projectDir);
7636
+ const initialValues = getInitialAgents({ allAgents: agents, savedPrefs, projectDir });
7637
+ const selected = await p4.multiselect({
7638
+ message: "Which agents should receive the skills?",
7639
+ options: agents.map((a) => ({
7640
+ value: a.name,
7641
+ label: a.displayName,
7642
+ hint: a.isUniversal ? "always included" : a.skillsDir
7643
+ })),
7644
+ initialValues,
7645
+ required: true
7646
+ });
7647
+ if (p4.isCancel(selected)) {
7648
+ p4.cancel("Installation cancelled.");
7649
+ return;
7650
+ }
7651
+ const finalNames = ensureUniversalAgents({ selected, allAgents: agents });
7652
+ saveAgentPrefs(projectDir, selected);
7653
+ const nameSet = new Set(finalNames);
7654
+ targetAgents = agents.filter((a) => nameSet.has(a.name));
7844
7655
  }
7845
7656
  let installed = 0;
7846
7657
  let failed = 0;
@@ -7893,7 +7704,14 @@ async function install({ names, options }) {
7893
7704
  checksum,
7894
7705
  size,
7895
7706
  agents: installedTo
7896
- } = installToAgents({ projectDir, slug: entry.slug, entry, content: result.content, format });
7707
+ } = installToAgents({
7708
+ projectDir,
7709
+ slug: entry.slug,
7710
+ entry,
7711
+ content: result.content,
7712
+ format,
7713
+ targetAgents
7714
+ });
7897
7715
  addEntry({
7898
7716
  projectDir,
7899
7717
  entry: {
@@ -8149,8 +7967,8 @@ async function update(name, options) {
8149
7967
 
8150
7968
  // src/index.ts
8151
7969
  var program = new Command();
8152
- program.name("llmstxt").description("Install llms.txt files from the llms-txt-hub registry into your AI coding tools").version("0.1.0").action(() => {
8153
- printBanner("0.1.0");
7970
+ program.name("llmstxt").description("Install llms.txt files from the llms-txt-hub registry into your AI coding tools").version("0.3.0").action(() => {
7971
+ printBanner("0.3.0");
8154
7972
  program.outputHelp();
8155
7973
  });
8156
7974
  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);