code-session-memory 0.9.0 → 0.11.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 +56 -18
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +15 -13
- package/dist/mcp/index.js.map +1 -1
- package/dist/src/cli-query.d.ts +1 -0
- package/dist/src/cli-query.d.ts.map +1 -1
- package/dist/src/cli-query.js +8 -3
- package/dist/src/cli-query.js.map +1 -1
- package/dist/src/cli-sessions.d.ts.map +1 -1
- package/dist/src/cli-sessions.js +73 -0
- package/dist/src/cli-sessions.js.map +1 -1
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +332 -57
- package/dist/src/cli.js.map +1 -1
- package/dist/src/clipboard.d.ts +24 -0
- package/dist/src/clipboard.d.ts.map +1 -0
- package/dist/src/clipboard.js +48 -0
- package/dist/src/clipboard.js.map +1 -0
- package/dist/src/codex-session-to-messages.d.ts +22 -0
- package/dist/src/codex-session-to-messages.d.ts.map +1 -0
- package/dist/src/codex-session-to-messages.js +212 -0
- package/dist/src/codex-session-to-messages.js.map +1 -0
- package/dist/src/indexer-cli-codex.d.ts +12 -0
- package/dist/src/indexer-cli-codex.d.ts.map +1 -0
- package/dist/src/indexer-cli-codex.js +126 -0
- package/dist/src/indexer-cli-codex.js.map +1 -0
- package/dist/src/indexer.d.ts +1 -1
- package/dist/src/indexer.js +1 -1
- package/dist/src/restart-launchers.d.ts +37 -0
- package/dist/src/restart-launchers.d.ts.map +1 -0
- package/dist/src/restart-launchers.js +68 -0
- package/dist/src/restart-launchers.js.map +1 -0
- package/dist/src/session-compactor.d.ts +48 -0
- package/dist/src/session-compactor.d.ts.map +1 -0
- package/dist/src/session-compactor.js +203 -0
- package/dist/src/session-compactor.js.map +1 -0
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/skill/memory.md +7 -4
package/dist/src/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* code-session-memory CLI
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
|
-
* npx code-session-memory install — install for
|
|
7
|
+
* npx code-session-memory install — install for all detected supported tools
|
|
8
8
|
* npx code-session-memory status — show installation status
|
|
9
9
|
* npx code-session-memory uninstall — remove all installed components
|
|
10
10
|
* npx code-session-memory reset-db — wipe the database (with confirmation)
|
|
@@ -51,6 +51,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
51
51
|
const path_1 = __importDefault(require("path"));
|
|
52
52
|
const os_1 = __importDefault(require("os"));
|
|
53
53
|
const clack = __importStar(require("@clack/prompts"));
|
|
54
|
+
const smol_toml_1 = require("smol-toml");
|
|
54
55
|
const database_1 = require("./database");
|
|
55
56
|
const cli_sessions_1 = require("./cli-sessions");
|
|
56
57
|
const cli_query_1 = require("./cli-query");
|
|
@@ -123,6 +124,9 @@ function getIndexerCliCursorPath() {
|
|
|
123
124
|
function getIndexerCliVscodePath() {
|
|
124
125
|
return path_1.default.join(getPackageRoot(), "dist", "src", "indexer-cli-vscode.js");
|
|
125
126
|
}
|
|
127
|
+
function getIndexerCliCodexPath() {
|
|
128
|
+
return path_1.default.join(getPackageRoot(), "dist", "src", "indexer-cli-codex.js");
|
|
129
|
+
}
|
|
126
130
|
// ---------------------------------------------------------------------------
|
|
127
131
|
// Paths — Cursor
|
|
128
132
|
// ---------------------------------------------------------------------------
|
|
@@ -167,6 +171,21 @@ function getVscodeHooksPath() {
|
|
|
167
171
|
return path_1.default.join(getVscodeConfigDir(), "hooks", "code-session-memory.json");
|
|
168
172
|
}
|
|
169
173
|
// ---------------------------------------------------------------------------
|
|
174
|
+
// Paths — Codex
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
function getCodexConfigDir() {
|
|
177
|
+
const envDir = process.env.CODEX_HOME;
|
|
178
|
+
if (envDir)
|
|
179
|
+
return envDir;
|
|
180
|
+
return path_1.default.join(os_1.default.homedir(), ".codex");
|
|
181
|
+
}
|
|
182
|
+
function getCodexConfigPath() {
|
|
183
|
+
return path_1.default.join(getCodexConfigDir(), "config.toml");
|
|
184
|
+
}
|
|
185
|
+
function getCodexSkillDst() {
|
|
186
|
+
return path_1.default.join(getCodexConfigDir(), "skills", "code-session-memory", "SKILL.md");
|
|
187
|
+
}
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
170
189
|
// Helpers
|
|
171
190
|
// ---------------------------------------------------------------------------
|
|
172
191
|
/**
|
|
@@ -652,7 +671,7 @@ function installCursorSkill(skillSrc) {
|
|
|
652
671
|
const cursorFrontmatter = [
|
|
653
672
|
"---",
|
|
654
673
|
"name: code-session-memory",
|
|
655
|
-
"description: Search past AI coding sessions semantically across OpenCode, Claude Code, and
|
|
674
|
+
"description: Search past AI coding sessions semantically across OpenCode, Claude Code, Cursor, VS Code, and Codex. Use this when the user asks about past work, decisions, or implementations.",
|
|
656
675
|
"---",
|
|
657
676
|
"",
|
|
658
677
|
].join("\n");
|
|
@@ -891,6 +910,172 @@ function checkVscodeMcpConfigured() {
|
|
|
891
910
|
}
|
|
892
911
|
}
|
|
893
912
|
// ---------------------------------------------------------------------------
|
|
913
|
+
// Codex — config.toml (TOML)
|
|
914
|
+
// ---------------------------------------------------------------------------
|
|
915
|
+
function parseCodexConfigOrEmpty(configPath) {
|
|
916
|
+
if (!fs_1.default.existsSync(configPath))
|
|
917
|
+
return {};
|
|
918
|
+
try {
|
|
919
|
+
return (0, smol_toml_1.parse)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
920
|
+
}
|
|
921
|
+
catch {
|
|
922
|
+
throw new Error(`Could not parse existing ${configPath} — please check it is valid TOML.`);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function mergeCodexEnvVarsPassthrough(existing) {
|
|
926
|
+
const values = Array.isArray(existing)
|
|
927
|
+
? existing.filter((v) => typeof v === "string" && v.trim().length > 0)
|
|
928
|
+
: [];
|
|
929
|
+
if (!values.includes("OPENAI_API_KEY"))
|
|
930
|
+
values.push("OPENAI_API_KEY");
|
|
931
|
+
return values;
|
|
932
|
+
}
|
|
933
|
+
function installCodexMcpConfig(mcpServerPath) {
|
|
934
|
+
const configPath = getCodexConfigPath();
|
|
935
|
+
const existed = fs_1.default.existsSync(configPath);
|
|
936
|
+
const config = parseCodexConfigOrEmpty(configPath);
|
|
937
|
+
const mcpServersRaw = config.mcp_servers;
|
|
938
|
+
const mcpServers = mcpServersRaw && typeof mcpServersRaw === "object"
|
|
939
|
+
? mcpServersRaw
|
|
940
|
+
: {};
|
|
941
|
+
const existingServer = mcpServers["code-session-memory"];
|
|
942
|
+
const serverConfig = existingServer && typeof existingServer === "object"
|
|
943
|
+
? existingServer
|
|
944
|
+
: {};
|
|
945
|
+
mcpServers["code-session-memory"] = {
|
|
946
|
+
...serverConfig,
|
|
947
|
+
command: "node",
|
|
948
|
+
args: [mcpServerPath],
|
|
949
|
+
// Codex MCP servers run with a restricted environment by default.
|
|
950
|
+
// Pass-through env vars are configured via env_vars (env is a map of fixed values).
|
|
951
|
+
env_vars: mergeCodexEnvVarsPassthrough(serverConfig.env_vars),
|
|
952
|
+
};
|
|
953
|
+
config.mcp_servers = mcpServers;
|
|
954
|
+
ensureDir(path_1.default.dirname(configPath));
|
|
955
|
+
fs_1.default.writeFileSync(configPath, (0, smol_toml_1.stringify)(config) + "\n", "utf8");
|
|
956
|
+
return { configPath, existed };
|
|
957
|
+
}
|
|
958
|
+
function uninstallCodexMcpConfig() {
|
|
959
|
+
const configPath = getCodexConfigPath();
|
|
960
|
+
if (!fs_1.default.existsSync(configPath))
|
|
961
|
+
return "not_found";
|
|
962
|
+
try {
|
|
963
|
+
const config = (0, smol_toml_1.parse)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
964
|
+
const mcpServers = config.mcp_servers;
|
|
965
|
+
if (!mcpServers || !(Object.prototype.hasOwnProperty.call(mcpServers, "code-session-memory"))) {
|
|
966
|
+
return "not_found";
|
|
967
|
+
}
|
|
968
|
+
delete mcpServers["code-session-memory"];
|
|
969
|
+
fs_1.default.writeFileSync(configPath, (0, smol_toml_1.stringify)(config) + "\n", "utf8");
|
|
970
|
+
return "done";
|
|
971
|
+
}
|
|
972
|
+
catch {
|
|
973
|
+
return "not_found";
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
function checkCodexMcpConfigured() {
|
|
977
|
+
const configPath = getCodexConfigPath();
|
|
978
|
+
try {
|
|
979
|
+
const config = (0, smol_toml_1.parse)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
980
|
+
const mcpServers = config.mcp_servers;
|
|
981
|
+
return !!(mcpServers && Object.prototype.hasOwnProperty.call(mcpServers, "code-session-memory"));
|
|
982
|
+
}
|
|
983
|
+
catch {
|
|
984
|
+
return false;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
function checkCodexOpenAiPassthroughConfigured() {
|
|
988
|
+
const configPath = getCodexConfigPath();
|
|
989
|
+
try {
|
|
990
|
+
const config = (0, smol_toml_1.parse)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
991
|
+
const mcpServers = config.mcp_servers;
|
|
992
|
+
const server = mcpServers?.["code-session-memory"];
|
|
993
|
+
if (!server || typeof server !== "object")
|
|
994
|
+
return false;
|
|
995
|
+
const envVars = server.env_vars;
|
|
996
|
+
return Array.isArray(envVars) && envVars.includes("OPENAI_API_KEY");
|
|
997
|
+
}
|
|
998
|
+
catch {
|
|
999
|
+
return false;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
function installCodexHook(indexerCliCodexPath) {
|
|
1003
|
+
const configPath = getCodexConfigPath();
|
|
1004
|
+
const existed = fs_1.default.existsSync(configPath);
|
|
1005
|
+
const config = parseCodexConfigOrEmpty(configPath);
|
|
1006
|
+
config.notify = ["node", indexerCliCodexPath];
|
|
1007
|
+
ensureDir(path_1.default.dirname(configPath));
|
|
1008
|
+
fs_1.default.writeFileSync(configPath, (0, smol_toml_1.stringify)(config) + "\n", "utf8");
|
|
1009
|
+
return { configPath, existed };
|
|
1010
|
+
}
|
|
1011
|
+
function uninstallCodexHook() {
|
|
1012
|
+
const configPath = getCodexConfigPath();
|
|
1013
|
+
if (!fs_1.default.existsSync(configPath))
|
|
1014
|
+
return "not_found";
|
|
1015
|
+
try {
|
|
1016
|
+
const config = (0, smol_toml_1.parse)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
1017
|
+
const notify = config.notify;
|
|
1018
|
+
if (!Array.isArray(notify))
|
|
1019
|
+
return "not_found";
|
|
1020
|
+
const hasOurHook = notify.some((v) => typeof v === "string" && v.includes("indexer-cli-codex"));
|
|
1021
|
+
if (!hasOurHook)
|
|
1022
|
+
return "not_found";
|
|
1023
|
+
delete config.notify;
|
|
1024
|
+
fs_1.default.writeFileSync(configPath, (0, smol_toml_1.stringify)(config) + "\n", "utf8");
|
|
1025
|
+
return "done";
|
|
1026
|
+
}
|
|
1027
|
+
catch {
|
|
1028
|
+
return "not_found";
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function checkCodexHookInstalled() {
|
|
1032
|
+
const configPath = getCodexConfigPath();
|
|
1033
|
+
try {
|
|
1034
|
+
const config = (0, smol_toml_1.parse)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
1035
|
+
const notify = config.notify;
|
|
1036
|
+
if (!Array.isArray(notify))
|
|
1037
|
+
return false;
|
|
1038
|
+
return notify.some((v) => typeof v === "string" && v.includes("indexer-cli-codex"));
|
|
1039
|
+
}
|
|
1040
|
+
catch {
|
|
1041
|
+
return false;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
function installCodexSkill(skillSrc) {
|
|
1045
|
+
const dstPath = getCodexSkillDst();
|
|
1046
|
+
const existed = fs_1.default.existsSync(dstPath);
|
|
1047
|
+
if (!fs_1.default.existsSync(skillSrc)) {
|
|
1048
|
+
throw new Error(`Skill source not found: ${skillSrc}\nDid you run "npm run build" first?`);
|
|
1049
|
+
}
|
|
1050
|
+
const skillBody = fs_1.default.readFileSync(skillSrc, "utf8");
|
|
1051
|
+
const bodyWithoutFrontmatter = skillBody
|
|
1052
|
+
.replace(/^---[\s\S]*?---\s*\n?/, "")
|
|
1053
|
+
.trimStart();
|
|
1054
|
+
const codexFrontmatter = [
|
|
1055
|
+
"---",
|
|
1056
|
+
"name: code-session-memory",
|
|
1057
|
+
"description: Search past AI coding sessions semantically across OpenCode, Claude Code, Cursor, VS Code, and Codex.",
|
|
1058
|
+
"---",
|
|
1059
|
+
"",
|
|
1060
|
+
].join("\n");
|
|
1061
|
+
ensureDir(path_1.default.dirname(dstPath));
|
|
1062
|
+
fs_1.default.writeFileSync(dstPath, codexFrontmatter + bodyWithoutFrontmatter, "utf8");
|
|
1063
|
+
return { dstPath, existed };
|
|
1064
|
+
}
|
|
1065
|
+
function uninstallCodexSkill() {
|
|
1066
|
+
const dstPath = getCodexSkillDst();
|
|
1067
|
+
if (!fs_1.default.existsSync(dstPath))
|
|
1068
|
+
return "not_found";
|
|
1069
|
+
fs_1.default.unlinkSync(dstPath);
|
|
1070
|
+
try {
|
|
1071
|
+
const dir = path_1.default.dirname(dstPath);
|
|
1072
|
+
if (fs_1.default.readdirSync(dir).length === 0)
|
|
1073
|
+
fs_1.default.rmdirSync(dir);
|
|
1074
|
+
}
|
|
1075
|
+
catch { /* ignore */ }
|
|
1076
|
+
return "done";
|
|
1077
|
+
}
|
|
1078
|
+
// ---------------------------------------------------------------------------
|
|
894
1079
|
// Formatting helpers
|
|
895
1080
|
// ---------------------------------------------------------------------------
|
|
896
1081
|
function bold(s) { return `\x1b[1m${s}\x1b[0m`; }
|
|
@@ -898,6 +1083,24 @@ function green(s) { return `\x1b[32m${s}\x1b[0m`; }
|
|
|
898
1083
|
function red(s) { return `\x1b[31m${s}\x1b[0m`; }
|
|
899
1084
|
function dim(s) { return `\x1b[2m${s}\x1b[0m`; }
|
|
900
1085
|
function ok(v) { return v ? green("✓") : red("✗"); }
|
|
1086
|
+
// ---------------------------------------------------------------------------
|
|
1087
|
+
// Tool detection
|
|
1088
|
+
// ---------------------------------------------------------------------------
|
|
1089
|
+
function isOpenCodeInstalled() {
|
|
1090
|
+
return fs_1.default.existsSync(getOpenCodeConfigDir());
|
|
1091
|
+
}
|
|
1092
|
+
function isClaudeCodeInstalled() {
|
|
1093
|
+
return fs_1.default.existsSync(getClaudeConfigDir());
|
|
1094
|
+
}
|
|
1095
|
+
function isCursorInstalled() {
|
|
1096
|
+
return fs_1.default.existsSync(getCursorConfigDir());
|
|
1097
|
+
}
|
|
1098
|
+
function isVscodeInstalled() {
|
|
1099
|
+
return fs_1.default.existsSync(getVscodeConfigDir());
|
|
1100
|
+
}
|
|
1101
|
+
function isCodexInstalled() {
|
|
1102
|
+
return fs_1.default.existsSync(getCodexConfigDir());
|
|
1103
|
+
}
|
|
901
1104
|
function step(label, fn) {
|
|
902
1105
|
process.stdout.write(` ${label}... `);
|
|
903
1106
|
try {
|
|
@@ -910,6 +1113,13 @@ function step(label, fn) {
|
|
|
910
1113
|
process.exit(1);
|
|
911
1114
|
}
|
|
912
1115
|
}
|
|
1116
|
+
function stepIf(condition, label, fn) {
|
|
1117
|
+
if (!condition) {
|
|
1118
|
+
console.log(` ${dim("○")} ${dim(label)} ${dim("(tool not detected — skipped)")}`);
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
step(label, fn);
|
|
1122
|
+
}
|
|
913
1123
|
// ---------------------------------------------------------------------------
|
|
914
1124
|
// Commands
|
|
915
1125
|
// ---------------------------------------------------------------------------
|
|
@@ -920,6 +1130,12 @@ function install() {
|
|
|
920
1130
|
const indexerClaudePath = getIndexerCliClaudePath();
|
|
921
1131
|
const indexerCursorPath = getIndexerCliCursorPath();
|
|
922
1132
|
const indexerVscodePath = getIndexerCliVscodePath();
|
|
1133
|
+
const indexerCodexPath = getIndexerCliCodexPath();
|
|
1134
|
+
const openCodeInstalled = isOpenCodeInstalled();
|
|
1135
|
+
const claudeInstalled = isClaudeCodeInstalled();
|
|
1136
|
+
const cursorInstalled = isCursorInstalled();
|
|
1137
|
+
const vscodeInstalled = isVscodeInstalled();
|
|
1138
|
+
const codexInstalled = isCodexInstalled();
|
|
923
1139
|
// 1. DB
|
|
924
1140
|
step("Initialising database", () => {
|
|
925
1141
|
ensureDir(path_1.default.dirname(dbPath));
|
|
@@ -927,68 +1143,73 @@ function install() {
|
|
|
927
1143
|
db.close();
|
|
928
1144
|
return dbPath;
|
|
929
1145
|
});
|
|
930
|
-
//
|
|
931
|
-
|
|
1146
|
+
// OpenCode
|
|
1147
|
+
stepIf(openCodeInstalled, "Installing OpenCode plugin", () => {
|
|
932
1148
|
const dst = getOpenCodePluginDst();
|
|
933
1149
|
installOpenCodePlugin(getPluginSrc(), dst);
|
|
934
1150
|
return dst;
|
|
935
1151
|
});
|
|
936
|
-
|
|
937
|
-
step("Installing OpenCode skill", () => {
|
|
1152
|
+
stepIf(openCodeInstalled, "Installing OpenCode skill", () => {
|
|
938
1153
|
const dst = getOpenCodeSkillDst();
|
|
939
1154
|
copyFile(getSkillSrc(), dst);
|
|
940
1155
|
return dst;
|
|
941
1156
|
});
|
|
942
|
-
|
|
943
|
-
step("Configuring OpenCode MCP server", () => {
|
|
1157
|
+
stepIf(openCodeInstalled, "Configuring OpenCode MCP server", () => {
|
|
944
1158
|
const { configPath, existed } = installOpenCodeMcpConfig(mcpPath);
|
|
945
1159
|
return `${existed ? "updated" : "created"} ${configPath}`;
|
|
946
1160
|
});
|
|
947
|
-
//
|
|
948
|
-
|
|
1161
|
+
// Claude Code
|
|
1162
|
+
stepIf(claudeInstalled, "Configuring Claude Code MCP server", () => {
|
|
949
1163
|
const { configPath, existed } = installClaudeMcpConfig(mcpPath);
|
|
950
1164
|
return `${existed ? "updated" : "created"} ${configPath}`;
|
|
951
1165
|
});
|
|
952
|
-
|
|
953
|
-
step("Installing Claude Code Stop hook", () => {
|
|
1166
|
+
stepIf(claudeInstalled, "Installing Claude Code Stop hook", () => {
|
|
954
1167
|
const { settingsPath, existed } = installClaudeHook(indexerClaudePath);
|
|
955
1168
|
return `${existed ? "updated" : "created"} ${settingsPath}`;
|
|
956
1169
|
});
|
|
957
|
-
|
|
958
|
-
step("Installing Claude Code context (CLAUDE.md)", () => {
|
|
1170
|
+
stepIf(claudeInstalled, "Installing Claude Code context (CLAUDE.md)", () => {
|
|
959
1171
|
const { mdPath, existed } = installClaudeMd(getSkillSrc());
|
|
960
1172
|
return `${existed ? "updated" : "created"} ${mdPath}`;
|
|
961
1173
|
});
|
|
962
|
-
//
|
|
963
|
-
|
|
1174
|
+
// Cursor
|
|
1175
|
+
stepIf(cursorInstalled, "Configuring Cursor MCP server", () => {
|
|
964
1176
|
const { configPath, existed } = installCursorMcpConfig(mcpPath);
|
|
965
1177
|
return `${existed ? "updated" : "created"} ${configPath}`;
|
|
966
1178
|
});
|
|
967
|
-
|
|
968
|
-
step("Installing Cursor stop hook", () => {
|
|
1179
|
+
stepIf(cursorInstalled, "Installing Cursor stop hook", () => {
|
|
969
1180
|
const { hooksPath, existed } = installCursorHook(indexerCursorPath);
|
|
970
1181
|
return `${existed ? "updated" : "created"} ${hooksPath}`;
|
|
971
1182
|
});
|
|
972
|
-
|
|
973
|
-
step("Installing Cursor skill", () => {
|
|
1183
|
+
stepIf(cursorInstalled, "Installing Cursor skill", () => {
|
|
974
1184
|
const { dstPath, existed } = installCursorSkill(getSkillSrc());
|
|
975
1185
|
return `${existed ? "updated" : "created"} ${dstPath}`;
|
|
976
1186
|
});
|
|
977
|
-
//
|
|
978
|
-
|
|
1187
|
+
// VS Code
|
|
1188
|
+
stepIf(vscodeInstalled, "Configuring VS Code MCP server", () => {
|
|
979
1189
|
const { configPath, existed } = installVscodeMcpConfig(mcpPath);
|
|
980
1190
|
return `${existed ? "updated" : "created"} ${configPath}`;
|
|
981
1191
|
});
|
|
982
|
-
|
|
983
|
-
step("Installing VS Code Stop hook", () => {
|
|
1192
|
+
stepIf(vscodeInstalled, "Installing VS Code Stop hook", () => {
|
|
984
1193
|
const { hooksPath, existed } = installVscodeHook(indexerVscodePath);
|
|
985
1194
|
return `${existed ? "updated" : "created"} ${hooksPath}`;
|
|
986
1195
|
});
|
|
987
|
-
|
|
988
|
-
step("Registering VS Code hook location", () => {
|
|
1196
|
+
stepIf(vscodeInstalled, "Registering VS Code hook location", () => {
|
|
989
1197
|
const { settingsPath, existed } = installVscodeHookLocation();
|
|
990
1198
|
return `${existed ? "updated" : "created"} ${settingsPath}`;
|
|
991
1199
|
});
|
|
1200
|
+
// Codex
|
|
1201
|
+
stepIf(codexInstalled, "Configuring Codex MCP server", () => {
|
|
1202
|
+
const { configPath, existed } = installCodexMcpConfig(mcpPath);
|
|
1203
|
+
return `${existed ? "updated" : "created"} ${configPath}`;
|
|
1204
|
+
});
|
|
1205
|
+
stepIf(codexInstalled, "Installing Codex notify hook", () => {
|
|
1206
|
+
const { configPath, existed } = installCodexHook(indexerCodexPath);
|
|
1207
|
+
return `${existed ? "updated" : "created"} ${configPath}`;
|
|
1208
|
+
});
|
|
1209
|
+
stepIf(codexInstalled, "Installing Codex skill", () => {
|
|
1210
|
+
const { dstPath, existed } = installCodexSkill(getSkillSrc());
|
|
1211
|
+
return `${existed ? "updated" : "created"} ${dstPath}`;
|
|
1212
|
+
});
|
|
992
1213
|
console.log(`
|
|
993
1214
|
${bold("Installation complete!")}
|
|
994
1215
|
|
|
@@ -997,9 +1218,10 @@ ${bold("Required environment variable:")}
|
|
|
997
1218
|
|
|
998
1219
|
${bold("Default DB path:")} ${dbPath}
|
|
999
1220
|
|
|
1000
|
-
Restart ${bold("OpenCode")}, ${bold("Claude Code")}, ${bold("Cursor")},
|
|
1221
|
+
Restart ${bold("OpenCode")}, ${bold("Claude Code")}, ${bold("Cursor")}, ${bold("VS Code")}, and ${bold("Codex")} to activate.
|
|
1001
1222
|
|
|
1002
1223
|
${bold("VS Code note:")} Ensure ${bold("Chat: Use Hooks")} is enabled in VS Code settings.
|
|
1224
|
+
${bold("Codex note:")} The notify hook and OPENAI_API_KEY passthrough are set in ${dim(getCodexConfigPath())}.
|
|
1003
1225
|
Run ${bold("npx code-session-memory status")} to verify.
|
|
1004
1226
|
`);
|
|
1005
1227
|
}
|
|
@@ -1007,22 +1229,57 @@ function status() {
|
|
|
1007
1229
|
console.log(bold("\ncode-session-memory status\n"));
|
|
1008
1230
|
const dbPath = (0, database_1.resolveDbPath)();
|
|
1009
1231
|
const mcpPath = getMcpServerPath();
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1232
|
+
const openCodeInstalled = isOpenCodeInstalled();
|
|
1233
|
+
const claudeInstalled = isClaudeCodeInstalled();
|
|
1234
|
+
const cursorInstalled = isCursorInstalled();
|
|
1235
|
+
const vscodeInstalled = isVscodeInstalled();
|
|
1236
|
+
const codexInstalled = isCodexInstalled();
|
|
1237
|
+
if (openCodeInstalled) {
|
|
1238
|
+
console.log(bold(" OpenCode"));
|
|
1239
|
+
console.log(` ${ok(fs_1.default.existsSync(getOpenCodePluginDst()))} Plugin ${dim(getOpenCodePluginDst())}`);
|
|
1240
|
+
console.log(` ${ok(fs_1.default.existsSync(getOpenCodeSkillDst()))} Skill ${dim(getOpenCodeSkillDst())}`);
|
|
1241
|
+
console.log(` ${ok(checkMcpConfigured())} MCP config ${dim(getGlobalOpenCodeConfigPath())}`);
|
|
1242
|
+
}
|
|
1243
|
+
else {
|
|
1244
|
+
console.log(bold(" OpenCode") + dim(" (not installed — skipped)"));
|
|
1245
|
+
}
|
|
1246
|
+
if (claudeInstalled) {
|
|
1247
|
+
console.log(bold("\n Claude Code"));
|
|
1248
|
+
console.log(` ${ok(checkClaudeMcpConfigured())} MCP config ${dim(getClaudeUserConfigPath())}`);
|
|
1249
|
+
console.log(` ${ok(checkClaudeHookInstalled())} Stop hook ${dim(getClaudeSettingsPath())}`);
|
|
1250
|
+
console.log(` ${ok(checkClaudeMdInstalled())} CLAUDE.md ${dim(getClaudeMdPath())}`);
|
|
1251
|
+
}
|
|
1252
|
+
else {
|
|
1253
|
+
console.log(bold("\n Claude Code") + dim(" (not installed — skipped)"));
|
|
1254
|
+
}
|
|
1255
|
+
if (cursorInstalled) {
|
|
1256
|
+
console.log(bold("\n Cursor"));
|
|
1257
|
+
console.log(` ${ok(checkCursorMcpConfigured())} MCP config ${dim(getCursorMcpConfigPath())}`);
|
|
1258
|
+
console.log(` ${ok(checkCursorHookInstalled())} Stop hook ${dim(getCursorHooksPath())}`);
|
|
1259
|
+
console.log(` ${ok(fs_1.default.existsSync(getCursorSkillDst()))} Skill ${dim(getCursorSkillDst())}`);
|
|
1260
|
+
}
|
|
1261
|
+
else {
|
|
1262
|
+
console.log(bold("\n Cursor") + dim(" (not installed — skipped)"));
|
|
1263
|
+
}
|
|
1264
|
+
if (vscodeInstalled) {
|
|
1265
|
+
console.log(bold("\n VS Code"));
|
|
1266
|
+
console.log(` ${ok(checkVscodeMcpConfigured())} MCP config ${dim(getVscodeMcpConfigPath())}`);
|
|
1267
|
+
console.log(` ${ok(checkVscodeHookInstalled())} Stop hook ${dim(getVscodeHooksPath())}`);
|
|
1268
|
+
console.log(` ${ok(checkVscodeHookLocationRegistered())} Hook loc ${dim(getVscodeSettingsPath())}`);
|
|
1269
|
+
}
|
|
1270
|
+
else {
|
|
1271
|
+
console.log(bold("\n VS Code") + dim(" (not installed — skipped)"));
|
|
1272
|
+
}
|
|
1273
|
+
if (codexInstalled) {
|
|
1274
|
+
console.log(bold("\n Codex"));
|
|
1275
|
+
console.log(` ${ok(checkCodexMcpConfigured())} MCP config ${dim(getCodexConfigPath())}`);
|
|
1276
|
+
console.log(` ${ok(checkCodexOpenAiPassthroughConfigured())} OPENAI_KEY ${dim(getCodexConfigPath())}`);
|
|
1277
|
+
console.log(` ${ok(checkCodexHookInstalled())} Notify hook ${dim(getCodexConfigPath())}`);
|
|
1278
|
+
console.log(` ${ok(fs_1.default.existsSync(getCodexSkillDst()))} Skill ${dim(getCodexSkillDst())}`);
|
|
1279
|
+
}
|
|
1280
|
+
else {
|
|
1281
|
+
console.log(bold("\n Codex") + dim(" (not installed — skipped)"));
|
|
1282
|
+
}
|
|
1026
1283
|
console.log(bold("\n Shared"));
|
|
1027
1284
|
console.log(` ${ok(fs_1.default.existsSync(mcpPath))} MCP server ${dim(mcpPath)}`);
|
|
1028
1285
|
console.log(` ${ok(fs_1.default.existsSync(dbPath))} Database ${dim(dbPath)}`);
|
|
@@ -1046,18 +1303,22 @@ function status() {
|
|
|
1046
1303
|
}
|
|
1047
1304
|
catch { /* DB might be empty */ }
|
|
1048
1305
|
}
|
|
1049
|
-
const allOk = fs_1.default.existsSync(getOpenCodePluginDst()) &&
|
|
1306
|
+
const allOk = (!openCodeInstalled || (fs_1.default.existsSync(getOpenCodePluginDst()) &&
|
|
1050
1307
|
fs_1.default.existsSync(getOpenCodeSkillDst()) &&
|
|
1051
|
-
checkMcpConfigured() &&
|
|
1052
|
-
checkClaudeMcpConfigured() &&
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
checkCursorMcpConfigured() &&
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
checkVscodeMcpConfigured() &&
|
|
1059
|
-
|
|
1060
|
-
|
|
1308
|
+
checkMcpConfigured())) &&
|
|
1309
|
+
(!claudeInstalled || (checkClaudeMcpConfigured() &&
|
|
1310
|
+
checkClaudeHookInstalled() &&
|
|
1311
|
+
checkClaudeMdInstalled())) &&
|
|
1312
|
+
(!cursorInstalled || (checkCursorMcpConfigured() &&
|
|
1313
|
+
checkCursorHookInstalled() &&
|
|
1314
|
+
fs_1.default.existsSync(getCursorSkillDst()))) &&
|
|
1315
|
+
(!vscodeInstalled || (checkVscodeMcpConfigured() &&
|
|
1316
|
+
checkVscodeHookInstalled() &&
|
|
1317
|
+
checkVscodeHookLocationRegistered())) &&
|
|
1318
|
+
(!codexInstalled || (checkCodexMcpConfigured() &&
|
|
1319
|
+
checkCodexOpenAiPassthroughConfigured() &&
|
|
1320
|
+
checkCodexHookInstalled() &&
|
|
1321
|
+
fs_1.default.existsSync(getCodexSkillDst()))) &&
|
|
1061
1322
|
fs_1.default.existsSync(mcpPath) &&
|
|
1062
1323
|
fs_1.default.existsSync(dbPath);
|
|
1063
1324
|
console.log(`\n ${allOk
|
|
@@ -1121,6 +1382,18 @@ function uninstall() {
|
|
|
1121
1382
|
if (uninstallVscodeHookLocation() === "not_found")
|
|
1122
1383
|
throw new Error("not found");
|
|
1123
1384
|
}],
|
|
1385
|
+
["Codex MCP config", () => {
|
|
1386
|
+
if (uninstallCodexMcpConfig() === "not_found")
|
|
1387
|
+
throw new Error("not found");
|
|
1388
|
+
}],
|
|
1389
|
+
["Codex notify hook", () => {
|
|
1390
|
+
if (uninstallCodexHook() === "not_found")
|
|
1391
|
+
throw new Error("not found");
|
|
1392
|
+
}],
|
|
1393
|
+
["Codex skill", () => {
|
|
1394
|
+
if (uninstallCodexSkill() === "not_found")
|
|
1395
|
+
throw new Error("not found");
|
|
1396
|
+
}],
|
|
1124
1397
|
];
|
|
1125
1398
|
for (const [label, fn] of items) {
|
|
1126
1399
|
process.stdout.write(` Removing ${label}... `);
|
|
@@ -1175,15 +1448,15 @@ async function resetDb() {
|
|
|
1175
1448
|
}
|
|
1176
1449
|
function help() {
|
|
1177
1450
|
console.log(`
|
|
1178
|
-
${bold("code-session-memory")} — Shared vector memory for OpenCode, Claude Code, and
|
|
1451
|
+
${bold("code-session-memory")} — Shared vector memory for OpenCode, Claude Code, Cursor, VS Code, and Codex sessions
|
|
1179
1452
|
|
|
1180
1453
|
${bold("Usage:")}
|
|
1181
|
-
npx code-session-memory install Install
|
|
1454
|
+
npx code-session-memory install Install components for detected tools
|
|
1182
1455
|
npx code-session-memory status Show installation status and DB stats
|
|
1183
1456
|
npx code-session-memory uninstall Remove all installed components (keeps DB)
|
|
1184
1457
|
npx code-session-memory reset-db Delete all indexed data (keeps installation)
|
|
1185
1458
|
npx code-session-memory query <text> Semantic search across all indexed sessions
|
|
1186
|
-
npx code-session-memory query <text> --source <s> Filter by source (opencode, claude-code, cursor)
|
|
1459
|
+
npx code-session-memory query <text> --source <s> Filter by source (opencode, claude-code, cursor, vscode, codex)
|
|
1187
1460
|
npx code-session-memory query <text> --limit <n> Max results (default: 5)
|
|
1188
1461
|
npx code-session-memory query <text> --from <date> Results from date (e.g. 2026-02-01)
|
|
1189
1462
|
npx code-session-memory query <text> --to <date> Results up to date (e.g. 2026-02-20)
|
|
@@ -1200,6 +1473,8 @@ ${bold("Environment variables:")}
|
|
|
1200
1473
|
OPENCODE_CONFIG_DIR Override the OpenCode config directory
|
|
1201
1474
|
CLAUDE_CONFIG_DIR Override the Claude Code config directory
|
|
1202
1475
|
CURSOR_CONFIG_DIR Override the Cursor config directory (~/.cursor)
|
|
1476
|
+
VSCODE_CONFIG_DIR Override the VS Code config directory
|
|
1477
|
+
CODEX_HOME Override the Codex home directory (~/.codex)
|
|
1203
1478
|
`);
|
|
1204
1479
|
}
|
|
1205
1480
|
// ---------------------------------------------------------------------------
|