@senoldogann/context-manager 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/ccm.js +44 -35
  2. package/package.json +1 -1
package/bin/ccm.js CHANGED
@@ -15,20 +15,15 @@ async function installMcp() {
15
15
  const home = os.homedir();
16
16
 
17
17
  if (os.platform() === 'darwin') {
18
- // MacOS Paths
19
18
  configPaths.push(path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'));
20
19
  configPaths.push(path.join(home, '.gemini', 'antigravity', 'mcp_config.json'));
21
- // VS Code Extensions (Cline & Roo Code)
22
20
  configPaths.push(path.join(home, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'));
23
21
  configPaths.push(path.join(home, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'rooveterinaryinc.roo-cline', 'settings', 'cline_mcp_settings.json'));
24
22
  } else if (os.platform() === 'win32') {
25
- // Windows Paths
26
23
  const appData = process.env.APPDATA || '';
27
24
  configPaths.push(path.join(appData, 'Claude', 'claude_desktop_config.json'));
28
- // VS Code Extensions on Windows
29
25
  configPaths.push(path.join(process.env.USERPROFILE || '', 'AppData', 'Roaming', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'));
30
26
  } else if (os.platform() === 'linux') {
31
- // Linux Paths
32
27
  configPaths.push(path.join(home, '.config', 'Claude', 'claude_desktop_config.json'));
33
28
  configPaths.push(path.join(home, '.config', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'));
34
29
  }
@@ -41,6 +36,10 @@ async function installMcp() {
41
36
  }
42
37
  };
43
38
 
39
+ console.log("[CCM] Pre-downloading binaries for all tools...");
40
+ await getBinaryFor('ccm-cli');
41
+ await getBinaryFor('ccm-mcp');
42
+
44
43
  let installedCount = 0;
45
44
  for (const configPath of configPaths) {
46
45
  const dir = path.dirname(configPath);
@@ -50,7 +49,6 @@ async function installMcp() {
50
49
  try {
51
50
  const content = fs.readFileSync(configPath, 'utf8');
52
51
  config = JSON.parse(content);
53
- // Backup
54
52
  fs.copyFileSync(configPath, `${configPath}.bak`);
55
53
  } catch (e) {
56
54
  console.warn(`[CCM] Could not parse ${configPath}, creating backup and starting fresh section.`);
@@ -75,9 +73,9 @@ async function installMcp() {
75
73
  }
76
74
  }
77
75
 
78
- async function getBinary() {
79
- const platform = os.platform(); // darwin, linux, win32
80
- const arch = os.arch(); // x64, arm64
76
+ async function getBinaryFor(commandName) {
77
+ const platform = os.platform();
78
+ const arch = os.arch();
81
79
 
82
80
  let target = '';
83
81
  if (platform === 'darwin') {
@@ -88,55 +86,67 @@ async function getBinary() {
88
86
  target = 'x86_64-pc-windows-msvc.exe';
89
87
  }
90
88
 
91
- // Detect which tool to run
92
- let commandName = 'ccm-cli'; // Default
93
- const binName = path.basename(process.argv[1]);
94
-
95
- if (binName.includes('mcp')) {
96
- commandName = 'ccm-mcp';
97
- } else if (process.argv[2] === 'mcp') {
98
- // Handle: npx @ccm/context-manager mcp
99
- commandName = 'ccm-mcp';
100
- process.argv.splice(2, 1); // Remove 'mcp' from args to be passed to binary
101
- } else if (process.argv[2] === 'install') {
102
- await installMcp();
103
- process.exit(0);
104
- }
105
-
106
89
  const binFilename = `${commandName}-v${VERSION}-${target}`;
107
90
  const binPath = path.join(BIN_DIR, binFilename);
108
91
 
92
+ // If file exists, ensure it is executable
109
93
  if (fs.existsSync(binPath)) {
110
- return binPath;
94
+ try {
95
+ fs.chmodSync(binPath, '755');
96
+ return binPath;
97
+ } catch (e) {
98
+ // If chmod fails, maybe it's a broken file, try to redownload
99
+ }
111
100
  }
112
101
 
113
- console.log(`[CCM] Binary not found. Downloading ${commandName} for ${target}...`);
102
+ console.log(`[CCM] Downloading ${commandName} v${VERSION} for ${target}...`);
114
103
 
115
104
  if (!fs.existsSync(BIN_DIR)) {
116
105
  fs.mkdirSync(BIN_DIR, { recursive: true });
117
106
  }
118
107
 
119
108
  const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${commandName}-${target}`;
109
+ const tmpPath = `${binPath}.tmp`;
120
110
 
121
- await downloadFile(url, binPath);
122
- fs.chmodSync(binPath, '755');
111
+ try {
112
+ await downloadFile(url, tmpPath);
113
+ fs.chmodSync(tmpPath, '755');
114
+ fs.renameSync(tmpPath, binPath);
115
+ } catch (err) {
116
+ if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
117
+ throw err;
118
+ }
123
119
 
124
120
  return binPath;
125
121
  }
126
122
 
123
+ async function getBinary() {
124
+ // Detect which tool to run
125
+ let commandName = 'ccm-cli';
126
+ const binName = path.basename(process.argv[1]);
127
+
128
+ if (binName.includes('mcp')) {
129
+ commandName = 'ccm-mcp';
130
+ } else if (process.argv[2] === 'mcp') {
131
+ commandName = 'ccm-mcp';
132
+ process.argv.splice(2, 1);
133
+ } else if (process.argv[2] === 'install') {
134
+ await installMcp();
135
+ process.exit(0);
136
+ }
137
+
138
+ return await getBinaryFor(commandName);
139
+ }
140
+
127
141
  function downloadFile(url, dest) {
128
142
  return new Promise((resolve, reject) => {
129
143
  https.get(url, (response) => {
130
- // Handle redirects BEFORE creating file
131
144
  if (response.statusCode === 302 || response.statusCode === 301) {
132
- downloadFile(response.headers.location, dest).then(resolve).catch(reject);
133
- return;
145
+ return downloadFile(response.headers.location, dest).then(resolve).catch(reject);
134
146
  }
135
147
  if (response.statusCode !== 200) {
136
- reject(new Error(`Failed to download: ${response.statusCode}`));
137
- return;
148
+ return reject(new Error(`Failed to download: ${response.statusCode}`));
138
149
  }
139
- // Only create file after we know we have a valid response
140
150
  const file = fs.createWriteStream(dest);
141
151
  response.pipe(file);
142
152
  file.on('finish', () => {
@@ -162,7 +172,6 @@ async function main() {
162
172
  stdio: 'inherit',
163
173
  env: {
164
174
  ...process.env,
165
- // Ensure MCP knows its project root if it can
166
175
  CCM_PROJECT_ROOT: process.env.CCM_PROJECT_ROOT || process.cwd()
167
176
  }
168
177
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@senoldogann/context-manager",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "LLM Context Manager MCP Server & CLI wrapper using npx",
5
5
  "main": "bin/ccm.js",
6
6
  "bin": {