memax-cli 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (97) hide show
  1. package/assets/skills/memax-memory/SKILL.md +154 -0
  2. package/dist/commands/auth.d.ts +1 -0
  3. package/dist/commands/auth.d.ts.map +1 -1
  4. package/dist/commands/auth.js +14 -7
  5. package/dist/commands/auth.js.map +1 -1
  6. package/dist/commands/capture.d.ts +17 -0
  7. package/dist/commands/capture.d.ts.map +1 -0
  8. package/dist/commands/capture.js +60 -0
  9. package/dist/commands/capture.js.map +1 -0
  10. package/dist/commands/delete.d.ts +1 -1
  11. package/dist/commands/delete.d.ts.map +1 -1
  12. package/dist/commands/delete.js +22 -5
  13. package/dist/commands/delete.js.map +1 -1
  14. package/dist/commands/hub.d.ts +4 -0
  15. package/dist/commands/hub.d.ts.map +1 -0
  16. package/dist/commands/hub.js +53 -0
  17. package/dist/commands/hub.js.map +1 -0
  18. package/dist/commands/list.d.ts +2 -1
  19. package/dist/commands/list.d.ts.map +1 -1
  20. package/dist/commands/list.js +35 -8
  21. package/dist/commands/list.js.map +1 -1
  22. package/dist/commands/login.d.ts.map +1 -1
  23. package/dist/commands/login.js +32 -7
  24. package/dist/commands/login.js.map +1 -1
  25. package/dist/commands/mcp.d.ts.map +1 -1
  26. package/dist/commands/mcp.js +226 -26
  27. package/dist/commands/mcp.js.map +1 -1
  28. package/dist/commands/push.d.ts +2 -1
  29. package/dist/commands/push.d.ts.map +1 -1
  30. package/dist/commands/push.js +49 -11
  31. package/dist/commands/push.js.map +1 -1
  32. package/dist/commands/recall.d.ts +1 -0
  33. package/dist/commands/recall.d.ts.map +1 -1
  34. package/dist/commands/recall.js +30 -27
  35. package/dist/commands/recall.js.map +1 -1
  36. package/dist/commands/setup-hooks.d.ts +12 -0
  37. package/dist/commands/setup-hooks.d.ts.map +1 -0
  38. package/dist/commands/setup-hooks.js +184 -0
  39. package/dist/commands/setup-hooks.js.map +1 -0
  40. package/dist/commands/setup-instructions.d.ts +21 -0
  41. package/dist/commands/setup-instructions.d.ts.map +1 -0
  42. package/dist/commands/setup-instructions.js +172 -0
  43. package/dist/commands/setup-instructions.js.map +1 -0
  44. package/dist/commands/setup-mcp.d.ts +14 -0
  45. package/dist/commands/setup-mcp.d.ts.map +1 -0
  46. package/dist/commands/setup-mcp.js +276 -0
  47. package/dist/commands/setup-mcp.js.map +1 -0
  48. package/dist/commands/setup-types.d.ts +20 -0
  49. package/dist/commands/setup-types.d.ts.map +1 -0
  50. package/dist/commands/setup-types.js +60 -0
  51. package/dist/commands/setup-types.js.map +1 -0
  52. package/dist/commands/setup.d.ts +18 -0
  53. package/dist/commands/setup.d.ts.map +1 -0
  54. package/dist/commands/setup.js +371 -0
  55. package/dist/commands/setup.js.map +1 -0
  56. package/dist/commands/show.d.ts.map +1 -1
  57. package/dist/commands/show.js +10 -13
  58. package/dist/commands/show.js.map +1 -1
  59. package/dist/commands/sync.d.ts +7 -2
  60. package/dist/commands/sync.d.ts.map +1 -1
  61. package/dist/commands/sync.js +614 -107
  62. package/dist/commands/sync.js.map +1 -1
  63. package/dist/index.js +85 -14
  64. package/dist/index.js.map +1 -1
  65. package/dist/lib/client.d.ts +6 -0
  66. package/dist/lib/client.d.ts.map +1 -0
  67. package/dist/lib/client.js +69 -0
  68. package/dist/lib/client.js.map +1 -0
  69. package/dist/lib/project-context.d.ts +40 -0
  70. package/dist/lib/project-context.d.ts.map +1 -0
  71. package/dist/lib/project-context.js +157 -0
  72. package/dist/lib/project-context.js.map +1 -0
  73. package/dist/lib/prompt.d.ts +7 -0
  74. package/dist/lib/prompt.d.ts.map +1 -0
  75. package/dist/lib/prompt.js +41 -0
  76. package/dist/lib/prompt.js.map +1 -0
  77. package/package.json +17 -13
  78. package/dist/lib/api.d.ts +0 -4
  79. package/dist/lib/api.d.ts.map +0 -1
  80. package/dist/lib/api.js +0 -95
  81. package/dist/lib/api.js.map +0 -1
  82. package/src/commands/auth.ts +0 -92
  83. package/src/commands/config.ts +0 -27
  84. package/src/commands/delete.ts +0 -20
  85. package/src/commands/hook.ts +0 -243
  86. package/src/commands/list.ts +0 -38
  87. package/src/commands/login.ts +0 -159
  88. package/src/commands/mcp.ts +0 -282
  89. package/src/commands/push.ts +0 -82
  90. package/src/commands/recall.ts +0 -160
  91. package/src/commands/show.ts +0 -35
  92. package/src/commands/sync.ts +0 -403
  93. package/src/index.ts +0 -167
  94. package/src/lib/api.ts +0 -110
  95. package/src/lib/config.ts +0 -61
  96. package/src/lib/credentials.ts +0 -42
  97. package/tsconfig.json +0 -9
@@ -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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memax-cli",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.21",
4
4
  "description": "CLI for Memax — universal context & memory hub for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,19 +12,11 @@
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
- "@memaxlabs/shared": "workspace:*",
25
16
  "@modelcontextprotocol/sdk": "^1.12.1",
26
17
  "chalk": "^5.4.0",
27
- "commander": "^13.0.0"
18
+ "commander": "^13.0.0",
19
+ "memax-sdk": "^0.1.1"
28
20
  },
29
21
  "devDependencies": {
30
22
  "@types/node": "^25.5.0",
@@ -40,5 +32,17 @@
40
32
  "claude-code",
41
33
  "agent"
42
34
  ],
43
- "license": "MIT"
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/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"}
package/dist/lib/api.js DELETED
@@ -1,95 +0,0 @@
1
- import { loadConfig } from "./config.js";
2
- import { loadCredentials, saveCredentials, isTokenExpired, } from "./credentials.js";
3
- function getApiUrl() {
4
- return loadConfig().api_url;
5
- }
6
- async function authHeaders() {
7
- // 1. MEMAX_API_KEY env var takes priority (CI/CD, non-interactive)
8
- const envKey = process.env.MEMAX_API_KEY;
9
- if (envKey) {
10
- return { Authorization: `Bearer ${envKey}` };
11
- }
12
- // 2. Stored credentials with auto-refresh
13
- const creds = loadCredentials();
14
- if (!creds?.access_token)
15
- return {};
16
- if (isTokenExpired() && creds.refresh_token) {
17
- // Attempt to refresh the access token
18
- try {
19
- const url = `${getApiUrl()}/v1/auth/refresh`;
20
- const res = await fetch(url, {
21
- method: "POST",
22
- headers: { "Content-Type": "application/json" },
23
- body: JSON.stringify({ refresh_token: creds.refresh_token }),
24
- });
25
- const json = (await res.json());
26
- if (json.data) {
27
- const tokens = json.data;
28
- saveCredentials({
29
- access_token: tokens.access_token,
30
- refresh_token: tokens.refresh_token,
31
- expires_at: Date.now() + tokens.expires_in * 1000,
32
- });
33
- return { Authorization: `Bearer ${tokens.access_token}` };
34
- }
35
- }
36
- catch {
37
- // Refresh failed — fall through to use stale token (server will reject)
38
- }
39
- }
40
- return { Authorization: `Bearer ${creds.access_token}` };
41
- }
42
- export async function apiPost(path, body) {
43
- const url = `${getApiUrl()}${path}`;
44
- let res;
45
- try {
46
- res = await fetch(url, {
47
- method: "POST",
48
- headers: { "Content-Type": "application/json", ...(await authHeaders()) },
49
- body: JSON.stringify(body),
50
- });
51
- }
52
- catch {
53
- throw new Error(`Cannot reach API at ${url} — is the server running?`);
54
- }
55
- const json = (await res.json());
56
- if (json.error) {
57
- throw new Error(json.error.message);
58
- }
59
- return json.data;
60
- }
61
- export async function apiGet(path) {
62
- const url = `${getApiUrl()}${path}`;
63
- let res;
64
- try {
65
- res = await fetch(url, {
66
- headers: { ...(await authHeaders()) },
67
- });
68
- }
69
- catch {
70
- throw new Error(`Cannot reach API at ${url} — is the server running?`);
71
- }
72
- const json = (await res.json());
73
- if (json.error) {
74
- throw new Error(json.error.message);
75
- }
76
- return json.data;
77
- }
78
- export async function apiDelete(path) {
79
- const url = `${getApiUrl()}${path}`;
80
- let res;
81
- try {
82
- res = await fetch(url, {
83
- method: "DELETE",
84
- headers: { ...(await authHeaders()) },
85
- });
86
- }
87
- catch {
88
- throw new Error(`Cannot reach API at ${url} — is the server running?`);
89
- }
90
- const json = (await res.json());
91
- if (json.error) {
92
- throw new Error(json.error.message);
93
- }
94
- }
95
- //# sourceMappingURL=api.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
@@ -1,92 +0,0 @@
1
- import { apiPost, apiGet, apiDelete } from "../lib/api.js";
2
-
3
- interface APIKeyCreateResponse {
4
- id: string;
5
- name: string;
6
- key: string;
7
- prefix: string;
8
- expires_at: string | null;
9
- created_at: string;
10
- }
11
-
12
- interface APIKeyListItem {
13
- id: string;
14
- name: string;
15
- prefix: string;
16
- scopes: string[];
17
- expires_at: string | null;
18
- last_used: string | null;
19
- created_at: string;
20
- }
21
-
22
- export async function createKeyCommand(
23
- name: string,
24
- opts: { expires?: string },
25
- ): Promise<void> {
26
- const expiresInDays = opts.expires ? parseInt(opts.expires, 10) : 0;
27
-
28
- try {
29
- const result = await apiPost<APIKeyCreateResponse>("/v1/auth/api-keys", {
30
- name,
31
- expires_in_days: expiresInDays || undefined,
32
- });
33
-
34
- console.log("\n API key created successfully.\n");
35
- console.log(` Name: ${result.name}`);
36
- console.log(` Key: ${result.key}`);
37
- if (result.expires_at) {
38
- console.log(
39
- ` Expires: ${new Date(result.expires_at).toLocaleDateString()}`,
40
- );
41
- } else {
42
- console.log(` Expires: never`);
43
- }
44
- console.log("\n ⚠ Save this key now — it cannot be retrieved again.\n");
45
- console.log(" Usage:");
46
- console.log(` export MEMAX_API_KEY=${result.key}\n`);
47
- } catch (err) {
48
- console.error(` Failed to create API key: ${(err as Error).message}\n`);
49
- process.exit(1);
50
- }
51
- }
52
-
53
- export async function listKeysCommand(): Promise<void> {
54
- try {
55
- const keys = await apiGet<APIKeyListItem[]>("/v1/auth/api-keys");
56
-
57
- if (keys.length === 0) {
58
- console.log(
59
- "\n No API keys. Create one with: memax auth create-key <name>\n",
60
- );
61
- return;
62
- }
63
-
64
- console.log("\n API Keys:\n");
65
- for (const key of keys) {
66
- const expires = key.expires_at
67
- ? new Date(key.expires_at).toLocaleDateString()
68
- : "never";
69
- const lastUsed = key.last_used
70
- ? new Date(key.last_used).toLocaleDateString()
71
- : "never";
72
- console.log(` ${key.prefix}... ${key.name}`);
73
- console.log(
74
- ` ID: ${key.id} Expires: ${expires} Last used: ${lastUsed}`,
75
- );
76
- }
77
- console.log();
78
- } catch (err) {
79
- console.error(` Failed to list API keys: ${(err as Error).message}\n`);
80
- process.exit(1);
81
- }
82
- }
83
-
84
- export async function revokeKeyCommand(id: string): Promise<void> {
85
- try {
86
- await apiDelete(`/v1/auth/api-keys/${id}`);
87
- console.log("\n API key revoked.\n");
88
- } catch (err) {
89
- console.error(` Failed to revoke API key: ${(err as Error).message}\n`);
90
- process.exit(1);
91
- }
92
- }
@@ -1,27 +0,0 @@
1
- import chalk from "chalk";
2
- import { loadConfig, saveConfig, getConfigDir } from "../lib/config.js";
3
-
4
- export function configGetCommand(key: string | undefined): void {
5
- const config = loadConfig();
6
-
7
- if (!key) {
8
- console.log(chalk.gray(`Config directory: ${getConfigDir()}`));
9
- console.log();
10
- for (const [k, v] of Object.entries(config)) {
11
- console.log(`${chalk.bold(k)}: ${v}`);
12
- }
13
- return;
14
- }
15
-
16
- const value = (config as unknown as Record<string, unknown>)[key];
17
- if (value === undefined) {
18
- console.error(chalk.red(`Unknown config key: ${key}`));
19
- process.exit(1);
20
- }
21
- console.log(String(value));
22
- }
23
-
24
- export function configSetCommand(key: string, value: string): void {
25
- saveConfig({ [key]: value });
26
- console.log(chalk.green("Set"), `${key} = ${value}`);
27
- }
@@ -1,20 +0,0 @@
1
- import chalk from "chalk";
2
- import { apiDelete } from "../lib/api.js";
3
-
4
- export async function deleteCommand(
5
- id: string,
6
- options: { confirm?: boolean },
7
- ): Promise<void> {
8
- if (!id) {
9
- console.error(chalk.red("Provide a note ID: memax delete <id>"));
10
- process.exit(1);
11
- }
12
-
13
- try {
14
- await apiDelete(`/v1/notes/${id}`);
15
- console.log(chalk.green("Deleted"), chalk.gray(id));
16
- } catch (err) {
17
- console.error(chalk.red(`Delete failed: ${(err as Error).message}`));
18
- process.exit(1);
19
- }
20
- }
@@ -1,243 +0,0 @@
1
- import chalk from "chalk";
2
- import {
3
- readFileSync,
4
- writeFileSync,
5
- mkdirSync,
6
- existsSync,
7
- chmodSync,
8
- } from "node:fs";
9
- import { join } from "node:path";
10
- import { homedir } from "node:os";
11
-
12
- type Agent = "claude-code";
13
-
14
- const SUPPORTED_AGENTS: Agent[] = ["claude-code"];
15
-
16
- export function hookCommand(action: string, agent: string): void {
17
- if (!SUPPORTED_AGENTS.includes(agent as Agent)) {
18
- console.error(chalk.red(`Unsupported agent: ${agent}`));
19
- console.error(chalk.gray(`Supported: ${SUPPORTED_AGENTS.join(", ")}`));
20
- process.exit(1);
21
- }
22
-
23
- switch (action) {
24
- case "install":
25
- installHook(agent as Agent);
26
- break;
27
- case "uninstall":
28
- uninstallHook(agent as Agent);
29
- break;
30
- default:
31
- console.error(
32
- chalk.red(`Unknown action: ${action}. Use install or uninstall.`),
33
- );
34
- process.exit(1);
35
- }
36
- }
37
-
38
- function installHook(agent: Agent): void {
39
- switch (agent) {
40
- case "claude-code":
41
- installClaudeCodeHook();
42
- break;
43
- }
44
- }
45
-
46
- function uninstallHook(agent: Agent): void {
47
- switch (agent) {
48
- case "claude-code":
49
- uninstallClaudeCodeHook();
50
- break;
51
- }
52
- }
53
-
54
- function installClaudeCodeHook(): void {
55
- // Write the hook script to ~/.memax/hooks/
56
- const hooksDir = join(homedir(), ".memax", "hooks");
57
- mkdirSync(hooksDir, { recursive: true });
58
-
59
- const scriptPath = join(hooksDir, "claude-code-recall.sh");
60
- writeFileSync(scriptPath, CLAUDE_CODE_HOOK_SCRIPT);
61
- chmodSync(scriptPath, 0o755);
62
-
63
- // Update Claude Code settings (~/.claude/settings.json)
64
- const claudeSettingsDir = join(homedir(), ".claude");
65
- const claudeSettingsFile = join(claudeSettingsDir, "settings.json");
66
- mkdirSync(claudeSettingsDir, { recursive: true });
67
-
68
- let settings: Record<string, unknown> = {};
69
- if (existsSync(claudeSettingsFile)) {
70
- try {
71
- settings = JSON.parse(readFileSync(claudeSettingsFile, "utf-8"));
72
- } catch {
73
- // Start fresh if parse fails
74
- }
75
- }
76
-
77
- // Add the hook
78
- const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;
79
- const hookEntry = {
80
- matcher: "",
81
- hooks: [
82
- {
83
- type: "command",
84
- command: scriptPath,
85
- timeout: 30,
86
- },
87
- ],
88
- };
89
-
90
- // Check if already installed
91
- const existing = hooks["UserPromptSubmit"] as
92
- | Array<{ hooks?: Array<{ command?: string }> }>
93
- | undefined;
94
- if (
95
- existing?.some((h) => h.hooks?.some((hh) => hh.command?.includes("memax")))
96
- ) {
97
- console.log(
98
- chalk.yellow("Memax hook is already installed for Claude Code."),
99
- );
100
- return;
101
- }
102
-
103
- hooks["UserPromptSubmit"] = [...(hooks["UserPromptSubmit"] ?? []), hookEntry];
104
- settings.hooks = hooks;
105
-
106
- writeFileSync(claudeSettingsFile, JSON.stringify(settings, null, 2) + "\n");
107
-
108
- console.log(chalk.green("Memax hook installed for Claude Code"));
109
- console.log();
110
- console.log(chalk.gray(" Hook script:"), scriptPath);
111
- console.log(chalk.gray(" Settings:"), claudeSettingsFile);
112
- console.log();
113
- console.log(
114
- chalk.gray(
115
- " Every prompt you type in Claude Code will now recall relevant\n" +
116
- " knowledge from Memax and inject it as context automatically.",
117
- ),
118
- );
119
- console.log();
120
- console.log(chalk.gray(" Make sure the Memax API server is running:"));
121
- console.log(chalk.gray(" cd packages/server && go run ./cmd/server"));
122
- console.log();
123
- console.log(
124
- chalk.gray(" To also enable MCP tools, add to your Claude Code settings:"),
125
- );
126
- console.log(
127
- chalk.gray(
128
- ` {
129
- "mcpServers": {
130
- "memax": {
131
- "command": "memax",
132
- "args": ["mcp", "serve"]
133
- }
134
- }
135
- }`,
136
- ),
137
- );
138
- }
139
-
140
- function uninstallClaudeCodeHook(): void {
141
- const claudeSettingsFile = join(homedir(), ".claude", "settings.json");
142
-
143
- if (!existsSync(claudeSettingsFile)) {
144
- console.log(
145
- chalk.yellow("No Claude Code settings found. Nothing to uninstall."),
146
- );
147
- return;
148
- }
149
-
150
- try {
151
- const settings = JSON.parse(readFileSync(claudeSettingsFile, "utf-8"));
152
- const hooks = settings.hooks as Record<string, unknown[]> | undefined;
153
-
154
- if (hooks?.["UserPromptSubmit"]) {
155
- hooks["UserPromptSubmit"] = (
156
- hooks["UserPromptSubmit"] as Array<{
157
- hooks?: Array<{ command?: string }>;
158
- }>
159
- ).filter((h) => !h.hooks?.some((hh) => hh.command?.includes("memax")));
160
-
161
- if ((hooks["UserPromptSubmit"] as unknown[]).length === 0) {
162
- delete hooks["UserPromptSubmit"];
163
- }
164
-
165
- settings.hooks = hooks;
166
- writeFileSync(
167
- claudeSettingsFile,
168
- JSON.stringify(settings, null, 2) + "\n",
169
- );
170
- }
171
-
172
- console.log(chalk.green("Memax hook uninstalled from Claude Code."));
173
- } catch {
174
- console.error(chalk.red("Failed to read Claude Code settings."));
175
- process.exit(1);
176
- }
177
- }
178
-
179
- const CLAUDE_CODE_HOOK_SCRIPT = `#!/bin/bash
180
- # Memax context injection hook for Claude Code
181
- # Installed by: memax hook install claude-code
182
- # This runs on every prompt, recalls relevant knowledge, and injects it.
183
-
184
- set -e
185
-
186
- # Read hook input from stdin
187
- INPUT=$(cat)
188
- PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty')
189
- CWD=$(echo "$INPUT" | jq -r '.cwd // empty')
190
-
191
- # Skip if no prompt
192
- if [ -z "$PROMPT" ]; then
193
- exit 0
194
- fi
195
-
196
- # Skip trivial prompts (less than 10 chars, or just "yes"/"no"/etc.)
197
- if [ \${#PROMPT} -lt 10 ]; then
198
- exit 0
199
- fi
200
-
201
- # Skip if prompt looks like a simple confirmation
202
- case "$PROMPT" in
203
- [Yy]|[Yy]es|[Nn]|[Nn]o|ok|OK|Ok|sure|Sure|thanks|Thanks|y|n)
204
- exit 0
205
- ;;
206
- esac
207
-
208
- # Change to the session's working directory
209
- if [ -n "$CWD" ]; then
210
- cd "$CWD" 2>/dev/null || true
211
- fi
212
-
213
- # Find memax CLI — check common locations
214
- MEMAX=""
215
- if command -v memax &>/dev/null; then
216
- MEMAX="memax"
217
- elif [ -x "$HOME/.memax/bin/memax" ]; then
218
- MEMAX="$HOME/.memax/bin/memax"
219
- else
220
- # Try to find it via node
221
- for dir in "$CWD" "$HOME"; do
222
- if [ -f "$dir/packages/cli/dist/index.js" ]; then
223
- MEMAX="node $dir/packages/cli/dist/index.js"
224
- break
225
- fi
226
- done
227
- fi
228
-
229
- # Gracefully exit if memax not found
230
- if [ -z "$MEMAX" ]; then
231
- exit 0
232
- fi
233
-
234
- # Recall context and output it (stdout is injected into Claude's context)
235
- CONTEXT=$($MEMAX recall "$PROMPT" --hook --limit 5 --max-tokens 3000 2>/dev/null) || exit 0
236
-
237
- # Only output if we got results
238
- if [ -n "$CONTEXT" ] && [ "$CONTEXT" != "<memax-context>" ]; then
239
- echo "$CONTEXT"
240
- fi
241
-
242
- exit 0
243
- `;
@@ -1,38 +0,0 @@
1
- import chalk from "chalk";
2
- import { apiGet } from "../lib/api.js";
3
- import type { Note } from "@memaxlabs/shared";
4
-
5
- interface ListOptions {
6
- category?: string;
7
- state?: string;
8
- limit?: string;
9
- }
10
-
11
- export async function listCommand(options: ListOptions): Promise<void> {
12
- try {
13
- const notes = (await apiGet<Note[]>("/v1/notes")) ?? [];
14
-
15
- if (notes.length === 0) {
16
- console.log(chalk.yellow("No notes yet. Push your first one:"));
17
- console.log(chalk.gray(" memax push --file ./README.md"));
18
- return;
19
- }
20
-
21
- console.log(
22
- chalk.blue(`${notes.length} note${notes.length > 1 ? "s" : ""}`),
23
- );
24
- console.log();
25
-
26
- for (const note of notes) {
27
- console.log(
28
- chalk.bold(note.title),
29
- chalk.gray(`[${note.category}]`),
30
- chalk.gray(`· ${note.source}`),
31
- );
32
- console.log(chalk.gray(` id: ${note.id}`));
33
- }
34
- } catch (err) {
35
- console.error(chalk.red(`List failed: ${(err as Error).message}`));
36
- process.exit(1);
37
- }
38
- }