@deeplake/hivemind 0.7.16 → 0.7.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle/cli.js CHANGED
@@ -3352,7 +3352,8 @@ var EXTENSION_PATH = join8(EXTENSIONS_DIR, "hivemind.ts");
3352
3352
  var VERSION_DIR = join8(PI_AGENT_DIR, ".hivemind");
3353
3353
  var WIKI_WORKER_DIR = join8(PI_AGENT_DIR, "hivemind");
3354
3354
  var WIKI_WORKER_PATH = join8(WIKI_WORKER_DIR, "wiki-worker.js");
3355
- var SKILIFY_WORKER_PATH = join8(WIKI_WORKER_DIR, "skilify-worker.js");
3355
+ var SKILLIFY_WORKER_PATH = join8(WIKI_WORKER_DIR, "skillify-worker.js");
3356
+ var AUTOPULL_WORKER_PATH = join8(WIKI_WORKER_DIR, "autopull-worker.js");
3356
3357
  var HIVEMIND_BLOCK_START = "<!-- BEGIN hivemind-memory -->";
3357
3358
  var HIVEMIND_BLOCK_END = "<!-- END hivemind-memory -->";
3358
3359
  var HIVEMIND_BLOCK_BODY = `${HIVEMIND_BLOCK_START}
@@ -3437,10 +3438,15 @@ function installPi() {
3437
3438
  ensureDir(WIKI_WORKER_DIR);
3438
3439
  copyFileSync2(srcWorker, WIKI_WORKER_PATH);
3439
3440
  }
3440
- const srcSkilifyWorker = join8(pkgRoot(), "pi", "bundle", "skilify-worker.js");
3441
- if (existsSync7(srcSkilifyWorker)) {
3441
+ const srcSkillifyWorker = join8(pkgRoot(), "pi", "bundle", "skillify-worker.js");
3442
+ if (existsSync7(srcSkillifyWorker)) {
3442
3443
  ensureDir(WIKI_WORKER_DIR);
3443
- copyFileSync2(srcSkilifyWorker, SKILIFY_WORKER_PATH);
3444
+ copyFileSync2(srcSkillifyWorker, SKILLIFY_WORKER_PATH);
3445
+ }
3446
+ const srcAutopullWorker = join8(pkgRoot(), "pi", "bundle", "autopull-worker.js");
3447
+ if (existsSync7(srcAutopullWorker)) {
3448
+ ensureDir(WIKI_WORKER_DIR);
3449
+ copyFileSync2(srcAutopullWorker, AUTOPULL_WORKER_PATH);
3444
3450
  }
3445
3451
  ensureDir(VERSION_DIR);
3446
3452
  writeVersionStamp(VERSION_DIR, getVersion());
@@ -3449,8 +3455,11 @@ function installPi() {
3449
3455
  if (existsSync7(WIKI_WORKER_PATH)) {
3450
3456
  log(` pi wiki-worker installed -> ${WIKI_WORKER_PATH}`);
3451
3457
  }
3452
- if (existsSync7(SKILIFY_WORKER_PATH)) {
3453
- log(` pi skilify-worker installed -> ${SKILIFY_WORKER_PATH}`);
3458
+ if (existsSync7(SKILLIFY_WORKER_PATH)) {
3459
+ log(` pi skillify-worker installed -> ${SKILLIFY_WORKER_PATH}`);
3460
+ }
3461
+ if (existsSync7(AUTOPULL_WORKER_PATH)) {
3462
+ log(` pi autopull-worker installed -> ${AUTOPULL_WORKER_PATH}`);
3454
3463
  }
3455
3464
  }
3456
3465
  function uninstallPi() {
@@ -4709,20 +4718,53 @@ if (process.argv[1] && process.argv[1].endsWith("auth-login.js")) {
4709
4718
  });
4710
4719
  }
4711
4720
 
4712
- // dist/src/commands/skilify.js
4713
- import { readdirSync as readdirSync4, existsSync as existsSync17, readFileSync as readFileSync13, mkdirSync as mkdirSync8, renameSync as renameSync3 } from "node:fs";
4714
- import { homedir as homedir10 } from "node:os";
4715
- import { dirname as dirname3, join as join20 } from "node:path";
4721
+ // dist/src/commands/skillify.js
4722
+ import { readdirSync as readdirSync4, existsSync as existsSync19, readFileSync as readFileSync13, mkdirSync as mkdirSync8, renameSync as renameSync4 } from "node:fs";
4723
+ import { homedir as homedir12 } from "node:os";
4724
+ import { dirname as dirname4, join as join22 } from "node:path";
4725
+
4726
+ // dist/src/skillify/scope-config.js
4727
+ import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
4728
+ import { homedir as homedir6 } from "node:os";
4729
+ import { join as join16 } from "node:path";
4716
4730
 
4717
- // dist/src/skilify/scope-config.js
4718
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
4731
+ // dist/src/skillify/legacy-migration.js
4732
+ import { existsSync as existsSync12, renameSync } from "node:fs";
4719
4733
  import { homedir as homedir5 } from "node:os";
4720
4734
  import { join as join15 } from "node:path";
4721
- var STATE_DIR = join15(homedir5(), ".deeplake", "state", "skilify");
4722
- var CONFIG_PATH2 = join15(STATE_DIR, "config.json");
4735
+ var dlog = (msg) => log2("skillify-migrate", msg);
4736
+ var attempted = false;
4737
+ function migrateLegacyStateDir() {
4738
+ if (attempted)
4739
+ return;
4740
+ attempted = true;
4741
+ const root = join15(homedir5(), ".deeplake", "state");
4742
+ const legacy = join15(root, "skilify");
4743
+ const current = join15(root, "skillify");
4744
+ if (!existsSync12(legacy))
4745
+ return;
4746
+ if (existsSync12(current))
4747
+ return;
4748
+ try {
4749
+ renameSync(legacy, current);
4750
+ dlog(`migrated ${legacy} -> ${current}`);
4751
+ } catch (err) {
4752
+ const code = err.code;
4753
+ if (code === "EXDEV" || code === "EPERM") {
4754
+ dlog(`migration failed (${code}); leaving legacy dir in place`);
4755
+ return;
4756
+ }
4757
+ throw err;
4758
+ }
4759
+ }
4760
+
4761
+ // dist/src/skillify/scope-config.js
4762
+ var STATE_DIR = join16(homedir6(), ".deeplake", "state", "skillify");
4763
+ var CONFIG_PATH2 = join16(STATE_DIR, "config.json");
4723
4764
  var DEFAULT = { scope: "me", team: [], install: "project" };
4724
4765
  function loadScopeConfig() {
4725
- if (!existsSync12(CONFIG_PATH2))
4766
+ migrateLegacyStateDir();
4767
+ if (!existsSync13(CONFIG_PATH2))
4726
4768
  return DEFAULT;
4727
4769
  try {
4728
4770
  const raw = JSON.parse(readFileSync9(CONFIG_PATH2, "utf-8"));
@@ -4735,19 +4777,20 @@ function loadScopeConfig() {
4735
4777
  }
4736
4778
  }
4737
4779
  function saveScopeConfig(cfg) {
4780
+ migrateLegacyStateDir();
4738
4781
  mkdirSync4(STATE_DIR, { recursive: true });
4739
4782
  writeFileSync6(CONFIG_PATH2, JSON.stringify(cfg, null, 2));
4740
4783
  }
4741
4784
 
4742
- // dist/src/skilify/pull.js
4743
- import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync7, renameSync as renameSync2 } from "node:fs";
4744
- import { homedir as homedir8 } from "node:os";
4745
- import { join as join18 } from "node:path";
4785
+ // dist/src/skillify/pull.js
4786
+ import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync7, renameSync as renameSync3, lstatSync as lstatSync4, readlinkSync as readlinkSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync8 } from "node:fs";
4787
+ import { homedir as homedir10 } from "node:os";
4788
+ import { dirname as dirname3, join as join20 } from "node:path";
4746
4789
 
4747
- // dist/src/skilify/skill-writer.js
4748
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync10, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync7 } from "node:fs";
4749
- import { homedir as homedir6 } from "node:os";
4750
- import { join as join16 } from "node:path";
4790
+ // dist/src/skillify/skill-writer.js
4791
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync7 } from "node:fs";
4792
+ import { homedir as homedir7 } from "node:os";
4793
+ import { join as join17 } from "node:path";
4751
4794
  function assertValidSkillName(name) {
4752
4795
  if (typeof name !== "string" || name.length === 0) {
4753
4796
  throw new Error(`invalid skill name: empty or non-string`);
@@ -4805,18 +4848,19 @@ function parseFrontmatter(text) {
4805
4848
  return { fm, body };
4806
4849
  }
4807
4850
 
4808
- // dist/src/skilify/manifest.js
4809
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync8 } from "node:fs";
4810
- import { homedir as homedir7 } from "node:os";
4811
- import { dirname as dirname2, join as join17 } from "node:path";
4851
+ // dist/src/skillify/manifest.js
4852
+ import { existsSync as existsSync15, lstatSync as lstatSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, unlinkSync as unlinkSync7, writeFileSync as writeFileSync8 } from "node:fs";
4853
+ import { homedir as homedir8 } from "node:os";
4854
+ import { dirname as dirname2, join as join18 } from "node:path";
4812
4855
  function emptyManifest() {
4813
4856
  return { version: 1, entries: [] };
4814
4857
  }
4815
4858
  function manifestPath() {
4816
- return join17(homedir7(), ".deeplake", "state", "skilify", "pulled.json");
4859
+ return join18(homedir8(), ".deeplake", "state", "skillify", "pulled.json");
4817
4860
  }
4818
4861
  function loadManifest(path = manifestPath()) {
4819
- if (!existsSync14(path))
4862
+ migrateLegacyStateDir();
4863
+ if (!existsSync15(path))
4820
4864
  return emptyManifest();
4821
4865
  let raw;
4822
4866
  try {
@@ -4846,6 +4890,8 @@ function loadManifest(path = manifestPath()) {
4846
4890
  continue;
4847
4891
  if (e.install !== "global" && e.install !== "project")
4848
4892
  continue;
4893
+ const symlinks = Array.isArray(e.symlinks) ? e.symlinks.filter((p) => typeof p === "string" && p.length > 0 && (p.startsWith("/") || /^[A-Za-z]:[\\/]/.test(p)) && // absolute (POSIX or Windows)
4894
+ !p.includes("..")) : [];
4849
4895
  entries.push({
4850
4896
  dirName: e.dirName,
4851
4897
  name: e.name,
@@ -4854,7 +4900,8 @@ function loadManifest(path = manifestPath()) {
4854
4900
  remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
4855
4901
  install: e.install,
4856
4902
  installRoot: e.installRoot,
4857
- pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString()
4903
+ pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
4904
+ symlinks
4858
4905
  });
4859
4906
  }
4860
4907
  return { version: 1, entries };
@@ -4863,10 +4910,11 @@ function loadManifest(path = manifestPath()) {
4863
4910
  }
4864
4911
  }
4865
4912
  function saveManifest(m, path = manifestPath()) {
4913
+ migrateLegacyStateDir();
4866
4914
  mkdirSync6(dirname2(path), { recursive: true });
4867
4915
  const tmp = `${path}.tmp`;
4868
4916
  writeFileSync8(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
4869
- renameSync(tmp, path);
4917
+ renameSync2(tmp, path);
4870
4918
  }
4871
4919
  function recordPull(entry, path = manifestPath()) {
4872
4920
  const m = loadManifest(path);
@@ -4887,8 +4935,64 @@ function removePullEntry(install, installRoot, dirName, path = manifestPath()) {
4887
4935
  function entriesForRoot(m, install, installRoot) {
4888
4936
  return m.entries.filter((e) => e.install === install && e.installRoot === installRoot);
4889
4937
  }
4938
+ function unlinkSymlinks(paths) {
4939
+ for (const path of paths) {
4940
+ let st;
4941
+ try {
4942
+ st = lstatSync3(path);
4943
+ } catch {
4944
+ continue;
4945
+ }
4946
+ if (!st.isSymbolicLink())
4947
+ continue;
4948
+ try {
4949
+ unlinkSync7(path);
4950
+ } catch {
4951
+ }
4952
+ }
4953
+ }
4954
+ function pruneOrphanedEntries(path = manifestPath()) {
4955
+ const m = loadManifest(path);
4956
+ const live = [];
4957
+ let pruned = 0;
4958
+ for (const e of m.entries) {
4959
+ if (existsSync15(join18(e.installRoot, e.dirName))) {
4960
+ live.push(e);
4961
+ continue;
4962
+ }
4963
+ unlinkSymlinks(e.symlinks);
4964
+ pruned++;
4965
+ }
4966
+ if (pruned > 0)
4967
+ saveManifest({ version: 1, entries: live }, path);
4968
+ return pruned;
4969
+ }
4970
+
4971
+ // dist/src/skillify/agent-roots.js
4972
+ import { existsSync as existsSync16 } from "node:fs";
4973
+ import { homedir as homedir9 } from "node:os";
4974
+ import { join as join19 } from "node:path";
4975
+ function resolveDetected(home) {
4976
+ const out = [];
4977
+ const codexInstalled = existsSync16(join19(home, ".codex"));
4978
+ const piInstalled = existsSync16(join19(home, ".pi", "agent"));
4979
+ const hermesInstalled = existsSync16(join19(home, ".hermes"));
4980
+ if (codexInstalled || piInstalled) {
4981
+ out.push(join19(home, ".agents", "skills"));
4982
+ }
4983
+ if (hermesInstalled) {
4984
+ out.push(join19(home, ".hermes", "skills"));
4985
+ }
4986
+ if (piInstalled) {
4987
+ out.push(join19(home, ".pi", "agent", "skills"));
4988
+ }
4989
+ return out;
4990
+ }
4991
+ function detectAgentSkillsRoots(canonicalRoot, home = homedir9()) {
4992
+ return resolveDetected(home).filter((p) => p !== canonicalRoot);
4993
+ }
4890
4994
 
4891
- // dist/src/skilify/pull.js
4995
+ // dist/src/skillify/pull.js
4892
4996
  function assertValidAuthor(author) {
4893
4997
  if (!author)
4894
4998
  throw new Error("author is empty");
@@ -4920,10 +5024,78 @@ function isMissingTableError(message) {
4920
5024
  }
4921
5025
  function resolvePullDestination(install, cwd) {
4922
5026
  if (install === "global")
4923
- return join18(homedir8(), ".claude", "skills");
5027
+ return join20(homedir10(), ".claude", "skills");
4924
5028
  if (!cwd)
4925
5029
  throw new Error("install=project requires a cwd");
4926
- return join18(cwd, ".claude", "skills");
5030
+ return join20(cwd, ".claude", "skills");
5031
+ }
5032
+ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
5033
+ const out = [];
5034
+ for (const root of agentRoots) {
5035
+ const link = join20(root, dirName);
5036
+ let existing;
5037
+ try {
5038
+ existing = lstatSync4(link);
5039
+ } catch {
5040
+ existing = null;
5041
+ }
5042
+ if (existing) {
5043
+ if (!existing.isSymbolicLink()) {
5044
+ continue;
5045
+ }
5046
+ let current;
5047
+ try {
5048
+ current = readlinkSync2(link);
5049
+ } catch {
5050
+ current = null;
5051
+ }
5052
+ if (current === canonicalDir) {
5053
+ out.push(link);
5054
+ continue;
5055
+ }
5056
+ try {
5057
+ unlinkSync8(link);
5058
+ } catch {
5059
+ continue;
5060
+ }
5061
+ }
5062
+ try {
5063
+ mkdirSync7(dirname3(link), { recursive: true });
5064
+ symlinkSync2(canonicalDir, link, "dir");
5065
+ out.push(link);
5066
+ } catch {
5067
+ }
5068
+ }
5069
+ return out;
5070
+ }
5071
+ function backfillSymlinks(installRoot) {
5072
+ const manifest = loadManifest();
5073
+ const entries = entriesForRoot(manifest, "global", installRoot);
5074
+ if (entries.length === 0)
5075
+ return;
5076
+ const detected = detectAgentSkillsRoots(installRoot);
5077
+ for (const entry of entries) {
5078
+ const canonical = join20(entry.installRoot, entry.dirName);
5079
+ if (!existsSync17(canonical))
5080
+ continue;
5081
+ const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
5082
+ if (sameSorted(fresh, entry.symlinks))
5083
+ continue;
5084
+ try {
5085
+ recordPull({ ...entry, symlinks: fresh });
5086
+ } catch {
5087
+ }
5088
+ }
5089
+ }
5090
+ function sameSorted(a, b) {
5091
+ if (a.length !== b.length)
5092
+ return false;
5093
+ const sa = [...a].sort();
5094
+ const sb = [...b].sort();
5095
+ for (let i = 0; i < sa.length; i++)
5096
+ if (sa[i] !== sb[i])
5097
+ return false;
5098
+ return true;
4927
5099
  }
4928
5100
  function selectLatestPerName(rows) {
4929
5101
  const seen = /* @__PURE__ */ new Set();
@@ -4989,7 +5161,7 @@ function renderFrontmatter(fm) {
4989
5161
  return lines.join("\n");
4990
5162
  }
4991
5163
  function readLocalVersion(path) {
4992
- if (!existsSync15(path))
5164
+ if (!existsSync17(path))
4993
5165
  return null;
4994
5166
  try {
4995
5167
  const text = readFileSync12(path, "utf-8");
@@ -5009,6 +5181,8 @@ function decideAction(args) {
5009
5181
  return args.dryRun ? "dryrun" : "wrote";
5010
5182
  }
5011
5183
  async function runPull(opts) {
5184
+ if (!opts.dryRun)
5185
+ pruneOrphanedEntries();
5012
5186
  const sql = buildPullSql({
5013
5187
  tableName: opts.tableName,
5014
5188
  users: opts.users,
@@ -5076,8 +5250,8 @@ async function runPull(opts) {
5076
5250
  summary.skipped++;
5077
5251
  continue;
5078
5252
  }
5079
- const skillDir = join18(root, dirName);
5080
- const skillFile = join18(skillDir, "SKILL.md");
5253
+ const skillDir = join20(root, dirName);
5254
+ const skillFile = join20(skillDir, "SKILL.md");
5081
5255
  const remoteVersion = Number(row.version ?? 1);
5082
5256
  const localVersion = readLocalVersion(skillFile);
5083
5257
  const action = decideAction({
@@ -5089,13 +5263,14 @@ async function runPull(opts) {
5089
5263
  let manifestError;
5090
5264
  if (action === "wrote") {
5091
5265
  mkdirSync7(skillDir, { recursive: true });
5092
- if (existsSync15(skillFile)) {
5266
+ if (existsSync17(skillFile)) {
5093
5267
  try {
5094
- renameSync2(skillFile, `${skillFile}.bak`);
5268
+ renameSync3(skillFile, `${skillFile}.bak`);
5095
5269
  } catch {
5096
5270
  }
5097
5271
  }
5098
5272
  writeFileSync9(skillFile, renderSkillFile(row));
5273
+ const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir, dirName, detectAgentSkillsRoots(root)) : [];
5099
5274
  try {
5100
5275
  recordPull({
5101
5276
  dirName,
@@ -5105,7 +5280,8 @@ async function runPull(opts) {
5105
5280
  remoteVersion,
5106
5281
  install: opts.install,
5107
5282
  installRoot: root,
5108
- pulledAt: (/* @__PURE__ */ new Date()).toISOString()
5283
+ pulledAt: (/* @__PURE__ */ new Date()).toISOString(),
5284
+ symlinks
5109
5285
  });
5110
5286
  } catch (e) {
5111
5287
  manifestError = e?.message ?? String(e);
@@ -5128,19 +5304,22 @@ async function runPull(opts) {
5128
5304
  else
5129
5305
  summary.skipped++;
5130
5306
  }
5307
+ if (!opts.dryRun && opts.install === "global") {
5308
+ backfillSymlinks(root);
5309
+ }
5131
5310
  return summary;
5132
5311
  }
5133
5312
 
5134
- // dist/src/skilify/unpull.js
5135
- import { existsSync as existsSync16, readdirSync as readdirSync3, rmSync as rmSync5, statSync as statSync3 } from "node:fs";
5136
- import { homedir as homedir9 } from "node:os";
5137
- import { join as join19 } from "node:path";
5313
+ // dist/src/skillify/unpull.js
5314
+ import { existsSync as existsSync18, readdirSync as readdirSync3, rmSync as rmSync5, statSync as statSync3 } from "node:fs";
5315
+ import { homedir as homedir11 } from "node:os";
5316
+ import { join as join21 } from "node:path";
5138
5317
  function resolveUnpullRoot(install, cwd) {
5139
5318
  if (install === "global")
5140
- return join19(homedir9(), ".claude", "skills");
5319
+ return join21(homedir11(), ".claude", "skills");
5141
5320
  if (!cwd)
5142
5321
  throw new Error("cwd required when install === 'project'");
5143
- return join19(cwd, ".claude", "skills");
5322
+ return join21(cwd, ".claude", "skills");
5144
5323
  }
5145
5324
  function runUnpull(opts) {
5146
5325
  const root = resolveUnpullRoot(opts.install, opts.cwd);
@@ -5163,10 +5342,12 @@ function runUnpull(opts) {
5163
5342
  const entries = entriesForRoot(manifest, opts.install, root);
5164
5343
  for (const entry of entries) {
5165
5344
  summary.scanned++;
5166
- const path = join19(root, entry.dirName);
5167
- if (!existsSync16(path)) {
5168
- if (!opts.dryRun)
5345
+ const path = join21(root, entry.dirName);
5346
+ if (!existsSync18(path)) {
5347
+ if (!opts.dryRun) {
5348
+ unlinkSymlinks(entry.symlinks);
5169
5349
  removePullEntry(opts.install, entry.installRoot, entry.dirName);
5350
+ }
5170
5351
  summary.entries.push({
5171
5352
  dirName: entry.dirName,
5172
5353
  kind: "manifest-orphan",
@@ -5203,6 +5384,7 @@ function runUnpull(opts) {
5203
5384
  } else {
5204
5385
  try {
5205
5386
  rmSync5(path, { recursive: true, force: true });
5387
+ unlinkSymlinks(entry.symlinks);
5206
5388
  removePullEntry(opts.install, entry.installRoot, entry.dirName);
5207
5389
  result.action = "removed";
5208
5390
  summary.removed++;
@@ -5214,12 +5396,12 @@ function runUnpull(opts) {
5214
5396
  }
5215
5397
  summary.entries.push(result);
5216
5398
  }
5217
- if (existsSync16(root) && (opts.all || opts.legacyCleanup)) {
5399
+ if (existsSync18(root) && (opts.all || opts.legacyCleanup)) {
5218
5400
  const manifestDirNames = new Set(entries.map((e) => e.dirName));
5219
5401
  for (const dirName of readdirSync3(root)) {
5220
5402
  if (manifestDirNames.has(dirName))
5221
5403
  continue;
5222
- const path = join19(root, dirName);
5404
+ const path = join21(root, dirName);
5223
5405
  let st;
5224
5406
  try {
5225
5407
  st = statSync3(path);
@@ -5296,9 +5478,9 @@ function decideTargetForManifestEntry(entry, opts, userFilter, haveUserFilter) {
5296
5478
  return { shouldRemove: true };
5297
5479
  }
5298
5480
 
5299
- // dist/src/commands/skilify.js
5481
+ // dist/src/commands/skillify.js
5300
5482
  function stateDir() {
5301
- return join20(homedir10(), ".deeplake", "state", "skilify");
5483
+ return join22(homedir12(), ".deeplake", "state", "skillify");
5302
5484
  }
5303
5485
  function showStatus() {
5304
5486
  const cfg = loadScopeConfig();
@@ -5306,11 +5488,11 @@ function showStatus() {
5306
5488
  console.log(`team: ${cfg.team.length === 0 ? "(empty)" : cfg.team.join(", ")}`);
5307
5489
  console.log(`install: ${cfg.install} (${cfg.install === "global" ? "~/.claude/skills/" : "<project>/.claude/skills/"})`);
5308
5490
  const dir = stateDir();
5309
- if (!existsSync17(dir)) {
5491
+ if (!existsSync19(dir)) {
5310
5492
  console.log(`state: (no projects tracked yet)`);
5311
5493
  return;
5312
5494
  }
5313
- const files = readdirSync4(dir).filter((f) => f.endsWith(".json") && f !== "config.json" && f !== "pulled.json");
5495
+ const files = readdirSync4(dir).filter((f) => f.endsWith(".json") && f !== "config.json" && f !== "pulled.json" && f !== "autopull-last-run.json");
5314
5496
  if (files.length === 0) {
5315
5497
  console.log(`state: (no projects tracked yet)`);
5316
5498
  return;
@@ -5318,9 +5500,10 @@ function showStatus() {
5318
5500
  console.log(`state: ${files.length} project(s) tracked`);
5319
5501
  for (const f of files) {
5320
5502
  try {
5321
- const s = JSON.parse(readFileSync13(join20(dir, f), "utf-8"));
5322
- const skills = s.skillsGenerated.length === 0 ? "none" : s.skillsGenerated.join(", ");
5323
- console.log(` - ${s.project} (counter=${s.counter}, last=${s.lastDate ?? "never"}, skills=${skills})`);
5503
+ const s = JSON.parse(readFileSync13(join22(dir, f), "utf-8"));
5504
+ const last = typeof s.updatedAt === "number" ? new Date(s.updatedAt).toISOString() : s.lastDate ?? "never";
5505
+ const skills = Array.isArray(s.skillsGenerated) && s.skillsGenerated.length > 0 ? s.skillsGenerated.join(", ") : "none";
5506
+ console.log(` - ${s.project} (counter=${s.counter}, last=${last}, skills=${skills})`);
5324
5507
  } catch {
5325
5508
  }
5326
5509
  }
@@ -5334,7 +5517,7 @@ function setScope(scope) {
5334
5517
  saveScopeConfig({ ...cfg, scope });
5335
5518
  console.log(`Scope set to '${scope}'.`);
5336
5519
  if (scope === "team" && cfg.team.length === 0) {
5337
- console.log(`Note: team list is empty. Use 'hivemind skilify team add <username>' to populate it.`);
5520
+ console.log(`Note: team list is empty. Use 'hivemind skillify team add <username>' to populate it.`);
5338
5521
  }
5339
5522
  }
5340
5523
  function setInstall(loc) {
@@ -5344,31 +5527,31 @@ function setInstall(loc) {
5344
5527
  }
5345
5528
  const cfg = loadScopeConfig();
5346
5529
  saveScopeConfig({ ...cfg, install: loc });
5347
- const path = loc === "global" ? join20(homedir10(), ".claude", "skills") : "<cwd>/.claude/skills";
5530
+ const path = loc === "global" ? join22(homedir12(), ".claude", "skills") : "<cwd>/.claude/skills";
5348
5531
  console.log(`Install location set to '${loc}'. New skills will be written to ${path}/<name>/SKILL.md.`);
5349
5532
  }
5350
5533
  function promoteSkill(name, cwd) {
5351
5534
  if (!name) {
5352
- console.error("Usage: hivemind skilify promote <skill-name>");
5535
+ console.error("Usage: hivemind skillify promote <skill-name>");
5353
5536
  process.exit(1);
5354
5537
  }
5355
- const projectPath = join20(cwd, ".claude", "skills", name);
5356
- const globalPath = join20(homedir10(), ".claude", "skills", name);
5357
- if (!existsSync17(join20(projectPath, "SKILL.md"))) {
5538
+ const projectPath = join22(cwd, ".claude", "skills", name);
5539
+ const globalPath = join22(homedir12(), ".claude", "skills", name);
5540
+ if (!existsSync19(join22(projectPath, "SKILL.md"))) {
5358
5541
  console.error(`Skill '${name}' not found at ${projectPath}/SKILL.md`);
5359
5542
  process.exit(1);
5360
5543
  }
5361
- if (existsSync17(join20(globalPath, "SKILL.md"))) {
5544
+ if (existsSync19(join22(globalPath, "SKILL.md"))) {
5362
5545
  console.error(`Skill '${name}' already exists at ${globalPath}/SKILL.md \u2014 refusing to overwrite. Remove it first or rename the project skill.`);
5363
5546
  process.exit(1);
5364
5547
  }
5365
- mkdirSync8(dirname3(globalPath), { recursive: true });
5366
- renameSync3(projectPath, globalPath);
5548
+ mkdirSync8(dirname4(globalPath), { recursive: true });
5549
+ renameSync4(projectPath, globalPath);
5367
5550
  console.log(`Promoted '${name}' from ${projectPath} \u2192 ${globalPath}.`);
5368
5551
  }
5369
5552
  function teamAdd(name) {
5370
5553
  if (!name) {
5371
- console.error("Usage: hivemind skilify team add <username>");
5554
+ console.error("Usage: hivemind skillify team add <username>");
5372
5555
  process.exit(1);
5373
5556
  }
5374
5557
  const cfg = loadScopeConfig();
@@ -5382,7 +5565,7 @@ function teamAdd(name) {
5382
5565
  }
5383
5566
  function teamRemove(name) {
5384
5567
  if (!name) {
5385
- console.error("Usage: hivemind skilify team remove <username>");
5568
+ console.error("Usage: hivemind skillify team remove <username>");
5386
5569
  process.exit(1);
5387
5570
  }
5388
5571
  const cfg = loadScopeConfig();
@@ -5405,14 +5588,14 @@ function teamList() {
5405
5588
  }
5406
5589
  function usage() {
5407
5590
  console.log("Usage:");
5408
- console.log(" hivemind skilify show current scope, team, install, and per-project state");
5409
- console.log(" hivemind skilify scope <me|team|org> set the mining scope");
5410
- console.log(" hivemind skilify install <project|global> set where new skills are written");
5411
- console.log(" hivemind skilify promote <skill-name> move a project skill to the global location");
5412
- console.log(" hivemind skilify team add <username> add a username to the team list");
5413
- console.log(" hivemind skilify team remove <username> remove a username from the team list");
5414
- console.log(" hivemind skilify team list list current team members");
5415
- console.log(" hivemind skilify pull [skill-name] [opts] fetch skills from Deeplake to local FS");
5591
+ console.log(" hivemind skillify show current scope, team, install, and per-project state");
5592
+ console.log(" hivemind skillify scope <me|team|org> set the mining scope");
5593
+ console.log(" hivemind skillify install <project|global> set where new skills are written");
5594
+ console.log(" hivemind skillify promote <skill-name> move a project skill to the global location");
5595
+ console.log(" hivemind skillify team add <username> add a username to the team list");
5596
+ console.log(" hivemind skillify team remove <username> remove a username from the team list");
5597
+ console.log(" hivemind skillify team list list current team members");
5598
+ console.log(" hivemind skillify pull [skill-name] [opts] fetch skills from Deeplake to local FS");
5416
5599
  console.log(" Options for pull:");
5417
5600
  console.log(" --to <project|global> destination (default: global)");
5418
5601
  console.log(" --user <name> only skills authored by this user");
@@ -5420,7 +5603,7 @@ function usage() {
5420
5603
  console.log(" --all-users all authors (default \u2014 equivalent to no filter)");
5421
5604
  console.log(" --dry-run show what would be written, don't touch disk");
5422
5605
  console.log(" --force overwrite even when local version >= remote");
5423
- console.log(" hivemind skilify unpull [opts] remove skills previously installed by pull");
5606
+ console.log(" hivemind skillify unpull [opts] remove skills previously installed by pull");
5424
5607
  console.log(" Options for unpull:");
5425
5608
  console.log(" --to <project|global> where to scan (default: global)");
5426
5609
  console.log(" --user <name> only entries authored by this user");
@@ -5429,7 +5612,7 @@ function usage() {
5429
5612
  console.log(" --dry-run show what would be removed");
5430
5613
  console.log(" --all also remove flat-layout (locally-mined) entries");
5431
5614
  console.log(" --legacy-cleanup also remove pre-`--author`-layout legacy `<projectKey>/` dirs");
5432
- console.log(" hivemind skilify status show per-project state");
5615
+ console.log(" hivemind skillify status show per-project state");
5433
5616
  }
5434
5617
  function takeFlagValue(args, flag) {
5435
5618
  const idx = args.indexOf(flag);
@@ -5493,7 +5676,7 @@ async function pullSkills(args) {
5493
5676
  console.error(`pull failed: ${e?.message ?? e}`);
5494
5677
  process.exit(1);
5495
5678
  }
5496
- const dest = toRaw === "global" ? join20(homedir10(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
5679
+ const dest = toRaw === "global" ? join22(homedir12(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
5497
5680
  const filterDesc = users.length === 0 ? "all users" : users.join(", ");
5498
5681
  console.log(`Destination: ${dest}`);
5499
5682
  console.log(`Filter: ${filterDesc}${skillName ? ` \xB7 skill='${skillName}'` : ""}${dryRun ? " \xB7 dry-run" : ""}${force ? " \xB7 force" : ""}`);
@@ -5543,7 +5726,7 @@ async function unpullSkills(args) {
5543
5726
  all,
5544
5727
  legacyCleanup
5545
5728
  });
5546
- const dest = toRaw === "global" ? join20(homedir10(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
5729
+ const dest = toRaw === "global" ? join22(homedir12(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
5547
5730
  const filterParts = [];
5548
5731
  if (users.length > 0)
5549
5732
  filterParts.push(`users=${users.join(",")}`);
@@ -5568,7 +5751,7 @@ async function unpullSkills(args) {
5568
5751
  const prunedNote = summary.manifestPruned > 0 ? `, ${summary.manifestPruned} manifest-pruned` : "";
5569
5752
  console.log(`Result: ${summary.removed} removed, ${summary.wouldRemove} dry-run, ${summary.kept} kept${prunedNote}.`);
5570
5753
  }
5571
- function runSkilifyCommand(args) {
5754
+ function runSkillifyCommand(args) {
5572
5755
  const sub = args[0];
5573
5756
  if (!sub || sub === "status") {
5574
5757
  showStatus();
@@ -5615,30 +5798,30 @@ function runSkilifyCommand(args) {
5615
5798
  teamList();
5616
5799
  return;
5617
5800
  }
5618
- console.error("Usage: hivemind skilify team <add|remove|list> [name]");
5801
+ console.error("Usage: hivemind skillify team <add|remove|list> [name]");
5619
5802
  process.exit(1);
5620
5803
  }
5621
5804
  if (sub === "--help" || sub === "-h" || sub === "help") {
5622
5805
  usage();
5623
5806
  return;
5624
5807
  }
5625
- console.error(`Unknown skilify subcommand: ${sub}`);
5808
+ console.error(`Unknown skillify subcommand: ${sub}`);
5626
5809
  usage();
5627
5810
  process.exit(1);
5628
5811
  }
5629
- if (process.argv[1] && process.argv[1].endsWith("skilify.js")) {
5630
- runSkilifyCommand(process.argv.slice(2));
5812
+ if (process.argv[1] && process.argv[1].endsWith("skillify.js")) {
5813
+ runSkillifyCommand(process.argv.slice(2));
5631
5814
  }
5632
5815
 
5633
5816
  // dist/src/cli/update.js
5634
5817
  import { execFileSync as execFileSync4 } from "node:child_process";
5635
- import { existsSync as existsSync18, readFileSync as readFileSync15, realpathSync } from "node:fs";
5636
- import { dirname as dirname5, sep } from "node:path";
5818
+ import { existsSync as existsSync20, readFileSync as readFileSync15, realpathSync } from "node:fs";
5819
+ import { dirname as dirname6, sep } from "node:path";
5637
5820
  import { fileURLToPath as fileURLToPath2 } from "node:url";
5638
5821
 
5639
5822
  // dist/src/utils/version-check.js
5640
5823
  import { readFileSync as readFileSync14 } from "node:fs";
5641
- import { dirname as dirname4, join as join21 } from "node:path";
5824
+ import { dirname as dirname5, join as join23 } from "node:path";
5642
5825
  function isNewer(latest, current) {
5643
5826
  const parse = (v) => v.split(".").map(Number);
5644
5827
  const [la, lb, lc] = parse(latest);
@@ -5657,7 +5840,7 @@ function detectInstallKind(argv1) {
5657
5840
  return argv1 ?? process.argv[1] ?? fileURLToPath2(import.meta.url);
5658
5841
  }
5659
5842
  })();
5660
- let dir = dirname5(realArgv1);
5843
+ let dir = dirname6(realArgv1);
5661
5844
  let installDir = null;
5662
5845
  for (let i = 0; i < 10; i++) {
5663
5846
  const pkgPath = `${dir}${sep}package.json`;
@@ -5669,12 +5852,12 @@ function detectInstallKind(argv1) {
5669
5852
  }
5670
5853
  } catch {
5671
5854
  }
5672
- const parent = dirname5(dir);
5855
+ const parent = dirname6(dir);
5673
5856
  if (parent === dir)
5674
5857
  break;
5675
5858
  dir = parent;
5676
5859
  }
5677
- installDir ??= dirname5(realArgv1);
5860
+ installDir ??= dirname6(realArgv1);
5678
5861
  if (realArgv1.includes(`${sep}_npx${sep}`) || realArgv1.includes(`${sep}.npx${sep}`)) {
5679
5862
  return { kind: "npx", installDir };
5680
5863
  }
@@ -5683,10 +5866,10 @@ function detectInstallKind(argv1) {
5683
5866
  }
5684
5867
  let gitDir = installDir;
5685
5868
  for (let i = 0; i < 6; i++) {
5686
- if (existsSync18(`${gitDir}${sep}.git`)) {
5869
+ if (existsSync20(`${gitDir}${sep}.git`)) {
5687
5870
  return { kind: "local-dev", installDir };
5688
5871
  }
5689
- const parent = dirname5(gitDir);
5872
+ const parent = dirname6(gitDir);
5690
5873
  if (parent === gitDir)
5691
5874
  break;
5692
5875
  gitDir = parent;
@@ -5840,22 +6023,28 @@ Semantic search (embeddings):
5840
6023
  to run "embeddings install" automatically after installing the agent(s).
5841
6024
 
5842
6025
  Skill management (mine + share reusable Claude skills across the org):
5843
- hivemind skilify Show scope, team, install, and per-project state.
5844
- hivemind skilify pull [skill-name] Sync skills from the org table to local FS.
6026
+ hivemind skillify Show scope, team, install, and per-project state.
6027
+ hivemind skillify pull [skill-name] Sync skills from the org table to local FS.
5845
6028
  Options: --user <email>, --users a,b,c,
5846
6029
  --all-users, --to <project|global>,
5847
6030
  --dry-run, --force.
5848
- hivemind skilify unpull Remove skills previously installed by pull.
6031
+ Note: every agent's SessionStart hook
6032
+ auto-runs 'pull --all-users --to global'
6033
+ on every session. File writes are
6034
+ idempotent (skipped when local is
6035
+ at-or-newer than remote). Disable via
6036
+ HIVEMIND_AUTOPULL_DISABLED=1.
6037
+ hivemind skillify unpull Remove skills previously installed by pull.
5849
6038
  Options: --user, --users, --not-mine,
5850
6039
  --to <project|global>, --dry-run,
5851
6040
  --all (also locally-mined),
5852
6041
  --legacy-cleanup (pre-suffix-author dirs).
5853
- hivemind skilify scope <me|team|org> Set the sharing scope for newly mined skills.
5854
- hivemind skilify install <project|global> Set where new skills are written.
5855
- hivemind skilify promote <name> Move a project skill to the global location.
5856
- hivemind skilify team add <username> Add a username to the team list.
5857
- hivemind skilify team remove <username> Remove a username from the team list.
5858
- hivemind skilify team list List current team members.
6042
+ hivemind skillify scope <me|team|org> Set the sharing scope for newly mined skills.
6043
+ hivemind skillify install <project|global> Set where new skills are written.
6044
+ hivemind skillify promote <name> Move a project skill to the global location.
6045
+ hivemind skillify team add <username> Add a username to the team list.
6046
+ hivemind skillify team remove <username> Remove a username from the team list.
6047
+ hivemind skillify team list List current team members.
5859
6048
 
5860
6049
  Account / org / workspace:
5861
6050
  hivemind whoami Show current user, org, workspace.
@@ -6006,8 +6195,8 @@ async function main() {
6006
6195
  const code = await runUpdate({ dryRun: hasFlag(args.slice(1), "--dry-run") });
6007
6196
  process.exit(code);
6008
6197
  }
6009
- if (cmd === "skilify") {
6010
- runSkilifyCommand(args.slice(1));
6198
+ if (cmd === "skillify") {
6199
+ runSkillifyCommand(args.slice(1));
6011
6200
  return;
6012
6201
  }
6013
6202
  if (cmd === "embeddings") {