@phren/cli 0.0.33 → 0.0.34

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/mcp/dist/hooks.js CHANGED
@@ -200,6 +200,44 @@ exit $status
200
200
  return false;
201
201
  }
202
202
  }
203
+ /**
204
+ * Install a lightweight `phren` CLI wrapper at ~/.local/bin/phren so the bare
205
+ * `phren` command works without a global npm install. The wrapper simply execs
206
+ * `node <entry_script> "$@"`.
207
+ */
208
+ export function installPhrenCliWrapper(phrenPath) {
209
+ const entry = resolveCliEntryScript();
210
+ if (!entry)
211
+ return false;
212
+ const localBinDir = homePath(".local", "bin");
213
+ const wrapperPath = path.join(localBinDir, "phren");
214
+ // Don't overwrite a real global install — only our own wrapper
215
+ if (fs.existsSync(wrapperPath)) {
216
+ try {
217
+ const existing = fs.readFileSync(wrapperPath, "utf8");
218
+ if (!existing.includes("PHREN_CLI_WRAPPER"))
219
+ return false;
220
+ }
221
+ catch { /* unreadable — skip */ }
222
+ }
223
+ const content = `#!/bin/sh
224
+ # PHREN_CLI_WRAPPER — managed by phren init; safe to delete
225
+ set -u
226
+ PHREN_PATH="\${PHREN_PATH:-${shellEscape(phrenPath)}}"
227
+ export PHREN_PATH
228
+ exec node ${shellEscape(entry)} "$@"
229
+ `;
230
+ try {
231
+ fs.mkdirSync(localBinDir, { recursive: true });
232
+ atomicWriteText(wrapperPath, content);
233
+ fs.chmodSync(wrapperPath, 0o755);
234
+ return true;
235
+ }
236
+ catch (err) {
237
+ debugLog(`installPhrenCliWrapper: failed: ${errorMessage(err)}`);
238
+ return false;
239
+ }
240
+ }
203
241
  function validateCopilotConfig(config) {
204
242
  return (typeof config.version === "number" &&
205
243
  Array.isArray(config.hooks?.sessionStart) &&
@@ -6,7 +6,7 @@ import * as fs from "fs";
6
6
  import * as path from "path";
7
7
  import * as crypto from "crypto";
8
8
  import { execFileSync, spawnSync } from "child_process";
9
- import { configureAllHooks } from "../hooks.js";
9
+ import { configureAllHooks, installPhrenCliWrapper } 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";
12
12
  import { isValidProjectName, errorMessage } from "../utils.js";
@@ -969,6 +969,15 @@ function configureHooksIfEnabled(phrenPath, hooksEnabled, verb) {
969
969
  else {
970
970
  log(` Hooks are disabled by preference (run: npx phren hooks-mode on)`);
971
971
  }
972
+ // Install phren CLI wrapper at ~/.local/bin/phren so the bare command works
973
+ try {
974
+ if (installPhrenCliWrapper(phrenPath)) {
975
+ log(` ${verb} CLI wrapper: ~/.local/bin/phren`);
976
+ }
977
+ }
978
+ catch (err) {
979
+ debugLog(`installPhrenCliWrapper failed: ${errorMessage(err)}`);
980
+ }
972
981
  }
973
982
  export async function runInit(opts = {}) {
974
983
  if ((opts.mode || "shared") === "project-local") {
@@ -1956,9 +1965,9 @@ export async function runUninstall(opts = {}) {
1956
1965
  catch (err) {
1957
1966
  debugLog(`uninstall: cleanup failed for ${codexHooksFile}: ${errorMessage(err)}`);
1958
1967
  }
1959
- // Remove session wrapper scripts (written by installSessionWrapper)
1968
+ // Remove session wrapper scripts (written by installSessionWrapper) and CLI wrapper
1960
1969
  const localBinDir = path.join(home, ".local", "bin");
1961
- for (const tool of ["copilot", "cursor", "codex"]) {
1970
+ for (const tool of ["copilot", "cursor", "codex", "phren"]) {
1962
1971
  const wrapperPath = path.join(localBinDir, tool);
1963
1972
  try {
1964
1973
  if (fs.existsSync(wrapperPath)) {
@@ -402,6 +402,15 @@ export async function runDoctor(phrenPath, fix = false, checkData = false) {
402
402
  : `${tool} wrapper missing or not first in PATH`,
403
403
  });
404
404
  }
405
+ // Check phren CLI wrapper
406
+ const phrenCliActive = isWrapperActive("phren");
407
+ checks.push({
408
+ name: "wrapper:phren-cli",
409
+ ok: phrenCliActive,
410
+ detail: phrenCliActive
411
+ ? "phren CLI wrapper active via ~/.local/bin/phren"
412
+ : "phren CLI wrapper missing — run init to install, or npm i -g @phren/cli",
413
+ });
405
414
  if (fix) {
406
415
  const repaired = repairPreexistingInstall(phrenPath);
407
416
  const details = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phren/cli",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "Knowledge layer for AI agents. Phren learns and recalls.",
5
5
  "type": "module",
6
6
  "bin": {