@hona/ralph-cli 0.1.0

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 (3) hide show
  1. package/bin/ralph +134 -0
  2. package/package.json +29 -0
  3. package/postinstall.mjs +145 -0
package/bin/ralph ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Ralph CLI Launcher
4
+ *
5
+ * This is a thin JavaScript wrapper that finds and executes the correct
6
+ * platform-specific binary for the current OS/architecture.
7
+ *
8
+ * The binary is located in one of the optional dependency packages:
9
+ * - ralph-opencode-darwin-arm64
10
+ * - ralph-opencode-darwin-x64
11
+ * - ralph-opencode-linux-arm64
12
+ * - ralph-opencode-linux-x64
13
+ * - ralph-opencode-windows-x64
14
+ *
15
+ * Environment variables:
16
+ * RALPH_BIN_PATH - Override path to the ralph binary
17
+ */
18
+
19
+ const childProcess = require("child_process");
20
+ const fs = require("fs");
21
+ const path = require("path");
22
+ const os = require("os");
23
+
24
+ /**
25
+ * Run the binary with inherited stdio
26
+ */
27
+ function run(target) {
28
+ const result = childProcess.spawnSync(target, process.argv.slice(2), {
29
+ stdio: "inherit",
30
+ });
31
+
32
+ if (result.error) {
33
+ console.error(result.error.message);
34
+ process.exit(1);
35
+ }
36
+
37
+ const code = typeof result.status === "number" ? result.status : 0;
38
+ process.exit(code);
39
+ }
40
+
41
+ // Check for environment variable override
42
+ const envPath = process.env.RALPH_BIN_PATH;
43
+ if (envPath) {
44
+ run(envPath);
45
+ }
46
+
47
+ // Get the real path of this script (resolves symlinks)
48
+ const scriptPath = fs.realpathSync(__filename);
49
+ const scriptDir = path.dirname(scriptPath);
50
+
51
+ // Map OS and architecture to package naming conventions
52
+ const platformMap = {
53
+ darwin: "darwin",
54
+ linux: "linux",
55
+ win32: "windows",
56
+ };
57
+
58
+ const archMap = {
59
+ x64: "x64",
60
+ arm64: "arm64",
61
+ };
62
+
63
+ let platform = platformMap[os.platform()];
64
+ if (!platform) {
65
+ platform = os.platform();
66
+ }
67
+
68
+ let arch = archMap[os.arch()];
69
+ if (!arch) {
70
+ arch = os.arch();
71
+ }
72
+
73
+ // Construct package and binary names
74
+ const packageBase = "@hona/ralph-cli-" + platform + "-" + arch;
75
+ const binaryName = platform === "windows" ? "ralph.exe" : "ralph";
76
+
77
+ /**
78
+ * Search for the binary in node_modules hierarchy
79
+ */
80
+ function findBinary(startDir) {
81
+ let current = startDir;
82
+
83
+ for (;;) {
84
+ const modules = path.join(current, "node_modules");
85
+
86
+ if (fs.existsSync(modules)) {
87
+ const entries = fs.readdirSync(modules);
88
+
89
+ for (const entry of entries) {
90
+ // Match package name (could have version suffix in some package managers)
91
+ if (!entry.startsWith(packageBase)) {
92
+ continue;
93
+ }
94
+
95
+ const candidate = path.join(modules, entry, "bin", binaryName);
96
+ if (fs.existsSync(candidate)) {
97
+ return candidate;
98
+ }
99
+ }
100
+ }
101
+
102
+ // Move up to parent directory
103
+ const parent = path.dirname(current);
104
+ if (parent === current) {
105
+ // Reached filesystem root
106
+ return;
107
+ }
108
+ current = parent;
109
+ }
110
+ }
111
+
112
+ // Try to find the binary
113
+ const resolved = findBinary(scriptDir);
114
+
115
+ if (!resolved) {
116
+ console.error(
117
+ "Error: Could not find the ralph binary for your platform.\n\n" +
118
+ "It seems that your package manager failed to install the correct version\n" +
119
+ "of the ralph CLI for your platform (" +
120
+ platform +
121
+ "-" +
122
+ arch +
123
+ ").\n\n" +
124
+ 'You can try manually installing the "' +
125
+ packageBase +
126
+ '" package:\n\n' +
127
+ " npm install " +
128
+ packageBase +
129
+ "\n"
130
+ );
131
+ process.exit(1);
132
+ }
133
+
134
+ run(resolved);
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@hona/ralph-cli",
3
+ "version": "0.1.0",
4
+ "description": "Ralph - AI coding assistant CLI",
5
+ "bin": {
6
+ "ralph": "./bin/ralph"
7
+ },
8
+ "scripts": {
9
+ "postinstall": "node ./postinstall.mjs"
10
+ },
11
+ "optionalDependencies": {
12
+ "@hona/ralph-cli-darwin-arm64": "0.1.0",
13
+ "@hona/ralph-cli-darwin-x64": "0.1.0",
14
+ "@hona/ralph-cli-linux-arm64": "0.1.0",
15
+ "@hona/ralph-cli-linux-x64": "0.1.0",
16
+ "@hona/ralph-cli-windows-x64": "0.1.0"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/hona/opencode-ralph.git"
21
+ },
22
+ "keywords": [
23
+ "cli",
24
+ "ai",
25
+ "coding",
26
+ "assistant"
27
+ ],
28
+ "license": "MIT"
29
+ }
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Postinstall script for ralph-opencode
4
+ *
5
+ * This script runs after `npm install ralph-opencode` and symlinks the
6
+ * platform-specific binary to the bin directory.
7
+ *
8
+ * On Windows, npm handles the .exe directly so we skip symlinking.
9
+ */
10
+
11
+ import fs from "fs";
12
+ import path from "path";
13
+ import os from "os";
14
+ import { fileURLToPath } from "url";
15
+ import { createRequire } from "module";
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
+ const require = createRequire(import.meta.url);
19
+
20
+ /**
21
+ * Detect the current platform and architecture
22
+ */
23
+ function detectPlatformAndArch() {
24
+ let platform;
25
+ switch (os.platform()) {
26
+ case "darwin":
27
+ platform = "darwin";
28
+ break;
29
+ case "linux":
30
+ platform = "linux";
31
+ break;
32
+ case "win32":
33
+ platform = "windows";
34
+ break;
35
+ default:
36
+ platform = os.platform();
37
+ break;
38
+ }
39
+
40
+ let arch;
41
+ switch (os.arch()) {
42
+ case "x64":
43
+ arch = "x64";
44
+ break;
45
+ case "arm64":
46
+ arch = "arm64";
47
+ break;
48
+ default:
49
+ arch = os.arch();
50
+ break;
51
+ }
52
+
53
+ return { platform, arch };
54
+ }
55
+
56
+ /**
57
+ * Find the platform-specific binary package
58
+ */
59
+ function findBinary() {
60
+ const { platform, arch } = detectPlatformAndArch();
61
+ const packageName = `@hona/ralph-cli-${platform}-${arch}`;
62
+ const binaryName = platform === "windows" ? "ralph.exe" : "ralph";
63
+
64
+ try {
65
+ // Use require.resolve to find the package
66
+ const packageJsonPath = require.resolve(`${packageName}/package.json`);
67
+ const packageDir = path.dirname(packageJsonPath);
68
+ const binaryPath = path.join(packageDir, "bin", binaryName);
69
+
70
+ if (!fs.existsSync(binaryPath)) {
71
+ throw new Error(`Binary not found at ${binaryPath}`);
72
+ }
73
+
74
+ return { binaryPath, binaryName, packageName };
75
+ } catch (error) {
76
+ throw new Error(`Could not find package ${packageName}: ${error.message}`);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Prepare the bin directory and return paths
82
+ */
83
+ function prepareBinDirectory(binaryName) {
84
+ const binDir = path.join(__dirname, "bin");
85
+ const targetPath = path.join(binDir, binaryName);
86
+
87
+ // Ensure bin directory exists
88
+ if (!fs.existsSync(binDir)) {
89
+ fs.mkdirSync(binDir, { recursive: true });
90
+ }
91
+
92
+ // Remove existing binary/symlink if it exists
93
+ if (fs.existsSync(targetPath)) {
94
+ fs.unlinkSync(targetPath);
95
+ }
96
+
97
+ return { binDir, targetPath };
98
+ }
99
+
100
+ /**
101
+ * Create symlink to the platform binary
102
+ */
103
+ function symlinkBinary(sourcePath, binaryName) {
104
+ const { targetPath } = prepareBinDirectory(binaryName);
105
+
106
+ fs.symlinkSync(sourcePath, targetPath);
107
+ console.log(`ralph binary symlinked: ${targetPath} -> ${sourcePath}`);
108
+
109
+ // Verify the file exists after operation
110
+ if (!fs.existsSync(targetPath)) {
111
+ throw new Error(`Failed to symlink binary to ${targetPath}`);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Main function
117
+ */
118
+ async function main() {
119
+ try {
120
+ // On Windows, npm handles the .exe directly via the bin field
121
+ // No postinstall symlinking needed
122
+ if (os.platform() === "win32") {
123
+ console.log(
124
+ "Windows detected: binary setup not needed (using packaged .exe)"
125
+ );
126
+ return;
127
+ }
128
+
129
+ const { binaryPath, binaryName, packageName } = findBinary();
130
+ console.log(`Found ${packageName} at ${binaryPath}`);
131
+ symlinkBinary(binaryPath, binaryName);
132
+ } catch (error) {
133
+ console.error("Failed to setup ralph binary:", error.message);
134
+ // Don't fail the install - the JS launcher will handle finding the binary
135
+ process.exit(0);
136
+ }
137
+ }
138
+
139
+ try {
140
+ main();
141
+ } catch (error) {
142
+ console.error("Postinstall script error:", error.message);
143
+ // Exit gracefully - don't break npm install
144
+ process.exit(0);
145
+ }