@calmhive/calmhive-cli
Version:
🐝 Intelligent Claude CLI wrapper with rule injection, AFk background processing, voice interface, and adaptive retry
201 lines (173 loc) • 4.98 kB
JavaScript
/**
* Centralized path management for Calmhive
* Single source of truth for all file and directory paths
*/
const path = require('path');
const fs = require('fs');
class PathManager {
/**
* Initialize PathManager with environment detection
* Determines if running from npm package vs development environment
* Sets up root directory path for all subsequent path operations
*/
constructor() {
// Detect if we're running from npm package or development
this.isNpmPackage = this.detectNpmEnvironment();
this.rootDir = this.findRootDirectory();
}
/**
* Detect if running from npm package installation vs development environment
* Uses node_modules presence in path as primary detection method
* @returns {boolean} true if running from npm package, false if in development
*/
detectNpmEnvironment() {
// Check if we're in node_modules
const currentPath = __dirname;
return currentPath.includes('node_modules');
}
/**
* Find the root directory of the calmhive installation by searching for package.json
* Traverses up the directory tree looking for package.json with '@calmhive/calmhive-cli' name
* Uses fallback logic for edge cases where package.json isn't found
* @returns {string} Absolute path to the calmhive root directory
*/
findRootDirectory() {
let currentDir = __dirname;
// Go up until we find package.json with our name
while (currentDir !== path.dirname(currentDir)) {
const packagePath = path.join(currentDir, 'package.json');
if (fs.existsSync(packagePath)) {
try {
const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
if (packageData.name === '@calmhive/calmhive-cli') {
return currentDir;
}
} catch (error) {
// Continue searching if package.json is malformed
}
}
currentDir = path.dirname(currentDir);
}
// Fallback - assume we're in lib/ directory
return path.dirname(__dirname);
}
/**
* Get the main bin directory
*/
getBinDir() {
return path.join(this.rootDir, 'bin');
}
/**
* Get the commands directory (for executable commands)
*/
getCommandsDir() {
return path.join(this.rootDir, 'cmd');
}
/**
* Get the templates directory (for Claude Code markdown files)
*/
getTemplatesDir() {
return path.join(this.rootDir, 'commands');
}
/**
* Get the lib directory
*/
getLibDir() {
return path.join(this.rootDir, 'lib');
}
/**
* Get the config directory
*/
getConfigDir() {
return path.join(this.rootDir, 'config');
}
/**
* Get path to specific command executable
*/
getCommandPath(commandName) {
return path.join(this.getCommandsDir(), commandName);
}
/**
* Get path to specific template file
*/
getTemplatePath(templateName) {
return path.join(this.getTemplatesDir(), templateName);
}
/**
* Get path to specific lib file
*/
getLibPath(libName) {
return path.join(this.getLibDir(), libName);
}
/**
* Check if a command exists
*/
commandExists(commandName) {
return fs.existsSync(this.getCommandPath(commandName));
}
/**
* Check if a template exists
*/
templateExists(templateName) {
return fs.existsSync(this.getTemplatePath(templateName));
}
/**
* Get all available commands
*/
getAvailableCommands() {
const commandsDir = this.getCommandsDir();
if (!fs.existsSync(commandsDir)) {
return [];
}
return fs.readdirSync(commandsDir)
.filter(file => {
const filePath = path.join(commandsDir, file);
return fs.statSync(filePath).isFile();
});
}
/**
* Get all available templates
*/
getAvailableTemplates() {
const templatesDir = this.getTemplatesDir();
if (!fs.existsSync(templatesDir)) {
return [];
}
return fs.readdirSync(templatesDir)
.filter(file => {
const filePath = path.join(templatesDir, file);
return fs.statSync(filePath).isFile() && file.endsWith('.md');
});
}
/**
* Get version from package.json
*/
getVersion() {
try {
const packagePath = path.join(this.rootDir, 'package.json');
const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
return packageData.version;
} catch (error) {
return 'unknown';
}
}
/**
* Get debug information about paths
*/
getDebugInfo() {
return {
isNpmPackage: this.isNpmPackage,
rootDir: this.rootDir,
binDir: this.getBinDir(),
commandsDir: this.getCommandsDir(),
templatesDir: this.getTemplatesDir(),
libDir: this.getLibDir(),
configDir: this.getConfigDir(),
version: this.getVersion(),
availableCommands: this.getAvailableCommands(),
availableTemplates: this.getAvailableTemplates()
};
}
}
// Export singleton instance
module.exports = new PathManager();