{"record":{"id":"916e88f4b93a43ad","repo":"affaan-m/ECC","slug":"missing-codex-plugin-root","errorCode":null,"errorMessage":"Missing Codex PLUGIN_ROOT","messagePattern":"Missing Codex PLUGIN_ROOT","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"hooks/codex-hooks.json","lineNumber":10,"sourceCode":"{\n  \"description\": \"ECC native Codex hook: verified SessionStart bootstrap. Claude hook profiles remain separate.\",\n  \"hooks\": {\n    \"SessionStart\": [\n      {\n        \"matcher\": \".*\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"node -e \\\"if(!process.env.PLUGIN_ROOT)throw new Error('Missing Codex PLUGIN_ROOT');process.env.CLAUDE_PLUGIN_ROOT=process.env.PLUGIN_ROOT;const p=require('path');const r=(function(){var p=require('path'),f=require('fs'),o=require('os');var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var d=p.join(o.homedir(),'.claude');function L(x){try{return require(p.join(x,'scripts','lib','resolve-ecc-root')).resolveEccRoot()}catch(_){return null}}var r=L(d);if(r)return r;var s=['ecc','ecc@ecc','marketplaces/ecc','everything-claude-code','everything-claude-code@everything-claude-code','marketplaces/everything-claude-code'];for(var i=0;i<s.length;i++){r=L(p.join(d,'plugins',s[i]));if(r)return r}try{var g=['ecc','everything-claude-code'];for(var j=0;j<g.length;j++){var c=p.join(d,'plugins','cache',g[j]);var O=f.readdirSync(c);for(var k=0;k<O.length;k++){var q=p.join(c,O[k]);var V=f.readdirSync(q);for(var m=0;m<V.length;m++){r=L(p.join(q,V[m]));if(r)return r}}}}catch(_){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\\\" node scripts/hooks/session-start-bootstrap.js\"\n          }\n        ],\n        \"description\": \"Load previous context and detect package manager on new session\",\n        \"id\": \"session:start\"\n      }\n    ]\n  }\n}\n","sourceCodeStart":1,"sourceCodeEnd":19,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/hooks/codex-hooks.json#L1-L19","documentation":"The Codex SessionStart hook bootstrap refuses to run when the PLUGIN_ROOT environment variable is not set. Codex does not expose the plugin directory the way Claude Code does (CLAUDE_PLUGIN_ROOT), so this wrapper requires the caller (Codex host or installer) to inject PLUGIN_ROOT explicitly, then forwards it as CLAUDE_PLUGIN_ROOT for the underlying bootstrap script. Without it the hook exits immediately with this Error, so session-start context loading and package-manager detection never run.","triggerScenarios":"Running the ECC plugin under Codex without PLUGIN_ROOT in the environment; invoking the SessionStart command from hooks/codex-hooks.json in a shell or config where the installer failed to export PLUGIN_ROOT; migrating a Claude Code install to Codex and forgetting the Codex-specific env var.","commonSituations":"Users install the ECC plugin via one harness and copy hooks config to the other; Codex config files that don't support env interpolation; CI or headless shells where plugin env vars are not propagated.","solutions":["Set PLUGIN_ROOT to the absolute path of the ECC plugin root before Codex launches the hook, e.g. export PLUGIN_ROOT=\"$HOME/.claude/plugins/ecc\" in your shell profile or Codex env config.","Re-run the ECC install script for the Codex harness so it wires PLUGIN_ROOT into the generated hooks config.","Sanity-check the value: PLUGIN_ROOT must point at the directory containing scripts/hooks/plugin-hook-bootstrap.js.","As a diagnostic, run the node command manually with PLUGIN_ROOT set to confirm the bootstrap resolves."],"exampleFix":"// before (Codex config, no env)\n\"command\": \"node -e \\\"if(!process.env.PLUGIN_ROOT)throw new Error('Missing Codex PLUGIN_ROOT');...\\\"\"\n// after\n\"command\": \"PLUGIN_ROOT=/home/me/.claude/plugins/ecc node -e \\\"if(!process.env.PLUGIN_ROOT)throw new Error('Missing Codex PLUGIN_ROOT');...\\\"\"","handlingStrategy":"validation","validationCode":"function hasPluginRoot() {\n  return typeof process.env.PLUGIN_ROOT === 'string'\n    && process.env.PLUGIN_ROOT.trim().length > 0\n    && require('fs').existsSync(require('path').join(process.env.PLUGIN_ROOT.trim(), 'scripts/hooks/plugin-hook-bootstrap.js'));\n}\nif (!hasPluginRoot()) throw new Error('PLUGIN_ROOT must point to the ECC plugin root containing scripts/hooks');","typeGuard":"const isValidPluginRoot = (v) => typeof v === 'string' && v.trim().length > 0 && v.trim() !== '/';","tryCatchPattern":"try {\n  runSessionStartHook();\n} catch (err) {\n  if (err.message.includes('Missing Codex PLUGIN_ROOT')) {\n    console.error('Set PLUGIN_ROOT to the ECC plugin directory before launching Codex.');\n  }\n  throw err;\n}","preventionTips":["Export PLUGIN_ROOT in your shell profile or Codex env config after every ECC install/reinstall.","Verify the path contains scripts/hooks/plugin-hook-bootstrap.js before launching.","Prefer the official ECC installer for Codex, which wires the env var automatically.","Add a smoke check in CI that runs the SessionStart command with PLUGIN_ROOT set."],"tags":["config","environment","codex","hooks"],"backgroundTag":"missing-env-var","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}