@memextend/cursor 0.1.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/README.md +411 -0
- package/dist/cli/capture.cjs +776 -0
- package/dist/cli/capture.d.ts +2 -0
- package/dist/cli/capture.d.ts.map +1 -0
- package/dist/cli/capture.js +222 -0
- package/dist/cli/capture.js.map +1 -0
- package/dist/cli/index.cjs +245 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +252 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/inject.cjs +1029 -0
- package/dist/cli/inject.d.ts +2 -0
- package/dist/cli/inject.d.ts.map +1 -0
- package/dist/cli/inject.js +279 -0
- package/dist/cli/inject.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +15 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.cjs +14865 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +384 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/utils/index.d.ts +44 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +123 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +65 -0
- package/scripts/build-cli.js +59 -0
- package/scripts/build-mcp.js +46 -0
- package/scripts/postinstall.js +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/cli/capture.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// packages/adapters/cursor/src/cli/capture.ts
|
|
2
|
+
// Copyright (c) 2026 ZodTTD LLC. MIT License.
|
|
3
|
+
/**
|
|
4
|
+
* Session Capture CLI for Cursor
|
|
5
|
+
*
|
|
6
|
+
* Since Cursor doesn't have hooks like Claude Code, this CLI tool provides
|
|
7
|
+
* a way to capture session content manually or via automation.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* memextend-cursor-capture [options]
|
|
11
|
+
* memextend-cursor-capture --file <path> # Capture from file
|
|
12
|
+
* memextend-cursor-capture --stdin # Capture from stdin
|
|
13
|
+
* memextend-cursor-capture --content "..." # Capture direct content
|
|
14
|
+
* memextend-cursor-capture --workspace <dir> # Specify workspace
|
|
15
|
+
*
|
|
16
|
+
* This can be integrated with Cursor's tasks or keyboard shortcuts.
|
|
17
|
+
*/
|
|
18
|
+
import { randomUUID, createHash } from 'crypto';
|
|
19
|
+
import { existsSync } from 'fs';
|
|
20
|
+
import { readFile } from 'fs/promises';
|
|
21
|
+
import { join, basename, resolve } from 'path';
|
|
22
|
+
import { homedir } from 'os';
|
|
23
|
+
import { execSync } from 'child_process';
|
|
24
|
+
import { SQLiteStorage, LanceDBStorage, createEmbedFunction } from '@memextend/core';
|
|
25
|
+
const MEMEXTEND_DIR = join(homedir(), '.memextend');
|
|
26
|
+
const DB_PATH = join(MEMEXTEND_DIR, 'memextend.db');
|
|
27
|
+
const VECTORS_PATH = join(MEMEXTEND_DIR, 'vectors');
|
|
28
|
+
const MODELS_PATH = join(MEMEXTEND_DIR, 'models');
|
|
29
|
+
function parseArgs() {
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
const options = {};
|
|
32
|
+
for (let i = 0; i < args.length; i++) {
|
|
33
|
+
const arg = args[i];
|
|
34
|
+
const next = args[i + 1];
|
|
35
|
+
switch (arg) {
|
|
36
|
+
case '--content':
|
|
37
|
+
case '-c':
|
|
38
|
+
options.content = next;
|
|
39
|
+
i++;
|
|
40
|
+
break;
|
|
41
|
+
case '--file':
|
|
42
|
+
case '-f':
|
|
43
|
+
options.file = next;
|
|
44
|
+
i++;
|
|
45
|
+
break;
|
|
46
|
+
case '--stdin':
|
|
47
|
+
case '-i':
|
|
48
|
+
options.stdin = true;
|
|
49
|
+
break;
|
|
50
|
+
case '--workspace':
|
|
51
|
+
case '-w':
|
|
52
|
+
options.workspace = next;
|
|
53
|
+
i++;
|
|
54
|
+
break;
|
|
55
|
+
case '--type':
|
|
56
|
+
case '-t':
|
|
57
|
+
options.type = next;
|
|
58
|
+
i++;
|
|
59
|
+
break;
|
|
60
|
+
case '--source':
|
|
61
|
+
case '-s':
|
|
62
|
+
options.sourceTool = next;
|
|
63
|
+
i++;
|
|
64
|
+
break;
|
|
65
|
+
case '--session':
|
|
66
|
+
options.sessionId = next;
|
|
67
|
+
i++;
|
|
68
|
+
break;
|
|
69
|
+
case '--quiet':
|
|
70
|
+
case '-q':
|
|
71
|
+
options.quiet = true;
|
|
72
|
+
break;
|
|
73
|
+
case '--help':
|
|
74
|
+
case '-h':
|
|
75
|
+
printHelp();
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return options;
|
|
80
|
+
}
|
|
81
|
+
function printHelp() {
|
|
82
|
+
console.log(`
|
|
83
|
+
memextend-cursor-capture - Capture session content to memory
|
|
84
|
+
|
|
85
|
+
USAGE:
|
|
86
|
+
memextend-cursor-capture [OPTIONS]
|
|
87
|
+
|
|
88
|
+
OPTIONS:
|
|
89
|
+
-c, --content <text> Content to capture directly
|
|
90
|
+
-f, --file <path> Read content from file
|
|
91
|
+
-i, --stdin Read content from stdin
|
|
92
|
+
-w, --workspace <dir> Workspace directory (default: cwd)
|
|
93
|
+
-t, --type <type> Memory type: summary, tool_capture, manual (default: manual)
|
|
94
|
+
-s, --source <tool> Source tool name (for tool_capture type)
|
|
95
|
+
--session <id> Session ID for grouping captures
|
|
96
|
+
-q, --quiet Suppress output
|
|
97
|
+
-h, --help Show this help
|
|
98
|
+
|
|
99
|
+
EXAMPLES:
|
|
100
|
+
# Capture direct content
|
|
101
|
+
memextend-cursor-capture -c "Implemented Redis caching for user sessions"
|
|
102
|
+
|
|
103
|
+
# Capture from file
|
|
104
|
+
memextend-cursor-capture -f session-notes.txt
|
|
105
|
+
|
|
106
|
+
# Capture from pipe (e.g., from AI output)
|
|
107
|
+
echo "Fixed authentication bug" | memextend-cursor-capture --stdin
|
|
108
|
+
|
|
109
|
+
# Capture with workspace context
|
|
110
|
+
memextend-cursor-capture -c "Added API endpoints" -w /path/to/project
|
|
111
|
+
|
|
112
|
+
INTEGRATION:
|
|
113
|
+
Add as a Cursor task in tasks.json or bind to a keyboard shortcut.
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
async function readStdin() {
|
|
117
|
+
const chunks = [];
|
|
118
|
+
for await (const chunk of process.stdin) {
|
|
119
|
+
chunks.push(chunk);
|
|
120
|
+
}
|
|
121
|
+
return Buffer.concat(chunks).toString('utf-8');
|
|
122
|
+
}
|
|
123
|
+
function getProjectId(cwd) {
|
|
124
|
+
try {
|
|
125
|
+
const gitRoot = execSync('git rev-parse --show-toplevel', {
|
|
126
|
+
cwd,
|
|
127
|
+
encoding: 'utf-8',
|
|
128
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
129
|
+
}).trim();
|
|
130
|
+
return createHash('sha256').update(gitRoot).digest('hex').slice(0, 16);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function main() {
|
|
137
|
+
const options = parseArgs();
|
|
138
|
+
// Check if memextend is initialized
|
|
139
|
+
if (!existsSync(DB_PATH)) {
|
|
140
|
+
console.error('Error: memextend not initialized. Run `memextend init` first.');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
// Get content from specified source
|
|
144
|
+
let content;
|
|
145
|
+
if (options.content) {
|
|
146
|
+
content = options.content;
|
|
147
|
+
}
|
|
148
|
+
else if (options.file) {
|
|
149
|
+
if (!existsSync(options.file)) {
|
|
150
|
+
console.error(`Error: File not found: ${options.file}`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
content = await readFile(options.file, 'utf-8');
|
|
154
|
+
}
|
|
155
|
+
else if (options.stdin) {
|
|
156
|
+
content = await readStdin();
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
console.error('Error: No content source specified. Use --content, --file, or --stdin');
|
|
160
|
+
console.error('Run with --help for usage information.');
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
content = content.trim();
|
|
164
|
+
if (!content || content.length < 5) {
|
|
165
|
+
console.error('Error: Content is empty or too short (minimum 5 characters)');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
// Determine workspace
|
|
169
|
+
const workspace = options.workspace ? resolve(options.workspace) : process.cwd();
|
|
170
|
+
const projectId = getProjectId(workspace);
|
|
171
|
+
// Initialize storage
|
|
172
|
+
const sqlite = new SQLiteStorage(DB_PATH);
|
|
173
|
+
const lancedb = await LanceDBStorage.create(VECTORS_PATH);
|
|
174
|
+
const embedder = await createEmbedFunction(MODELS_PATH);
|
|
175
|
+
try {
|
|
176
|
+
// Ensure project is registered
|
|
177
|
+
const project = sqlite.getProject(projectId);
|
|
178
|
+
if (!project) {
|
|
179
|
+
sqlite.insertProject({
|
|
180
|
+
id: projectId,
|
|
181
|
+
name: basename(workspace),
|
|
182
|
+
path: workspace,
|
|
183
|
+
createdAt: new Date().toISOString()
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Create memory
|
|
187
|
+
const memoryId = randomUUID();
|
|
188
|
+
const memory = {
|
|
189
|
+
id: memoryId,
|
|
190
|
+
projectId,
|
|
191
|
+
content,
|
|
192
|
+
type: options.type ?? 'manual',
|
|
193
|
+
sourceTool: options.sourceTool ?? null,
|
|
194
|
+
createdAt: new Date().toISOString(),
|
|
195
|
+
sessionId: options.sessionId ?? null,
|
|
196
|
+
metadata: null,
|
|
197
|
+
};
|
|
198
|
+
// Store in SQLite
|
|
199
|
+
sqlite.insertMemory(memory);
|
|
200
|
+
// Generate and store embedding
|
|
201
|
+
const vector = await embedder.embed(content);
|
|
202
|
+
await lancedb.insertVector(memoryId, vector);
|
|
203
|
+
if (!options.quiet) {
|
|
204
|
+
console.log(`Memory captured successfully!`);
|
|
205
|
+
console.log(` ID: ${memoryId}`);
|
|
206
|
+
console.log(` Project: ${basename(workspace)}`);
|
|
207
|
+
console.log(` Type: ${memory.type}`);
|
|
208
|
+
console.log(` Content: ${content.slice(0, 100)}${content.length > 100 ? '...' : ''}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
// Cleanup
|
|
213
|
+
sqlite.close();
|
|
214
|
+
await lancedb.close();
|
|
215
|
+
await embedder.close();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
main().catch(error => {
|
|
219
|
+
console.error('Error:', error.message);
|
|
220
|
+
process.exit(1);
|
|
221
|
+
});
|
|
222
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/cli/capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/cli/index.ts
|
|
22
|
+
var cli_exports = {};
|
|
23
|
+
__export(cli_exports, {
|
|
24
|
+
setupCursor: () => setupCursor,
|
|
25
|
+
showStatus: () => showStatus
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(cli_exports);
|
|
28
|
+
var import_fs = require("fs");
|
|
29
|
+
var import_promises = require("fs/promises");
|
|
30
|
+
var import_path = require("path");
|
|
31
|
+
var import_os = require("os");
|
|
32
|
+
var import_child_process = require("child_process");
|
|
33
|
+
var MEMEXTEND_DIR = (0, import_path.join)((0, import_os.homedir)(), ".memextend");
|
|
34
|
+
var DB_PATH = (0, import_path.join)(MEMEXTEND_DIR, "memextend.db");
|
|
35
|
+
var CURSOR_CONFIG_PATHS = [
|
|
36
|
+
(0, import_path.join)((0, import_os.homedir)(), ".cursor", "mcp.json"),
|
|
37
|
+
(0, import_path.join)((0, import_os.homedir)(), "Library", "Application Support", "Cursor", "User", "mcp.json"),
|
|
38
|
+
// macOS
|
|
39
|
+
(0, import_path.join)((0, import_os.homedir)(), ".config", "Cursor", "User", "mcp.json"),
|
|
40
|
+
// Linux
|
|
41
|
+
(0, import_path.join)((0, import_os.homedir)(), "AppData", "Roaming", "Cursor", "User", "mcp.json")
|
|
42
|
+
// Windows
|
|
43
|
+
];
|
|
44
|
+
function getScriptDir() {
|
|
45
|
+
return __dirname;
|
|
46
|
+
}
|
|
47
|
+
function getMcpServerPath() {
|
|
48
|
+
const scriptDir = getScriptDir();
|
|
49
|
+
return (0, import_path.join)(scriptDir, "..", "mcp", "server.cjs");
|
|
50
|
+
}
|
|
51
|
+
function findCursorConfigPath() {
|
|
52
|
+
for (const configPath of CURSOR_CONFIG_PATHS) {
|
|
53
|
+
const configDir = (0, import_path.dirname)(configPath);
|
|
54
|
+
if ((0, import_fs.existsSync)(configDir)) {
|
|
55
|
+
return configPath;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
async function setupCursor() {
|
|
61
|
+
console.log("Setting up memextend for Cursor...\n");
|
|
62
|
+
if (!(0, import_fs.existsSync)(DB_PATH)) {
|
|
63
|
+
console.log("Warning: memextend not initialized. Run `memextend init` first.\n");
|
|
64
|
+
}
|
|
65
|
+
const configPath = findCursorConfigPath();
|
|
66
|
+
if (!configPath) {
|
|
67
|
+
console.log("Could not find Cursor configuration directory.");
|
|
68
|
+
console.log("Please ensure Cursor is installed and has been run at least once.\n");
|
|
69
|
+
console.log("Manual setup instructions:");
|
|
70
|
+
printManualSetupInstructions();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const mcpServerPath = getMcpServerPath();
|
|
74
|
+
if (!(0, import_fs.existsSync)(mcpServerPath)) {
|
|
75
|
+
console.log(`Error: MCP server not found at ${mcpServerPath}`);
|
|
76
|
+
console.log("Please run `npm run build` in the @memextend/cursor package first.\n");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let config = { mcpServers: {} };
|
|
80
|
+
if ((0, import_fs.existsSync)(configPath)) {
|
|
81
|
+
try {
|
|
82
|
+
const content = await (0, import_promises.readFile)(configPath, "utf-8");
|
|
83
|
+
config = JSON.parse(content);
|
|
84
|
+
if (!config.mcpServers) {
|
|
85
|
+
config.mcpServers = {};
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.log("Warning: Could not parse existing mcp.json, creating new one");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (config.mcpServers.memextend) {
|
|
92
|
+
console.log("memextend is already configured in Cursor.");
|
|
93
|
+
console.log(`Current path: ${config.mcpServers.memextend.args?.[0] || "unknown"}`);
|
|
94
|
+
console.log("\nTo update, remove the existing entry and run setup again.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
config.mcpServers.memextend = {
|
|
98
|
+
command: "node",
|
|
99
|
+
args: [(0, import_path.resolve)(mcpServerPath)]
|
|
100
|
+
};
|
|
101
|
+
await (0, import_promises.mkdir)((0, import_path.dirname)(configPath), { recursive: true });
|
|
102
|
+
await (0, import_promises.writeFile)(configPath, JSON.stringify(config, null, 2));
|
|
103
|
+
console.log("Success! memextend MCP server added to Cursor.\n");
|
|
104
|
+
console.log(`Configuration file: ${configPath}`);
|
|
105
|
+
console.log(`MCP server path: ${(0, import_path.resolve)(mcpServerPath)}
|
|
106
|
+
`);
|
|
107
|
+
console.log("Next steps:");
|
|
108
|
+
console.log("1. Restart Cursor to load the new MCP server");
|
|
109
|
+
console.log("2. In Cursor, ask Claude to use memextend tools");
|
|
110
|
+
console.log('3. Try: "Search my memories for [topic]" or "Save this to memory"');
|
|
111
|
+
}
|
|
112
|
+
function printManualSetupInstructions() {
|
|
113
|
+
const mcpServerPath = getMcpServerPath();
|
|
114
|
+
console.log(`
|
|
115
|
+
Create or edit ~/.cursor/mcp.json with the following content:
|
|
116
|
+
|
|
117
|
+
{
|
|
118
|
+
"mcpServers": {
|
|
119
|
+
"memextend": {
|
|
120
|
+
"command": "node",
|
|
121
|
+
"args": ["${(0, import_path.resolve)(mcpServerPath)}"]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
Then restart Cursor to load the MCP server.
|
|
127
|
+
`);
|
|
128
|
+
}
|
|
129
|
+
async function showStatus() {
|
|
130
|
+
console.log("memextend Cursor Adapter Status\n");
|
|
131
|
+
if ((0, import_fs.existsSync)(DB_PATH)) {
|
|
132
|
+
console.log("[OK] memextend initialized");
|
|
133
|
+
} else {
|
|
134
|
+
console.log("[!] memextend not initialized - run `memextend init`");
|
|
135
|
+
}
|
|
136
|
+
const configPath = findCursorConfigPath();
|
|
137
|
+
if (configPath && (0, import_fs.existsSync)(configPath)) {
|
|
138
|
+
try {
|
|
139
|
+
const content = await (0, import_promises.readFile)(configPath, "utf-8");
|
|
140
|
+
const config = JSON.parse(content);
|
|
141
|
+
if (config.mcpServers?.memextend) {
|
|
142
|
+
console.log("[OK] Cursor MCP configured");
|
|
143
|
+
console.log(` Config: ${configPath}`);
|
|
144
|
+
} else {
|
|
145
|
+
console.log("[!] Cursor MCP not configured - run `memextend-cursor setup`");
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
console.log("[!] Could not read Cursor config");
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
console.log("[!] Cursor config not found");
|
|
152
|
+
}
|
|
153
|
+
const mcpServerPath = getMcpServerPath();
|
|
154
|
+
if ((0, import_fs.existsSync)(mcpServerPath)) {
|
|
155
|
+
console.log("[OK] MCP server built");
|
|
156
|
+
console.log(` Path: ${(0, import_path.resolve)(mcpServerPath)}`);
|
|
157
|
+
} else {
|
|
158
|
+
console.log("[!] MCP server not built - run `npm run build`");
|
|
159
|
+
}
|
|
160
|
+
console.log("");
|
|
161
|
+
}
|
|
162
|
+
function printHelp() {
|
|
163
|
+
console.log(`
|
|
164
|
+
memextend-cursor - Cursor IDE adapter for memextend
|
|
165
|
+
|
|
166
|
+
USAGE:
|
|
167
|
+
memextend-cursor <command> [options]
|
|
168
|
+
|
|
169
|
+
COMMANDS:
|
|
170
|
+
setup Configure Cursor to use memextend MCP server
|
|
171
|
+
status Check memextend and Cursor configuration status
|
|
172
|
+
capture Capture content to memory (alias for memextend-cursor-capture)
|
|
173
|
+
inject Get context for session (alias for memextend-cursor-inject)
|
|
174
|
+
help Show this help message
|
|
175
|
+
|
|
176
|
+
EXAMPLES:
|
|
177
|
+
# Initial setup
|
|
178
|
+
memextend-cursor setup
|
|
179
|
+
|
|
180
|
+
# Check status
|
|
181
|
+
memextend-cursor status
|
|
182
|
+
|
|
183
|
+
# Capture a memory
|
|
184
|
+
memextend-cursor capture -c "Implemented user auth with JWT"
|
|
185
|
+
|
|
186
|
+
# Get session context
|
|
187
|
+
memextend-cursor inject
|
|
188
|
+
|
|
189
|
+
For more details on capture and inject commands:
|
|
190
|
+
memextend-cursor capture --help
|
|
191
|
+
memextend-cursor inject --help
|
|
192
|
+
|
|
193
|
+
DOCUMENTATION:
|
|
194
|
+
See the README.md for complete setup and usage instructions.
|
|
195
|
+
`);
|
|
196
|
+
}
|
|
197
|
+
async function main() {
|
|
198
|
+
const args = process.argv.slice(2);
|
|
199
|
+
const command = args[0];
|
|
200
|
+
switch (command) {
|
|
201
|
+
case "setup":
|
|
202
|
+
await setupCursor();
|
|
203
|
+
break;
|
|
204
|
+
case "status":
|
|
205
|
+
await showStatus();
|
|
206
|
+
break;
|
|
207
|
+
case "capture": {
|
|
208
|
+
const scriptDir = getScriptDir();
|
|
209
|
+
const captureScript = (0, import_path.join)(scriptDir, "capture.cjs");
|
|
210
|
+
const child = (0, import_child_process.spawn)("node", [captureScript, ...args.slice(1)], {
|
|
211
|
+
stdio: "inherit"
|
|
212
|
+
});
|
|
213
|
+
child.on("close", (code) => process.exit(code ?? 0));
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case "inject": {
|
|
217
|
+
const scriptDir = getScriptDir();
|
|
218
|
+
const injectScript = (0, import_path.join)(scriptDir, "inject.cjs");
|
|
219
|
+
const child = (0, import_child_process.spawn)("node", [injectScript, ...args.slice(1)], {
|
|
220
|
+
stdio: "inherit"
|
|
221
|
+
});
|
|
222
|
+
child.on("close", (code) => process.exit(code ?? 0));
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case "help":
|
|
226
|
+
case "--help":
|
|
227
|
+
case "-h":
|
|
228
|
+
case void 0:
|
|
229
|
+
printHelp();
|
|
230
|
+
break;
|
|
231
|
+
default:
|
|
232
|
+
console.error(`Unknown command: ${command}`);
|
|
233
|
+
console.error("Run `memextend-cursor help` for usage information.");
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
main().catch((error) => {
|
|
238
|
+
console.error("Error:", error.message);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
});
|
|
241
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
242
|
+
0 && (module.exports = {
|
|
243
|
+
setupCursor,
|
|
244
|
+
showStatus
|
|
245
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AA4DA,iBAAe,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAmE1C;AAqBD,iBAAe,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAuCzC;AA4FD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC"}
|