@kevin0181/memoc 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/cli.js +126 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npx @kevin0181/memoc init
|
|
|
12
12
|
|
|
13
13
|
Run inside your project directory. Detects your stack automatically and generates everything agents need.
|
|
14
14
|
|
|
15
|
-
`init` also creates
|
|
15
|
+
`init` also creates PATH helpers so agents can keep using memoc even when the global/npm bin is not on PATH. It installs a user-local `memoc` launcher and adds that launcher directory to PATH on Windows, macOS, and Linux; open a new terminal if the current shell does not pick it up immediately.
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
# PowerShell
|
package/bin/cli.js
CHANGED
|
@@ -220,6 +220,14 @@ function tplMemocShWrapper() {
|
|
|
220
220
|
return `#!/bin/sh\nexec npx @kevin0181/memoc "$@"\n`;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
function defaultUserBinDir() {
|
|
224
|
+
if (process.env.MEMOC_USER_BIN_DIR) return process.env.MEMOC_USER_BIN_DIR;
|
|
225
|
+
if (currentPlatform() === 'win32') {
|
|
226
|
+
return path.join(process.env.LOCALAPPDATA || path.join(process.env.USERPROFILE || process.cwd(), 'AppData', 'Local'), 'memoc', 'bin');
|
|
227
|
+
}
|
|
228
|
+
return path.join(process.env.HOME || process.cwd(), '.local', 'bin');
|
|
229
|
+
}
|
|
230
|
+
|
|
223
231
|
function tplEnvPs1() {
|
|
224
232
|
return `$memocBin = Join-Path $PSScriptRoot 'bin'\n$parts = $env:PATH -split [IO.Path]::PathSeparator\nif ($parts -notcontains $memocBin) {\n $env:PATH = \"$memocBin$([IO.Path]::PathSeparator)$env:PATH\"\n}\n`;
|
|
225
233
|
}
|
|
@@ -245,6 +253,121 @@ function ensurePathHelpers(dir, mark) {
|
|
|
245
253
|
}
|
|
246
254
|
}
|
|
247
255
|
|
|
256
|
+
function ensureUserLauncher(mark) {
|
|
257
|
+
const userBin = defaultUserBinDir();
|
|
258
|
+
const files = [
|
|
259
|
+
[path.join(userBin, 'memoc.cmd'), tplMemocCmdWrapper, false],
|
|
260
|
+
[path.join(userBin, 'memoc.ps1'), tplMemocPs1Wrapper, false],
|
|
261
|
+
[path.join(userBin, 'memoc'), tplMemocShWrapper, true],
|
|
262
|
+
];
|
|
263
|
+
|
|
264
|
+
for (const [fp, tpl, executable] of files) {
|
|
265
|
+
const added = ensure(fp, tpl());
|
|
266
|
+
if (executable) chmodExecutable(fp);
|
|
267
|
+
mark(added ? 'add' : 'skip', `user bin ${path.basename(fp)}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return userBin;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function ensurePathRegistration(dir, mark) {
|
|
274
|
+
const binDir = ensureUserLauncher(mark);
|
|
275
|
+
const pathSep = path.delimiter;
|
|
276
|
+
|
|
277
|
+
if ((process.env.PATH || '').split(pathSep).some(p => samePath(p, binDir))) {
|
|
278
|
+
mark('skip', 'PATH (user memoc bin already active)');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
process.env.PATH = `${binDir}${pathSep}${process.env.PATH || ''}`;
|
|
283
|
+
|
|
284
|
+
if (process.env.MEMOC_SKIP_PATH_REGISTER === '1') {
|
|
285
|
+
mark('skip', 'PATH registration (test mode)');
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (currentPlatform() !== 'win32') {
|
|
290
|
+
const updated = ensureUnixPathRegistration(binDir);
|
|
291
|
+
mark(updated ? 'update' : 'skip', `${currentPlatform()} PATH (${userPathShellHint(binDir)})`);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
const current = require('child_process')
|
|
297
|
+
.execFileSync('powershell.exe', [
|
|
298
|
+
'-NoProfile',
|
|
299
|
+
'-ExecutionPolicy', 'Bypass',
|
|
300
|
+
'-Command',
|
|
301
|
+
"[Environment]::GetEnvironmentVariable('Path','User')",
|
|
302
|
+
], { encoding: 'utf8' })
|
|
303
|
+
.trim();
|
|
304
|
+
const parts = current.split(pathSep).filter(Boolean);
|
|
305
|
+
if (parts.some(p => samePath(p, binDir))) {
|
|
306
|
+
mark('skip', 'User PATH (memoc bin already registered)');
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const nextPath = [binDir, ...parts].join(pathSep);
|
|
310
|
+
require('child_process').execFileSync('powershell.exe', [
|
|
311
|
+
'-NoProfile',
|
|
312
|
+
'-ExecutionPolicy', 'Bypass',
|
|
313
|
+
'-Command',
|
|
314
|
+
`[Environment]::SetEnvironmentVariable('Path', ${JSON.stringify(nextPath)}, 'User')`,
|
|
315
|
+
], { stdio: 'ignore' });
|
|
316
|
+
mark('update', 'User PATH (memoc bin added; open a new terminal if needed)');
|
|
317
|
+
} catch {
|
|
318
|
+
mark('skip', 'User PATH registration failed (use . .\\.memoc\\env.ps1)');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function ensureUnixPathRegistration(binDir) {
|
|
323
|
+
if (process.env.MEMOC_SKIP_PATH_REGISTER === '1') return false;
|
|
324
|
+
|
|
325
|
+
const home = process.env.HOME;
|
|
326
|
+
if (!home) return false;
|
|
327
|
+
|
|
328
|
+
const block = [
|
|
329
|
+
'# memoc PATH',
|
|
330
|
+
`MEMOC_BIN=${shellSingleQuote(binDir)}`,
|
|
331
|
+
'case ":$PATH:" in *":$MEMOC_BIN:"*) ;; *) PATH="$MEMOC_BIN:$PATH"; export PATH ;; esac',
|
|
332
|
+
'# end memoc PATH',
|
|
333
|
+
].join('\n');
|
|
334
|
+
|
|
335
|
+
const candidates = [
|
|
336
|
+
path.join(home, '.profile'),
|
|
337
|
+
path.join(home, '.zshrc'),
|
|
338
|
+
path.join(home, '.bashrc'),
|
|
339
|
+
];
|
|
340
|
+
|
|
341
|
+
let changed = false;
|
|
342
|
+
for (const fp of candidates) {
|
|
343
|
+
try {
|
|
344
|
+
const src = fs.existsSync(fp) ? fs.readFileSync(fp, 'utf8') : '';
|
|
345
|
+
if (src.includes(binDir) || src.includes('# memoc PATH')) continue;
|
|
346
|
+
fs.appendFileSync(fp, `${src.endsWith('\n') || !src ? '' : '\n'}\n${block}\n`, 'utf8');
|
|
347
|
+
changed = true;
|
|
348
|
+
} catch {}
|
|
349
|
+
}
|
|
350
|
+
return changed;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function userPathShellHint(binDir) {
|
|
354
|
+
return `user bin ${binDir} ${process.env.MEMOC_SKIP_PATH_REGISTER === '1' ? 'test mode' : 'registered; open a new terminal if needed'}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function currentPlatform() {
|
|
358
|
+
return process.env.MEMOC_PLATFORM || process.platform;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function shellSingleQuote(value) {
|
|
362
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function samePath(a, b) {
|
|
366
|
+
if (!a || !b) return false;
|
|
367
|
+
const norm = p => path.resolve(p).toLowerCase().replace(/[\\/]+$/, '');
|
|
368
|
+
try { return norm(a) === norm(b); } catch { return false; }
|
|
369
|
+
}
|
|
370
|
+
|
|
248
371
|
function updateSection(filePath, startMark, endMark, inner) {
|
|
249
372
|
if (!fs.existsSync(filePath)) return false;
|
|
250
373
|
const src = fs.readFileSync(filePath, 'utf8');
|
|
@@ -290,7 +413,7 @@ function managedBlock() {
|
|
|
290
413
|
## Session Start
|
|
291
414
|
- [ ] Read \`.memoc/session-summary.md\`
|
|
292
415
|
- [ ] \`.pending\` exists? → review changed files → update memory if needed → delete it
|
|
293
|
-
- [ ]
|
|
416
|
+
- [ ] If \`memoc\` is not found in an existing shell, open a new terminal or load the local helper: PowerShell \`. .\\.memoc\\env.ps1\`; sh \`. ./.memoc/env.sh\`
|
|
294
417
|
|
|
295
418
|
## Before Opening More Files
|
|
296
419
|
- [ ] Run memoc commands in this order: \`memoc search "<query>"\` → \`.\\.memoc\\bin\\memoc.cmd search "<query>"\` (Windows) or \`.memoc/bin/memoc search "<query>"\` (sh) → \`npx @kevin0181/memoc search "<query>"\`
|
|
@@ -1074,6 +1197,7 @@ function run(dir, forceUpdate) {
|
|
|
1074
1197
|
|
|
1075
1198
|
// PATH helpers — let agents run memoc even when the npm bin is not on PATH
|
|
1076
1199
|
ensurePathHelpers(dir, mark);
|
|
1200
|
+
ensurePathRegistration(dir, mark);
|
|
1077
1201
|
|
|
1078
1202
|
} else {
|
|
1079
1203
|
// ── UPDATE MODE
|
|
@@ -1166,6 +1290,7 @@ function run(dir, forceUpdate) {
|
|
|
1166
1290
|
|
|
1167
1291
|
// PATH helpers — let agents run memoc even when the npm bin is not on PATH
|
|
1168
1292
|
ensurePathHelpers(dir, mark);
|
|
1293
|
+
ensurePathRegistration(dir, mark);
|
|
1169
1294
|
|
|
1170
1295
|
// Append update record to log.md
|
|
1171
1296
|
const logPath = path.join(memDir, 'log.md');
|