@just-every/code 0.1.3 → 0.1.5
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.
- package/bin/{code.js → coder.js} +28 -7
- package/bin/codex.js +36 -3
- package/package.json +15 -3
- package/postinstall.js +245 -0
- package/bin/code-aarch64-apple-darwin +0 -0
- package/bin/code-aarch64-unknown-linux-gnu +0 -0
- package/bin/code-aarch64-unknown-linux-musl +0 -0
- package/bin/code-exec-aarch64-apple-darwin +0 -0
- package/bin/code-exec-aarch64-unknown-linux-gnu +0 -0
- package/bin/code-exec-aarch64-unknown-linux-musl +0 -0
- package/bin/code-exec-x86_64-apple-darwin +0 -0
- package/bin/code-exec-x86_64-pc-windows-msvc.exe +0 -0
- package/bin/code-exec-x86_64-unknown-linux-gnu +0 -0
- package/bin/code-exec-x86_64-unknown-linux-musl +0 -0
- package/bin/code-tui-aarch64-apple-darwin +0 -0
- package/bin/code-tui-aarch64-unknown-linux-gnu +0 -0
- package/bin/code-tui-aarch64-unknown-linux-musl +0 -0
- package/bin/code-tui-x86_64-apple-darwin +0 -0
- package/bin/code-tui-x86_64-pc-windows-msvc.exe +0 -0
- package/bin/code-tui-x86_64-unknown-linux-gnu +0 -0
- package/bin/code-tui-x86_64-unknown-linux-musl +0 -0
- package/bin/code-x86_64-apple-darwin +0 -0
- package/bin/code-x86_64-pc-windows-msvc.exe +0 -0
- package/bin/code-x86_64-unknown-linux-gnu +0 -0
- package/bin/code-x86_64-unknown-linux-musl +0 -0
package/bin/{code.js → coder.js}
RENAMED
|
@@ -56,7 +56,26 @@ if (!targetTriple) {
|
|
|
56
56
|
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
const binaryPath = path.join(__dirname, "..", "bin", `
|
|
59
|
+
const binaryPath = path.join(__dirname, "..", "bin", `coder-${targetTriple}`);
|
|
60
|
+
|
|
61
|
+
// Check if binary exists and try to fix permissions if needed
|
|
62
|
+
import { existsSync, chmodSync } from "fs";
|
|
63
|
+
if (existsSync(binaryPath)) {
|
|
64
|
+
try {
|
|
65
|
+
// Ensure binary is executable on Unix-like systems
|
|
66
|
+
if (platform !== "win32") {
|
|
67
|
+
chmodSync(binaryPath, 0o755);
|
|
68
|
+
}
|
|
69
|
+
} catch (e) {
|
|
70
|
+
// Ignore permission errors, will be caught below if it's a real problem
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
console.error(`Binary not found: ${binaryPath}`);
|
|
74
|
+
console.error(`Please try reinstalling the package:`);
|
|
75
|
+
console.error(` npm uninstall -g @just-every/code`);
|
|
76
|
+
console.error(` npm install -g @just-every/code`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
60
79
|
|
|
61
80
|
// Use an asynchronous spawn instead of spawnSync so that Node is able to
|
|
62
81
|
// respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
|
|
@@ -67,15 +86,18 @@ const { spawn } = await import("child_process");
|
|
|
67
86
|
|
|
68
87
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
69
88
|
stdio: "inherit",
|
|
70
|
-
env: { ...process.env,
|
|
89
|
+
env: { ...process.env, CODER_MANAGED_BY_NPM: "1", CODEX_MANAGED_BY_NPM: "1" },
|
|
71
90
|
});
|
|
72
91
|
|
|
73
92
|
child.on("error", (err) => {
|
|
74
93
|
// Typically triggered when the binary is missing or not executable.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
if (err.code === 'EACCES') {
|
|
95
|
+
console.error(`Permission denied: ${binaryPath}`);
|
|
96
|
+
console.error(`Try running: chmod +x "${binaryPath}"`);
|
|
97
|
+
console.error(`Or reinstall the package with: npm install -g @just-every/code`);
|
|
98
|
+
} else {
|
|
99
|
+
console.error(err);
|
|
100
|
+
}
|
|
79
101
|
process.exit(1);
|
|
80
102
|
});
|
|
81
103
|
|
|
@@ -120,4 +142,3 @@ if (childResult.type === "signal") {
|
|
|
120
142
|
} else {
|
|
121
143
|
process.exit(childResult.exitCode);
|
|
122
144
|
}
|
|
123
|
-
|
package/bin/codex.js
CHANGED
|
@@ -43,7 +43,7 @@ switch (platform) {
|
|
|
43
43
|
targetTriple = "x86_64-pc-windows-msvc.exe";
|
|
44
44
|
break;
|
|
45
45
|
case "arm64":
|
|
46
|
-
|
|
46
|
+
// We do not build this today, fall through...
|
|
47
47
|
default:
|
|
48
48
|
break;
|
|
49
49
|
}
|
|
@@ -65,9 +65,43 @@ const binaryPath = path.join(__dirname, "..", "bin", `codex-${targetTriple}`);
|
|
|
65
65
|
// receives a fatal signal, both processes exit in a predictable manner.
|
|
66
66
|
const { spawn } = await import("child_process");
|
|
67
67
|
|
|
68
|
+
async function tryImport(moduleName) {
|
|
69
|
+
try {
|
|
70
|
+
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
|
71
|
+
return await import(moduleName);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function resolveRgDir() {
|
|
78
|
+
const ripgrep = await tryImport("@vscode/ripgrep");
|
|
79
|
+
if (!ripgrep?.rgPath) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return path.dirname(ripgrep.rgPath);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getUpdatedPath(newDirs) {
|
|
86
|
+
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
87
|
+
const existingPath = process.env.PATH || "";
|
|
88
|
+
const updatedPath = [
|
|
89
|
+
...newDirs,
|
|
90
|
+
...existingPath.split(pathSep).filter(Boolean),
|
|
91
|
+
].join(pathSep);
|
|
92
|
+
return updatedPath;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const additionalDirs = [];
|
|
96
|
+
const rgDir = await resolveRgDir();
|
|
97
|
+
if (rgDir) {
|
|
98
|
+
additionalDirs.push(rgDir);
|
|
99
|
+
}
|
|
100
|
+
const updatedPath = getUpdatedPath(additionalDirs);
|
|
101
|
+
|
|
68
102
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
69
103
|
stdio: "inherit",
|
|
70
|
-
env: { ...process.env, CODEX_MANAGED_BY_NPM: "1" },
|
|
104
|
+
env: { ...process.env, PATH: updatedPath, CODEX_MANAGED_BY_NPM: "1" },
|
|
71
105
|
});
|
|
72
106
|
|
|
73
107
|
child.on("error", (err) => {
|
|
@@ -120,4 +154,3 @@ if (childResult.type === "signal") {
|
|
|
120
154
|
} else {
|
|
121
155
|
process.exit(childResult.exitCode);
|
|
122
156
|
}
|
|
123
|
-
|
package/package.json
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@just-every/code",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Lightweight coding agent that runs in your terminal - fork of OpenAI Codex",
|
|
6
6
|
"bin": {
|
|
7
|
-
"code": "bin/
|
|
7
|
+
"code": "bin/coder.js",
|
|
8
|
+
"coder": "bin/coder.js"
|
|
8
9
|
},
|
|
9
10
|
"type": "module",
|
|
10
11
|
"engines": {
|
|
11
12
|
"node": ">=20"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
14
|
-
"bin",
|
|
15
|
+
"bin/coder.js",
|
|
16
|
+
"bin/codex.js",
|
|
17
|
+
"postinstall.js",
|
|
15
18
|
"dist"
|
|
16
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"postinstall": "node postinstall.js"
|
|
22
|
+
},
|
|
17
23
|
"repository": {
|
|
18
24
|
"type": "git",
|
|
19
25
|
"url": "git+https://github.com/just-every/code.git"
|
|
20
26
|
},
|
|
21
27
|
"publishConfig": {
|
|
22
28
|
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@vscode/ripgrep": "^1.15.14"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"prettier": "^3.3.3"
|
|
23
35
|
}
|
|
24
36
|
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, mkdirSync, createWriteStream, chmodSync, readFileSync, readSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { get } from 'https';
|
|
7
|
+
import { platform, arch } from 'os';
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
|
|
12
|
+
// Map Node.js platform/arch to Rust target triples
|
|
13
|
+
function getTargetTriple() {
|
|
14
|
+
const platformMap = {
|
|
15
|
+
'darwin': 'apple-darwin',
|
|
16
|
+
'linux': 'unknown-linux-musl', // Default to musl for better compatibility
|
|
17
|
+
'win32': 'pc-windows-msvc'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const archMap = {
|
|
21
|
+
'x64': 'x86_64',
|
|
22
|
+
'arm64': 'aarch64'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const rustArch = archMap[arch()] || arch();
|
|
26
|
+
const rustPlatform = platformMap[platform()] || platform();
|
|
27
|
+
|
|
28
|
+
return `${rustArch}-${rustPlatform}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function downloadBinary(url, dest) {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const file = createWriteStream(dest);
|
|
34
|
+
|
|
35
|
+
get(url, (response) => {
|
|
36
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
37
|
+
// Follow redirect
|
|
38
|
+
get(response.headers.location, (redirectResponse) => {
|
|
39
|
+
redirectResponse.pipe(file);
|
|
40
|
+
file.on('finish', () => {
|
|
41
|
+
file.close();
|
|
42
|
+
resolve();
|
|
43
|
+
});
|
|
44
|
+
}).on('error', reject);
|
|
45
|
+
} else if (response.statusCode === 200) {
|
|
46
|
+
response.pipe(file);
|
|
47
|
+
file.on('finish', () => {
|
|
48
|
+
file.close();
|
|
49
|
+
resolve();
|
|
50
|
+
});
|
|
51
|
+
} else {
|
|
52
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
53
|
+
}
|
|
54
|
+
}).on('error', reject);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function main() {
|
|
59
|
+
// Detect potential PATH conflict with an existing `code` command (e.g., VS Code)
|
|
60
|
+
try {
|
|
61
|
+
const whichCmd = process.platform === 'win32' ? 'where code' : 'command -v code || which code || true';
|
|
62
|
+
const resolved = execSync(whichCmd, { stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform !== 'win32' }).toString().split(/\r?\n/).filter(Boolean)[0];
|
|
63
|
+
if (resolved) {
|
|
64
|
+
let contents = '';
|
|
65
|
+
try {
|
|
66
|
+
contents = readFileSync(resolved, 'utf8');
|
|
67
|
+
} catch {
|
|
68
|
+
contents = '';
|
|
69
|
+
}
|
|
70
|
+
const looksLikeOurs = contents.includes('@just-every/code') || contents.includes('bin/coder.js');
|
|
71
|
+
if (!looksLikeOurs) {
|
|
72
|
+
console.warn('[notice] Found an existing `code` on PATH at:');
|
|
73
|
+
console.warn(` ${resolved}`);
|
|
74
|
+
console.warn('[notice] We will still install our CLI, also available as `coder`.');
|
|
75
|
+
console.warn(' If `code` runs another tool, prefer using: coder');
|
|
76
|
+
console.warn(' Or run our CLI explicitly via: npx -y @just-every/code');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
// Ignore detection failures; proceed with install.
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const targetTriple = getTargetTriple();
|
|
84
|
+
const isWindows = platform() === 'win32';
|
|
85
|
+
const binaryExt = isWindows ? '.exe' : '';
|
|
86
|
+
|
|
87
|
+
const binDir = join(__dirname, 'bin');
|
|
88
|
+
if (!existsSync(binDir)) {
|
|
89
|
+
mkdirSync(binDir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Get package version - use readFileSync for compatibility
|
|
93
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
94
|
+
const version = packageJson.version;
|
|
95
|
+
|
|
96
|
+
// Binary names to download (Rust artifacts remain named 'coder*')
|
|
97
|
+
const binaries = ['coder', 'coder-tui', 'coder-exec'];
|
|
98
|
+
|
|
99
|
+
console.log(`Installing @just-every/code v${version} for ${targetTriple}...`);
|
|
100
|
+
|
|
101
|
+
for (const binary of binaries) {
|
|
102
|
+
const binaryName = `${binary}-${targetTriple}${binaryExt}`;
|
|
103
|
+
const localPath = join(binDir, binaryName);
|
|
104
|
+
|
|
105
|
+
// Skip if already exists and has correct permissions
|
|
106
|
+
if (existsSync(localPath)) {
|
|
107
|
+
// Always try to fix permissions on Unix-like systems
|
|
108
|
+
if (!isWindows) {
|
|
109
|
+
try {
|
|
110
|
+
chmodSync(localPath, 0o755);
|
|
111
|
+
console.log(`✓ ${binaryName} already exists (permissions fixed)`);
|
|
112
|
+
} catch (e) {
|
|
113
|
+
console.log(`✓ ${binaryName} already exists`);
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
console.log(`✓ ${binaryName} already exists`);
|
|
117
|
+
}
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const downloadUrl = `https://github.com/just-every/code/releases/download/v${version}/${binaryName}`;
|
|
122
|
+
|
|
123
|
+
console.log(`Downloading ${binaryName}...`);
|
|
124
|
+
try {
|
|
125
|
+
await downloadBinary(downloadUrl, localPath);
|
|
126
|
+
|
|
127
|
+
// Make executable on Unix-like systems
|
|
128
|
+
if (!isWindows) {
|
|
129
|
+
chmodSync(localPath, 0o755);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log(`✓ Downloaded ${binaryName}`);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(`✗ Failed to download ${binaryName}: ${error.message}`);
|
|
135
|
+
console.error(` URL: ${downloadUrl}`);
|
|
136
|
+
// Continue with other binaries even if one fails
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Create platform-specific symlink/copy for main binary
|
|
141
|
+
const mainBinary = `coder-${targetTriple}${binaryExt}`;
|
|
142
|
+
const mainBinaryPath = join(binDir, mainBinary);
|
|
143
|
+
|
|
144
|
+
if (existsSync(mainBinaryPath)) {
|
|
145
|
+
console.log('Setting up main coder binary...');
|
|
146
|
+
|
|
147
|
+
// On Windows, we can't use symlinks easily, so update the JS wrapper
|
|
148
|
+
// On Unix, the JS wrapper will find the correct binary
|
|
149
|
+
console.log('✓ Installation complete!');
|
|
150
|
+
} else {
|
|
151
|
+
console.warn('⚠ Main coder binary not found. You may need to build from source.');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// With bin name = 'code', handle collisions with existing 'code' (e.g., VS Code)
|
|
155
|
+
try {
|
|
156
|
+
const isTTY = process.stdout && process.stdout.isTTY;
|
|
157
|
+
const isWindows = platform() === 'win32';
|
|
158
|
+
|
|
159
|
+
let globalBin = '';
|
|
160
|
+
try {
|
|
161
|
+
globalBin = execSync('npm bin -g', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
162
|
+
} catch {}
|
|
163
|
+
|
|
164
|
+
const ourShim = join(globalBin || '', isWindows ? 'code.cmd' : 'code');
|
|
165
|
+
|
|
166
|
+
// Resolve which 'code' is currently on PATH
|
|
167
|
+
const resolveOnPath = (cmd) => {
|
|
168
|
+
try {
|
|
169
|
+
if (isWindows) {
|
|
170
|
+
const out = execSync(`where ${cmd}`, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().split(/\r?\n/)[0]?.trim();
|
|
171
|
+
return out || '';
|
|
172
|
+
} else {
|
|
173
|
+
return execSync(`command -v ${cmd}`, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
174
|
+
}
|
|
175
|
+
} catch { return ''; }
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const codeResolved = resolveOnPath('code');
|
|
179
|
+
const collision = codeResolved && ourShim && codeResolved !== ourShim;
|
|
180
|
+
|
|
181
|
+
if (collision) {
|
|
182
|
+
console.log('⚠ Detected an existing `code` command on your PATH (likely VS Code).');
|
|
183
|
+
if (globalBin) {
|
|
184
|
+
// Create a 'coder' shim that forwards to our installed 'code' in the same dir
|
|
185
|
+
try {
|
|
186
|
+
const coderShim = join(globalBin, isWindows ? 'coder.cmd' : 'coder');
|
|
187
|
+
if (isWindows) {
|
|
188
|
+
const content = `@echo off\r\n"%~dp0code" %*\r\n`;
|
|
189
|
+
writeFileSync(coderShim, content);
|
|
190
|
+
} else {
|
|
191
|
+
const content = `#!/bin/sh\nexec "$(dirname \"$0\")/code" "$@"\n`;
|
|
192
|
+
writeFileSync(coderShim, content);
|
|
193
|
+
chmodSync(coderShim, 0o755);
|
|
194
|
+
}
|
|
195
|
+
console.log(`✓ Created fallback command \`coder\` -> our \`code\``);
|
|
196
|
+
} catch (e) {
|
|
197
|
+
console.log(`⚠ Failed to create 'coder' fallback: ${e.message}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Offer to create a 'vscode' alias that points to the existing system VS Code
|
|
201
|
+
if (isTTY && codeResolved) {
|
|
202
|
+
const prompt = (msg) => {
|
|
203
|
+
process.stdout.write(msg);
|
|
204
|
+
try {
|
|
205
|
+
const buf = Buffer.alloc(1024);
|
|
206
|
+
const bytes = readSync(0, buf, 0, 1024, null);
|
|
207
|
+
const ans = buf.slice(0, bytes).toString('utf8').trim().toLowerCase();
|
|
208
|
+
return ans;
|
|
209
|
+
} catch { return 'n'; }
|
|
210
|
+
};
|
|
211
|
+
const ans = prompt('Create a `vscode` alias for your existing editor? [y/N] ');
|
|
212
|
+
if (ans === 'y' || ans === 'yes') {
|
|
213
|
+
try {
|
|
214
|
+
const vscodeShim = join(globalBin, isWindows ? 'vscode.cmd' : 'vscode');
|
|
215
|
+
if (isWindows) {
|
|
216
|
+
const content = `@echo off\r\n"${codeResolved}" %*\r\n`;
|
|
217
|
+
writeFileSync(vscodeShim, content);
|
|
218
|
+
} else {
|
|
219
|
+
const content = `#!/bin/sh\nexec "${codeResolved}" "$@"\n`;
|
|
220
|
+
writeFileSync(vscodeShim, content);
|
|
221
|
+
chmodSync(vscodeShim, 0o755);
|
|
222
|
+
}
|
|
223
|
+
console.log('✓ Created `vscode` alias for your editor');
|
|
224
|
+
} catch (e) {
|
|
225
|
+
console.log(`⚠ Failed to create 'vscode' alias: ${e.message}`);
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
console.log('Skipping creation of `vscode` alias.');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log('→ Use `coder` to run this tool, and `vscode` (if created) for your editor.');
|
|
233
|
+
} else {
|
|
234
|
+
console.log('Note: could not determine npm global bin; skipping alias creation.');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch {
|
|
238
|
+
// non-fatal
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
main().catch(error => {
|
|
243
|
+
console.error('Installation failed:', error);
|
|
244
|
+
process.exit(1);
|
|
245
|
+
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|