@piut/cli 3.9.0 → 3.10.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/README.md +1 -1
  2. package/dist/cli.js +430 -231
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -28,9 +28,9 @@ __export(tree_prompt_exports, {
28
28
  loadChildren: () => loadChildren,
29
29
  shouldShowInTree: () => shouldShowInTree
30
30
  });
31
- import fs14 from "fs";
32
- import path14 from "path";
33
- import os8 from "os";
31
+ import fs15 from "fs";
32
+ import path16 from "path";
33
+ import os9 from "os";
34
34
  import {
35
35
  createPrompt,
36
36
  useState,
@@ -50,19 +50,19 @@ function shouldShowInTree(name) {
50
50
  }
51
51
  function shouldShowFile(name) {
52
52
  if (name.startsWith(".")) return false;
53
- const ext = path14.extname(name).toLowerCase();
53
+ const ext = path16.extname(name).toLowerCase();
54
54
  return !HIDDEN_FILE_EXTENSIONS.has(ext);
55
55
  }
56
56
  function loadChildren(parentPath, parentDepth, includeFiles = false) {
57
57
  try {
58
- const entries = fs14.readdirSync(parentPath, { withFileTypes: true });
58
+ const entries = fs15.readdirSync(parentPath, { withFileTypes: true });
59
59
  const dirs = [];
60
60
  const files = [];
61
61
  for (const entry of entries) {
62
62
  if (entry.isDirectory()) {
63
63
  if (!shouldShowInTree(entry.name)) continue;
64
64
  dirs.push({
65
- path: path14.join(parentPath, entry.name),
65
+ path: path16.join(parentPath, entry.name),
66
66
  name: entry.name,
67
67
  depth: parentDepth + 1,
68
68
  expanded: false,
@@ -72,7 +72,7 @@ function loadChildren(parentPath, parentDepth, includeFiles = false) {
72
72
  } else if (includeFiles && entry.isFile()) {
73
73
  if (!shouldShowFile(entry.name)) continue;
74
74
  files.push({
75
- path: path14.join(parentPath, entry.name),
75
+ path: path16.join(parentPath, entry.name),
76
76
  name: entry.name,
77
77
  depth: parentDepth + 1,
78
78
  expanded: false,
@@ -214,7 +214,7 @@ var init_tree_prompt = __esm({
214
214
  ".map"
215
215
  ]);
216
216
  treePrompt = createPrompt((config, done) => {
217
- const root = config.root ?? os8.homedir();
217
+ const root = config.root ?? os9.homedir();
218
218
  const pageSize = config.pageSize ?? 15;
219
219
  const mode = config.mode ?? "folders";
220
220
  const includeFiles = mode === "files";
@@ -325,9 +325,9 @@ import { Command } from "commander";
325
325
 
326
326
  // src/commands/setup.ts
327
327
  init_esm_shims();
328
- import fs4 from "fs";
329
- import path7 from "path";
330
- import { execSync } from "child_process";
328
+ import fs6 from "fs";
329
+ import path9 from "path";
330
+ import { execSync as execSync2 } from "child_process";
331
331
  import { password, confirm, checkbox } from "@inquirer/prompts";
332
332
  import chalk2 from "chalk";
333
333
 
@@ -641,7 +641,7 @@ var TOOLS = [
641
641
  project: [".mcp.json"]
642
642
  },
643
643
  skillFilePath: "CLAUDE.md",
644
- quickCommand: (slug, key) => `claude mcp add-json piut-context '${JSON.stringify({
644
+ quickCommand: (slug, key) => `claude mcp add-json piut '${JSON.stringify({
645
645
  type: "http",
646
646
  url: MCP_URL(slug),
647
647
  headers: { ...AUTH_HEADER(key), ...machineHeaders("Claude Code") }
@@ -776,7 +776,7 @@ var TOOLS = [
776
776
  win32: ["~/.mcporter/mcporter.json", "~/.openclaw/workspace/config/mcporter.json"],
777
777
  linux: ["~/.mcporter/mcporter.json", "~/.openclaw/workspace/config/mcporter.json"]
778
778
  },
779
- quickCommand: (slug, key) => `npx mcporter config add piut-context ${MCP_URL(slug)} --header "Authorization=Bearer ${key}"`,
779
+ quickCommand: (slug, key) => `npx mcporter config add piut ${MCP_URL(slug)} --header "Authorization=Bearer ${key}"`,
780
780
  generateConfig: (slug, key) => ({
781
781
  url: MCP_URL(slug),
782
782
  headers: { ...AUTH_HEADER(key), ...machineHeaders("OpenClaw") }
@@ -820,6 +820,8 @@ function resolveConfigPaths(tool) {
820
820
  init_esm_shims();
821
821
  import fs from "fs";
822
822
  import path4 from "path";
823
+ var SERVER_KEY = "piut";
824
+ var LEGACY_SERVER_KEY = "piut-context";
823
825
  function readConfig(filePath) {
824
826
  let raw;
825
827
  try {
@@ -867,12 +869,13 @@ function isPiutConfigured(filePath, configKey) {
867
869
  const config = readConfig(filePath);
868
870
  if (!config) return false;
869
871
  const servers = resolveKeyPath(config, configKey);
870
- return !!servers?.["piut-context"];
872
+ return !!(servers?.[SERVER_KEY] || servers?.[LEGACY_SERVER_KEY]);
871
873
  }
872
874
  function mergeConfig(filePath, configKey, serverConfig) {
873
875
  const existing = readConfig(filePath) || {};
874
876
  const servers = resolveKeyPath(existing, configKey) || {};
875
- servers["piut-context"] = serverConfig;
877
+ delete servers[LEGACY_SERVER_KEY];
878
+ servers[SERVER_KEY] = serverConfig;
876
879
  setAtKeyPath(existing, configKey, servers);
877
880
  writeConfig(filePath, existing);
878
881
  }
@@ -880,7 +883,7 @@ function getPiutConfig(filePath, configKey) {
880
883
  const config = readConfig(filePath);
881
884
  if (!config) return null;
882
885
  const servers = resolveKeyPath(config, configKey);
883
- const piut = servers?.["piut-context"];
886
+ const piut = servers?.[SERVER_KEY] || servers?.[LEGACY_SERVER_KEY];
884
887
  return piut ?? null;
885
888
  }
886
889
  function extractKeyFromConfig(piutConfig) {
@@ -932,8 +935,11 @@ function removeFromConfig(filePath, configKey) {
932
935
  const config = readConfig(filePath);
933
936
  if (!config) return false;
934
937
  const servers = resolveKeyPath(config, configKey);
935
- if (!servers?.["piut-context"]) return false;
936
- delete servers["piut-context"];
938
+ const hasNew = !!servers?.[SERVER_KEY];
939
+ const hasLegacy = !!servers?.[LEGACY_SERVER_KEY];
940
+ if (!hasNew && !hasLegacy) return false;
941
+ delete servers[SERVER_KEY];
942
+ delete servers[LEGACY_SERVER_KEY];
937
943
  if (Object.keys(servers).length === 0 && !configKey.includes(".")) {
938
944
  delete config[configKey];
939
945
  }
@@ -945,7 +951,7 @@ function removeFromConfig(filePath, configKey) {
945
951
  init_esm_shims();
946
952
  import fs2 from "fs";
947
953
  import path5 from "path";
948
- var SKILL_SNIPPET = `## p\u0131ut Context (MCP Server: piut-context)
954
+ var SKILL_SNIPPET = `## p\u0131ut Context (MCP Server: piut)
949
955
 
950
956
  This project uses p\u0131ut for persistent personal context via MCP (Model Context Protocol).
951
957
  p\u0131ut provides MCP tools \u2014 do NOT read local .piut/ files directly. Use the MCP tools.
@@ -965,7 +971,7 @@ p\u0131ut provides MCP tools \u2014 do NOT read local .piut/ files directly. Use
965
971
  4. Never read .piut/config.json directly \u2014 always use the MCP tools
966
972
 
967
973
  Skill reference: https://raw.githubusercontent.com/M-Flat-Inc/piut/main/skill.md`;
968
- var PROJECT_SKILL_SNIPPET = `## p\u0131ut Context (MCP Server: piut-context)
974
+ var PROJECT_SKILL_SNIPPET = `## p\u0131ut Context (MCP Server: piut)
969
975
 
970
976
  This project uses p\u0131ut for persistent personal context via MCP (Model Context Protocol).
971
977
  p\u0131ut provides MCP tools \u2014 do NOT read local .piut/ files directly. Use the MCP tools.
@@ -1114,6 +1120,42 @@ function hasPiutDir(projectPath) {
1114
1120
  return fs3.existsSync(path6.join(piutDir(projectPath), CONFIG_FILE));
1115
1121
  }
1116
1122
 
1123
+ // src/lib/global-install.ts
1124
+ init_esm_shims();
1125
+ import { execSync } from "child_process";
1126
+ import fs5 from "fs";
1127
+ import path8 from "path";
1128
+ import os5 from "os";
1129
+
1130
+ // src/lib/store.ts
1131
+ init_esm_shims();
1132
+ import fs4 from "fs";
1133
+ import path7 from "path";
1134
+ import os4 from "os";
1135
+ var CONFIG_DIR = path7.join(os4.homedir(), ".piut");
1136
+ var CONFIG_FILE2 = path7.join(CONFIG_DIR, "config.json");
1137
+ function readStore() {
1138
+ try {
1139
+ const raw = fs4.readFileSync(CONFIG_FILE2, "utf-8");
1140
+ return JSON.parse(raw);
1141
+ } catch {
1142
+ return {};
1143
+ }
1144
+ }
1145
+ function updateStore(updates) {
1146
+ const config = readStore();
1147
+ const updated = { ...config, ...updates };
1148
+ fs4.mkdirSync(CONFIG_DIR, { recursive: true });
1149
+ fs4.writeFileSync(CONFIG_FILE2, JSON.stringify(updated, null, 2) + "\n", "utf-8");
1150
+ return updated;
1151
+ }
1152
+ function clearStore() {
1153
+ try {
1154
+ fs4.unlinkSync(CONFIG_FILE2);
1155
+ } catch {
1156
+ }
1157
+ }
1158
+
1117
1159
  // src/lib/ui.ts
1118
1160
  init_esm_shims();
1119
1161
  import chalk from "chalk";
@@ -1200,6 +1242,65 @@ var Spinner = class {
1200
1242
  }
1201
1243
  };
1202
1244
 
1245
+ // src/lib/global-install.ts
1246
+ function isPiutInPath() {
1247
+ try {
1248
+ execSync(process.platform === "win32" ? "where piut" : "which piut", { stdio: "pipe" });
1249
+ return true;
1250
+ } catch {
1251
+ return false;
1252
+ }
1253
+ }
1254
+ function getShellProfile() {
1255
+ const shell = process.env.SHELL || "";
1256
+ const home2 = os5.homedir();
1257
+ if (shell.includes("zsh")) {
1258
+ return path8.join(home2, ".zshrc");
1259
+ }
1260
+ if (shell.includes("bash")) {
1261
+ const profile = path8.join(home2, ".bash_profile");
1262
+ if (process.platform === "darwin" && fs5.existsSync(profile)) {
1263
+ return profile;
1264
+ }
1265
+ return path8.join(home2, ".bashrc");
1266
+ }
1267
+ return null;
1268
+ }
1269
+ function addShellAlias(profilePath) {
1270
+ try {
1271
+ const content = fs5.existsSync(profilePath) ? fs5.readFileSync(profilePath, "utf-8") : "";
1272
+ if (content.includes("alias piut=") || content.includes("piut()")) {
1273
+ return true;
1274
+ }
1275
+ const alias = '\n# p\u0131ut CLI shortcut\nalias piut="npx @piut/cli"\n';
1276
+ fs5.appendFileSync(profilePath, alias);
1277
+ return true;
1278
+ } catch {
1279
+ return false;
1280
+ }
1281
+ }
1282
+ async function offerGlobalInstall() {
1283
+ if (isPiutInPath()) return;
1284
+ const store = readStore();
1285
+ if (store.globalInstallOffered) return;
1286
+ updateStore({ globalInstallOffered: true });
1287
+ try {
1288
+ execSync("npm install -g @piut/cli", { stdio: "pipe", timeout: 3e4 });
1289
+ if (isPiutInPath()) {
1290
+ console.log(dim(" Installed `piut` command for quick access"));
1291
+ return;
1292
+ }
1293
+ } catch {
1294
+ }
1295
+ const profile = getShellProfile();
1296
+ if (profile) {
1297
+ if (addShellAlias(profile)) {
1298
+ console.log(dim(` Added \`piut\` shortcut to ${path8.basename(profile)}`));
1299
+ return;
1300
+ }
1301
+ }
1302
+ }
1303
+
1203
1304
  // src/types.ts
1204
1305
  init_esm_shims();
1205
1306
  var CliError = class extends Error {
@@ -1255,8 +1356,8 @@ async function setupCommand(options) {
1255
1356
  if (tool.skillOnly) continue;
1256
1357
  const paths = resolveConfigPaths(tool);
1257
1358
  for (const { filePath, configKey } of paths) {
1258
- const exists = fs4.existsSync(filePath);
1259
- const parentExists = fs4.existsSync(path7.dirname(filePath));
1359
+ const exists = fs6.existsSync(filePath);
1360
+ const parentExists = fs6.existsSync(path9.dirname(filePath));
1260
1361
  if (exists || parentExists) {
1261
1362
  const configured2 = exists && !!configKey && isPiutConfigured(filePath, configKey);
1262
1363
  let staleKey = false;
@@ -1336,7 +1437,7 @@ async function setupCommand(options) {
1336
1437
  if (tool.id === "claude-code" && tool.quickCommand && isCommandAvailable("claude")) {
1337
1438
  let quickSuccess = false;
1338
1439
  try {
1339
- execSync(tool.quickCommand(slug, apiKey), { stdio: "pipe" });
1440
+ execSync2(tool.quickCommand(slug, apiKey), { stdio: "pipe" });
1340
1441
  const claudeJson = expandPath("~/.claude.json");
1341
1442
  const written = tool.configKey ? getPiutConfig(claudeJson, tool.configKey) : null;
1342
1443
  if (written) {
@@ -1346,7 +1447,7 @@ async function setupCommand(options) {
1346
1447
  continue;
1347
1448
  }
1348
1449
  try {
1349
- execSync(tool.quickCommand(slug, apiKey) + " --scope user", { stdio: "pipe" });
1450
+ execSync2(tool.quickCommand(slug, apiKey) + " --scope user", { stdio: "pipe" });
1350
1451
  const retryCheck = tool.configKey ? getPiutConfig(claudeJson, tool.configKey) : null;
1351
1452
  if (retryCheck) {
1352
1453
  quickSuccess = true;
@@ -1396,7 +1497,7 @@ async function setupCommand(options) {
1396
1497
  }
1397
1498
  if (configured.length > 0) {
1398
1499
  const cwd = process.cwd();
1399
- const isProject2 = fs4.existsSync(path7.join(cwd, ".git")) || fs4.existsSync(path7.join(cwd, "package.json"));
1500
+ const isProject2 = fs6.existsSync(path9.join(cwd, ".git")) || fs6.existsSync(path9.join(cwd, "package.json"));
1400
1501
  if (isProject2) {
1401
1502
  const { serverUrl } = validationResult;
1402
1503
  writePiutConfig(cwd, { slug, apiKey, serverUrl });
@@ -1438,6 +1539,7 @@ async function setupCommand(options) {
1438
1539
  if (skipped.length > 0) {
1439
1540
  console.log(dim(` Skipped: ${skipped.join(", ")}`));
1440
1541
  }
1542
+ await offerGlobalInstall();
1441
1543
  console.log();
1442
1544
  console.log(dim(" Restart your AI tools for changes to take effect."));
1443
1545
  console.log(dim(' Verify: ask any AI "What do you know about me from my context?"'));
@@ -1446,7 +1548,7 @@ async function setupCommand(options) {
1446
1548
  }
1447
1549
  function isCommandAvailable(cmd) {
1448
1550
  try {
1449
- execSync(process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`, { stdio: "pipe" });
1551
+ execSync2(process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`, { stdio: "pipe" });
1450
1552
  return true;
1451
1553
  } catch {
1452
1554
  return false;
@@ -1455,16 +1557,16 @@ function isCommandAvailable(cmd) {
1455
1557
 
1456
1558
  // src/commands/status.ts
1457
1559
  init_esm_shims();
1458
- import fs7 from "fs";
1459
- import os6 from "os";
1460
- import path10 from "path";
1560
+ import fs8 from "fs";
1561
+ import os7 from "os";
1562
+ import path11 from "path";
1461
1563
  import chalk3 from "chalk";
1462
1564
 
1463
1565
  // src/lib/brain-scanner.ts
1464
1566
  init_esm_shims();
1465
- import fs5 from "fs";
1466
- import path8 from "path";
1467
- import os4 from "os";
1567
+ import fs7 from "fs";
1568
+ import path10 from "path";
1569
+ import os6 from "os";
1468
1570
 
1469
1571
  // src/lib/file-types.ts
1470
1572
  init_esm_shims();
@@ -1483,7 +1585,7 @@ var AI_CONFIG_FILENAMES = /* @__PURE__ */ new Set([
1483
1585
  ]);
1484
1586
 
1485
1587
  // src/lib/brain-scanner.ts
1486
- var home = os4.homedir();
1588
+ var home = os6.homedir();
1487
1589
  var SKIP_DIRS = /* @__PURE__ */ new Set([
1488
1590
  "node_modules",
1489
1591
  ".git",
@@ -1547,22 +1649,22 @@ var INCLUDE_DOT_DIRS = /* @__PURE__ */ new Set([
1547
1649
  function getDefaultScanDirs() {
1548
1650
  const dirs = [];
1549
1651
  try {
1550
- const entries = fs5.readdirSync(home, { withFileTypes: true });
1652
+ const entries = fs7.readdirSync(home, { withFileTypes: true });
1551
1653
  for (const entry of entries) {
1552
1654
  if (!entry.isDirectory()) continue;
1553
1655
  if (entry.name.startsWith(".") && !INCLUDE_DOT_DIRS.has(entry.name)) continue;
1554
1656
  if (SKIP_HOME_DIRS.has(entry.name)) continue;
1555
- dirs.push(path8.join(home, entry.name));
1657
+ dirs.push(path10.join(home, entry.name));
1556
1658
  }
1557
1659
  } catch {
1558
1660
  }
1559
- const cloudStorage = path8.join(home, "Library", "CloudStorage");
1661
+ const cloudStorage = path10.join(home, "Library", "CloudStorage");
1560
1662
  try {
1561
- if (fs5.existsSync(cloudStorage) && fs5.statSync(cloudStorage).isDirectory()) {
1562
- const entries = fs5.readdirSync(cloudStorage, { withFileTypes: true });
1663
+ if (fs7.existsSync(cloudStorage) && fs7.statSync(cloudStorage).isDirectory()) {
1664
+ const entries = fs7.readdirSync(cloudStorage, { withFileTypes: true });
1563
1665
  for (const entry of entries) {
1564
1666
  if (!entry.isDirectory()) continue;
1565
- const fullPath = path8.join(cloudStorage, entry.name);
1667
+ const fullPath = path10.join(cloudStorage, entry.name);
1566
1668
  if (!dirs.includes(fullPath)) {
1567
1669
  dirs.push(fullPath);
1568
1670
  }
@@ -1574,22 +1676,22 @@ function getDefaultScanDirs() {
1574
1676
  return dirs;
1575
1677
  }
1576
1678
  function isProject(dirPath) {
1577
- return fs5.existsSync(path8.join(dirPath, ".git")) || fs5.existsSync(path8.join(dirPath, "package.json")) || fs5.existsSync(path8.join(dirPath, "Cargo.toml")) || fs5.existsSync(path8.join(dirPath, "pyproject.toml")) || fs5.existsSync(path8.join(dirPath, "go.mod"));
1679
+ return fs7.existsSync(path10.join(dirPath, ".git")) || fs7.existsSync(path10.join(dirPath, "package.json")) || fs7.existsSync(path10.join(dirPath, "Cargo.toml")) || fs7.existsSync(path10.join(dirPath, "pyproject.toml")) || fs7.existsSync(path10.join(dirPath, "go.mod"));
1578
1680
  }
1579
1681
  function buildProjectInfo(projectPath) {
1580
- const hasPkgJson = fs5.existsSync(path8.join(projectPath, "package.json"));
1682
+ const hasPkgJson = fs7.existsSync(path10.join(projectPath, "package.json"));
1581
1683
  let description = "";
1582
1684
  if (hasPkgJson) {
1583
1685
  try {
1584
- const pkg = JSON.parse(fs5.readFileSync(path8.join(projectPath, "package.json"), "utf-8"));
1686
+ const pkg = JSON.parse(fs7.readFileSync(path10.join(projectPath, "package.json"), "utf-8"));
1585
1687
  description = pkg.description || "";
1586
1688
  } catch {
1587
1689
  }
1588
1690
  }
1589
- const readmePath = path8.join(projectPath, "README.md");
1590
- if (!description && fs5.existsSync(readmePath)) {
1691
+ const readmePath = path10.join(projectPath, "README.md");
1692
+ if (!description && fs7.existsSync(readmePath)) {
1591
1693
  try {
1592
- const content = fs5.readFileSync(readmePath, "utf-8");
1694
+ const content = fs7.readFileSync(readmePath, "utf-8");
1593
1695
  const lines = content.split("\n");
1594
1696
  let foundHeading = false;
1595
1697
  for (const line of lines) {
@@ -1606,15 +1708,15 @@ function buildProjectInfo(projectPath) {
1606
1708
  }
1607
1709
  }
1608
1710
  return {
1609
- name: path8.basename(projectPath),
1711
+ name: path10.basename(projectPath),
1610
1712
  path: projectPath,
1611
1713
  description,
1612
- hasClaudeMd: fs5.existsSync(path8.join(projectPath, "CLAUDE.md")) || fs5.existsSync(path8.join(projectPath, ".claude", "rules")),
1613
- hasCursorRules: fs5.existsSync(path8.join(projectPath, ".cursorrules")) || fs5.existsSync(path8.join(projectPath, ".cursor", "rules")),
1614
- hasWindsurfRules: fs5.existsSync(path8.join(projectPath, ".windsurfrules")) || fs5.existsSync(path8.join(projectPath, ".windsurf", "rules")),
1615
- hasCopilotInstructions: fs5.existsSync(path8.join(projectPath, ".github", "copilot-instructions.md")) || fs5.existsSync(path8.join(projectPath, ".github", "instructions")),
1616
- hasConventionsMd: fs5.existsSync(path8.join(projectPath, "CONVENTIONS.md")) || fs5.existsSync(path8.join(projectPath, ".amazonq", "rules")),
1617
- hasZedRules: fs5.existsSync(path8.join(projectPath, ".rules"))
1714
+ hasClaudeMd: fs7.existsSync(path10.join(projectPath, "CLAUDE.md")) || fs7.existsSync(path10.join(projectPath, ".claude", "rules")),
1715
+ hasCursorRules: fs7.existsSync(path10.join(projectPath, ".cursorrules")) || fs7.existsSync(path10.join(projectPath, ".cursor", "rules")),
1716
+ hasWindsurfRules: fs7.existsSync(path10.join(projectPath, ".windsurfrules")) || fs7.existsSync(path10.join(projectPath, ".windsurf", "rules")),
1717
+ hasCopilotInstructions: fs7.existsSync(path10.join(projectPath, ".github", "copilot-instructions.md")) || fs7.existsSync(path10.join(projectPath, ".github", "instructions")),
1718
+ hasConventionsMd: fs7.existsSync(path10.join(projectPath, "CONVENTIONS.md")) || fs7.existsSync(path10.join(projectPath, ".amazonq", "rules")),
1719
+ hasZedRules: fs7.existsSync(path10.join(projectPath, ".rules"))
1618
1720
  };
1619
1721
  }
1620
1722
  var MAX_PROJECT_DEPTH = 4;
@@ -1624,11 +1726,11 @@ function detectProjects(scanDirs, onProgress) {
1624
1726
  function walk(dir, depth) {
1625
1727
  if (depth > MAX_PROJECT_DEPTH) return;
1626
1728
  try {
1627
- const items = fs5.readdirSync(dir, { withFileTypes: true });
1729
+ const items = fs7.readdirSync(dir, { withFileTypes: true });
1628
1730
  for (const item of items) {
1629
1731
  if (!item.isDirectory()) continue;
1630
1732
  if (shouldSkipDir(item.name)) continue;
1631
- const fullPath = path8.join(dir, item.name);
1733
+ const fullPath = path10.join(dir, item.name);
1632
1734
  if (seen.has(fullPath)) continue;
1633
1735
  seen.add(fullPath);
1634
1736
  if (isProject(fullPath)) {
@@ -1652,20 +1754,20 @@ var MAX_BRAIN_INPUT_BYTES = 1e6;
1652
1754
  function collectGlobalConfigFiles(onProgress) {
1653
1755
  const configs = [];
1654
1756
  const globalPaths = [
1655
- path8.join(home, ".claude", "MEMORY.md"),
1656
- path8.join(home, ".claude", "CLAUDE.md"),
1657
- path8.join(home, ".openclaw", "workspace", "SOUL.md"),
1658
- path8.join(home, ".openclaw", "workspace", "MEMORY.md"),
1659
- path8.join(home, ".gemini", "MEMORY.md"),
1660
- path8.join(home, ".paperclip", "IDENTITY.md")
1757
+ path10.join(home, ".claude", "MEMORY.md"),
1758
+ path10.join(home, ".claude", "CLAUDE.md"),
1759
+ path10.join(home, ".openclaw", "workspace", "SOUL.md"),
1760
+ path10.join(home, ".openclaw", "workspace", "MEMORY.md"),
1761
+ path10.join(home, ".gemini", "MEMORY.md"),
1762
+ path10.join(home, ".paperclip", "IDENTITY.md")
1661
1763
  ];
1662
1764
  for (const gp of globalPaths) {
1663
1765
  try {
1664
- const stat = fs5.statSync(gp);
1766
+ const stat = fs7.statSync(gp);
1665
1767
  if (!stat.isFile() || stat.size > MAX_CONFIG_SIZE) continue;
1666
- const content = fs5.readFileSync(gp, "utf-8");
1768
+ const content = fs7.readFileSync(gp, "utf-8");
1667
1769
  if (content.trim()) {
1668
- const name = path8.relative(home, gp);
1770
+ const name = path10.relative(home, gp);
1669
1771
  configs.push({ name, content });
1670
1772
  onProgress?.({ phase: "configs", message: name });
1671
1773
  }
@@ -1678,11 +1780,11 @@ function collectProjectConfigFiles(projects, onProgress) {
1678
1780
  const configs = [];
1679
1781
  for (const project of projects) {
1680
1782
  for (const fileName of AI_CONFIG_FILENAMES) {
1681
- const filePath = path8.join(project.path, fileName);
1783
+ const filePath = path10.join(project.path, fileName);
1682
1784
  try {
1683
- const stat = fs5.statSync(filePath);
1785
+ const stat = fs7.statSync(filePath);
1684
1786
  if (!stat.isFile() || stat.size > MAX_CONFIG_SIZE) continue;
1685
- const content = fs5.readFileSync(filePath, "utf-8");
1787
+ const content = fs7.readFileSync(filePath, "utf-8");
1686
1788
  if (content.trim()) {
1687
1789
  const name = `${project.name}/${fileName}`;
1688
1790
  configs.push({ name, content });
@@ -1691,11 +1793,11 @@ function collectProjectConfigFiles(projects, onProgress) {
1691
1793
  } catch {
1692
1794
  }
1693
1795
  }
1694
- const pkgPath = path8.join(project.path, "package.json");
1796
+ const pkgPath = path10.join(project.path, "package.json");
1695
1797
  try {
1696
- const stat = fs5.statSync(pkgPath);
1798
+ const stat = fs7.statSync(pkgPath);
1697
1799
  if (stat.isFile() && stat.size <= MAX_CONFIG_SIZE) {
1698
- const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
1800
+ const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
1699
1801
  const summary = JSON.stringify({ name: pkg.name, description: pkg.description }, null, 2);
1700
1802
  configs.push({ name: `${project.name}/package.json`, content: summary });
1701
1803
  onProgress?.({ phase: "configs", message: `${project.name}/package.json` });
@@ -1715,35 +1817,6 @@ function formatSize(bytes) {
1715
1817
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1716
1818
  }
1717
1819
 
1718
- // src/lib/store.ts
1719
- init_esm_shims();
1720
- import fs6 from "fs";
1721
- import path9 from "path";
1722
- import os5 from "os";
1723
- var CONFIG_DIR = path9.join(os5.homedir(), ".piut");
1724
- var CONFIG_FILE2 = path9.join(CONFIG_DIR, "config.json");
1725
- function readStore() {
1726
- try {
1727
- const raw = fs6.readFileSync(CONFIG_FILE2, "utf-8");
1728
- return JSON.parse(raw);
1729
- } catch {
1730
- return {};
1731
- }
1732
- }
1733
- function updateStore(updates) {
1734
- const config = readStore();
1735
- const updated = { ...config, ...updates };
1736
- fs6.mkdirSync(CONFIG_DIR, { recursive: true });
1737
- fs6.writeFileSync(CONFIG_FILE2, JSON.stringify(updated, null, 2) + "\n", "utf-8");
1738
- return updated;
1739
- }
1740
- function clearStore() {
1741
- try {
1742
- fs6.unlinkSync(CONFIG_FILE2);
1743
- } catch {
1744
- }
1745
- }
1746
-
1747
1820
  // src/commands/status.ts
1748
1821
  var API_BASE3 = process.env.PIUT_API_BASE || "https://piut.com";
1749
1822
  var PIUT_FILES = [
@@ -1756,7 +1829,7 @@ var PIUT_FILES = [
1756
1829
  ];
1757
1830
  function hasPiutReference(filePath) {
1758
1831
  try {
1759
- const content = fs7.readFileSync(filePath, "utf-8");
1832
+ const content = fs8.readFileSync(filePath, "utf-8");
1760
1833
  return content.includes("p\u0131ut Context") || content.includes("piut Context");
1761
1834
  } catch {
1762
1835
  return false;
@@ -1808,7 +1881,7 @@ async function statusCommand(options = {}) {
1808
1881
  await verifyStatus();
1809
1882
  return;
1810
1883
  }
1811
- const thisHostname = os6.hostname();
1884
+ const thisHostname = os7.hostname();
1812
1885
  const thisMachineId = getMachineId2();
1813
1886
  console.log(` AI tools on this machine ${dim(`(${thisHostname})`)}:`);
1814
1887
  console.log();
@@ -1816,7 +1889,7 @@ async function statusCommand(options = {}) {
1816
1889
  for (const tool of TOOLS) {
1817
1890
  const paths = resolveConfigPaths(tool);
1818
1891
  for (const { filePath, configKey } of paths) {
1819
- if (!fs7.existsSync(filePath)) continue;
1892
+ if (!fs8.existsSync(filePath)) continue;
1820
1893
  foundAny = true;
1821
1894
  const configured = isPiutConfigured(filePath, configKey);
1822
1895
  if (configured) {
@@ -1839,8 +1912,8 @@ async function statusCommand(options = {}) {
1839
1912
  for (const project of projects) {
1840
1913
  const connectedFiles = [];
1841
1914
  for (const file of PIUT_FILES) {
1842
- const absPath = path10.join(project.path, file);
1843
- if (fs7.existsSync(absPath) && hasPiutReference(absPath)) {
1915
+ const absPath = path11.join(project.path, file);
1916
+ if (fs8.existsSync(absPath) && hasPiutReference(absPath)) {
1844
1917
  connectedFiles.push(file);
1845
1918
  }
1846
1919
  }
@@ -1913,7 +1986,7 @@ async function verifyStatus() {
1913
1986
  for (const tool of TOOLS) {
1914
1987
  const paths = resolveConfigPaths(tool);
1915
1988
  for (const { filePath, configKey } of paths) {
1916
- if (!fs7.existsSync(filePath)) continue;
1989
+ if (!fs8.existsSync(filePath)) continue;
1917
1990
  const piutConfig = getPiutConfig(filePath, configKey);
1918
1991
  if (!piutConfig) {
1919
1992
  toolLine(tool.name, dim("installed, not connected"), "\u25CB");
@@ -1957,7 +2030,7 @@ async function verifyStatus() {
1957
2030
 
1958
2031
  // src/commands/remove.ts
1959
2032
  init_esm_shims();
1960
- import fs8 from "fs";
2033
+ import fs9 from "fs";
1961
2034
  import { checkbox as checkbox2, confirm as confirm2 } from "@inquirer/prompts";
1962
2035
  async function removeCommand() {
1963
2036
  banner();
@@ -1966,7 +2039,7 @@ async function removeCommand() {
1966
2039
  if (!tool.configKey) continue;
1967
2040
  const paths = resolveConfigPaths(tool);
1968
2041
  for (const { filePath, configKey } of paths) {
1969
- if (fs8.existsSync(filePath) && isPiutConfigured(filePath, configKey)) {
2042
+ if (fs9.existsSync(filePath) && isPiutConfigured(filePath, configKey)) {
1970
2043
  configured.push({ tool, configPath: filePath, resolvedConfigKey: configKey });
1971
2044
  break;
1972
2045
  }
@@ -2020,7 +2093,7 @@ async function removeCommand() {
2020
2093
  init_esm_shims();
2021
2094
  import { confirm as confirm3 } from "@inquirer/prompts";
2022
2095
  import chalk5 from "chalk";
2023
- import os7 from "os";
2096
+ import os8 from "os";
2024
2097
 
2025
2098
  // src/lib/auth.ts
2026
2099
  init_esm_shims();
@@ -2224,10 +2297,95 @@ async function resolveApiKeyWithResult(keyOption) {
2224
2297
  }
2225
2298
  }
2226
2299
 
2300
+ // src/lib/sync.ts
2301
+ init_esm_shims();
2302
+ import fs10 from "fs";
2303
+ import path12 from "path";
2304
+ function syncStaleConfigs(slug, apiKey, serverUrl) {
2305
+ const updated = [];
2306
+ for (const tool of TOOLS) {
2307
+ if (tool.skillOnly || !tool.generateConfig || !tool.configKey) continue;
2308
+ const paths = resolveConfigPaths(tool);
2309
+ for (const { filePath, configKey } of paths) {
2310
+ if (!fs10.existsSync(filePath)) continue;
2311
+ const piutConfig = getPiutConfig(filePath, configKey);
2312
+ if (!piutConfig) continue;
2313
+ const existingKey = extractKeyFromConfig(piutConfig);
2314
+ const existingSlug = extractSlugFromConfig(piutConfig);
2315
+ const keyStale = !!existingKey && existingKey !== apiKey;
2316
+ const slugStale = !!existingSlug && existingSlug !== slug;
2317
+ if (keyStale || slugStale) {
2318
+ const newConfig = tool.generateConfig(slug, apiKey);
2319
+ mergeConfig(filePath, configKey, newConfig);
2320
+ updated.push(tool.name);
2321
+ }
2322
+ break;
2323
+ }
2324
+ }
2325
+ const cwd = process.cwd();
2326
+ const existing = readPiutConfig(cwd);
2327
+ if (existing && (existing.apiKey !== apiKey || existing.slug !== slug)) {
2328
+ writePiutConfig(cwd, { slug, apiKey, serverUrl });
2329
+ updated.push(".piut/config.json");
2330
+ }
2331
+ return updated;
2332
+ }
2333
+ function getConfiguredToolNames() {
2334
+ const names = [];
2335
+ for (const tool of TOOLS) {
2336
+ if (tool.skillOnly || !tool.configKey) continue;
2337
+ const paths = resolveConfigPaths(tool);
2338
+ for (const { filePath, configKey } of paths) {
2339
+ if (!fs10.existsSync(filePath)) continue;
2340
+ if (getPiutConfig(filePath, configKey)) {
2341
+ names.push(tool.name);
2342
+ break;
2343
+ }
2344
+ }
2345
+ }
2346
+ return names;
2347
+ }
2348
+ async function cycleConfigEntry(filePath, configKey, freshConfig) {
2349
+ removeFromConfig(filePath, configKey);
2350
+ await new Promise((resolve) => setTimeout(resolve, 500));
2351
+ mergeConfig(filePath, configKey, freshConfig);
2352
+ }
2353
+ async function cycleMcpConfigs(slug, apiKey) {
2354
+ for (const tool of TOOLS) {
2355
+ if (tool.skillOnly || !tool.generateConfig || !tool.configKey) continue;
2356
+ const paths = resolveConfigPaths(tool);
2357
+ for (const { filePath, configKey } of paths) {
2358
+ if (!fs10.existsSync(filePath)) continue;
2359
+ if (!getPiutConfig(filePath, configKey)) continue;
2360
+ await cycleConfigEntry(filePath, configKey, tool.generateConfig(slug, apiKey));
2361
+ break;
2362
+ }
2363
+ }
2364
+ }
2365
+ async function cycleProjectConfigs(slug, apiKey, serverUrl) {
2366
+ const projects = scanForProjects();
2367
+ const refreshed = [];
2368
+ const vscodeTool = TOOLS.find((t) => t.id === "vscode");
2369
+ for (const project of projects) {
2370
+ if (!hasPiutDir(project.path)) continue;
2371
+ const projectName = path12.basename(project.path);
2372
+ writePiutConfig(project.path, { slug, apiKey, serverUrl });
2373
+ await writePiutSkill(project.path, slug, apiKey);
2374
+ if (vscodeTool?.generateConfig && vscodeTool.configKey) {
2375
+ const vscodeMcpPath = path12.join(project.path, ".vscode", "mcp.json");
2376
+ if (fs10.existsSync(vscodeMcpPath) && isPiutConfigured(vscodeMcpPath, "servers")) {
2377
+ await cycleConfigEntry(vscodeMcpPath, "servers", vscodeTool.generateConfig(slug, apiKey));
2378
+ }
2379
+ }
2380
+ refreshed.push(projectName);
2381
+ }
2382
+ return refreshed;
2383
+ }
2384
+
2227
2385
  // src/commands/build.ts
2228
2386
  async function buildCommand(options) {
2229
2387
  banner();
2230
- const { apiKey, serverUrl } = await resolveApiKeyWithResult(options.key);
2388
+ const { apiKey, serverUrl, slug } = await resolveApiKeyWithResult(options.key);
2231
2389
  console.log(dim(" \u2501\u2501\u2501 BUILD YOUR BRAIN \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
2232
2390
  console.log();
2233
2391
  console.log(dim(" Scanning for AI config files..."));
@@ -2289,7 +2447,7 @@ async function buildCommand(options) {
2289
2447
  return;
2290
2448
  }
2291
2449
  }
2292
- const home2 = os7.homedir();
2450
+ const home2 = os8.homedir();
2293
2451
  const brainInput = {
2294
2452
  summary: {
2295
2453
  projects: projects.map((p) => ({
@@ -2300,9 +2458,9 @@ async function buildCommand(options) {
2300
2458
  configFiles: allConfigs
2301
2459
  }
2302
2460
  };
2303
- await streamBuild(apiKey, serverUrl, brainInput, options);
2461
+ await streamBuild(apiKey, serverUrl, slug, brainInput, options);
2304
2462
  }
2305
- async function streamBuild(apiKey, serverUrl, brainInput, options) {
2463
+ async function streamBuild(apiKey, serverUrl, slug, brainInput, options) {
2306
2464
  const spinner = new Spinner();
2307
2465
  spinner.start("Generating brain...");
2308
2466
  try {
@@ -2381,6 +2539,7 @@ async function streamBuild(apiKey, serverUrl, brainInput, options) {
2381
2539
  console.log(` ${brand(serverUrl)}`);
2382
2540
  console.log(dim(" (accessible only with secure authentication)"));
2383
2541
  console.log();
2542
+ await cycleMcpConfigs(slug, apiKey);
2384
2543
  } catch (err) {
2385
2544
  console.log();
2386
2545
  const msg = err.message;
@@ -2427,6 +2586,7 @@ async function deployCommand(options) {
2427
2586
  console.log(` ${brand(serverUrl)}`);
2428
2587
  console.log(dim(" (securely accessible only with authentication)"));
2429
2588
  console.log();
2589
+ await cycleMcpConfigs(slug, apiKey);
2430
2590
  console.log(dim(" Next: run ") + brand("piut connect") + dim(" to add brain references to your projects."));
2431
2591
  console.log();
2432
2592
  } catch (err) {
@@ -2447,33 +2607,33 @@ async function deployCommand(options) {
2447
2607
 
2448
2608
  // src/commands/connect.ts
2449
2609
  init_esm_shims();
2450
- import fs9 from "fs";
2451
- import path11 from "path";
2610
+ import fs11 from "fs";
2611
+ import path13 from "path";
2452
2612
  import { checkbox as checkbox3 } from "@inquirer/prompts";
2453
2613
  var RULE_FILES = [
2454
2614
  {
2455
2615
  tool: "Claude Code",
2456
2616
  filePath: "CLAUDE.md",
2457
2617
  strategy: "append",
2458
- detect: (p) => p.hasClaudeMd || fs9.existsSync(path11.join(p.path, ".claude"))
2618
+ detect: (p) => p.hasClaudeMd || fs11.existsSync(path13.join(p.path, ".claude"))
2459
2619
  },
2460
2620
  {
2461
2621
  tool: "Cursor",
2462
2622
  filePath: ".cursor/rules/piut.mdc",
2463
2623
  strategy: "create",
2464
- detect: (p) => p.hasCursorRules || fs9.existsSync(path11.join(p.path, ".cursor"))
2624
+ detect: (p) => p.hasCursorRules || fs11.existsSync(path13.join(p.path, ".cursor"))
2465
2625
  },
2466
2626
  {
2467
2627
  tool: "Windsurf",
2468
2628
  filePath: ".windsurf/rules/piut.md",
2469
2629
  strategy: "create",
2470
- detect: (p) => p.hasWindsurfRules || fs9.existsSync(path11.join(p.path, ".windsurf"))
2630
+ detect: (p) => p.hasWindsurfRules || fs11.existsSync(path13.join(p.path, ".windsurf"))
2471
2631
  },
2472
2632
  {
2473
2633
  tool: "VS Code",
2474
2634
  filePath: ".github/copilot-instructions.md",
2475
2635
  strategy: "append",
2476
- detect: (p) => p.hasCopilotInstructions || fs9.existsSync(path11.join(p.path, ".github"))
2636
+ detect: (p) => p.hasCopilotInstructions || fs11.existsSync(path13.join(p.path, ".github"))
2477
2637
  },
2478
2638
  {
2479
2639
  tool: "Amazon Q",
@@ -2485,22 +2645,22 @@ var RULE_FILES = [
2485
2645
  tool: "Zed",
2486
2646
  filePath: ".zed/rules.md",
2487
2647
  strategy: "create",
2488
- detect: (p) => p.hasZedRules || fs9.existsSync(path11.join(p.path, ".zed"))
2648
+ detect: (p) => p.hasZedRules || fs11.existsSync(path13.join(p.path, ".zed"))
2489
2649
  },
2490
2650
  {
2491
2651
  tool: "Gemini CLI",
2492
2652
  filePath: "GEMINI.md",
2493
2653
  strategy: "append",
2494
- detect: (p) => fs9.existsSync(path11.join(p.path, ".gemini"))
2654
+ detect: (p) => fs11.existsSync(path13.join(p.path, ".gemini"))
2495
2655
  },
2496
2656
  {
2497
2657
  tool: "Paperclip",
2498
2658
  filePath: "AGENTS.md",
2499
2659
  strategy: "append",
2500
- detect: (p) => fs9.existsSync(path11.join(p.path, ".paperclip"))
2660
+ detect: (p) => fs11.existsSync(path13.join(p.path, ".paperclip"))
2501
2661
  }
2502
2662
  ];
2503
- var DEDICATED_FILE_CONTENT = `## p\u0131ut Context (MCP Server: piut-context)
2663
+ var DEDICATED_FILE_CONTENT = `## p\u0131ut Context (MCP Server: piut)
2504
2664
 
2505
2665
  This project uses p\u0131ut for persistent personal context via MCP (Model Context Protocol).
2506
2666
  p\u0131ut provides MCP tools \u2014 do NOT read local .piut/ files directly. Use the MCP tools.
@@ -2523,7 +2683,7 @@ Full skill reference: .piut/skill.md
2523
2683
  `;
2524
2684
  var APPEND_SECTION = `
2525
2685
 
2526
- ## p\u0131ut Context (MCP Server: piut-context)
2686
+ ## p\u0131ut Context (MCP Server: piut)
2527
2687
 
2528
2688
  p\u0131ut provides MCP tools for persistent personal context. Do NOT read local .piut/ files.
2529
2689
  Available tools: \`get_context\`, \`get_section\`, \`search_brain\`, \`append_brain\`, \`update_brain\`, \`prompt_brain\`
@@ -2532,7 +2692,7 @@ Full skill reference: .piut/skill.md
2532
2692
  `;
2533
2693
  function hasPiutReference2(filePath) {
2534
2694
  try {
2535
- const content = fs9.readFileSync(filePath, "utf-8");
2695
+ const content = fs11.readFileSync(filePath, "utf-8");
2536
2696
  return content.includes("p\u0131ut Context") || content.includes("piut Context");
2537
2697
  } catch {
2538
2698
  return false;
@@ -2572,20 +2732,20 @@ async function connectCommand(options) {
2572
2732
  for (const project of projects) {
2573
2733
  for (const rule of RULE_FILES) {
2574
2734
  if (!rule.detect(project)) continue;
2575
- const absPath = path11.join(project.path, rule.filePath);
2576
- if (fs9.existsSync(absPath) && hasPiutReference2(absPath)) continue;
2735
+ const absPath = path13.join(project.path, rule.filePath);
2736
+ if (fs11.existsSync(absPath) && hasPiutReference2(absPath)) continue;
2577
2737
  actions.push({
2578
2738
  project,
2579
2739
  tool: rule.tool,
2580
2740
  filePath: rule.filePath,
2581
2741
  absPath,
2582
- action: rule.strategy === "create" || !fs9.existsSync(absPath) ? "create" : "append"
2742
+ action: rule.strategy === "create" || !fs11.existsSync(absPath) ? "create" : "append"
2583
2743
  });
2584
2744
  }
2585
2745
  const hasAnyAction = actions.some((a) => a.project === project);
2586
2746
  if (!hasAnyAction) {
2587
- const claudeMdPath = path11.join(project.path, "CLAUDE.md");
2588
- if (!fs9.existsSync(claudeMdPath)) {
2747
+ const claudeMdPath = path13.join(project.path, "CLAUDE.md");
2748
+ if (!fs11.existsSync(claudeMdPath)) {
2589
2749
  actions.push({
2590
2750
  project,
2591
2751
  tool: "Claude Code",
@@ -2625,7 +2785,7 @@ async function connectCommand(options) {
2625
2785
  console.log();
2626
2786
  const projectChoices = [];
2627
2787
  for (const [projectPath, projectActions] of byProject) {
2628
- const projectName = path11.basename(projectPath);
2788
+ const projectName = path13.basename(projectPath);
2629
2789
  const desc = projectActions.map((a) => {
2630
2790
  const verb = a.action === "create" ? "will create" : "will append to";
2631
2791
  return `${verb} ${a.filePath}`;
@@ -2654,15 +2814,15 @@ async function connectCommand(options) {
2654
2814
  const vscodeTool = TOOLS.find((t) => t.id === "vscode");
2655
2815
  for (const projectPath of selectedPaths) {
2656
2816
  const projectActions = byProject.get(projectPath) || [];
2657
- const projectName = path11.basename(projectPath);
2817
+ const projectName = path13.basename(projectPath);
2658
2818
  writePiutConfig(projectPath, { slug, apiKey, serverUrl });
2659
2819
  await writePiutSkill(projectPath, slug, apiKey);
2660
2820
  ensureGitignored(projectPath);
2661
2821
  console.log(success(` \u2713 ${projectName}/.piut/`) + dim(" \u2014 credentials + skill"));
2662
2822
  if (vscodeTool) {
2663
- const hasVscode = fs9.existsSync(path11.join(projectPath, ".github", "copilot-instructions.md")) || fs9.existsSync(path11.join(projectPath, ".github"));
2823
+ const hasVscode = fs11.existsSync(path13.join(projectPath, ".github", "copilot-instructions.md")) || fs11.existsSync(path13.join(projectPath, ".github"));
2664
2824
  if (hasVscode) {
2665
- const vscodeMcpPath = path11.join(projectPath, ".vscode", "mcp.json");
2825
+ const vscodeMcpPath = path13.join(projectPath, ".vscode", "mcp.json");
2666
2826
  const serverConfig = vscodeTool.generateConfig(slug, apiKey);
2667
2827
  mergeConfig(vscodeMcpPath, vscodeTool.configKey, serverConfig);
2668
2828
  console.log(success(` \u2713 ${projectName}/.vscode/mcp.json`) + dim(" \u2014 VS Code MCP"));
@@ -2672,11 +2832,11 @@ async function connectCommand(options) {
2672
2832
  if (action.action === "create") {
2673
2833
  const isAppendType = RULE_FILES.find((r) => r.filePath === action.filePath)?.strategy === "append";
2674
2834
  const content = isAppendType ? PROJECT_SKILL_SNIPPET + "\n" : DEDICATED_FILE_CONTENT;
2675
- fs9.mkdirSync(path11.dirname(action.absPath), { recursive: true });
2676
- fs9.writeFileSync(action.absPath, content, "utf-8");
2835
+ fs11.mkdirSync(path13.dirname(action.absPath), { recursive: true });
2836
+ fs11.writeFileSync(action.absPath, content, "utf-8");
2677
2837
  console.log(success(` \u2713 ${projectName}/${action.filePath}`) + dim(" \u2014 created"));
2678
2838
  } else {
2679
- fs9.appendFileSync(action.absPath, APPEND_SECTION);
2839
+ fs11.appendFileSync(action.absPath, APPEND_SECTION);
2680
2840
  console.log(success(` \u2713 ${projectName}/${action.filePath}`) + dim(" \u2014 appended"));
2681
2841
  }
2682
2842
  connected++;
@@ -2686,7 +2846,7 @@ async function connectCommand(options) {
2686
2846
  const hostname = getHostname();
2687
2847
  for (const projectPath of selectedPaths) {
2688
2848
  const projectActions = byProject.get(projectPath) || [];
2689
- const projectName = path11.basename(projectPath);
2849
+ const projectName = path13.basename(projectPath);
2690
2850
  const toolsDetected = [...new Set(projectActions.map((a) => a.tool))];
2691
2851
  const configFilesWritten = projectActions.map((a) => a.filePath);
2692
2852
  registerProject(apiKey, {
@@ -2706,8 +2866,8 @@ async function connectCommand(options) {
2706
2866
 
2707
2867
  // src/commands/disconnect.ts
2708
2868
  init_esm_shims();
2709
- import fs10 from "fs";
2710
- import path12 from "path";
2869
+ import fs12 from "fs";
2870
+ import path14 from "path";
2711
2871
  import { checkbox as checkbox4, confirm as confirm5 } from "@inquirer/prompts";
2712
2872
  var DEDICATED_FILES = /* @__PURE__ */ new Set([
2713
2873
  ".cursor/rules/piut.mdc",
@@ -2723,7 +2883,7 @@ var APPEND_FILES = [
2723
2883
  ];
2724
2884
  function hasPiutReference3(filePath) {
2725
2885
  try {
2726
- const content = fs10.readFileSync(filePath, "utf-8");
2886
+ const content = fs12.readFileSync(filePath, "utf-8");
2727
2887
  return content.includes("p\u0131ut Context") || content.includes("piut Context");
2728
2888
  } catch {
2729
2889
  return false;
@@ -2731,7 +2891,7 @@ function hasPiutReference3(filePath) {
2731
2891
  }
2732
2892
  function removePiutSection(filePath) {
2733
2893
  try {
2734
- let content = fs10.readFileSync(filePath, "utf-8");
2894
+ let content = fs12.readFileSync(filePath, "utf-8");
2735
2895
  const patterns = [
2736
2896
  /\n*## p[ıi]ut Context[\s\S]*?(?=\n## |\n---\n|$)/g
2737
2897
  ];
@@ -2745,7 +2905,7 @@ function removePiutSection(filePath) {
2745
2905
  }
2746
2906
  if (changed) {
2747
2907
  content = content.replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
2748
- fs10.writeFileSync(filePath, content, "utf-8");
2908
+ fs12.writeFileSync(filePath, content, "utf-8");
2749
2909
  }
2750
2910
  return changed;
2751
2911
  } catch {
@@ -2762,10 +2922,10 @@ async function disconnectCommand(options) {
2762
2922
  const projects = scanForProjects(scanFolders);
2763
2923
  const actions = [];
2764
2924
  for (const project of projects) {
2765
- const projectName = path12.basename(project.path);
2925
+ const projectName = path14.basename(project.path);
2766
2926
  for (const dedicatedFile of DEDICATED_FILES) {
2767
- const absPath = path12.join(project.path, dedicatedFile);
2768
- if (fs10.existsSync(absPath) && hasPiutReference3(absPath)) {
2927
+ const absPath = path14.join(project.path, dedicatedFile);
2928
+ if (fs12.existsSync(absPath) && hasPiutReference3(absPath)) {
2769
2929
  actions.push({
2770
2930
  projectPath: project.path,
2771
2931
  projectName,
@@ -2776,8 +2936,8 @@ async function disconnectCommand(options) {
2776
2936
  }
2777
2937
  }
2778
2938
  for (const appendFile of APPEND_FILES) {
2779
- const absPath = path12.join(project.path, appendFile);
2780
- if (fs10.existsSync(absPath) && hasPiutReference3(absPath)) {
2939
+ const absPath = path14.join(project.path, appendFile);
2940
+ if (fs12.existsSync(absPath) && hasPiutReference3(absPath)) {
2781
2941
  actions.push({
2782
2942
  projectPath: project.path,
2783
2943
  projectName,
@@ -2792,12 +2952,12 @@ async function disconnectCommand(options) {
2792
2952
  projectPath: project.path,
2793
2953
  projectName,
2794
2954
  filePath: ".piut/",
2795
- absPath: path12.join(project.path, ".piut"),
2955
+ absPath: path14.join(project.path, ".piut"),
2796
2956
  action: "remove-dir"
2797
2957
  });
2798
2958
  }
2799
- const vscodeMcpPath = path12.join(project.path, ".vscode", "mcp.json");
2800
- if (fs10.existsSync(vscodeMcpPath) && isPiutConfigured(vscodeMcpPath, "servers")) {
2959
+ const vscodeMcpPath = path14.join(project.path, ".vscode", "mcp.json");
2960
+ if (fs12.existsSync(vscodeMcpPath) && isPiutConfigured(vscodeMcpPath, "servers")) {
2801
2961
  actions.push({
2802
2962
  projectPath: project.path,
2803
2963
  projectName,
@@ -2819,7 +2979,7 @@ async function disconnectCommand(options) {
2819
2979
  }
2820
2980
  console.log();
2821
2981
  const projectChoices = Array.from(byProject.entries()).map(([projectPath, projectActions]) => {
2822
- const name = path12.basename(projectPath);
2982
+ const name = path14.basename(projectPath);
2823
2983
  const files = projectActions.map((a) => a.filePath).join(", ");
2824
2984
  return {
2825
2985
  name: `${name} ${dim(`(${files})`)}`,
@@ -2848,11 +3008,11 @@ async function disconnectCommand(options) {
2848
3008
  let disconnected = 0;
2849
3009
  for (const projectPath of selectedPaths) {
2850
3010
  const projectActions = byProject.get(projectPath) || [];
2851
- const projectName = path12.basename(projectPath);
3011
+ const projectName = path14.basename(projectPath);
2852
3012
  for (const action of projectActions) {
2853
3013
  if (action.action === "delete") {
2854
3014
  try {
2855
- fs10.unlinkSync(action.absPath);
3015
+ fs12.unlinkSync(action.absPath);
2856
3016
  console.log(success(` \u2713 ${projectName}/${action.filePath}`) + dim(" \u2014 deleted"));
2857
3017
  disconnected++;
2858
3018
  } catch {
@@ -2866,7 +3026,7 @@ async function disconnectCommand(options) {
2866
3026
  } else if (action.action === "remove-mcp") {
2867
3027
  try {
2868
3028
  removeFromConfig(action.absPath, "servers");
2869
- console.log(success(` \u2713 ${projectName}/${action.filePath}`) + dim(" \u2014 piut-context removed"));
3029
+ console.log(success(` \u2713 ${projectName}/${action.filePath}`) + dim(" \u2014 piut removed"));
2870
3030
  disconnected++;
2871
3031
  } catch {
2872
3032
  console.log(warning(` \u2717 ${projectName}/${action.filePath}`) + dim(" \u2014 could not update"));
@@ -3033,7 +3193,7 @@ async function updateCommand(currentVersion) {
3033
3193
 
3034
3194
  // src/commands/doctor.ts
3035
3195
  init_esm_shims();
3036
- import fs11 from "fs";
3196
+ import fs13 from "fs";
3037
3197
  import chalk10 from "chalk";
3038
3198
  async function doctorCommand(options) {
3039
3199
  if (!options.json) banner();
@@ -3085,7 +3245,7 @@ async function doctorCommand(options) {
3085
3245
  for (const tool of TOOLS) {
3086
3246
  const paths = resolveConfigPaths(tool);
3087
3247
  for (const { filePath: configPath, configKey: resolvedKey } of paths) {
3088
- if (!fs11.existsSync(configPath)) continue;
3248
+ if (!fs13.existsSync(configPath)) continue;
3089
3249
  const piutConfig = getPiutConfig(configPath, resolvedKey);
3090
3250
  if (!piutConfig) {
3091
3251
  result.tools.push({
@@ -3185,6 +3345,12 @@ async function doctorCommand(options) {
3185
3345
  }
3186
3346
  if (result.issues === 0) {
3187
3347
  console.log(success(" All checks passed."));
3348
+ if (result.mcp.ok && result.tools.some((t) => t.configured)) {
3349
+ console.log();
3350
+ console.log(dim(" Tip: If your AI tool can't access your brain but everything"));
3351
+ console.log(dim(" checks out here, try toggling the MCP server off and on in"));
3352
+ console.log(dim(" your tool's settings. MCP connections can go stale."));
3353
+ }
3188
3354
  } else {
3189
3355
  console.log(warning(` ${result.issues} issue(s) found.`));
3190
3356
  const staleTools = result.tools.filter((t) => t.keyMatch === "stale" && !t.fixed);
@@ -3200,10 +3366,49 @@ async function doctorCommand(options) {
3200
3366
  if (result.issues > 0) throw new CliError(`${result.issues} issue(s) found`);
3201
3367
  }
3202
3368
 
3369
+ // src/commands/refresh.ts
3370
+ init_esm_shims();
3371
+ async function refreshCommand(options) {
3372
+ banner();
3373
+ const { apiKey, slug, serverUrl, status } = await resolveApiKeyWithResult(options.key);
3374
+ const configuredTools = getConfiguredToolNames();
3375
+ const isDeployed = status === "active";
3376
+ if (configuredTools.length === 0 && !isDeployed) {
3377
+ console.log();
3378
+ console.log(warning(" Nothing to refresh."));
3379
+ console.log(dim(" Run ") + brand("piut setup") + dim(" first to configure your AI tools."));
3380
+ console.log();
3381
+ return;
3382
+ }
3383
+ console.log(dim(" Refreshing..."));
3384
+ if (isDeployed) {
3385
+ try {
3386
+ await publishServer(apiKey);
3387
+ console.log(success(" \u2713 Server republished"));
3388
+ } catch {
3389
+ console.log(warning(" \u2717 Could not republish server"));
3390
+ }
3391
+ }
3392
+ if (configuredTools.length > 0) {
3393
+ await cycleMcpConfigs(slug, apiKey);
3394
+ console.log(success(" \u2713 Refreshed MCP connections"));
3395
+ console.log(dim(` Cycled: ${configuredTools.join(", ")}`));
3396
+ }
3397
+ const refreshedProjects = await cycleProjectConfigs(slug, apiKey, serverUrl);
3398
+ if (refreshedProjects.length > 0) {
3399
+ console.log(success(" \u2713 Refreshed connected projects"));
3400
+ console.log(dim(` Updated: ${refreshedProjects.join(", ")}`));
3401
+ }
3402
+ console.log();
3403
+ console.log(dim(" Tools that watch config files will reconnect automatically."));
3404
+ console.log(dim(" If a tool doesn't refresh, restart it manually."));
3405
+ console.log();
3406
+ }
3407
+
3203
3408
  // src/commands/vault.ts
3204
3409
  init_esm_shims();
3205
- import fs12 from "fs";
3206
- import path13 from "path";
3410
+ import fs14 from "fs";
3411
+ import path15 from "path";
3207
3412
  import chalk11 from "chalk";
3208
3413
  import { confirm as confirm7 } from "@inquirer/prompts";
3209
3414
  var DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -3256,26 +3461,26 @@ async function vaultListCommand(options) {
3256
3461
  }
3257
3462
  async function vaultUploadCommand(filePath, options) {
3258
3463
  const key = resolveApiKey(options);
3259
- const resolved = path13.resolve(filePath);
3260
- if (!fs12.existsSync(resolved)) {
3464
+ const resolved = path15.resolve(filePath);
3465
+ if (!fs14.existsSync(resolved)) {
3261
3466
  console.log(chalk11.red(` File not found: ${filePath}`));
3262
3467
  throw new CliError();
3263
3468
  }
3264
- const stat = fs12.statSync(resolved);
3469
+ const stat = fs14.statSync(resolved);
3265
3470
  if (!stat.isFile()) {
3266
3471
  console.log(chalk11.red(` Not a file: ${filePath}`));
3267
3472
  throw new CliError();
3268
3473
  }
3269
- const filename = path13.basename(resolved);
3474
+ const filename = path15.basename(resolved);
3270
3475
  const ext = filename.includes(".") ? filename.split(".").pop()?.toLowerCase() || "" : "";
3271
3476
  const isDocument = DOCUMENT_EXTENSIONS.has(ext);
3272
3477
  let content;
3273
3478
  let encoding;
3274
3479
  if (isDocument) {
3275
- content = fs12.readFileSync(resolved).toString("base64");
3480
+ content = fs14.readFileSync(resolved).toString("base64");
3276
3481
  encoding = "base64";
3277
3482
  } else {
3278
- content = fs12.readFileSync(resolved, "utf-8");
3483
+ content = fs14.readFileSync(resolved, "utf-8");
3279
3484
  }
3280
3485
  const spinner = new Spinner();
3281
3486
  spinner.start(`Uploading ${filename}...`);
@@ -3298,8 +3503,8 @@ async function vaultReadCommand(filename, options) {
3298
3503
  try {
3299
3504
  const file = await readVaultFile(key, filename);
3300
3505
  if (options.output) {
3301
- const outPath = path13.resolve(options.output);
3302
- fs12.writeFileSync(outPath, file.content, "utf-8");
3506
+ const outPath = path15.resolve(options.output);
3507
+ fs14.writeFileSync(outPath, file.content, "utf-8");
3303
3508
  console.log(success(` Saved to ${outPath}`));
3304
3509
  console.log();
3305
3510
  } else {
@@ -3333,45 +3538,10 @@ async function vaultDeleteCommand(filename, options) {
3333
3538
  // src/commands/interactive.ts
3334
3539
  init_esm_shims();
3335
3540
  import { select as select2, confirm as confirm8, checkbox as checkbox5, Separator } from "@inquirer/prompts";
3336
- import fs15 from "fs";
3337
- import path15 from "path";
3541
+ import fs16 from "fs";
3542
+ import path17 from "path";
3338
3543
  import { exec as exec2 } from "child_process";
3339
3544
  import chalk13 from "chalk";
3340
-
3341
- // src/lib/sync.ts
3342
- init_esm_shims();
3343
- import fs13 from "fs";
3344
- function syncStaleConfigs(slug, apiKey, serverUrl) {
3345
- const updated = [];
3346
- for (const tool of TOOLS) {
3347
- if (tool.skillOnly || !tool.generateConfig || !tool.configKey) continue;
3348
- const paths = resolveConfigPaths(tool);
3349
- for (const { filePath, configKey } of paths) {
3350
- if (!fs13.existsSync(filePath)) continue;
3351
- const piutConfig = getPiutConfig(filePath, configKey);
3352
- if (!piutConfig) continue;
3353
- const existingKey = extractKeyFromConfig(piutConfig);
3354
- const existingSlug = extractSlugFromConfig(piutConfig);
3355
- const keyStale = !!existingKey && existingKey !== apiKey;
3356
- const slugStale = !!existingSlug && existingSlug !== slug;
3357
- if (keyStale || slugStale) {
3358
- const newConfig = tool.generateConfig(slug, apiKey);
3359
- mergeConfig(filePath, configKey, newConfig);
3360
- updated.push(tool.name);
3361
- }
3362
- break;
3363
- }
3364
- }
3365
- const cwd = process.cwd();
3366
- const existing = readPiutConfig(cwd);
3367
- if (existing && (existing.apiKey !== apiKey || existing.slug !== slug)) {
3368
- writePiutConfig(cwd, { slug, apiKey, serverUrl });
3369
- updated.push(".piut/config.json");
3370
- }
3371
- return updated;
3372
- }
3373
-
3374
- // src/commands/interactive.ts
3375
3545
  var DOCUMENT_EXTENSIONS2 = /* @__PURE__ */ new Set([
3376
3546
  "pdf",
3377
3547
  "docx",
@@ -3426,6 +3596,34 @@ async function interactiveMenu() {
3426
3596
  if (synced.length > 0) {
3427
3597
  console.log(dim(` Updated ${synced.length} stale config(s): ${synced.join(", ")}`));
3428
3598
  }
3599
+ await offerGlobalInstall();
3600
+ const configuredTools = getConfiguredToolNames();
3601
+ const isDeployed = currentValidation.status === "active";
3602
+ if (configuredTools.length > 0 || isDeployed) {
3603
+ const parts = [];
3604
+ if (isDeployed) {
3605
+ try {
3606
+ await publishServer(apiKey);
3607
+ parts.push("server");
3608
+ } catch {
3609
+ }
3610
+ }
3611
+ if (configuredTools.length > 0) {
3612
+ await cycleMcpConfigs(currentValidation.slug, apiKey);
3613
+ parts.push(`${configuredTools.length} tool(s)`);
3614
+ }
3615
+ const refreshedProjects = await cycleProjectConfigs(
3616
+ currentValidation.slug,
3617
+ apiKey,
3618
+ currentValidation.serverUrl
3619
+ );
3620
+ if (refreshedProjects.length > 0) {
3621
+ parts.push(`${refreshedProjects.length} project(s)`);
3622
+ }
3623
+ if (parts.length > 0) {
3624
+ console.log(dim(` Refreshed: ${parts.join(", ")}`));
3625
+ }
3626
+ }
3429
3627
  console.log();
3430
3628
  if (currentValidation.status === "no_brain") {
3431
3629
  console.log(warning(" You haven\u2019t built a brain yet."));
@@ -3461,7 +3659,7 @@ async function interactiveMenu() {
3461
3659
  }
3462
3660
  while (true) {
3463
3661
  const hasBrain = currentValidation.status !== "no_brain";
3464
- const isDeployed = currentValidation.status === "active";
3662
+ const isDeployed2 = currentValidation.status === "active";
3465
3663
  let action;
3466
3664
  try {
3467
3665
  action = await select2({
@@ -3487,22 +3685,22 @@ async function interactiveMenu() {
3487
3685
  },
3488
3686
  new Separator(),
3489
3687
  {
3490
- name: isDeployed ? "Undeploy Brain" : "Deploy Brain",
3688
+ name: isDeployed2 ? "Undeploy Brain" : "Deploy Brain",
3491
3689
  value: "deploy",
3492
- description: isDeployed ? "Take your MCP server offline" : "Publish your MCP server (requires paid account)"
3690
+ description: isDeployed2 ? "Take your MCP server offline" : "Publish your MCP server (requires paid account)"
3493
3691
  },
3494
3692
  new Separator(),
3495
3693
  {
3496
3694
  name: "Connect Tools",
3497
3695
  value: "connect-tools",
3498
3696
  description: "Manage which AI tools use your MCP server",
3499
- disabled: !isDeployed && "(deploy brain first)"
3697
+ disabled: !isDeployed2 && "(deploy brain first)"
3500
3698
  },
3501
3699
  {
3502
3700
  name: "Connect Projects",
3503
3701
  value: "connect-projects",
3504
3702
  description: "Manage brain references in project config files",
3505
- disabled: !isDeployed && "(deploy brain first)"
3703
+ disabled: !isDeployed2 && "(deploy brain first)"
3506
3704
  },
3507
3705
  new Separator(),
3508
3706
  {
@@ -3549,7 +3747,7 @@ async function interactiveMenu() {
3549
3747
  handleEditBrain();
3550
3748
  break;
3551
3749
  case "deploy":
3552
- if (isDeployed) {
3750
+ if (isDeployed2) {
3553
3751
  await handleUndeploy(apiKey);
3554
3752
  } else {
3555
3753
  await deployCommand({ key: apiKey });
@@ -3620,8 +3818,8 @@ async function handleConnectTools(apiKey, validation) {
3620
3818
  for (const tool of TOOLS) {
3621
3819
  const paths = resolveConfigPaths(tool);
3622
3820
  for (const { filePath, configKey } of paths) {
3623
- const exists = fs15.existsSync(filePath);
3624
- const parentExists = fs15.existsSync(path15.dirname(filePath));
3821
+ const exists = fs16.existsSync(filePath);
3822
+ const parentExists = fs16.existsSync(path17.dirname(filePath));
3625
3823
  if (exists || parentExists) {
3626
3824
  const connected = exists && !!configKey && isPiutConfigured(filePath, configKey);
3627
3825
  detected.push({ tool, configPath: filePath, resolvedConfigKey: configKey, connected });
@@ -3744,29 +3942,29 @@ async function handleManageProjects(apiKey, validation) {
3744
3942
  console.log();
3745
3943
  const copilotTool = TOOLS.find((t) => t.id === "copilot");
3746
3944
  for (const { project } of toConnect) {
3747
- const projectName = path15.basename(project.path);
3945
+ const projectName = path17.basename(project.path);
3748
3946
  writePiutConfig(project.path, { slug, apiKey, serverUrl });
3749
3947
  await writePiutSkill(project.path, slug, apiKey);
3750
3948
  ensureGitignored(project.path);
3751
3949
  if (copilotTool) {
3752
- const hasCopilot = fs15.existsSync(path15.join(project.path, ".github", "copilot-instructions.md")) || fs15.existsSync(path15.join(project.path, ".github"));
3950
+ const hasCopilot = fs16.existsSync(path17.join(project.path, ".github", "copilot-instructions.md")) || fs16.existsSync(path17.join(project.path, ".github"));
3753
3951
  if (hasCopilot) {
3754
- const vscodeMcpPath = path15.join(project.path, ".vscode", "mcp.json");
3952
+ const vscodeMcpPath = path17.join(project.path, ".vscode", "mcp.json");
3755
3953
  const serverConfig = copilotTool.generateConfig(slug, apiKey);
3756
3954
  mergeConfig(vscodeMcpPath, copilotTool.configKey, serverConfig);
3757
3955
  }
3758
3956
  }
3759
3957
  for (const rule of RULE_FILES) {
3760
3958
  if (!rule.detect(project)) continue;
3761
- const absPath = path15.join(project.path, rule.filePath);
3762
- if (fs15.existsSync(absPath) && hasPiutReference2(absPath)) continue;
3763
- if (rule.strategy === "create" || !fs15.existsSync(absPath)) {
3959
+ const absPath = path17.join(project.path, rule.filePath);
3960
+ if (fs16.existsSync(absPath) && hasPiutReference2(absPath)) continue;
3961
+ if (rule.strategy === "create" || !fs16.existsSync(absPath)) {
3764
3962
  const isAppendType = rule.strategy === "append";
3765
3963
  const content = isAppendType ? PROJECT_SKILL_SNIPPET + "\n" : DEDICATED_FILE_CONTENT;
3766
- fs15.mkdirSync(path15.dirname(absPath), { recursive: true });
3767
- fs15.writeFileSync(absPath, content, "utf-8");
3964
+ fs16.mkdirSync(path17.dirname(absPath), { recursive: true });
3965
+ fs16.writeFileSync(absPath, content, "utf-8");
3768
3966
  } else {
3769
- fs15.appendFileSync(absPath, APPEND_SECTION);
3967
+ fs16.appendFileSync(absPath, APPEND_SECTION);
3770
3968
  }
3771
3969
  }
3772
3970
  toolLine(projectName, success("connected"), "\u2714");
@@ -3782,24 +3980,24 @@ async function handleManageProjects(apiKey, validation) {
3782
3980
  });
3783
3981
  }
3784
3982
  for (const { project } of toDisconnect) {
3785
- const projectName = path15.basename(project.path);
3983
+ const projectName = path17.basename(project.path);
3786
3984
  for (const dedicatedFile of DEDICATED_FILES) {
3787
- const absPath = path15.join(project.path, dedicatedFile);
3788
- if (fs15.existsSync(absPath) && hasPiutReference2(absPath)) {
3985
+ const absPath = path17.join(project.path, dedicatedFile);
3986
+ if (fs16.existsSync(absPath) && hasPiutReference2(absPath)) {
3789
3987
  try {
3790
- fs15.unlinkSync(absPath);
3988
+ fs16.unlinkSync(absPath);
3791
3989
  } catch {
3792
3990
  }
3793
3991
  }
3794
3992
  }
3795
3993
  for (const appendFile of APPEND_FILES) {
3796
- const absPath = path15.join(project.path, appendFile);
3797
- if (fs15.existsSync(absPath) && hasPiutReference2(absPath)) {
3994
+ const absPath = path17.join(project.path, appendFile);
3995
+ if (fs16.existsSync(absPath) && hasPiutReference2(absPath)) {
3798
3996
  removePiutSection(absPath);
3799
3997
  }
3800
3998
  }
3801
- const vscodeMcpPath = path15.join(project.path, ".vscode", "mcp.json");
3802
- if (fs15.existsSync(vscodeMcpPath) && isPiutConfigured(vscodeMcpPath, "servers")) {
3999
+ const vscodeMcpPath = path17.join(project.path, ".vscode", "mcp.json");
4000
+ if (fs16.existsSync(vscodeMcpPath) && isPiutConfigured(vscodeMcpPath, "servers")) {
3803
4001
  removeFromConfig(vscodeMcpPath, "servers");
3804
4002
  }
3805
4003
  removePiutDir(project.path);
@@ -3891,16 +4089,16 @@ async function handleVaultUpload(apiKey) {
3891
4089
  console.log();
3892
4090
  let uploaded = 0;
3893
4091
  for (const filePath of files) {
3894
- const filename = path15.basename(filePath);
4092
+ const filename = path17.basename(filePath);
3895
4093
  const ext = filename.includes(".") ? filename.split(".").pop()?.toLowerCase() || "" : "";
3896
4094
  const isDocument = DOCUMENT_EXTENSIONS2.has(ext);
3897
4095
  let content;
3898
4096
  let encoding;
3899
4097
  if (isDocument) {
3900
- content = fs15.readFileSync(filePath).toString("base64");
4098
+ content = fs16.readFileSync(filePath).toString("base64");
3901
4099
  encoding = "base64";
3902
4100
  } else {
3903
- content = fs15.readFileSync(filePath, "utf-8");
4101
+ content = fs16.readFileSync(filePath, "utf-8");
3904
4102
  }
3905
4103
  const spinner = new Spinner();
3906
4104
  spinner.start(`Uploading ${filename}...`);
@@ -3976,7 +4174,7 @@ async function handleViewBrain(apiKey) {
3976
4174
  }
3977
4175
 
3978
4176
  // src/cli.ts
3979
- var VERSION = "3.9.0";
4177
+ var VERSION = "3.10.0";
3980
4178
  function withExit(fn) {
3981
4179
  return async (...args2) => {
3982
4180
  try {
@@ -4002,6 +4200,7 @@ program.command("remove").description("Remove all p\u0131ut configurations").act
4002
4200
  program.command("login").description("Authenticate with p\u0131ut (email, browser, or API key)").action(withExit(loginCommand));
4003
4201
  program.command("logout").description("Remove saved API key").action(logoutCommand);
4004
4202
  program.command("doctor").description("Diagnose and fix connection issues").option("-k, --key <key>", "API key to verify against").option("--fix", "Auto-fix stale configurations").option("--json", "Output results as JSON").action(withExit(doctorCommand));
4203
+ program.command("refresh").description("Force all configured tools to reconnect to your MCP server").option("-k, --key <key>", "API key").action(withExit(refreshCommand));
4005
4204
  var vault = program.command("vault").description("Manage your file vault (upload, list, read, delete)");
4006
4205
  vault.command("list").description("List all files in your vault").option("-k, --key <key>", "API key").action(withExit(vaultListCommand));
4007
4206
  vault.command("upload <file>").description("Upload a file to your vault").option("-k, --key <key>", "API key").action(withExit(vaultUploadCommand));