2026-03-20 01:38:15 -07:00
'use strict' ;
const fs = require ( 'fs' );
const path = require ( 'path' );
const os = require ( 'os' );
/**
* Resolve the ECC source root directory.
*
* Tries, in order:
* 1. CLAUDE_PLUGIN_ROOT env var (set by Claude Code for hooks, or by user)
* 2. Standard install location (~/.claude/) — when scripts exist there
2026-03-24 23:08:27 -04:00
* 3. Exact legacy plugin roots under ~/.claude/plugins/
* 4. Plugin cache auto-detection — scans ~/.claude/plugins/cache/everything-claude-code/
* 5. Fallback to ~/.claude/ (original behaviour)
2026-03-20 01:38:15 -07:00
*
* @param {object} [options]
* @param {string} [options.homeDir] Override home directory (for testing)
* @param {string} [options.envRoot] Override CLAUDE_PLUGIN_ROOT (for testing)
* @param {string} [options.probe] Relative path used to verify a candidate root
* contains ECC scripts. Default: 'scripts/lib/utils.js'
* @returns {string} Resolved ECC root path
*/
function resolveEccRoot ( options = {}) {
const envRoot = options . envRoot !== undefined
? options . envRoot
: ( process . env . CLAUDE_PLUGIN_ROOT || '' );
if ( envRoot && envRoot . trim ()) {
return envRoot . trim ();
}
const homeDir = options . homeDir || os . homedir ();
const claudeDir = path . join ( homeDir , '.claude' );
const probe = options . probe || path . join ( 'scripts' , 'lib' , 'utils.js' );
// Standard install — files are copied directly into ~/.claude/
if ( fs . existsSync ( path . join ( claudeDir , probe ))) {
return claudeDir ;
}
2026-03-24 23:08:27 -04:00
// Exact legacy plugin install locations. These preserve backwards
// compatibility without scanning arbitrary plugin trees.
const legacyPluginRoots = [
path . join ( claudeDir , 'plugins' , 'everything-claude-code' ),
path . join ( claudeDir , 'plugins' , 'everything-claude-code@everything-claude-code' ),
path . join ( claudeDir , 'plugins' , 'marketplace' , 'everything-claude-code' )
];
for ( const candidate of legacyPluginRoots ) {
if ( fs . existsSync ( path . join ( candidate , probe ))) {
return candidate ;
}
}
2026-03-20 01:38:15 -07:00
// Plugin cache — Claude Code stores marketplace plugins under
// ~/.claude/plugins/cache/<plugin-name>/<org>/<version>/
try {
const cacheBase = path . join ( claudeDir , 'plugins' , 'cache' , 'everything-claude-code' );
const orgDirs = fs . readdirSync ( cacheBase , { withFileTypes : true });
for ( const orgEntry of orgDirs ) {
if ( ! orgEntry . isDirectory ()) continue ;
const orgPath = path . join ( cacheBase , orgEntry . name );
let versionDirs ;
try {
versionDirs = fs . readdirSync ( orgPath , { withFileTypes : true });
} catch {
continue ;
}
for ( const verEntry of versionDirs ) {
if ( ! verEntry . isDirectory ()) continue ;
const candidate = path . join ( orgPath , verEntry . name );
if ( fs . existsSync ( path . join ( candidate , probe ))) {
return candidate ;
}
}
}
} catch {
// Plugin cache doesn't exist or isn't readable — continue to fallback
}
return claudeDir ;
}
/**
* Compact inline version for embedding in command .md code blocks.
*
* This is the minified form of resolveEccRoot() suitable for use in
* node -e "..." scripts where require() is not available before the
* root is known.
*
* Usage in commands:
* const _r = <paste INLINE_RESOLVE>;
* const sm = require(_r + '/scripts/lib/session-manager');
*/
2026-03-24 23:08:27 -04:00
const INLINE_RESOLVE = `(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var l of [p.join(d,'plugins','everything-claude-code'),p.join(d,'plugins','everything-claude-code@everything-claude-code'),p.join(d,'plugins','marketplace','everything-claude-code')])if(f.existsSync(p.join(l,q)))return l;try{var b=p.join(d,'plugins','cache','everything-claude-code');for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}catch(x){}return d})()` ;
2026-03-20 01:38:15 -07:00
module . exports = {
resolveEccRoot ,
INLINE_RESOLVE ,
};