consortium
Version:
Remote control and session sharing CLI for AI coding agents
143 lines (127 loc) • 4.75 kB
JavaScript
/**
* link-dev.cjs - Create symlink for consortium-dev only
*
* This script creates a symlink for the consortium-dev command pointing to the local
* development version, while leaving the stable npm version of `consortium` untouched.
*
* Usage: yarn link:dev
*
* What it does:
* 1. Finds the global npm bin directory
* 2. Creates/updates a symlink: consortium-dev -> ./bin/consortium-dev.mjs
*
* To undo: yarn unlink:dev
*/
const { execFileSync } = require('child_process');
const { join, dirname } = require('path');
const fs = require('fs');
const projectRoot = dirname(__dirname);
const binSource = join(projectRoot, 'bin', 'consortium-dev.mjs');
// Get the action from command line args
const action = process.argv[2] || 'link';
function getGlobalBinDir() {
// Try npm global bin first using execFileSync (safer than execSync)
try {
const npmBin = execFileSync('npm', ['bin', '-g'], { encoding: 'utf8' }).trim();
if (fs.existsSync(npmBin)) {
return npmBin;
}
} catch (e) {
// Fall through to alternatives
}
// Common locations by platform
if (process.platform === 'darwin') {
// macOS with Homebrew Node (Apple Silicon)
const homebrewBin = '/opt/homebrew/bin';
if (fs.existsSync(homebrewBin)) {
return homebrewBin;
}
// Intel Mac Homebrew
const homebrewUsrBin = '/usr/local/bin';
if (fs.existsSync(homebrewUsrBin)) {
return homebrewUsrBin;
}
}
// Fallback to /usr/local/bin
return '/usr/local/bin';
}
function link() {
const globalBin = getGlobalBinDir();
const binTarget = join(globalBin, 'consortium-dev');
console.log('Creating symlink for consortium-dev...');
console.log(` Source: ${binSource}`);
console.log(` Target: ${binTarget}`);
// Check if source exists
if (!fs.existsSync(binSource)) {
console.error(`\n❌ Error: ${binSource} does not exist.`);
console.error(" Run 'yarn build' first to compile the project.");
process.exit(1);
}
// Remove existing symlink or file
try {
const stat = fs.lstatSync(binTarget);
if (stat.isSymbolicLink() || stat.isFile()) {
fs.unlinkSync(binTarget);
console.log(` Removed existing: ${binTarget}`);
}
} catch (e) {
// File doesn't exist, that's fine
}
// Create the symlink
try {
fs.symlinkSync(binSource, binTarget);
console.log('\n✅ Successfully linked consortium-dev to local development version');
console.log('\nNow you can use:');
console.log(' consortium → stable npm version (unchanged)');
console.log(' consortium-dev → local development version');
console.log('\nTo undo: yarn unlink:dev');
} catch (e) {
if (e.code === 'EACCES') {
console.error('\n❌ Permission denied. Try running with sudo:');
console.error(' sudo yarn link:dev');
} else {
console.error(`\n❌ Error creating symlink: ${e.message}`);
}
process.exit(1);
}
}
function unlink() {
const globalBin = getGlobalBinDir();
const binTarget = join(globalBin, 'consortium-dev');
console.log('Removing consortium-dev symlink...');
try {
const stat = fs.lstatSync(binTarget);
if (stat.isSymbolicLink()) {
const linkTarget = fs.readlinkSync(binTarget);
if (linkTarget === binSource || linkTarget.includes('consortium-cli')) {
fs.unlinkSync(binTarget);
console.log('\n✅ Removed consortium-dev development symlink');
console.log('\nTo restore npm version: npm install -g consortium');
} else {
console.log(`\n⚠️ consortium-dev symlink points elsewhere: ${linkTarget}`);
console.log(' Not removing. Remove manually if needed.');
}
} else {
console.log(`\n⚠️ ${binTarget} exists but is not a symlink.`);
console.log(' Not removing. This may be the npm-installed version.');
}
} catch (e) {
if (e.code === 'ENOENT') {
console.log("\n✅ consortium-dev symlink doesn't exist (already removed or never created)");
} else if (e.code === 'EACCES') {
console.error('\n❌ Permission denied. Try running with sudo:');
console.error(' sudo yarn unlink:dev');
process.exit(1);
} else {
console.error(`\n❌ Error: ${e.message}`);
process.exit(1);
}
}
}
// Main
if (action === 'unlink') {
unlink();
} else {
link();
}