memax-cli 0.1.0-alpha.4 → 0.1.0-alpha.41

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 (177) hide show
  1. package/assets/skills/memax-memory/SKILL.md +154 -0
  2. package/dist/commands/agent-sessions.d.ts +62 -0
  3. package/dist/commands/agent-sessions.d.ts.map +1 -0
  4. package/dist/commands/agent-sessions.js +1338 -0
  5. package/dist/commands/agent-sessions.js.map +1 -0
  6. package/dist/commands/agent-sessions.test.d.ts +2 -0
  7. package/dist/commands/agent-sessions.test.d.ts.map +1 -0
  8. package/dist/commands/agent-sessions.test.js +255 -0
  9. package/dist/commands/agent-sessions.test.js.map +1 -0
  10. package/dist/commands/agents.d.ts +3 -0
  11. package/dist/commands/agents.d.ts.map +1 -0
  12. package/dist/commands/agents.js +36 -0
  13. package/dist/commands/agents.js.map +1 -0
  14. package/dist/commands/ask.d.ts +13 -0
  15. package/dist/commands/ask.d.ts.map +1 -0
  16. package/dist/commands/ask.js +459 -0
  17. package/dist/commands/ask.js.map +1 -0
  18. package/dist/commands/auth.d.ts +3 -0
  19. package/dist/commands/auth.d.ts.map +1 -1
  20. package/dist/commands/auth.js +38 -7
  21. package/dist/commands/auth.js.map +1 -1
  22. package/dist/commands/capture.d.ts +19 -0
  23. package/dist/commands/capture.d.ts.map +1 -0
  24. package/dist/commands/capture.js +69 -0
  25. package/dist/commands/capture.js.map +1 -0
  26. package/dist/commands/config.d.ts +2 -0
  27. package/dist/commands/config.d.ts.map +1 -1
  28. package/dist/commands/config.js +13 -0
  29. package/dist/commands/config.js.map +1 -1
  30. package/dist/commands/delete.d.ts +3 -1
  31. package/dist/commands/delete.d.ts.map +1 -1
  32. package/dist/commands/delete.js +30 -5
  33. package/dist/commands/delete.js.map +1 -1
  34. package/dist/commands/dreams.d.ts +22 -0
  35. package/dist/commands/dreams.d.ts.map +1 -0
  36. package/dist/commands/dreams.js +205 -0
  37. package/dist/commands/dreams.js.map +1 -0
  38. package/dist/commands/dreams.test.d.ts +2 -0
  39. package/dist/commands/dreams.test.d.ts.map +1 -0
  40. package/dist/commands/dreams.test.js +39 -0
  41. package/dist/commands/dreams.test.js.map +1 -0
  42. package/dist/commands/hook.d.ts +2 -0
  43. package/dist/commands/hook.d.ts.map +1 -1
  44. package/dist/commands/hook.js +6 -0
  45. package/dist/commands/hook.js.map +1 -1
  46. package/dist/commands/hub.d.ts +31 -0
  47. package/dist/commands/hub.d.ts.map +1 -0
  48. package/dist/commands/hub.js +295 -0
  49. package/dist/commands/hub.js.map +1 -0
  50. package/dist/commands/hub.test.d.ts +2 -0
  51. package/dist/commands/hub.test.d.ts.map +1 -0
  52. package/dist/commands/hub.test.js +62 -0
  53. package/dist/commands/hub.test.js.map +1 -0
  54. package/dist/commands/list.d.ts +8 -1
  55. package/dist/commands/list.d.ts.map +1 -1
  56. package/dist/commands/list.js +110 -9
  57. package/dist/commands/list.js.map +1 -1
  58. package/dist/commands/list.test.d.ts +2 -0
  59. package/dist/commands/list.test.d.ts.map +1 -0
  60. package/dist/commands/list.test.js +14 -0
  61. package/dist/commands/list.test.js.map +1 -0
  62. package/dist/commands/login.d.ts +2 -0
  63. package/dist/commands/login.d.ts.map +1 -1
  64. package/dist/commands/login.js +50 -19
  65. package/dist/commands/login.js.map +1 -1
  66. package/dist/commands/mcp.d.ts.map +1 -1
  67. package/dist/commands/mcp.js +285 -42
  68. package/dist/commands/mcp.js.map +1 -1
  69. package/dist/commands/push.d.ts +6 -1
  70. package/dist/commands/push.d.ts.map +1 -1
  71. package/dist/commands/push.js +73 -11
  72. package/dist/commands/push.js.map +1 -1
  73. package/dist/commands/recall.d.ts +9 -0
  74. package/dist/commands/recall.d.ts.map +1 -1
  75. package/dist/commands/recall.js +206 -39
  76. package/dist/commands/recall.js.map +1 -1
  77. package/dist/commands/recall.test.d.ts +2 -0
  78. package/dist/commands/recall.test.d.ts.map +1 -0
  79. package/dist/commands/recall.test.js +31 -0
  80. package/dist/commands/recall.test.js.map +1 -0
  81. package/dist/commands/setup-hooks.d.ts +12 -0
  82. package/dist/commands/setup-hooks.d.ts.map +1 -0
  83. package/dist/commands/setup-hooks.js +193 -0
  84. package/dist/commands/setup-hooks.js.map +1 -0
  85. package/dist/commands/setup-instructions.d.ts +21 -0
  86. package/dist/commands/setup-instructions.d.ts.map +1 -0
  87. package/dist/commands/setup-instructions.js +172 -0
  88. package/dist/commands/setup-instructions.js.map +1 -0
  89. package/dist/commands/setup-mcp.d.ts +14 -0
  90. package/dist/commands/setup-mcp.d.ts.map +1 -0
  91. package/dist/commands/setup-mcp.js +288 -0
  92. package/dist/commands/setup-mcp.js.map +1 -0
  93. package/dist/commands/setup-types.d.ts +20 -0
  94. package/dist/commands/setup-types.d.ts.map +1 -0
  95. package/dist/commands/setup-types.js +60 -0
  96. package/dist/commands/setup-types.js.map +1 -0
  97. package/dist/commands/setup.d.ts +8 -1
  98. package/dist/commands/setup.d.ts.map +1 -1
  99. package/dist/commands/setup.js +163 -307
  100. package/dist/commands/setup.js.map +1 -1
  101. package/dist/commands/show.d.ts +2 -0
  102. package/dist/commands/show.d.ts.map +1 -1
  103. package/dist/commands/show.js +25 -13
  104. package/dist/commands/show.js.map +1 -1
  105. package/dist/commands/sync.d.ts +47 -2
  106. package/dist/commands/sync.d.ts.map +1 -1
  107. package/dist/commands/sync.js +1299 -119
  108. package/dist/commands/sync.js.map +1 -1
  109. package/dist/commands/sync.test.d.ts +2 -0
  110. package/dist/commands/sync.test.d.ts.map +1 -0
  111. package/dist/commands/sync.test.js +130 -0
  112. package/dist/commands/sync.test.js.map +1 -0
  113. package/dist/commands/topic.d.ts +32 -0
  114. package/dist/commands/topic.d.ts.map +1 -0
  115. package/dist/commands/topic.js +223 -0
  116. package/dist/commands/topic.js.map +1 -0
  117. package/dist/commands/topic.test.d.ts +2 -0
  118. package/dist/commands/topic.test.d.ts.map +1 -0
  119. package/dist/commands/topic.test.js +114 -0
  120. package/dist/commands/topic.test.js.map +1 -0
  121. package/dist/index.js +35 -125
  122. package/dist/index.js.map +1 -1
  123. package/dist/lib/client.d.ts +9 -0
  124. package/dist/lib/client.d.ts.map +1 -0
  125. package/dist/lib/client.js +77 -0
  126. package/dist/lib/client.js.map +1 -0
  127. package/dist/lib/config.d.ts +45 -0
  128. package/dist/lib/config.d.ts.map +1 -1
  129. package/dist/lib/config.js +74 -1
  130. package/dist/lib/config.js.map +1 -1
  131. package/dist/lib/hubs.d.ts +7 -0
  132. package/dist/lib/hubs.d.ts.map +1 -0
  133. package/dist/lib/hubs.js +33 -0
  134. package/dist/lib/hubs.js.map +1 -0
  135. package/dist/lib/hubs.test.d.ts +2 -0
  136. package/dist/lib/hubs.test.d.ts.map +1 -0
  137. package/dist/lib/hubs.test.js +58 -0
  138. package/dist/lib/hubs.test.js.map +1 -0
  139. package/dist/lib/project-context.d.ts +56 -0
  140. package/dist/lib/project-context.d.ts.map +1 -0
  141. package/dist/lib/project-context.js +231 -0
  142. package/dist/lib/project-context.js.map +1 -0
  143. package/dist/lib/project-context.test.d.ts +2 -0
  144. package/dist/lib/project-context.test.d.ts.map +1 -0
  145. package/dist/lib/project-context.test.js +75 -0
  146. package/dist/lib/project-context.test.js.map +1 -0
  147. package/dist/lib/prompt.d.ts +7 -0
  148. package/dist/lib/prompt.d.ts.map +1 -0
  149. package/dist/lib/prompt.js +41 -0
  150. package/dist/lib/prompt.js.map +1 -0
  151. package/dist/lib/trash.d.ts +6 -0
  152. package/dist/lib/trash.d.ts.map +1 -0
  153. package/dist/lib/trash.js +28 -0
  154. package/dist/lib/trash.js.map +1 -0
  155. package/package.json +17 -13
  156. package/.vscode/mcp.json +0 -8
  157. package/dist/lib/api.d.ts +0 -4
  158. package/dist/lib/api.d.ts.map +0 -1
  159. package/dist/lib/api.js +0 -95
  160. package/dist/lib/api.js.map +0 -1
  161. package/src/commands/auth.ts +0 -92
  162. package/src/commands/config.ts +0 -27
  163. package/src/commands/delete.ts +0 -20
  164. package/src/commands/hook.ts +0 -243
  165. package/src/commands/list.ts +0 -38
  166. package/src/commands/login.ts +0 -162
  167. package/src/commands/mcp.ts +0 -357
  168. package/src/commands/push.ts +0 -82
  169. package/src/commands/recall.ts +0 -163
  170. package/src/commands/setup.ts +0 -682
  171. package/src/commands/show.ts +0 -35
  172. package/src/commands/sync.ts +0 -403
  173. package/src/index.ts +0 -192
  174. package/src/lib/api.ts +0 -110
  175. package/src/lib/config.ts +0 -61
  176. package/src/lib/credentials.ts +0 -42
  177. package/tsconfig.json +0 -9
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hubs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubs.test.d.ts","sourceRoot":"","sources":["../../src/lib/hubs.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { findHubMatch, getHubReference, PERSONAL_HUB_ALIAS } from "./hubs.js";
3
+ describe("getHubReference", () => {
4
+ it("uses the reserved personal alias for personal hubs", () => {
5
+ expect(getHubReference({
6
+ id: "h1",
7
+ name: "Personal",
8
+ slug: "user-123",
9
+ hub_type: "personal",
10
+ owner_id: "u1",
11
+ })).toBe(PERSONAL_HUB_ALIAS);
12
+ });
13
+ it("uses the real slug for team hubs", () => {
14
+ expect(getHubReference({
15
+ id: "h2",
16
+ name: "Memax",
17
+ slug: "memax",
18
+ hub_type: "team",
19
+ owner_id: "u1",
20
+ })).toBe("memax");
21
+ });
22
+ });
23
+ describe("findHubMatch", () => {
24
+ const hubs = [
25
+ {
26
+ hub: {
27
+ id: "personal-id",
28
+ name: "Personal",
29
+ slug: "user-123",
30
+ hub_type: "personal",
31
+ owner_id: "u1",
32
+ },
33
+ role: "owner",
34
+ memory_count: 0,
35
+ },
36
+ {
37
+ hub: {
38
+ id: "team-id",
39
+ name: "Memax",
40
+ slug: "memax",
41
+ hub_type: "team",
42
+ owner_id: "u1",
43
+ },
44
+ role: "owner",
45
+ memory_count: 0,
46
+ },
47
+ ];
48
+ it("resolves the reserved personal alias to the personal hub", () => {
49
+ expect(findHubMatch([...hubs], "personal")?.hub.id).toBe("personal-id");
50
+ });
51
+ it("matches team hubs by slug", () => {
52
+ expect(findHubMatch([...hubs], "memax")?.hub.id).toBe("team-id");
53
+ });
54
+ it("matches hubs by id", () => {
55
+ expect(findHubMatch([...hubs], "team-id")?.hub.slug).toBe("memax");
56
+ });
57
+ });
58
+ //# sourceMappingURL=hubs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubs.test.js","sourceRoot":"","sources":["../../src/lib/hubs.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE9E,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,CACJ,eAAe,CAAC;YACd,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CACJ,eAAe,CAAC;YACd,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,MAAM,IAAI,GAAG;QACX;YACE,GAAG,EAAE;gBACH,EAAE,EAAE,aAAa;gBACjB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,IAAI;aACf;YACD,IAAI,EAAE,OAAO;YACb,YAAY,EAAE,CAAC;SAChB;QACD;YACE,GAAG,EAAE;gBACH,EAAE,EAAE,SAAS;gBACb,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,IAAI;aACf;YACD,IAAI,EAAE,OAAO;YACb,YAAY,EAAE,CAAC;SAChB;KACO,CAAC;IAEX,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { Scope } from "memax-sdk";
2
+ /**
3
+ * Normalize a git remote URL to a canonical form for use as a project identifier.
4
+ *
5
+ * All of these produce the same result: `github.com/memaxlabs/memax`
6
+ * - https://github.com/MemaxLabs/memax.git
7
+ * - git@github.com:MemaxLabs/memax.git
8
+ * - ssh://git@github.com/MemaxLabs/memax
9
+ */
10
+ export declare function normalizeRepoUrl(url: string): string;
11
+ export interface MemaxYmlConfig {
12
+ hub?: string;
13
+ project_id?: string;
14
+ }
15
+ export type ProjectScope = Scope | "project";
16
+ export interface ProjectScopeResolution {
17
+ scope: ProjectScope;
18
+ source: "memax_yml" | "git_remote" | "fallback";
19
+ warning?: string;
20
+ }
21
+ export declare function isCanonicalProjectScope(scope: ProjectScope): scope is Scope;
22
+ export declare function findNearestMemaxYmlPath(dir?: string): string | null;
23
+ export declare function readMemaxYmlConfig(dir?: string): MemaxYmlConfig | undefined;
24
+ /**
25
+ * Get a canonical project scope string for the given directory.
26
+ *
27
+ * Returns:
28
+ * "project:<project-id>" — .memax.yml project_id or git remote available
29
+ * "project" — no canonical cross-device project identity
30
+ */
31
+ export declare function getProjectScope(dir?: string): ProjectScope;
32
+ export declare function resolveProjectScope(dir?: string): ProjectScopeResolution;
33
+ export declare function resolveProjectRootPath(dir?: string): string | null;
34
+ /**
35
+ * Resolve a Claude Code mangled project folder name to a normalized repo URL.
36
+ *
37
+ * Claude Code names project folders by replacing "/" with "-" in the absolute path:
38
+ * "-workspaces-memax" → /workspaces/memax
39
+ * "-Users-ziyang-code-memax" → /Users/ziyang/code/memax
40
+ *
41
+ * Returns the normalized repo URL if the path exists and is a git repo, null otherwise.
42
+ */
43
+ export declare function resolveClaudeProjectFolder(mangledName: string): string | null;
44
+ export declare function resolveClaudeProjectPath(mangledName: string): string | null;
45
+ /**
46
+ * Normalize a file path for cross-platform consistency.
47
+ * - Forward slashes only
48
+ * - No leading "./"
49
+ * - No double slashes
50
+ */
51
+ export declare function normalizeFilePath(p: string): string;
52
+ /** Detect git project context (repo URL, project name, branch). */
53
+ export declare function detectProjectContext(dir?: string): Record<string, string>;
54
+ /** Walk up from cwd looking for .memax.yml with a hub field. */
55
+ export declare function readMemaxYmlHub(): string | undefined;
56
+ //# sourceMappingURL=project-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context.d.ts","sourceRoot":"","sources":["../../src/lib/project-context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAMvC;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgBpD;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,SAAS,CAAC;AAE7C,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,IAAI,KAAK,CAE3E;AA2BD,wBAAgB,uBAAuB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEnE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CA0B3E;AAiBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,sBAAsB,CA4BxE;AAED,wBAAgB,sBAAsB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBlE;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS7E;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,mEAAmE;AACnE,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4BzE;AAED,gEAAgE;AAChE,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpD"}
@@ -0,0 +1,231 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ // =============================================================================
5
+ // Git URL normalization — canonical project identity for cross-machine sync
6
+ // =============================================================================
7
+ /**
8
+ * Normalize a git remote URL to a canonical form for use as a project identifier.
9
+ *
10
+ * All of these produce the same result: `github.com/memaxlabs/memax`
11
+ * - https://github.com/MemaxLabs/memax.git
12
+ * - git@github.com:MemaxLabs/memax.git
13
+ * - ssh://git@github.com/MemaxLabs/memax
14
+ */
15
+ export function normalizeRepoUrl(url) {
16
+ let s = url.trim();
17
+ // Strip protocol (https://, ssh://, git://)
18
+ s = s.replace(/^(https?:\/\/|ssh:\/\/|git:\/\/)/, "");
19
+ // Strip user@ prefix (e.g., git@)
20
+ s = s.replace(/^[^@]+@/, "");
21
+ // SSH colon syntax → slash (github.com:org/repo → github.com/org/repo)
22
+ // Skip if followed by digits (port number like git.corp.com:8443/repo)
23
+ s = s.replace(/^([^/:]+):(?![0-9])/, "$1/");
24
+ // Remove .git suffix
25
+ s = s.replace(/\.git$/, "");
26
+ // Trailing slashes
27
+ s = s.replace(/\/+$/, "");
28
+ // Lowercase + forward slashes
29
+ s = s.toLowerCase().replace(/\\/g, "/");
30
+ return s;
31
+ }
32
+ export function isCanonicalProjectScope(scope) {
33
+ return scope !== "project";
34
+ }
35
+ function normalizeProjectID(projectID) {
36
+ let s = projectID.trim();
37
+ s = s.replace(/^project:/, "");
38
+ s = normalizeRepoUrl(s);
39
+ if (!s || /\s/.test(s)) {
40
+ throw new Error("invalid project_id");
41
+ }
42
+ return s;
43
+ }
44
+ function findNearestMemaxYml(startDir) {
45
+ let dir = startDir;
46
+ const root = "/";
47
+ while (true) {
48
+ const ymlPath = join(dir, ".memax.yml");
49
+ if (existsSync(ymlPath)) {
50
+ return ymlPath;
51
+ }
52
+ const parent = join(dir, "..");
53
+ if (parent === dir || dir === root)
54
+ break;
55
+ dir = parent;
56
+ }
57
+ return null;
58
+ }
59
+ export function findNearestMemaxYmlPath(dir) {
60
+ return findNearestMemaxYml(dir ?? process.cwd());
61
+ }
62
+ export function readMemaxYmlConfig(dir) {
63
+ const cwd = dir ?? process.cwd();
64
+ const ymlPath = findNearestMemaxYml(cwd);
65
+ if (!ymlPath) {
66
+ return undefined;
67
+ }
68
+ try {
69
+ const content = readFileSync(ymlPath, "utf-8");
70
+ const hubMatch = content.match(/^hub:\s*(.+)$/m);
71
+ const projectMatch = content.match(/^project_id:\s*(.+)$/m);
72
+ const cfg = {};
73
+ if (hubMatch) {
74
+ cfg.hub = hubMatch[1].trim();
75
+ }
76
+ if (projectMatch) {
77
+ cfg.project_id = normalizeProjectID(projectMatch[1].trim());
78
+ }
79
+ if (!cfg.hub && !cfg.project_id) {
80
+ return undefined;
81
+ }
82
+ return cfg;
83
+ }
84
+ catch {
85
+ return undefined;
86
+ }
87
+ }
88
+ function getGitOriginProjectID(cwd) {
89
+ try {
90
+ const repo = execSync("git remote get-url origin", {
91
+ cwd,
92
+ encoding: "utf-8",
93
+ timeout: 2000,
94
+ stdio: ["pipe", "pipe", "pipe"],
95
+ }).trim();
96
+ if (repo) {
97
+ return normalizeRepoUrl(repo);
98
+ }
99
+ }
100
+ catch { }
101
+ return undefined;
102
+ }
103
+ /**
104
+ * Get a canonical project scope string for the given directory.
105
+ *
106
+ * Returns:
107
+ * "project:<project-id>" — .memax.yml project_id or git remote available
108
+ * "project" — no canonical cross-device project identity
109
+ */
110
+ export function getProjectScope(dir) {
111
+ return resolveProjectScope(dir).scope;
112
+ }
113
+ export function resolveProjectScope(dir) {
114
+ const cwd = dir ?? process.cwd();
115
+ const memaxCfg = readMemaxYmlConfig(cwd);
116
+ const gitProjectID = getGitOriginProjectID(cwd);
117
+ if (memaxCfg?.project_id) {
118
+ const warning = gitProjectID && gitProjectID !== memaxCfg.project_id
119
+ ? `.memax.yml project_id (${memaxCfg.project_id}) overrides git origin (${gitProjectID})`
120
+ : undefined;
121
+ return {
122
+ scope: `project:${memaxCfg.project_id}`,
123
+ source: "memax_yml",
124
+ warning,
125
+ };
126
+ }
127
+ if (gitProjectID) {
128
+ return {
129
+ scope: `project:${gitProjectID}`,
130
+ source: "git_remote",
131
+ };
132
+ }
133
+ return {
134
+ scope: "project",
135
+ source: "fallback",
136
+ };
137
+ }
138
+ export function resolveProjectRootPath(dir) {
139
+ const cwd = dir ?? process.cwd();
140
+ const ymlPath = findNearestMemaxYml(cwd);
141
+ if (ymlPath) {
142
+ return dirname(ymlPath);
143
+ }
144
+ try {
145
+ const root = execSync("git rev-parse --show-toplevel", {
146
+ cwd,
147
+ encoding: "utf-8",
148
+ timeout: 2000,
149
+ stdio: ["pipe", "pipe", "pipe"],
150
+ }).trim();
151
+ return root || null;
152
+ }
153
+ catch { }
154
+ return null;
155
+ }
156
+ /**
157
+ * Resolve a Claude Code mangled project folder name to a normalized repo URL.
158
+ *
159
+ * Claude Code names project folders by replacing "/" with "-" in the absolute path:
160
+ * "-workspaces-memax" → /workspaces/memax
161
+ * "-Users-ziyang-code-memax" → /Users/ziyang/code/memax
162
+ *
163
+ * Returns the normalized repo URL if the path exists and is a git repo, null otherwise.
164
+ */
165
+ export function resolveClaudeProjectFolder(mangledName) {
166
+ // Convert mangled name back to absolute path
167
+ const absolutePath = mangledName.replace(/-/g, "/");
168
+ if (!existsSync(absolutePath))
169
+ return null;
170
+ const resolution = resolveProjectScope(absolutePath);
171
+ if (resolution.scope === "project") {
172
+ return null;
173
+ }
174
+ return resolution.scope.replace(/^project:/, "");
175
+ }
176
+ export function resolveClaudeProjectPath(mangledName) {
177
+ const absolutePath = mangledName.replace(/-/g, "/");
178
+ if (!existsSync(absolutePath))
179
+ return null;
180
+ return absolutePath;
181
+ }
182
+ /**
183
+ * Normalize a file path for cross-platform consistency.
184
+ * - Forward slashes only
185
+ * - No leading "./"
186
+ * - No double slashes
187
+ */
188
+ export function normalizeFilePath(p) {
189
+ return p.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
190
+ }
191
+ /** Detect git project context (repo URL, project name, branch). */
192
+ export function detectProjectContext(dir) {
193
+ const cwd = dir ?? process.cwd();
194
+ const ctx = {};
195
+ try {
196
+ const repo = execSync("git remote get-url origin", {
197
+ cwd,
198
+ encoding: "utf-8",
199
+ timeout: 2000,
200
+ }).trim();
201
+ if (repo)
202
+ ctx.repo = repo;
203
+ }
204
+ catch { }
205
+ try {
206
+ const project = execSync("git rev-parse --show-toplevel", {
207
+ cwd,
208
+ encoding: "utf-8",
209
+ timeout: 2000,
210
+ }).trim();
211
+ if (project)
212
+ ctx.project = project.split("/").pop();
213
+ }
214
+ catch { }
215
+ try {
216
+ const branch = execSync("git branch --show-current", {
217
+ cwd,
218
+ encoding: "utf-8",
219
+ timeout: 2000,
220
+ }).trim();
221
+ if (branch)
222
+ ctx.branch = branch;
223
+ }
224
+ catch { }
225
+ return ctx;
226
+ }
227
+ /** Walk up from cwd looking for .memax.yml with a hub field. */
228
+ export function readMemaxYmlHub() {
229
+ return readMemaxYmlConfig()?.hub;
230
+ }
231
+ //# sourceMappingURL=project-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context.js","sourceRoot":"","sources":["../../src/lib/project-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,gFAAgF;AAChF,4EAA4E;AAC5E,gFAAgF;AAEhF;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,4CAA4C;IAC5C,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC;IACtD,kCAAkC;IAClC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7B,uEAAuE;IACvE,uEAAuE;IACvE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;IAC5C,qBAAqB;IACrB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC5B,mBAAmB;IACnB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,8BAA8B;IAC9B,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxC,OAAO,CAAC,CAAC;AACX,CAAC;AAeD,MAAM,UAAU,uBAAuB,CAAC,KAAmB;IACzD,OAAO,KAAK,KAAK,SAAS,CAAC;AAC7B,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,MAAM,IAAI,GAAG,GAAG,CAAC;IACjB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACxC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,GAAG,IAAI,GAAG,KAAK,IAAI;YAAE,MAAM;QAC1C,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,GAAY;IAClD,OAAO,mBAAmB,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,MAAM,GAAG,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAE5D,MAAM,GAAG,GAAmB,EAAE,CAAC;QAC/B,IAAI,QAAQ,EAAE,CAAC;YACb,GAAG,CAAC,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,YAAY,EAAE,CAAC;YACjB,GAAG,CAAC,UAAU,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YAChC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,2BAA2B,EAAE;YACjD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,OAAO,mBAAmB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,MAAM,GAAG,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAEhD,IAAI,QAAQ,EAAE,UAAU,EAAE,CAAC;QACzB,MAAM,OAAO,GACX,YAAY,IAAI,YAAY,KAAK,QAAQ,CAAC,UAAU;YAClD,CAAC,CAAC,0BAA0B,QAAQ,CAAC,UAAU,2BAA2B,YAAY,GAAG;YACzF,CAAC,CAAC,SAAS,CAAC;QAChB,OAAO;YACL,KAAK,EAAE,WAAW,QAAQ,CAAC,UAAU,EAAE;YACvC,MAAM,EAAE,WAAW;YACnB,OAAO;SACR,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO;YACL,KAAK,EAAE,WAAW,YAAY,EAAE;YAChC,MAAM,EAAE,YAAY;SACrB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,UAAU;KACnB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,GAAY;IACjD,MAAM,GAAG,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,+BAA+B,EAAE;YACrD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,IAAI,IAAI,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CAAC,WAAmB;IAC5D,6CAA6C;IAC7C,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,UAAU,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAS;IACzC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACzE,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,MAAM,GAAG,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,2BAA2B,EAAE;YACjD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,+BAA+B,EAAE;YACxD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,OAAO;YAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,2BAA2B,EAAE;YACnD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,MAAM;YAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,eAAe;IAC7B,OAAO,kBAAkB,EAAE,EAAE,GAAG,CAAC;AACnC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=project-context.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context.test.d.ts","sourceRoot":"","sources":["../../src/lib/project-context.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ const { execSync, existsSync, readFileSync } = vi.hoisted(() => ({
3
+ execSync: vi.fn(),
4
+ existsSync: vi.fn(),
5
+ readFileSync: vi.fn(),
6
+ }));
7
+ vi.mock("node:child_process", () => ({
8
+ execSync,
9
+ }));
10
+ vi.mock("node:fs", async () => {
11
+ const actual = await vi.importActual("node:fs");
12
+ return {
13
+ ...actual,
14
+ existsSync,
15
+ readFileSync,
16
+ };
17
+ });
18
+ import { getProjectScope, normalizeRepoUrl, readMemaxYmlConfig, readMemaxYmlHub, resolveProjectScope, } from "./project-context.js";
19
+ describe("normalizeRepoUrl", () => {
20
+ it("normalizes common git remote forms", () => {
21
+ expect(normalizeRepoUrl("https://github.com/MemaxLabs/memax.git")).toBe("github.com/memaxlabs/memax");
22
+ expect(normalizeRepoUrl("git@github.com:MemaxLabs/memax.git")).toBe("github.com/memaxlabs/memax");
23
+ expect(normalizeRepoUrl("ssh://git@github.com/MemaxLabs/memax")).toBe("github.com/memaxlabs/memax");
24
+ });
25
+ });
26
+ describe("getProjectScope", () => {
27
+ beforeEach(() => {
28
+ execSync.mockReset();
29
+ existsSync.mockReset();
30
+ readFileSync.mockReset();
31
+ existsSync.mockReturnValue(false);
32
+ });
33
+ it("uses the normalized origin remote when present", () => {
34
+ execSync.mockReturnValueOnce("git@github.com:MemaxLabs/memax.git\n");
35
+ expect(getProjectScope("/workspaces/memax")).toBe("project:github.com/memaxlabs/memax");
36
+ });
37
+ it("returns generic project scope when there is no canonical remote", () => {
38
+ execSync.mockImplementation(() => {
39
+ throw new Error("no remote");
40
+ });
41
+ expect(getProjectScope("/workspaces/memax")).toBe("project");
42
+ });
43
+ it("uses .memax.yml project_id as an explicit override", () => {
44
+ existsSync.mockImplementation((path) => path.endsWith(".memax.yml"));
45
+ readFileSync.mockReturnValue("project_id: Acme.Internal/Payments-API\n");
46
+ expect(getProjectScope("/workspaces/memax")).toBe("project:acme.internal/payments-api");
47
+ });
48
+ it("reports when .memax.yml project_id overrides git origin", () => {
49
+ existsSync.mockImplementation((path) => path.endsWith(".memax.yml"));
50
+ readFileSync.mockReturnValue("project_id: github.com/acme/override\n");
51
+ execSync.mockReturnValueOnce("git@github.com:MemaxLabs/memax.git\n");
52
+ expect(resolveProjectScope("/workspaces/memax")).toEqual({
53
+ scope: "project:github.com/acme/override",
54
+ source: "memax_yml",
55
+ warning: ".memax.yml project_id (github.com/acme/override) overrides git origin (github.com/memaxlabs/memax)",
56
+ });
57
+ });
58
+ });
59
+ describe("readMemaxYmlConfig", () => {
60
+ beforeEach(() => {
61
+ existsSync.mockReset();
62
+ readFileSync.mockReset();
63
+ existsSync.mockReturnValue(false);
64
+ });
65
+ it("parses hub and project_id from .memax.yml", () => {
66
+ existsSync.mockImplementation((path) => path.endsWith(".memax.yml"));
67
+ readFileSync.mockReturnValue("hub: team-backend\nproject_id: github.com/MemaxLabs/memax\n");
68
+ expect(readMemaxYmlConfig("/workspaces/memax")).toEqual({
69
+ hub: "team-backend",
70
+ project_id: "github.com/memaxlabs/memax",
71
+ });
72
+ expect(readMemaxYmlHub()).toBe("team-backend");
73
+ });
74
+ });
75
+ //# sourceMappingURL=project-context.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context.test.js","sourceRoot":"","sources":["../../src/lib/project-context.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /** Ask a yes/no question. Returns true if user answers 'y'. */
2
+ export declare function confirm(message: string): Promise<boolean>;
3
+ /** Ask a question and return the trimmed answer. */
4
+ export declare function ask(message: string): Promise<string>;
5
+ /** Ask a yes/no question where Enter defaults to yes. */
6
+ export declare function confirmDefault(message: string): Promise<boolean>;
7
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/lib/prompt.ts"],"names":[],"mappings":"AAEA,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWzD;AAED,oDAAoD;AACpD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWpD;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWhE"}
@@ -0,0 +1,41 @@
1
+ import { createInterface } from "node:readline";
2
+ /** Ask a yes/no question. Returns true if user answers 'y'. */
3
+ export function confirm(message) {
4
+ return new Promise((resolve) => {
5
+ const rl = createInterface({
6
+ input: process.stdin,
7
+ output: process.stdout,
8
+ });
9
+ rl.question(message, (answer) => {
10
+ rl.close();
11
+ resolve(answer.trim().toLowerCase() === "y");
12
+ });
13
+ });
14
+ }
15
+ /** Ask a question and return the trimmed answer. */
16
+ export function ask(message) {
17
+ return new Promise((resolve) => {
18
+ const rl = createInterface({
19
+ input: process.stdin,
20
+ output: process.stdout,
21
+ });
22
+ rl.question(message, (answer) => {
23
+ rl.close();
24
+ resolve(answer.trim());
25
+ });
26
+ });
27
+ }
28
+ /** Ask a yes/no question where Enter defaults to yes. */
29
+ export function confirmDefault(message) {
30
+ return new Promise((resolve) => {
31
+ const rl = createInterface({
32
+ input: process.stdin,
33
+ output: process.stdout,
34
+ });
35
+ rl.question(message, (answer) => {
36
+ rl.close();
37
+ resolve(answer.trim().toLowerCase() !== "n");
38
+ });
39
+ });
40
+ }
41
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/lib/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,+DAA+D;AAC/D,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,eAAe,CAAC;YACzB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,eAAe,CAAC;YACzB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,eAAe,CAAC;YACzB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface TrashMoveResult {
2
+ moved: boolean;
3
+ trashPath?: string;
4
+ }
5
+ export declare function moveFileToTrash(sourcePath: string, kind: "agent-configs" | "agent-sessions"): TrashMoveResult;
6
+ //# sourceMappingURL=trash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trash.d.ts","sourceRoot":"","sources":["../../src/lib/trash.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,eAAe,GAAG,gBAAgB,GACvC,eAAe,CAiBjB"}
@@ -0,0 +1,28 @@
1
+ import { copyFileSync, existsSync, mkdirSync, renameSync, rmSync, } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { getConfigDir } from "./config.js";
4
+ function makeTrashPath(kind, sourcePath) {
5
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
6
+ const normalized = sourcePath.replace(/^\/+/, "");
7
+ return join(getConfigDir(), "trash", kind, timestamp, normalized);
8
+ }
9
+ export function moveFileToTrash(sourcePath, kind) {
10
+ if (!existsSync(sourcePath)) {
11
+ return { moved: false };
12
+ }
13
+ const trashPath = makeTrashPath(kind, sourcePath);
14
+ mkdirSync(dirname(trashPath), { recursive: true });
15
+ try {
16
+ renameSync(sourcePath, trashPath);
17
+ }
18
+ catch (err) {
19
+ const error = err;
20
+ if (error.code !== "EXDEV") {
21
+ throw err;
22
+ }
23
+ copyFileSync(sourcePath, trashPath);
24
+ rmSync(sourcePath);
25
+ }
26
+ return { moved: true, trashPath };
27
+ }
28
+ //# sourceMappingURL=trash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trash.js","sourceRoot":"","sources":["../../src/lib/trash.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,UAAU,EACV,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,SAAS,aAAa,CAAC,IAAY,EAAE,UAAkB;IACrD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,UAAkB,EAClB,IAAwC;IAExC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;IACD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClD,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAA4B,CAAC;QAC3C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,YAAY,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACpC,MAAM,CAAC,UAAU,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACpC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memax-cli",
3
- "version": "0.1.0-alpha.4",
3
+ "version": "0.1.0-alpha.41",
4
4
  "description": "CLI for Memax — universal context & memory hub for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,21 +12,13 @@
12
12
  "import": "./dist/index.js"
13
13
  }
14
14
  },
15
- "scripts": {
16
- "build": "tsc",
17
- "dev": "tsc --watch",
18
- "start": "node dist/index.js",
19
- "lint": "tsc --noEmit",
20
- "test": "vitest run --passWithNoTests",
21
- "clean": "rm -rf dist"
22
- },
23
15
  "dependencies": {
24
16
  "@modelcontextprotocol/sdk": "^1.12.1",
25
17
  "chalk": "^5.4.0",
26
- "commander": "^13.0.0"
18
+ "commander": "^13.0.0",
19
+ "memax-sdk": "^0.1.10"
27
20
  },
28
21
  "devDependencies": {
29
- "@memaxlabs/shared": "workspace:*",
30
22
  "@types/node": "^25.5.0",
31
23
  "typescript": "^5.8.0",
32
24
  "vitest": "^3.0.0"
@@ -40,5 +32,17 @@
40
32
  "claude-code",
41
33
  "agent"
42
34
  ],
43
- "license": "UNLICENSED"
44
- }
35
+ "files": [
36
+ "dist",
37
+ "assets"
38
+ ],
39
+ "license": "UNLICENSED",
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "dev": "tsc --watch",
43
+ "start": "node dist/index.js",
44
+ "lint": "tsc --noEmit",
45
+ "test": "vitest run --passWithNoTests",
46
+ "clean": "rm -rf dist"
47
+ }
48
+ }
package/.vscode/mcp.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "servers": {
3
- "memax": {
4
- "command": "memax",
5
- "args": ["mcp", "serve"]
6
- }
7
- }
8
- }
package/dist/lib/api.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare function apiPost<T>(path: string, body: unknown): Promise<T>;
2
- export declare function apiGet<T>(path: string): Promise<T>;
3
- export declare function apiDelete(path: string): Promise<void>;
4
- //# sourceMappingURL=api.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AA0DA,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBxE;AAED,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAexD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe3D"}