memoryrouter-codex 1.8.0 → 1.8.2

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 CHANGED
@@ -34,7 +34,7 @@ MemoryRouter is the **cross-machine, cross-tool, team-shareable, and auditable**
34
34
  - Node.js 18 or newer.
35
35
  - **Codex 0.145.0 or newer** for the complete lifecycle-hook integration. Version 0.146.0 was tested directly.
36
36
  - Local Codex CLI, ChatGPT desktop app's local Codex host, and Codex IDE extension share `config.toml` MCP configuration.
37
- - Hooks must be trusted once: Codex app **Settings > Hooks**, or `/hooks` in the CLI. OAuth (`mcp_tool`) hooks need a Codex build with MCP tool hooks (the current app and CLI 0.166 have them).
37
+ - Hooks must be trusted once: in the Codex app open a **New chat**, click the hooks icon next to **Ask for approval** in the message box, then **Allow all**; in the CLI, `/hooks`. OAuth (`mcp_tool`) hooks need a Codex build with MCP tool hooks (the current app and CLI 0.166 have them).
38
38
  - Project `.codex` config is loaded only for trusted projects.
39
39
  - ChatGPT web does **not** read a laptop's `~/.codex/config.toml` or local hooks. Use MemoryRouter's hosted plugin/connector surface there.
40
40
  - Codex cloud environments do not automatically inherit host-local user config or secrets. A project-scope install can travel with a repository, but the environment still needs Node, project trust, package/network availability for the stdio fallback, and `MEMORYROUTER_API_KEY` for hooks.
@@ -48,9 +48,9 @@ There is no dependency on the obsolete `experimental_use_rmcp_client` setting in
48
48
  1. Add the server in the app: **Settings > Plugins > Add > Add MCP server**, Type **Streamable HTTP**, Name `memoryrouter`, URL `https://mcp.memoryrouter.ai/mcp`, **Save**, then **Authenticate** and sign in (or create an account) in the browser tab that opens.
49
49
  2. In a Codex chat, paste:
50
50
 
51
- > Run `npx -y memoryrouter-codex@latest init` with network access, then tell me to trust the MemoryRouter hooks in Settings > Hooks.
51
+ > Run `npx -y memoryrouter-codex@latest init` with network access, then tell me to trust the MemoryRouter hooks.
52
52
 
53
- Then trust the three MemoryRouter hooks in **Settings > Hooks** and open a **New chat**.
53
+ Approve the internet access Codex asks for. Then open a **New chat**, click the hooks icon next to **Ask for approval** in the message box, and choose **Allow all** for the three MemoryRouter hooks (Recalling MemoryRouter context, Searching MemoryRouter, Saving to MemoryRouter).
54
54
 
55
55
  `init` keeps the server the app added (and its sign-in), adds the three `mcp_tool` hooks to `~/.codex/hooks.json` and the MemoryRouter guidance to `~/.codex/AGENTS.md`. The Codex CLI and IDE extension on the same Mac share all of it.
56
56
 
package/bin/cli.cjs CHANGED
@@ -134,7 +134,7 @@ async function main() {
134
134
  process.stdout.write('\nAutomatic memory: before every prompt Codex searches your vault and adds what it finds as context; after every turn it saves your message and its final response (never tool calls, tool output or intermediate steps). No API key needed.\n');
135
135
  process.stdout.write('\nNext:\n');
136
136
  if (!result.adoptedServer) process.stdout.write(' 1. Sign in: Codex app Settings > Plugins > memoryrouter > Authenticate (or run: codex mcp login memoryrouter)\n');
137
- process.stdout.write(` ${result.adoptedServer ? '1' : '2'}. Trust the MemoryRouter hooks once: Codex app Settings > Hooks (or /hooks in the CLI)\n`);
137
+ process.stdout.write(` ${result.adoptedServer ? '1' : '2'}. Trust the MemoryRouter hooks once: Codex app: open a New chat, click the hooks icon next to "Ask for approval", Allow all (CLI: /hooks)\n`);
138
138
  process.stdout.write(` ${result.adoptedServer ? '2' : '3'}. Start a New chat\n`);
139
139
  } else if (result.auth === 'oauth') {
140
140
  const pick = binding && binding.vault ? ` and select the vault ${vaultLabel(binding)} (the one your hooks use)` : '';
package/lib/installer.cjs CHANGED
@@ -117,10 +117,19 @@ function init(options = {}) {
117
117
  agentsFile: options.agents === false ? null : layout.agentsFile,
118
118
  runtimeDir: layout.runtimeDir,
119
119
  };
120
- const manifestDir = path.join(dataHome(options.env), 'installations');
121
- fs.mkdirSync(manifestDir, { recursive: true, mode: 0o700 });
122
- const manifestName = Buffer.from(`${layout.scope}:${layout.root}`).toString('base64url');
123
- fs.writeFileSync(path.join(manifestDir, `${manifestName}.json`), `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
120
+ // The manifest is bookkeeping only (nothing reads it to run hooks). Inside
121
+ // the Codex app's sandbox, writes outside CODEX_HOME need an extra approval,
122
+ // so a blocked write must never fail an otherwise complete install.
123
+ let manifestWritten = true;
124
+ try {
125
+ const manifestDir = path.join(dataHome(options.env), 'installations');
126
+ fs.mkdirSync(manifestDir, { recursive: true, mode: 0o700 });
127
+ const manifestName = Buffer.from(`${layout.scope}:${layout.root}`).toString('base64url');
128
+ fs.writeFileSync(path.join(manifestDir, `${manifestName}.json`), `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
129
+ } catch (error) {
130
+ if (options.apiKey) throw error;
131
+ manifestWritten = false;
132
+ }
124
133
  return {
125
134
  layout,
126
135
  auth,
@@ -128,6 +137,7 @@ function init(options = {}) {
128
137
  serverName,
129
138
  adoptedServer,
130
139
  results,
140
+ manifestWritten,
131
141
  automaticMemory: options.hooks !== false && (hookMode === 'mcp' || Boolean(options.apiKey || getApiKey(env, loadConfig(options.env)))),
132
142
  keySource: options.apiKey ? 'codex-config' : apiKeySource(env, loadConfig(options.env)),
133
143
  };
@@ -223,7 +233,7 @@ async function doctor(options = {}) {
223
233
  ? Object.values(mcpManagedGroups()).flat().flatMap(group => group.hooks || []).length
224
234
  : Object.values(managedGroups(layout.runtimeDir, layout.scope)).flat().flatMap(group => group.hooks || []).length;
225
235
  addCheck(checks, 'hooks', owned.length === expectedOwned ? 'pass' : 'error', owned.length
226
- ? `${owned.length} of ${expectedOwned} managed lifecycle hooks found${mcpHooks.length ? ' (over the signed-in MCP connection, no API key needed)' : ''}. Trust them once in Codex: app Settings > Hooks, or /hooks in the CLI.`
236
+ ? `${owned.length} of ${expectedOwned} managed lifecycle hooks found${mcpHooks.length ? ' (over the signed-in MCP connection, no API key needed)' : ''}. Trust them once: Codex app New chat > hooks icon by "Ask for approval" > Allow all; CLI: /hooks.`
227
237
  : 'Managed lifecycle hooks are missing or hooks.json is invalid.');
228
238
  addCheck(checks, 'agents', agentsText.includes(AGENTS_START) ? 'pass' : 'warn', agentsText.includes(AGENTS_START) ? 'Managed AGENTS.md guidance is present.' : 'Managed AGENTS.md guidance is missing.');
229
239
 
package/lib/managed.cjs CHANGED
@@ -151,9 +151,9 @@ function uninstallToml(file) {
151
151
 
152
152
  function agentsBlock(options = {}) {
153
153
  const automatic = options.hookMode === 'mcp'
154
- ? '- Automatic hooks (over the signed-in MemoryRouter connection) search the vault before each prompt and add what they find as context, then save each completed turn: the user\'s message and your final response only, never tool calls, tool output or intermediate steps.\n'
154
+ ? '- Automatic hooks (over the signed-in MemoryRouter connection) search the vault before each prompt and add what they find as context ("MemoryRouter recalled this for the current message"), then save each completed turn: the user\'s message and your final response only, never tool calls, tool output or intermediate steps.\n'
155
155
  : '- Automatic hooks search the vault before each prompt and save each completed turn (the user\'s message and your final response only) when a MemoryRouter API key is configured.\n';
156
- return `## MemoryRouter memory\n\n- MemoryRouter is the durable cross-machine, cross-tool, and team/auditable memory layer. Codex native Memories may remain enabled as the local personal recall layer.\n${automatic}- For explicit recall, search MemoryRouter before answering questions about prior decisions, preferences, incidents, or unfinished work. Depending on auth mode, the tool is named \`search_memories\` or \`memory_search\`.\n- Store only concise, durable decisions, preferences, facts, and incident outcomes. Depending on auth mode, use \`store_memory\` or \`memory_store\`. Do not duplicate a completed turn that hooks already captured.\n- Keep and cite returned \`mrh_...\` handles when a specific memory must be referenced later.\n- Project scope is derived from the canonical git remote when available, so worktrees and machines share identity without uploading local paths. It is the same project memory Claude Code uses through memoryrouter-claude, so decisions made in either agent are available in both.\n- If MemoryRouter is offline, continue the task without memory; never block work on recall or capture.`;
156
+ return `## MemoryRouter memory\n\n- MemoryRouter is the durable cross-machine, cross-tool, and team/auditable memory layer. Codex native Memories may remain enabled as the local personal recall layer.\n${automatic}- If the recalled context already answers the question, answer from it directly; do not search again. Call MemoryRouter search only when nothing relevant was recalled or you need more detail about prior decisions, preferences, incidents, or unfinished work. Depending on auth mode, the tool is named \`search_memories\` or \`memory_search\`.\n- Store only concise, durable decisions, preferences, facts, and incident outcomes. Depending on auth mode, use \`store_memory\` or \`memory_store\`. Do not duplicate a completed turn that hooks already captured.\n- Keep and cite returned \`mrh_...\` handles when a specific memory must be referenced later.\n- Project scope is derived from the canonical git remote when available, so worktrees and machines share identity without uploading local paths. It is the same project memory Claude Code uses through memoryrouter-claude, so decisions made in either agent are available in both.\n- If MemoryRouter is offline, continue the task without memory; never block work on recall or capture.`;
157
157
  }
158
158
 
159
159
  function installAgents(file, options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memoryrouter-codex",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "Automatic MemoryRouter memory for OpenAI Codex: one vault shared by every session, repo and tool, including Claude Code",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const INTEGRATION_VERSION = '1.8.0';
3
+ const INTEGRATION_VERSION = '1.8.2';
4
4
  const RUNTIME_SCHEMA_VERSION = 1;
5
5
  const API_BASE = 'https://api.memoryrouter.ai';
6
6
  const MCP_ENDPOINT = 'https://mcp.memoryrouter.ai/mcp';