Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ Terminal UI for managing git worktrees and launching your preferred coding tool
npm i -g opencode-worktree
```

Or run it without a global installation using Bun:

```bash
bunx opencode-worktree
```

## Run

```bash
Expand Down
53 changes: 8 additions & 45 deletions bin/opencode-worktree
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,29 @@

import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { spawn } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { getBinaryPath, installBinary } from '../script/runtime.mjs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const pkg = JSON.parse(
fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
);

const detectPlatformAndArch = () => {
let platform;
switch (os.platform()) {
case 'darwin':
platform = 'darwin';
break;
case 'linux':
platform = 'linux';
break;
case 'win32':
platform = 'windows';
break;
default:
platform = os.platform();
break;
}

let arch;
switch (os.arch()) {
case 'x64':
arch = 'x64';
break;
case 'arm64':
arch = 'arm64';
break;
default:
arch = os.arch();
break;
}

return { platform, arch };
};

const resolveBinaryPath = () => {
const { platform } = detectPlatformAndArch();
const binaryName = platform === 'windows' ? 'opencode-worktree.exe' : 'opencode-worktree-bin';
const binaryPath = path.join(__dirname, '..', 'bin', binaryName);

const resolveBinaryPath = async () => {
const packageRoot = path.join(__dirname, '..');
const { binaryPath } = getBinaryPath(packageRoot);
if (!fs.existsSync(binaryPath)) {
throw new Error(
`Binary not found at ${binaryPath}. Run npm install -g ${pkg.name} again to re-download.`,
);
console.error('Downloading opencode-worktree binary...');
await installBinary(packageRoot, pkg.version);
}

return binaryPath;
};

const run = () => {
const run = async () => {
try {
const binaryPath = resolveBinaryPath();
const binaryPath = await resolveBinaryPath();
const args = process.argv.slice(2);
const child = spawn(binaryPath, args, { stdio: 'inherit' });

Expand Down
69 changes: 5 additions & 64 deletions script/postinstall.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,19 @@

import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { fileURLToPath } from "node:url";
import { getBinaryPath, installBinary as downloadBinary } from "./runtime.mjs";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const pkg = JSON.parse(
fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"),
);

const detectPlatformAndArch = () => {
let platform;
switch (os.platform()) {
case "darwin":
platform = "darwin";
break;
case "linux":
platform = "linux";
break;
case "win32":
platform = "windows";
break;
default:
platform = os.platform();
break;
}

let arch;
switch (os.arch()) {
case "x64":
arch = "x64";
break;
case "arm64":
arch = "arm64";
break;
default:
arch = os.arch();
break;
}

return { platform, arch };
};

const downloadFile = async (url, targetPath) => {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to download ${url} (${response.status})`);
}

const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync(targetPath, buffer);
};

const installBinary = async () => {
const { platform, arch } = detectPlatformAndArch();
const isWindows = platform === "windows";
const binaryName = isWindows
? "opencode-worktree.exe"
: "opencode-worktree-bin";
const downloadName = `opencode-worktree-${platform}-${arch}${isWindows ? ".exe" : ""}`;
const version = pkg.version;
const downloadUrl = `https://github.com/arturosdg/opencode-worktree/releases/download/v${version}/${downloadName}`;

const binDir = path.join(__dirname, "..", "bin");
const binaryPath = path.join(binDir, binaryName);

fs.mkdirSync(binDir, { recursive: true });
await downloadFile(downloadUrl, binaryPath);

if (!isWindows) {
fs.chmodSync(binaryPath, 0o755);
}

return binaryPath;
const packageRoot = path.join(__dirname, "..");
const { binaryPath } = getBinaryPath(packageRoot);
if (fs.existsSync(binaryPath)) return binaryPath;
return downloadBinary(packageRoot, pkg.version);
};

try {
Expand Down
28 changes: 28 additions & 0 deletions script/runtime.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";

const detectPlatformAndArch = () => ({
platform: { darwin: "darwin", linux: "linux", win32: "windows" }[os.platform()] ?? os.platform(),
arch: { x64: "x64", arm64: "arm64" }[os.arch()] ?? os.arch(),
});

export const getBinaryPath = (packageRoot) => {
const { platform } = detectPlatformAndArch();
const binaryName = platform === "windows" ? "opencode-worktree.exe" : "opencode-worktree-bin";
return { binaryPath: path.join(packageRoot, "bin", binaryName), binaryName };
};

export const installBinary = async (packageRoot, version) => {
const { platform, arch } = detectPlatformAndArch();
const isWindows = platform === "windows";
const downloadName = `opencode-worktree-${platform}-${arch}${isWindows ? ".exe" : ""}`;
const downloadUrl = `https://github.com/arturosdg/opencode-worktree/releases/download/v${version}/${downloadName}`;
const { binaryPath } = getBinaryPath(packageRoot);
const response = await fetch(downloadUrl);
if (!response.ok) throw new Error(`Failed to download ${downloadUrl} (${response.status})`);
fs.mkdirSync(path.dirname(binaryPath), { recursive: true });
fs.writeFileSync(binaryPath, Buffer.from(await response.arrayBuffer()));
if (!isWindows) fs.chmodSync(binaryPath, 0o755);
return binaryPath;
};