yarkr-cli 1.0.1 → 1.0.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 (3) hide show
  1. package/README.md +2 -1
  2. package/dist/yarkr.js +75 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -16,7 +16,8 @@ harness's own layout (`~/.claude/skills/…`, `~/.agents/…`, MCP configs and s
16
16
 
17
17
  ```sh
18
18
  yarkr arks # list public arks
19
- yarkr sync acme/starter # install one into your home directory
19
+ yarkr sync acme/starter # install one into this folder
20
+ yarkr sync acme/starter -g # …or into your home directory
20
21
  yarkr sync acme/starter --harness claude-code # only write Claude Code's files
21
22
  yarkr ark # what your arks give you, and which version
22
23
  ```
package/dist/yarkr.js CHANGED
@@ -39519,6 +39519,25 @@ var ConnectRepoBody = external_exports.object({
39519
39519
  classification: Classification.optional(),
39520
39520
  root_path: external_exports.string().max(200).optional()
39521
39521
  });
39522
+ var AddRepoBody = external_exports.object({
39523
+ /** `owner/repo` or a github.com URL. */
39524
+ repo: external_exports.string().trim().min(3).max(300),
39525
+ /** Only index below this folder, e.g. `skills` to skip a repo's templates and examples. */
39526
+ root_path: external_exports.string().max(200).optional()
39527
+ });
39528
+ var BulkAddReposBody = external_exports.object({
39529
+ /** `owner/repo` or github.com URLs; duplicates are added once. */
39530
+ repos: external_exports.array(external_exports.string().trim().min(1).max(300)).min(1).max(100),
39531
+ /** Applied to every repo added. */
39532
+ root_path: external_exports.string().max(200).optional()
39533
+ });
39534
+ var BanRepoBody = external_exports.object({ reason: external_exports.string().trim().min(1).max(500) });
39535
+ var IndexJobQuery = external_exports.object({
39536
+ status: external_exports.enum(["active", "queued", "running", "error", "done", "all"]).default("active"),
39537
+ /** Part of the repo's `owner/repo`, any case. */
39538
+ repo: external_exports.string().trim().max(200).optional(),
39539
+ limit: external_exports.coerce.number().int().min(1).max(500).default(200)
39540
+ });
39522
39541
  var AuditQuery = external_exports.object({
39523
39542
  package: external_exports.string().optional(),
39524
39543
  /** `me`: only what you did yourself. Anyone may read their own events. */
@@ -41349,13 +41368,23 @@ async function detectAssets(input2) {
41349
41368
  const byName = /* @__PURE__ */ new Map();
41350
41369
  for (const a of found.sort((x, y) => x.path.localeCompare(y.path))) {
41351
41370
  const prev = byName.get(a.name);
41352
- if (prev)
41353
- problems.push({ path: a.path, message: `Another asset is already named "${a.name}" (${prev.path}). Rename one of them in its frontmatter.` });
41354
- else
41371
+ if (!prev)
41355
41372
  byName.set(a.name, a);
41373
+ else if (!await sameFiles(prev, a, input2.read))
41374
+ problems.push({ path: a.path, message: `Another asset is already named "${a.name}" (${prev.path}) and its files differ. Rename one of them in its frontmatter, or make the copies identical.` });
41356
41375
  }
41357
41376
  return { assets: [...byName.values()], problems };
41358
41377
  }
41378
+ async function sameFiles(a, b, read) {
41379
+ if (a.kind !== b.kind || a.files.size !== b.files.size)
41380
+ return false;
41381
+ for (const [pkgPath, repoPath] of a.files) {
41382
+ const other = b.files.get(pkgPath);
41383
+ if (other === void 0 || await read(repoPath) !== await read(other))
41384
+ return false;
41385
+ }
41386
+ return true;
41387
+ }
41359
41388
  function toolsetServers2(text, path18, problems) {
41360
41389
  let doc;
41361
41390
  try {
@@ -41811,18 +41840,20 @@ async function context(flags = {}) {
41811
41840
  const cwd = process.cwd();
41812
41841
  const conn = await resolveConnection({ dir: cwd, registry: flags.registry });
41813
41842
  const api = new Api(conn);
41814
- const project = flags.user ? null : await loadProjectConfig(cwd, { required: false });
41815
- if (project) return { dir: cwd, config: project, conn, api, lock: await loadLock(cwd), userMode: false };
41816
- const dir = userStateDir();
41843
+ const userMode = !!(flags.global || flags.user);
41844
+ const dir = userMode ? userStateDir() : cwd;
41817
41845
  let config2 = await loadProjectConfig(dir, { required: false });
41818
41846
  if (!config2) {
41819
- const detected2 = detectHarnesses2(os5.homedir());
41820
- config2 = { channel: "stable", scope: "user", harnesses: detected2.length ? detected2 : ["claude-code"], packages: {}, arks: "auto" };
41821
- await mkdir3(dir, { recursive: true });
41822
- await saveProjectConfig(dir, config2);
41823
- ui.info(`No ${CONFIG_FILE} here, so yarkr installs your arks into your home directory (${config2.harnesses.join(", ")}). Settings: ${path5.join(dir, CONFIG_FILE)}.`);
41847
+ const detected2 = detectHarnesses2(userMode ? os5.homedir() : cwd);
41848
+ config2 = { channel: "stable", scope: userMode ? "user" : "project", harnesses: detected2.length ? detected2 : ["claude-code"], packages: {}, arks: "auto" };
41849
+ if (!flags.dryRun && !flags.check && !flags.readOnly) {
41850
+ await mkdir3(dir, { recursive: true });
41851
+ await saveProjectConfig(dir, config2);
41852
+ if (userMode) ui.info(`Installing your arks into your home directory (${config2.harnesses.join(", ")}). Settings: ${path5.join(dir, CONFIG_FILE)}.`);
41853
+ else ui.info(`Created ${CONFIG_FILE} here for ${config2.harnesses.join(", ")}. Use -g to install into your home directory instead.`);
41854
+ }
41824
41855
  }
41825
- return { dir, config: config2, conn, api, lock: await loadLock(dir), userMode: true };
41856
+ return { dir, config: config2, conn, api, lock: await loadLock(dir), userMode };
41826
41857
  }
41827
41858
  async function sync(flags, update2, arkRefs = []) {
41828
41859
  const { dir, config: config2, conn, api, lock, userMode } = await context(flags);
@@ -42499,7 +42530,7 @@ async function mcpRemove(scopes, flags) {
42499
42530
  if (!flags.noSync) await sync(flags);
42500
42531
  }
42501
42532
  async function mcpList(flags) {
42502
- const { config: config2, conn } = await context(flags);
42533
+ const { config: config2, conn } = await context({ ...flags, readOnly: true });
42503
42534
  const rows = (config2.mcp ?? []).map((m) => connectionFor(conn.server, m));
42504
42535
  if (flags.json) return console.log(JSON.stringify(rows, null, 2));
42505
42536
  if (!rows.length) {
@@ -45038,14 +45069,39 @@ async function repoLint(dir, opts) {
45038
45069
  return { assets, findings };
45039
45070
  }
45040
45071
 
45072
+ // src/banner.ts
45073
+ var WEBSITE = "https://yarkr.com";
45074
+ var WORDMARK = [
45075
+ "\u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588",
45076
+ " \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588",
45077
+ " \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588",
45078
+ " \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588",
45079
+ " \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588"
45080
+ ];
45081
+ var rgb = (r, g, b) => (s) => kleur_default.enabled ? `\x1B[38;2;${r};${g};${b}m${s}\x1B[39m` : s;
45082
+ var petrol = rgb(74, 163, 191);
45083
+ function link(url2, text = url2) {
45084
+ return kleur_default.enabled ? `\x1B]8;;${url2}\x1B\\${text}\x1B]8;;\x1B\\` : text;
45085
+ }
45086
+ function banner(version2) {
45087
+ return [
45088
+ "",
45089
+ ...WORDMARK.map((l) => ` ${petrol(l)}`),
45090
+ "",
45091
+ ` ${kleur_default.bold("yarkr")} ${kleur_default.dim(`v${version2}`)} ${kleur_default.dim("\xB7")} skills, agents and MCP toolsets for every harness`,
45092
+ ` ${petrol("\u2192")} ${kleur_default.underline(petrol(link(WEBSITE)))}`,
45093
+ ""
45094
+ ].join("\n");
45095
+ }
45096
+
45041
45097
  // src/index.ts
45042
- var VERSION = true ? "1.0.1" : "0.0.0-dev";
45098
+ var VERSION = true ? "1.0.3" : "0.0.0-dev";
45043
45099
  var act = (fn) => async (...a) => {
45044
45100
  await fn(...a);
45045
45101
  };
45046
- var syncFlags = (c) => c.option("--harness <ids...>", `limit to some harnesses (${HARNESS_IDS.join(", ")})`).option("--dry-run", "show what would change; write nothing").option("--check", "exit 1 if anything is out of date (for CI)").option("--force", "overwrite files edited locally").option("--require-signatures", "refuse unsigned releases").option("--user", "use your arks and home directory even inside a project").option("--registry <url>", "registry to use (default: from .yarkrrc)");
45102
+ var syncFlags = (c) => c.option("--harness <ids...>", `limit to some harnesses (${HARNESS_IDS.join(", ")})`).option("--dry-run", "show what would change; write nothing").option("--check", "exit 1 if anything is out of date (for CI)").option("--force", "overwrite files edited locally").option("--require-signatures", "refuse unsigned releases").option("-g, --global", "install into your home directory instead of this folder").addOption(new Option("--user").hideHelp()).option("--registry <url>", "registry to use (default: from .yarkrrc)");
45047
45103
  function buildProgram() {
45048
- const program2 = new Command().name("yarkr").description("Yarkr: install your org's skills, agents and MCP configs into every harness.").version(VERSION).option("-q, --quiet", "only print warnings and errors").hook("preAction", (cmd) => {
45104
+ const program2 = new Command().name("yarkr").description("Yarkr: install your org's skills, agents and MCP configs into every harness.").version(VERSION).addHelpText("before", () => banner(VERSION)).option("-q, --quiet", "only print warnings and errors").hook("preAction", (cmd) => {
45049
45105
  ui.quiet = !!cmd.opts().quiet;
45050
45106
  });
45051
45107
  program2.command("login").description("sign in in the browser and keep a token in your keychain (or ~/.yarkrrc)").option("--registry <url>").option("--token <token>", "use this token instead of the browser (or pipe it on stdin)").option("--no-browser", "print a link to open on any device, then paste the token it shows").action(act(login));
@@ -45059,11 +45115,11 @@ function buildProgram() {
45059
45115
  program2.command("arks").description("list public arks: curated sets anyone can sync or connect over MCP").option("--json").action(act(publicArks));
45060
45116
  program2.command("lint").argument("[dir]", "a repo checkout", ".").description("check a repo is set up as a Yarkr source: what it publishes, problems the hub would refuse, and index typos or weak descriptions").option("--namespace <ns>", "namespace to show names in (default: the git owner)").option("--strict", "exit 1 on warnings too").option("--json").action(act(repoLint));
45061
45117
  program2.command("guide").argument("[name]", "a guide, e.g. create-ark; omit to list them").description("print instructions for your agent, e.g. how to build an ark for a topic").option("-o, --out <path>", "write to a file, or <dir>/SKILL.md for a directory (e.g. ~/.claude/skills/create-ark/)").option("--topic <topic>", "create-ark: what the ark is about").addOption(new Option("--type <type>", "create-ark: the kind of package it holds").choices(["skill", "agent", "mcp"])).action(act(guide));
45062
- syncFlags(program2.command("add").argument("<packages...>", "namespace/name[@range]").description("add packages to yarkr.json (outside a project: to your personal ark, or your user config when signed out) and sync").option("--no-sync", "only edit yarkr.json")).action(act((pkgs, o) => add(pkgs, { ...o, noSync: o.sync === false })));
45118
+ syncFlags(program2.command("add").argument("<packages...>", "namespace/name[@range]").description("add packages to yarkr.json (with -g: to your personal ark, or your user config when signed out) and sync").option("--no-sync", "only edit yarkr.json")).action(act((pkgs, o) => add(pkgs, { ...o, noSync: o.sync === false })));
45063
45119
  syncFlags(program2.command("remove").argument("<packages...>", "packages, or arks listed in yarkr.json").description("remove packages or arks (or opt out of optional ark items) and delete their files").option("--no-sync", "only edit yarkr.json")).action(act((pkgs, o) => remove(pkgs, { ...o, noSync: o.sync === false })));
45064
45120
  syncFlags(program2.command("update").argument("[packages...]").description("move packages to the newest release their range allows")).action(act((pkgs, o) => update(pkgs, o)));
45065
45121
  syncFlags(
45066
- program2.command("sync").argument("[arks...]", "arks to add first: <org>/<ark>, yours or another org's public ark (which needs no sign-in)").description("install locked releases into each harness's native layout (outside a project: your arks, into your home directory)")
45122
+ program2.command("sync").argument("[arks...]", "arks to add first: <org>/<ark>, yours or another org's public ark (which needs no sign-in)").description("install locked releases into each harness's native layout in this folder (with -g: your home directory)")
45067
45123
  ).action(act((refs, o) => sync(o, void 0, refs)));
45068
45124
  program2.command("yank").argument("<release>", "namespace/name@version").description("yank a release (org admins): ranges and stable skip it, exact pins still install it").option("--reason <text>", "why, shown to everyone who installed it").option("--undo", "un-yank it").action(act(yank));
45069
45125
  program2.command("diff").argument("[package]").description("show local edits to synced files").option("--name-only").action(act(diff));
@@ -45086,7 +45142,7 @@ function buildProgram() {
45086
45142
  act((scopes, o) => mcpAdd(scopes, { ...o, noSync: o.sync === false }))
45087
45143
  );
45088
45144
  mcpFlags(mcp.command("remove").argument("<scopes...>").description("remove MCP connections from every harness")).action(act((scopes, o) => mcpRemove(scopes, { ...o, noSync: o.sync === false })));
45089
- mcp.command("list").description("show configured MCP connections").option("--user", "your user config even inside a project").option("--json").action(act((o) => mcpList(o)));
45145
+ mcp.command("list").description("show configured MCP connections").option("-g, --global", "your user config instead of this folder's").addOption(new Option("--user").hideHelp()).option("--json").action(act((o) => mcpList(o)));
45090
45146
  program2.command("mcp-config").argument("<harness>", HARNESS_IDS.join(" | ")).description("print the config that connects a harness to Yarkr's MCP server").option("--token-env <name>", "environment variable holding the token", "YARKR_TOKEN").option("--registry <url>").action(act(mcpConfig));
45091
45147
  return program2;
45092
45148
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yarkr-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Install skills, agents and MCP toolsets from Yarkr into Claude Code, Codex, opencode, Cursor and more",
5
5
  "license": "MIT",
6
6
  "homepage": "https://yarkr.com",