@phren/cli 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/mcp/dist/init.js +66 -1
  2. package/package.json +1 -1
package/mcp/dist/init.js CHANGED
@@ -5,7 +5,7 @@
5
5
  import * as fs from "fs";
6
6
  import * as path from "path";
7
7
  import * as crypto from "crypto";
8
- import { execFileSync } from "child_process";
8
+ import { execFileSync, spawnSync } from "child_process";
9
9
  import { configureAllHooks } from "./hooks.js";
10
10
  import { getMachineName, machineFilePath, persistMachineName } from "./machine-identity.js";
11
11
  import { atomicWriteText, debugLog, isRecord, hookConfigPath, homeDir, homePath, expandHomePath, findPhrenPath, getProjectDirs, readRootManifest, writeRootManifest, } from "./shared.js";
@@ -24,6 +24,7 @@ import { DEFAULT_PHREN_PATH, STARTER_DIR, VERSION, log, confirmPrompt } from "./
24
24
  import { PROJECT_OWNERSHIP_MODES, getProjectOwnershipDefault, } from "./project-config.js";
25
25
  import { getWorkflowPolicy, updateWorkflowPolicy } from "./shared-governance.js";
26
26
  import { addProjectToProfile } from "./profile-store.js";
27
+ const PHREN_NPM_PACKAGE_NAME = "@phren/cli";
27
28
  function parseVersion(version) {
28
29
  const match = version.trim().match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?/);
29
30
  if (!match)
@@ -58,6 +59,56 @@ export function isVersionNewer(current, previous) {
58
59
  return true;
59
60
  return c.pre > p.pre;
60
61
  }
62
+ function getNpmCommand() {
63
+ return process.platform === "win32" ? "npm.cmd" : "npm";
64
+ }
65
+ function runSyncCommand(command, args) {
66
+ try {
67
+ const result = spawnSync(command, args, {
68
+ encoding: "utf8",
69
+ stdio: ["ignore", "pipe", "pipe"],
70
+ });
71
+ return {
72
+ ok: result.status === 0,
73
+ status: result.status,
74
+ stdout: typeof result.stdout === "string" ? result.stdout : "",
75
+ stderr: typeof result.stderr === "string" ? result.stderr : "",
76
+ };
77
+ }
78
+ catch (err) {
79
+ return {
80
+ ok: false,
81
+ status: null,
82
+ stdout: "",
83
+ stderr: errorMessage(err),
84
+ };
85
+ }
86
+ }
87
+ function shouldUninstallCurrentGlobalPackage() {
88
+ const entryScript = process.argv[1];
89
+ if (!entryScript)
90
+ return false;
91
+ const npmRootResult = runSyncCommand(getNpmCommand(), ["root", "-g"]);
92
+ if (!npmRootResult.ok)
93
+ return false;
94
+ const npmRoot = npmRootResult.stdout.trim();
95
+ if (!npmRoot)
96
+ return false;
97
+ const resolvedEntryScript = path.resolve(entryScript);
98
+ const resolvedGlobalPackageRoot = path.resolve(path.join(npmRoot, PHREN_NPM_PACKAGE_NAME));
99
+ return resolvedEntryScript === resolvedGlobalPackageRoot
100
+ || resolvedEntryScript.startsWith(`${resolvedGlobalPackageRoot}${path.sep}`);
101
+ }
102
+ function uninstallCurrentGlobalPackage() {
103
+ const result = runSyncCommand(getNpmCommand(), ["uninstall", "-g", PHREN_NPM_PACKAGE_NAME]);
104
+ if (result.ok) {
105
+ log(` Removed global npm package (${PHREN_NPM_PACKAGE_NAME})`);
106
+ return;
107
+ }
108
+ const detail = result.stderr.trim() || result.stdout.trim() || (result.status === null ? "failed to start command" : `exit code ${result.status}`);
109
+ log(` Warning: could not remove global npm package (${PHREN_NPM_PACKAGE_NAME})`);
110
+ debugLog(`uninstall: global npm cleanup failed: ${detail}`);
111
+ }
61
112
  export function parseMcpMode(raw) {
62
113
  if (!raw)
63
114
  return undefined;
@@ -1732,6 +1783,7 @@ export async function runUninstall(opts = {}) {
1732
1783
  return;
1733
1784
  }
1734
1785
  log("\nUninstalling phren...\n");
1786
+ const shouldRemoveGlobalPackage = shouldUninstallCurrentGlobalPackage();
1735
1787
  // Confirmation prompt (shared-mode only — project-local is low-stakes)
1736
1788
  if (!opts.yes) {
1737
1789
  const confirmed = phrenPath
@@ -1924,6 +1976,16 @@ export async function runUninstall(opts = {}) {
1924
1976
  catch (err) {
1925
1977
  debugLog(`uninstall: cleanup failed for ${machineFile}: ${errorMessage(err)}`);
1926
1978
  }
1979
+ const contextFile = homePath(".phren-context.md");
1980
+ try {
1981
+ if (fs.existsSync(contextFile)) {
1982
+ fs.unlinkSync(contextFile);
1983
+ log(` Removed machine context file (${contextFile})`);
1984
+ }
1985
+ }
1986
+ catch (err) {
1987
+ debugLog(`uninstall: cleanup failed for ${contextFile}: ${errorMessage(err)}`);
1988
+ }
1927
1989
  // Sweep agent skill directories for symlinks pointing into the phren store
1928
1990
  if (phrenPath) {
1929
1991
  try {
@@ -1943,6 +2005,9 @@ export async function runUninstall(opts = {}) {
1943
2005
  log(` Warning: could not remove phren root (${phrenPath})`);
1944
2006
  }
1945
2007
  }
2008
+ if (shouldRemoveGlobalPackage) {
2009
+ uninstallCurrentGlobalPackage();
2010
+ }
1946
2011
  log(`\nPhren config, hooks, and installed data removed.`);
1947
2012
  log(`Restart your agent(s) to apply changes.\n`);
1948
2013
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phren/cli",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "description": "Knowledge layer for AI agents. Phren learns and recalls.",
5
5
  "type": "module",
6
6
  "bin": {