Files
claude-mem/scripts/sync-marketplace.cjs
T
Alex Newman 1b68c55763 fix: resolve SDK spawn failures and sharp native binary crashes
- Strip CLAUDECODE env var from SDK subprocesses to prevent "cannot be
  launched inside another Claude Code session" error (Claude Code 2.1.42+)
- Lazy-load @chroma-core/default-embed to avoid eagerly pulling in
  sharp native binaries at bundle startup (fixes ERR_DLOPEN_FAILED)
- Add stderr capture to SDK spawn for diagnosing future process failures
- Exclude lockfiles from marketplace rsync and delete stale lockfiles
  before npm install to prevent native dep version mismatches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:47:27 -05:00

125 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Protected sync-marketplace script
*
* Prevents accidental rsync overwrite when installed plugin is on beta branch.
* If on beta, the user should use the UI to update instead.
*/
const { execSync } = require('child_process');
const { existsSync, readFileSync } = require('fs');
const path = require('path');
const os = require('os');
const INSTALLED_PATH = path.join(os.homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack');
const CACHE_BASE_PATH = path.join(os.homedir(), '.claude', 'plugins', 'cache', 'thedotmack', 'claude-mem');
function getCurrentBranch() {
try {
if (!existsSync(path.join(INSTALLED_PATH, '.git'))) {
return null;
}
return execSync('git rev-parse --abbrev-ref HEAD', {
cwd: INSTALLED_PATH,
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe']
}).trim();
} catch {
return null;
}
}
const branch = getCurrentBranch();
const isForce = process.argv.includes('--force');
if (branch && branch !== 'main' && !isForce) {
console.log('');
console.log('\x1b[33m%s\x1b[0m', `WARNING: Installed plugin is on beta branch: ${branch}`);
console.log('\x1b[33m%s\x1b[0m', 'Running rsync would overwrite beta code.');
console.log('');
console.log('Options:');
console.log(' 1. Use UI at http://localhost:37777 to update beta');
console.log(' 2. Switch to stable in UI first, then run sync');
console.log(' 3. Force rsync: npm run sync-marketplace:force');
console.log('');
process.exit(1);
}
// Get version from plugin.json
function getPluginVersion() {
try {
const pluginJsonPath = path.join(__dirname, '..', 'plugin', '.claude-plugin', 'plugin.json');
const pluginJson = JSON.parse(readFileSync(pluginJsonPath, 'utf-8'));
return pluginJson.version;
} catch (error) {
console.error('\x1b[31m%s\x1b[0m', 'Failed to read plugin version:', error.message);
process.exit(1);
}
}
// Normal rsync for main branch or fresh install
console.log('Syncing to marketplace...');
try {
execSync(
'rsync -av --delete --exclude=.git --exclude=/.mcp.json --exclude=bun.lock --exclude=package-lock.json ./ ~/.claude/plugins/marketplaces/thedotmack/',
{ stdio: 'inherit' }
);
// Remove stale lockfiles before install — they pin old native dep versions
const { unlinkSync } = require('fs');
for (const lockfile of ['package-lock.json', 'bun.lock']) {
const lockpath = path.join(INSTALLED_PATH, lockfile);
if (existsSync(lockpath)) {
unlinkSync(lockpath);
console.log(`Removed stale ${lockfile}`);
}
}
console.log('Running npm install in marketplace...');
execSync(
'cd ~/.claude/plugins/marketplaces/thedotmack/ && npm install',
{ stdio: 'inherit' }
);
// Sync to cache folder with version
const version = getPluginVersion();
const CACHE_VERSION_PATH = path.join(CACHE_BASE_PATH, version);
console.log(`Syncing to cache folder (version ${version})...`);
execSync(
`rsync -av --delete --exclude=.git plugin/ "${CACHE_VERSION_PATH}/"`,
{ stdio: 'inherit' }
);
console.log('\x1b[32m%s\x1b[0m', 'Sync complete!');
// Trigger worker restart after file sync
console.log('\n🔄 Triggering worker restart...');
const http = require('http');
const req = http.request({
hostname: '127.0.0.1',
port: 37777,
path: '/api/admin/restart',
method: 'POST',
timeout: 2000
}, (res) => {
if (res.statusCode === 200) {
console.log('\x1b[32m%s\x1b[0m', '✓ Worker restart triggered');
} else {
console.log('\x1b[33m%s\x1b[0m', ` Worker restart returned status ${res.statusCode}`);
}
});
req.on('error', () => {
console.log('\x1b[33m%s\x1b[0m', ' Worker not running, will start on next hook');
});
req.on('timeout', () => {
req.destroy();
console.log('\x1b[33m%s\x1b[0m', ' Worker restart timed out');
});
req.end();
} catch (error) {
console.error('\x1b[31m%s\x1b[0m', 'Sync failed:', error.message);
process.exit(1);
}