mnotes-cli 1.11.0 → 1.12.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.
- package/dist/commands/connect/__tests__/wizard.test.js +44 -6
- package/dist/commands/connect/wizard.js +9 -5
- package/dist/templates/claude-code/hooks.d.ts +13 -4
- package/dist/templates/claude-code/hooks.js +57 -7
- package/dist/templates/claude-code/index.d.ts +1 -1
- package/dist/templates/claude-code/index.js +3 -1
- package/package.json +1 -1
|
@@ -68,14 +68,16 @@ const DEFAULT_OPTS = {
|
|
|
68
68
|
// T-1: Template generation — hooks
|
|
69
69
|
// =============================================================
|
|
70
70
|
(0, vitest_1.describe)("hooks template", () => {
|
|
71
|
-
(0, vitest_1.it)("generates SessionStart hook referencing bash script", () => {
|
|
71
|
+
(0, vitest_1.it)("generates SessionStart hook referencing global bash script path", () => {
|
|
72
72
|
const hooks = (0, hooks_1.generateHooksTemplate)(DEFAULT_OPTS);
|
|
73
73
|
(0, vitest_1.expect)(hooks.SessionStart).toBeDefined();
|
|
74
74
|
(0, vitest_1.expect)(hooks.SessionStart).toHaveLength(1);
|
|
75
75
|
(0, vitest_1.expect)(hooks.SessionStart[0].matcher).toBe("");
|
|
76
76
|
(0, vitest_1.expect)(hooks.SessionStart[0].hooks).toHaveLength(1);
|
|
77
77
|
(0, vitest_1.expect)(hooks.SessionStart[0].hooks[0].type).toBe("command");
|
|
78
|
-
|
|
78
|
+
// Global path — resolves at generation time via os.homedir()
|
|
79
|
+
(0, vitest_1.expect)(hooks.SessionStart[0].hooks[0].command).toContain(path.join(".claude", "hooks", "mnotes", "scripts", "mnotes-session-start.sh"));
|
|
80
|
+
(0, vitest_1.expect)(path.isAbsolute(hooks.SessionStart[0].hooks[0].command)).toBe(true);
|
|
79
81
|
});
|
|
80
82
|
(0, vitest_1.it)("generates hook scripts with correct URL, workspaceId, and Accept headers", () => {
|
|
81
83
|
const scripts = (0, hooks_1.generateHookScripts)(DEFAULT_OPTS);
|
|
@@ -178,29 +180,45 @@ const DEFAULT_OPTS = {
|
|
|
178
180
|
// =============================================================
|
|
179
181
|
(0, vitest_1.describe)("scaffoldItems: hooks", () => {
|
|
180
182
|
let tmpDir;
|
|
183
|
+
let fakeHome;
|
|
184
|
+
let origHome;
|
|
181
185
|
(0, vitest_1.beforeEach)(() => {
|
|
182
186
|
tmpDir = makeTmpDir();
|
|
187
|
+
fakeHome = makeTmpDir();
|
|
188
|
+
origHome = process.env.HOME;
|
|
189
|
+
process.env.HOME = fakeHome;
|
|
183
190
|
});
|
|
184
191
|
(0, vitest_1.afterEach)(() => {
|
|
185
192
|
cleanTmpDir(tmpDir);
|
|
193
|
+
cleanTmpDir(fakeHome);
|
|
194
|
+
if (origHome === undefined)
|
|
195
|
+
delete process.env.HOME;
|
|
196
|
+
else
|
|
197
|
+
process.env.HOME = origHome;
|
|
186
198
|
});
|
|
187
|
-
(0, vitest_1.it)("
|
|
199
|
+
(0, vitest_1.it)("writes scripts to global ~/.claude/hooks/mnotes/scripts/ and settings.json to project (AC-4)", () => {
|
|
188
200
|
const results = (0, wizard_1.scaffoldItems)(tmpDir, ["hooks"], DEFAULT_OPTS);
|
|
189
201
|
(0, vitest_1.expect)(results).toHaveLength(1);
|
|
190
202
|
(0, vitest_1.expect)(results[0].item).toBe("hooks");
|
|
191
203
|
// 2 bash scripts + settings.json
|
|
192
204
|
(0, vitest_1.expect)(results[0].filesWritten).toHaveLength(3);
|
|
205
|
+
// settings.json is project-local
|
|
193
206
|
const settingsPath = path.join(tmpDir, ".claude", "settings.json");
|
|
194
207
|
(0, vitest_1.expect)(fs.existsSync(settingsPath)).toBe(true);
|
|
195
208
|
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
196
209
|
(0, vitest_1.expect)(settings.hooks).toBeDefined();
|
|
197
210
|
(0, vitest_1.expect)(settings.hooks.SessionStart).toBeDefined();
|
|
198
211
|
(0, vitest_1.expect)(settings.hooks.SessionStart).toHaveLength(1);
|
|
199
|
-
// Bash scripts
|
|
200
|
-
const
|
|
201
|
-
const
|
|
212
|
+
// Bash scripts live under fake HOME at ~/.claude/hooks/mnotes/scripts/
|
|
213
|
+
const globalScriptsDir = path.join(fakeHome, ".claude", "hooks", "mnotes", "scripts");
|
|
214
|
+
const startScript = path.join(globalScriptsDir, "mnotes-session-start.sh");
|
|
215
|
+
const stopScript = path.join(globalScriptsDir, "mnotes-session-stop.sh");
|
|
202
216
|
(0, vitest_1.expect)(fs.existsSync(startScript)).toBe(true);
|
|
203
217
|
(0, vitest_1.expect)(fs.existsSync(stopScript)).toBe(true);
|
|
218
|
+
// Project directory must NOT contain scripts
|
|
219
|
+
(0, vitest_1.expect)(fs.existsSync(path.join(tmpDir, ".claude", "hooks"))).toBe(false);
|
|
220
|
+
// settings.json references the global absolute path
|
|
221
|
+
(0, vitest_1.expect)(settings.hooks.SessionStart[0].hooks[0].command).toBe(startScript);
|
|
204
222
|
const startContent = fs.readFileSync(startScript, "utf-8");
|
|
205
223
|
(0, vitest_1.expect)(startContent).toContain("Accept: text/event-stream");
|
|
206
224
|
(0, vitest_1.expect)(startContent).toContain("Accept: application/json");
|
|
@@ -348,11 +366,16 @@ const DEFAULT_OPTS = {
|
|
|
348
366
|
// =============================================================
|
|
349
367
|
(0, vitest_1.describe)("handleClaudeCode with wizard flags", () => {
|
|
350
368
|
let tmpDir;
|
|
369
|
+
let fakeHome;
|
|
370
|
+
let origHome;
|
|
351
371
|
let origCwd;
|
|
352
372
|
let origExit;
|
|
353
373
|
let exitCode;
|
|
354
374
|
(0, vitest_1.beforeEach)(() => {
|
|
355
375
|
tmpDir = makeTmpDir();
|
|
376
|
+
fakeHome = makeTmpDir();
|
|
377
|
+
origHome = process.env.HOME;
|
|
378
|
+
process.env.HOME = fakeHome;
|
|
356
379
|
origCwd = process.cwd;
|
|
357
380
|
process.cwd = () => tmpDir;
|
|
358
381
|
exitCode = undefined;
|
|
@@ -366,6 +389,11 @@ const DEFAULT_OPTS = {
|
|
|
366
389
|
process.cwd = origCwd;
|
|
367
390
|
process.exit = origExit;
|
|
368
391
|
cleanTmpDir(tmpDir);
|
|
392
|
+
cleanTmpDir(fakeHome);
|
|
393
|
+
if (origHome === undefined)
|
|
394
|
+
delete process.env.HOME;
|
|
395
|
+
else
|
|
396
|
+
process.env.HOME = origHome;
|
|
369
397
|
vitest_1.vi.restoreAllMocks();
|
|
370
398
|
});
|
|
371
399
|
(0, vitest_1.it)("--no-wizard does core setup only, no extras (AC-6)", async () => {
|
|
@@ -430,10 +458,15 @@ const DEFAULT_OPTS = {
|
|
|
430
458
|
// =============================================================
|
|
431
459
|
(0, vitest_1.describe)("CLI flag integration", () => {
|
|
432
460
|
let tmpDir;
|
|
461
|
+
let fakeHome;
|
|
462
|
+
let origHome;
|
|
433
463
|
let origCwd;
|
|
434
464
|
let origExit;
|
|
435
465
|
(0, vitest_1.beforeEach)(() => {
|
|
436
466
|
tmpDir = makeTmpDir();
|
|
467
|
+
fakeHome = makeTmpDir();
|
|
468
|
+
origHome = process.env.HOME;
|
|
469
|
+
process.env.HOME = fakeHome;
|
|
437
470
|
origCwd = process.cwd;
|
|
438
471
|
process.cwd = () => tmpDir;
|
|
439
472
|
origExit = process.exit;
|
|
@@ -445,6 +478,11 @@ const DEFAULT_OPTS = {
|
|
|
445
478
|
process.cwd = origCwd;
|
|
446
479
|
process.exit = origExit;
|
|
447
480
|
cleanTmpDir(tmpDir);
|
|
481
|
+
cleanTmpDir(fakeHome);
|
|
482
|
+
if (origHome === undefined)
|
|
483
|
+
delete process.env.HOME;
|
|
484
|
+
else
|
|
485
|
+
process.env.HOME = origHome;
|
|
448
486
|
vitest_1.vi.restoreAllMocks();
|
|
449
487
|
});
|
|
450
488
|
(0, vitest_1.it)("--no-wizard flag is recognized by commander", async () => {
|
|
@@ -102,19 +102,23 @@ function scaffoldItems(dir, items, opts) {
|
|
|
102
102
|
return results;
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
|
-
* Merges hooks into
|
|
105
|
+
* Merges hooks into `<project>/.claude/settings.json` and writes bash scripts to
|
|
106
|
+
* `~/.claude/hooks/mnotes/scripts/` (user-global, namespaced under `mnotes`).
|
|
107
|
+
* Scripts live globally so they're shared across projects; settings.json stays
|
|
108
|
+
* project-local so each project opts in independently.
|
|
106
109
|
* Preserves all existing settings and hooks.
|
|
107
110
|
*/
|
|
108
111
|
function scaffoldHooks(dir, opts) {
|
|
109
112
|
const settingsPath = path.join(dir, ".claude", "settings.json");
|
|
110
113
|
const claudeDir = path.join(dir, ".claude");
|
|
111
|
-
const
|
|
112
|
-
fs.mkdirSync(
|
|
114
|
+
const hookScriptsDir = (0, index_1.getHookScriptsDir)();
|
|
115
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
116
|
+
fs.mkdirSync(hookScriptsDir, { recursive: true });
|
|
113
117
|
const filesWritten = [];
|
|
114
|
-
// 1. Write bash scripts to
|
|
118
|
+
// 1. Write bash scripts to ~/.claude/hooks/mnotes/scripts/
|
|
115
119
|
const scripts = (0, index_1.generateHookScripts)(opts);
|
|
116
120
|
for (const script of scripts) {
|
|
117
|
-
const scriptPath = path.join(
|
|
121
|
+
const scriptPath = path.join(hookScriptsDir, script.filename);
|
|
118
122
|
fs.writeFileSync(scriptPath, script.content, { mode: 0o755 });
|
|
119
123
|
filesWritten.push(scriptPath);
|
|
120
124
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Template for Claude Code session hooks.
|
|
3
|
-
* Generates bash scripts in
|
|
4
|
-
*
|
|
3
|
+
* Generates bash scripts in `~/.claude/hooks/mnotes/scripts/` (user-global,
|
|
4
|
+
* namespaced under `mnotes`) and hook entries for `.claude/settings.json`
|
|
5
|
+
* (project-local). Generated by m-notes CLI — do not edit manually.
|
|
5
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* Absolute path where m-notes hook scripts live (user-global, namespaced).
|
|
9
|
+
* Resolved via function so tests can override `HOME` to point to a tmp dir.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getHookScriptsDir(): string;
|
|
12
|
+
/** @deprecated kept for backward compatibility — use `getHookScriptsDir()` so HOME overrides work. */
|
|
13
|
+
export declare const HOOK_SCRIPTS_DIR: string;
|
|
6
14
|
export interface HooksTemplateOpts {
|
|
7
15
|
url: string;
|
|
8
16
|
workspaceId: string;
|
|
@@ -29,8 +37,9 @@ export interface HookScript {
|
|
|
29
37
|
export declare function generateHookScripts(opts: HooksTemplateOpts): HookScript[];
|
|
30
38
|
/**
|
|
31
39
|
* Generates the hooks object to merge into `.claude/settings.json`.
|
|
32
|
-
* References bash scripts in
|
|
40
|
+
* References bash scripts in `~/.claude/hooks/mnotes/scripts/` (absolute path
|
|
41
|
+
* so hooks work across projects without per-project script copies).
|
|
33
42
|
*/
|
|
34
|
-
export declare function generateHooksTemplate(
|
|
43
|
+
export declare function generateHooksTemplate(_opts: HooksTemplateOpts): ClaudeCodeHooks;
|
|
35
44
|
/** Header comment for the hooks section, used for identification. */
|
|
36
45
|
export declare const HOOKS_HEADER = "m-notes: auto-generated hooks";
|
|
@@ -1,13 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Template for Claude Code session hooks.
|
|
4
|
-
* Generates bash scripts in
|
|
5
|
-
*
|
|
4
|
+
* Generates bash scripts in `~/.claude/hooks/mnotes/scripts/` (user-global,
|
|
5
|
+
* namespaced under `mnotes`) and hook entries for `.claude/settings.json`
|
|
6
|
+
* (project-local). Generated by m-notes CLI — do not edit manually.
|
|
6
7
|
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
7
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.HOOKS_HEADER = void 0;
|
|
42
|
+
exports.HOOKS_HEADER = exports.HOOK_SCRIPTS_DIR = void 0;
|
|
43
|
+
exports.getHookScriptsDir = getHookScriptsDir;
|
|
9
44
|
exports.generateHookScripts = generateHookScripts;
|
|
10
45
|
exports.generateHooksTemplate = generateHooksTemplate;
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
/**
|
|
49
|
+
* Absolute path where m-notes hook scripts live (user-global, namespaced).
|
|
50
|
+
* Resolved via function so tests can override `HOME` to point to a tmp dir.
|
|
51
|
+
*/
|
|
52
|
+
function getHookScriptsDir() {
|
|
53
|
+
return path.join(os.homedir(), ".claude", "hooks", "mnotes", "scripts");
|
|
54
|
+
}
|
|
55
|
+
/** @deprecated kept for backward compatibility — use `getHookScriptsDir()` so HOME overrides work. */
|
|
56
|
+
exports.HOOK_SCRIPTS_DIR = getHookScriptsDir();
|
|
11
57
|
/**
|
|
12
58
|
* Generates bash scripts to be written to `.claude/hooks/`.
|
|
13
59
|
*/
|
|
@@ -61,9 +107,13 @@ curl -s \\
|
|
|
61
107
|
}
|
|
62
108
|
/**
|
|
63
109
|
* Generates the hooks object to merge into `.claude/settings.json`.
|
|
64
|
-
* References bash scripts in
|
|
110
|
+
* References bash scripts in `~/.claude/hooks/mnotes/scripts/` (absolute path
|
|
111
|
+
* so hooks work across projects without per-project script copies).
|
|
65
112
|
*/
|
|
66
|
-
function generateHooksTemplate(
|
|
113
|
+
function generateHooksTemplate(_opts) {
|
|
114
|
+
const dir = getHookScriptsDir();
|
|
115
|
+
const startScript = path.join(dir, "mnotes-session-start.sh");
|
|
116
|
+
const stopScript = path.join(dir, "mnotes-session-stop.sh");
|
|
67
117
|
return {
|
|
68
118
|
SessionStart: [
|
|
69
119
|
{
|
|
@@ -71,7 +121,7 @@ function generateHooksTemplate(opts) {
|
|
|
71
121
|
hooks: [
|
|
72
122
|
{
|
|
73
123
|
type: "command",
|
|
74
|
-
command:
|
|
124
|
+
command: startScript,
|
|
75
125
|
},
|
|
76
126
|
],
|
|
77
127
|
},
|
|
@@ -82,7 +132,7 @@ function generateHooksTemplate(opts) {
|
|
|
82
132
|
hooks: [
|
|
83
133
|
{
|
|
84
134
|
type: "command",
|
|
85
|
-
command:
|
|
135
|
+
command: stopScript,
|
|
86
136
|
},
|
|
87
137
|
],
|
|
88
138
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { generateHooksTemplate, generateHookScripts, HOOKS_HEADER } from "./hooks";
|
|
1
|
+
export { generateHooksTemplate, generateHookScripts, HOOKS_HEADER, HOOK_SCRIPTS_DIR, getHookScriptsDir } from "./hooks";
|
|
2
2
|
export type { HooksTemplateOpts, ClaudeCodeHooks, ClaudeCodeHook, HookScript } from "./hooks";
|
|
3
3
|
export { generateSkillTemplates } from "./skills";
|
|
4
4
|
export type { SkillTemplateOpts, SkillFile } from "./skills";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateAgentTemplates = exports.generateSkillTemplates = exports.HOOKS_HEADER = exports.generateHookScripts = exports.generateHooksTemplate = void 0;
|
|
3
|
+
exports.generateAgentTemplates = exports.generateSkillTemplates = exports.getHookScriptsDir = exports.HOOK_SCRIPTS_DIR = exports.HOOKS_HEADER = exports.generateHookScripts = exports.generateHooksTemplate = void 0;
|
|
4
4
|
var hooks_1 = require("./hooks");
|
|
5
5
|
Object.defineProperty(exports, "generateHooksTemplate", { enumerable: true, get: function () { return hooks_1.generateHooksTemplate; } });
|
|
6
6
|
Object.defineProperty(exports, "generateHookScripts", { enumerable: true, get: function () { return hooks_1.generateHookScripts; } });
|
|
7
7
|
Object.defineProperty(exports, "HOOKS_HEADER", { enumerable: true, get: function () { return hooks_1.HOOKS_HEADER; } });
|
|
8
|
+
Object.defineProperty(exports, "HOOK_SCRIPTS_DIR", { enumerable: true, get: function () { return hooks_1.HOOK_SCRIPTS_DIR; } });
|
|
9
|
+
Object.defineProperty(exports, "getHookScriptsDir", { enumerable: true, get: function () { return hooks_1.getHookScriptsDir; } });
|
|
8
10
|
var skills_1 = require("./skills");
|
|
9
11
|
Object.defineProperty(exports, "generateSkillTemplates", { enumerable: true, get: function () { return skills_1.generateSkillTemplates; } });
|
|
10
12
|
var agents_1 = require("./agents");
|