agentshq 0.1.0 → 0.1.3

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 (2) hide show
  1. package/dist/cli.mjs +76 -38
  2. package/package.json +48 -10
package/dist/cli.mjs CHANGED
@@ -22,36 +22,57 @@ import { createHash } from "crypto";
22
22
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
23
23
  const AGENTS_DIR$1 = ".agents";
24
24
  const AGENTS_SUBDIR = "agents";
25
- /** Base URL for the agents website/API. Override with AGENTS_BASE_URL env var. */
25
+ /** Base URL for the agents website (display links). Override with AGENTS_BASE_URL env var. */
26
26
  const BASE_URL = process.env.AGENTS_BASE_URL || "https://agentshq.sh";
27
+ /** Base URL for API requests. Override with AGENTS_API_URL env var. */
28
+ const API_URL = process.env.AGENTS_API_URL || "https://api.agentshq.sh";
27
29
  /** Default repo for agent definitions */
28
30
  const DEFAULT_REPO = "ulpi-io/agents";
29
31
  //#endregion
30
32
  //#region src/source-parser.ts
31
33
  /**
32
- * Extract owner/repo (or group/subgroup/repo for GitLab) from a parsed source
34
+ * Extract host/owner/repo (e.g., "github.com/ulpi-io/agents") from a parsed source
33
35
  * for lockfile tracking and telemetry.
34
36
  * Returns null for local paths or unparseable sources.
35
- * Supports any Git host with an owner/repo URL structure, including GitLab subgroups.
37
+ * The host is derived from the parsed source type:
38
+ * - github → github.com
39
+ * - gitlab → gitlab.com (or the actual host for self-hosted instances)
40
+ * - git → extracted from URL
41
+ * Bare owner/repo CLI input defaults to github.com.
36
42
  */
37
43
  function getOwnerRepo(parsed) {
38
44
  if (parsed.type === "local") return null;
39
- const sshMatch = parsed.url.match(/^git@[^:]+:(.+)$/);
45
+ const sshMatch = parsed.url.match(/^git@([^:]+):(.+)$/);
40
46
  if (sshMatch) {
41
- let path = sshMatch[1];
47
+ const host = sshMatch[1];
48
+ let path = sshMatch[2];
42
49
  path = path.replace(/\.git$/, "");
43
- if (path.includes("/")) return path;
50
+ if (path.includes("/")) return `${host}/${path}`;
44
51
  return null;
45
52
  }
46
53
  if (!parsed.url.startsWith("http://") && !parsed.url.startsWith("https://")) return null;
47
54
  try {
48
- let path = new URL(parsed.url).pathname.slice(1);
55
+ const url = new URL(parsed.url);
56
+ const host = url.hostname;
57
+ let path = url.pathname.slice(1);
49
58
  path = path.replace(/\.git$/, "");
50
- if (path.includes("/")) return path;
59
+ if (path.includes("/")) return `${host}/${path}`;
51
60
  } catch {}
52
61
  return null;
53
62
  }
54
63
  /**
64
+ * Strip the host prefix from a host/owner/repo string to get bare owner/repo.
65
+ * Returns null if the input doesn't have at least 3 segments (host/owner/repo).
66
+ * For GitLab subgroups, returns the full path after the host (e.g., "group/subgroup/repo").
67
+ */
68
+ function stripHost(hostOwnerRepo) {
69
+ const slashIndex = hostOwnerRepo.indexOf("/");
70
+ if (slashIndex === -1) return null;
71
+ const rest = hostOwnerRepo.slice(slashIndex + 1);
72
+ if (!rest.includes("/")) return null;
73
+ return rest;
74
+ }
75
+ /**
55
76
  * Extract owner and repo from an owner/repo string.
56
77
  * Returns null if the format is invalid.
57
78
  */
@@ -629,9 +650,9 @@ function detectFormat(filePath) {
629
650
  function parseFromFlatMd(content, filePath) {
630
651
  try {
631
652
  const { data, content: body } = (0, import_gray_matter.default)(content);
632
- const name = typeof data.name === "string" && data.name.length > 0 ? data.name : basename(filePath, ".md");
653
+ const name = typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
633
654
  const description = typeof data.description === "string" && data.description.length > 0 ? data.description : void 0;
634
- if (!name && !description) return null;
655
+ if (!name) return null;
635
656
  return {
636
657
  name,
637
658
  description: description ?? "",
@@ -999,26 +1020,36 @@ async function discoverAgents(basePath, subpath, options) {
999
1020
  join(searchPath, "agents/.system"),
1000
1021
  join(searchPath, ".agent/agents"),
1001
1022
  join(searchPath, ".agents/agents"),
1023
+ join(searchPath, ".augment/agents"),
1002
1024
  join(searchPath, ".claude/agents"),
1003
1025
  join(searchPath, ".cline/agents"),
1004
1026
  join(searchPath, ".codebuddy/agents"),
1005
1027
  join(searchPath, ".codex/agents"),
1006
1028
  join(searchPath, ".commandcode/agents"),
1007
1029
  join(searchPath, ".continue/agents"),
1030
+ join(searchPath, ".cortex/agents"),
1031
+ join(searchPath, ".crush/agents"),
1032
+ join(searchPath, ".factory/agents"),
1033
+ join(searchPath, ".gemini/agents"),
1008
1034
  join(searchPath, ".github/agents"),
1009
1035
  join(searchPath, ".goose/agents"),
1010
1036
  join(searchPath, ".iflow/agents"),
1011
1037
  join(searchPath, ".junie/agents"),
1012
1038
  join(searchPath, ".kilocode/agents"),
1013
1039
  join(searchPath, ".kiro/agents"),
1040
+ join(searchPath, ".kode/agents"),
1041
+ join(searchPath, ".mcpjam/agents"),
1014
1042
  join(searchPath, ".mux/agents"),
1015
1043
  join(searchPath, ".neovate/agents"),
1016
1044
  join(searchPath, ".opencode/agents"),
1017
1045
  join(searchPath, ".openhands/agents"),
1018
1046
  join(searchPath, ".pi/agents"),
1047
+ join(searchPath, ".pochi/agents"),
1019
1048
  join(searchPath, ".qoder/agents"),
1049
+ join(searchPath, ".qwen/agents"),
1020
1050
  join(searchPath, ".roo/agents"),
1021
1051
  join(searchPath, ".trae/agents"),
1052
+ join(searchPath, ".vibe/agents"),
1022
1053
  join(searchPath, ".windsurf/agents"),
1023
1054
  join(searchPath, ".zencoder/agents")
1024
1055
  ];
@@ -2632,8 +2663,8 @@ async function listInstalledAgents(options = {}) {
2632
2663
  }
2633
2664
  //#endregion
2634
2665
  //#region src/telemetry.ts
2635
- const TELEMETRY_URL = `${BASE_URL}/t`;
2636
- const AUDIT_URL = `${BASE_URL}/audit`;
2666
+ const TELEMETRY_URL = `${API_URL}/t`;
2667
+ const AUDIT_URL = `${API_URL}/audit`;
2637
2668
  let cliVersion = null;
2638
2669
  function isCI() {
2639
2670
  return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.CIRCLECI || process.env.TRAVIS || process.env.BUILDKITE || process.env.JENKINS_URL || process.env.TEAMCITY_VERSION);
@@ -2914,7 +2945,7 @@ var WellKnownProvider = class {
2914
2945
  const wellKnownProvider = new WellKnownProvider();
2915
2946
  //#endregion
2916
2947
  //#region package.json
2917
- var version$1 = "0.1.0";
2948
+ var version$1 = "0.1.3";
2918
2949
  //#endregion
2919
2950
  //#region src/add.ts
2920
2951
  const isCancelled$1 = (value) => typeof value === "symbol";
@@ -3131,8 +3162,9 @@ async function handleWellKnownAgents(source, url, options, spinner) {
3131
3162
  options: agentDefs.map((s) => ({
3132
3163
  value: s,
3133
3164
  label: s.installName,
3134
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3165
+ hint: s.description
3135
3166
  })),
3167
+ initialValues: agentDefs,
3136
3168
  required: true
3137
3169
  });
3138
3170
  if (pD(selected)) {
@@ -3262,7 +3294,7 @@ async function handleWellKnownAgents(source, url, options, spinner) {
3262
3294
  if (await isSourcePrivate(sourceIdentifier) !== true) track({
3263
3295
  event: "install",
3264
3296
  source: sourceIdentifier,
3265
- agents: targetIdes.join(","),
3297
+ agents: selectedAgents.map((s) => s.installName).join(","),
3266
3298
  ...installGlobally && { global: "1" },
3267
3299
  agentFiles: JSON.stringify(agentFiles),
3268
3300
  sourceType: "well-known"
@@ -3477,7 +3509,7 @@ async function runAdd(args, options = {}) {
3477
3509
  grouped[groupName].push({
3478
3510
  value: s,
3479
3511
  label: getAgentDisplayName(s),
3480
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3512
+ hint: s.description
3481
3513
  });
3482
3514
  }
3483
3515
  selected = await be({
@@ -3490,8 +3522,9 @@ async function runAdd(args, options = {}) {
3490
3522
  options: sortedAgents.map((s) => ({
3491
3523
  value: s,
3492
3524
  label: getAgentDisplayName(s),
3493
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3525
+ hint: s.description
3494
3526
  })),
3527
+ initialValues: sortedAgents,
3495
3528
  required: true
3496
3529
  });
3497
3530
  if (pD(selected)) {
@@ -3502,7 +3535,8 @@ async function runAdd(args, options = {}) {
3502
3535
  selectedAgents = selected;
3503
3536
  }
3504
3537
  const ownerRepoForAudit = getOwnerRepo(parsed);
3505
- const ownerRepoParsed = ownerRepoForAudit ? parseOwnerRepo(ownerRepoForAudit) : null;
3538
+ const bareOwnerRepo = ownerRepoForAudit ? stripHost(ownerRepoForAudit) : null;
3539
+ const ownerRepoParsed = bareOwnerRepo ? parseOwnerRepo(bareOwnerRepo) : null;
3506
3540
  const repoIsPrivate = ownerRepoParsed ? await isRepoPrivate(ownerRepoParsed.owner, ownerRepoParsed.repo) : null;
3507
3541
  const auditPromise = ownerRepoForAudit && repoIsPrivate === false ? fetchAuditData(ownerRepoForAudit, selectedAgents.map((s) => getAgentDisplayName(s))) : Promise.resolve(null);
3508
3542
  let targetIdes;
@@ -3667,11 +3701,12 @@ async function runAdd(args, options = {}) {
3667
3701
  agentFiles[agentDef.name] = relativePath;
3668
3702
  }
3669
3703
  const normalizedSource = getOwnerRepo(parsed);
3704
+ const bareNormalizedSource = normalizedSource ? stripHost(normalizedSource) : null;
3670
3705
  const lockSource = parsed.url.startsWith("git@") ? parsed.url : normalizedSource;
3671
3706
  if (normalizedSource && repoIsPrivate !== true) track({
3672
3707
  event: "install",
3673
3708
  source: normalizedSource,
3674
- agents: targetIdes.join(","),
3709
+ agents: selectedAgents.map((s) => getAgentDisplayName(s)).join(","),
3675
3710
  ...installGlobally && { global: "1" },
3676
3711
  agentFiles: JSON.stringify(agentFiles)
3677
3712
  });
@@ -3682,8 +3717,8 @@ async function runAdd(args, options = {}) {
3682
3717
  if (successfulAgentNames.has(agentDisplayName)) try {
3683
3718
  let agentFolderHash = "";
3684
3719
  const agentPathValue = agentFiles[agentDef.name];
3685
- if (parsed.type === "github" && agentPathValue) {
3686
- const hash = await fetchAgentFolderHash(normalizedSource, agentPathValue, getGitHubToken());
3720
+ if (parsed.type === "github" && agentPathValue && bareNormalizedSource) {
3721
+ const hash = await fetchAgentFolderHash(bareNormalizedSource, agentPathValue, getGitHubToken());
3687
3722
  if (hash) agentFolderHash = hash;
3688
3723
  }
3689
3724
  const installs = {};
@@ -3878,7 +3913,7 @@ const BOLD$2 = "\x1B[1m";
3878
3913
  const DIM$2 = "\x1B[38;5;102m";
3879
3914
  const TEXT$1 = "\x1B[38;5;145m";
3880
3915
  const CYAN$1 = "\x1B[36m";
3881
- const SEARCH_API_BASE = process.env.AGENTS_API_URL || BASE_URL;
3916
+ const SEARCH_API_BASE = API_URL;
3882
3917
  function formatInstalls(count) {
3883
3918
  if (!count || count <= 0) return "";
3884
3919
  if (count >= 1e6) return `${(count / 1e6).toFixed(1).replace(/\.0$/, "")}M installs`;
@@ -5105,26 +5140,29 @@ async function runCheck(args = []) {
5105
5140
  console.log(`${DIM}Checking ${totalAgents} agent(s) for updates...${RESET}`);
5106
5141
  const updates = [];
5107
5142
  const errors = [];
5108
- for (const [source, agents] of agentsBySource) for (const { name, entry } of agents) try {
5109
- const latestHash = await fetchAgentFolderHash(source, entry.agentPath, token);
5110
- if (!latestHash) {
5143
+ for (const [source, agents] of agentsBySource) {
5144
+ const bareSource = stripHost(source) ?? source;
5145
+ for (const { name, entry } of agents) try {
5146
+ const latestHash = await fetchAgentFolderHash(bareSource, entry.agentPath, token);
5147
+ if (!latestHash) {
5148
+ errors.push({
5149
+ name,
5150
+ source,
5151
+ error: "Could not fetch from GitHub"
5152
+ });
5153
+ continue;
5154
+ }
5155
+ if (latestHash !== entry.agentFolderHash) updates.push({
5156
+ name,
5157
+ source
5158
+ });
5159
+ } catch (err) {
5111
5160
  errors.push({
5112
5161
  name,
5113
5162
  source,
5114
- error: "Could not fetch from GitHub"
5163
+ error: err instanceof Error ? err.message : "Unknown error"
5115
5164
  });
5116
- continue;
5117
5165
  }
5118
- if (latestHash !== entry.agentFolderHash) updates.push({
5119
- name,
5120
- source
5121
- });
5122
- } catch (err) {
5123
- errors.push({
5124
- name,
5125
- source,
5126
- error: err instanceof Error ? err.message : "Unknown error"
5127
- });
5128
5166
  }
5129
5167
  console.log();
5130
5168
  if (updates.length === 0) console.log(`${TEXT}✓ All agents are up to date${RESET}`);
@@ -5175,7 +5213,7 @@ async function runUpdate() {
5175
5213
  continue;
5176
5214
  }
5177
5215
  try {
5178
- const latestHash = await fetchAgentFolderHash(entry.source, entry.agentPath, token);
5216
+ const latestHash = await fetchAgentFolderHash(stripHost(entry.source) ?? entry.source, entry.agentPath, token);
5179
5217
  if (latestHash && latestHash !== entry.agentFolderHash) updates.push({
5180
5218
  name: agentName,
5181
5219
  source: entry.source,
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "agentshq",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "The package manager for AI coding agents. Discover, install, and manage agent definitions across 43+ IDEs.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "agentshq": "./bin/cli.mjs",
8
- "add-agent": "./bin/cli.mjs"
7
+ "agentshq": "bin/cli.mjs",
8
+ "add-agent": "bin/cli.mjs"
9
9
  },
10
10
  "files": [
11
11
  "dist",
@@ -22,13 +22,51 @@
22
22
  "type-check": "tsc --noEmit"
23
23
  },
24
24
  "keywords": [
25
- "cli", "agent-definitions", "agents", "ai-agents", "amp", "antigravity", "augment",
26
- "claude-code", "openclaw", "cline", "codebuddy", "codex", "command-code",
27
- "continue", "cortex", "crush", "cursor", "droid", "gemini-cli",
28
- "github-copilot", "goose", "junie", "iflow-cli", "kilo", "kimi-cli",
29
- "kiro-cli", "kode", "mcpjam", "mistral-vibe", "mux", "opencode",
30
- "openhands", "pi", "qoder", "qwen-code", "replit", "roo", "trae",
31
- "trae-cn", "warp", "windsurf", "zencoder", "neovate", "pochi", "adal",
25
+ "cli",
26
+ "agent-definitions",
27
+ "agents",
28
+ "ai-agents",
29
+ "amp",
30
+ "antigravity",
31
+ "augment",
32
+ "claude-code",
33
+ "openclaw",
34
+ "cline",
35
+ "codebuddy",
36
+ "codex",
37
+ "command-code",
38
+ "continue",
39
+ "cortex",
40
+ "crush",
41
+ "cursor",
42
+ "droid",
43
+ "gemini-cli",
44
+ "github-copilot",
45
+ "goose",
46
+ "junie",
47
+ "iflow-cli",
48
+ "kilo",
49
+ "kimi-cli",
50
+ "kiro-cli",
51
+ "kode",
52
+ "mcpjam",
53
+ "mistral-vibe",
54
+ "mux",
55
+ "opencode",
56
+ "openhands",
57
+ "pi",
58
+ "qoder",
59
+ "qwen-code",
60
+ "replit",
61
+ "roo",
62
+ "trae",
63
+ "trae-cn",
64
+ "warp",
65
+ "windsurf",
66
+ "zencoder",
67
+ "neovate",
68
+ "pochi",
69
+ "adal",
32
70
  "universal"
33
71
  ],
34
72
  "repository": {