openmux 0.1.1
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/LICENSE +21 -0
- package/README.md +194 -0
- package/bin/openmux +27 -0
- package/package.json +75 -0
- package/scripts/postinstall.cjs +137 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 monotykamary
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# openmux
|
|
2
|
+
|
|
3
|
+
A terminal multiplexer with master-stack layout (Zellij-style), built with:
|
|
4
|
+
|
|
5
|
+
- **Bun** - Fast JavaScript runtime
|
|
6
|
+
- **OpenTUI** - Terminal UI library with React reconciler
|
|
7
|
+
- **bun-pty** - PTY support for Bun
|
|
8
|
+
- **ghostty-web** - Terminal emulation via WASM
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Master-stack tiling layout (like Zellij)
|
|
13
|
+
- i3-gaps style gaps and borders
|
|
14
|
+
- Vim-style `hjkl` navigation
|
|
15
|
+
- Tmux-style `Ctrl+b` prefix key
|
|
16
|
+
- 9 workspaces with isolated pane layouts
|
|
17
|
+
- Session persistence and management
|
|
18
|
+
- Pane zoom (fullscreen focused pane)
|
|
19
|
+
- Kitty Graphics and Sixel protocol support
|
|
20
|
+
- Mouse tracking (click to focus, tabbed pane switching)
|
|
21
|
+
- Scrollback support with mouse wheel and scrollbar
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Quick Install (curl)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
curl -fsSL https://raw.githubusercontent.com/monotykamary/openmux/main/scripts/install.sh | bash
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### npm / bun
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g openmux
|
|
35
|
+
# or
|
|
36
|
+
bun add -g openmux
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### From Source
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/monotykamary/openmux.git
|
|
43
|
+
cd openmux
|
|
44
|
+
bun install
|
|
45
|
+
bun run build --install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### GitHub Releases
|
|
49
|
+
|
|
50
|
+
Download prebuilt binaries from [GitHub Releases](https://github.com/monotykamary/openmux/releases).
|
|
51
|
+
|
|
52
|
+
Available platforms:
|
|
53
|
+
- macOS (Apple Silicon)
|
|
54
|
+
- Linux (x64 / arm64)
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
openmux
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For development:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
bun start # Run from source
|
|
66
|
+
bun dev # Run with watch mode
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Keyboard Shortcuts
|
|
70
|
+
|
|
71
|
+
### Normal Mode (Alt shortcuts - no prefix needed)
|
|
72
|
+
- `Alt+h/j/k/l` - Navigate panes
|
|
73
|
+
- `Alt+n` - New pane
|
|
74
|
+
- `Alt+1-9` - Switch to workspace 1-9
|
|
75
|
+
- `Alt+[` / `Alt+]` - Cycle layout mode (vertical → horizontal → stacked)
|
|
76
|
+
- `Alt+x` - Close pane
|
|
77
|
+
- `Alt+z` - Toggle zoom (fullscreen focused pane)
|
|
78
|
+
- `Alt+s` - Open session picker
|
|
79
|
+
- `Ctrl+b` - Enter prefix mode
|
|
80
|
+
|
|
81
|
+
### Mouse
|
|
82
|
+
- `Click` - Focus pane
|
|
83
|
+
- `Click tab` - Switch to stacked pane (in stacked mode)
|
|
84
|
+
- `Scroll wheel` - Scroll through terminal history (when not in alternate screen apps like vim)
|
|
85
|
+
- `Click scrollbar` - Jump to position in scrollback
|
|
86
|
+
- `Drag scrollbar` - Scroll through history by dragging
|
|
87
|
+
|
|
88
|
+
### Prefix Mode (Ctrl+b, 2s timeout)
|
|
89
|
+
- `n` or `Enter` - New pane
|
|
90
|
+
- `h/j/k/l` - Navigate panes
|
|
91
|
+
- `1-9` - Switch to workspace 1-9
|
|
92
|
+
- `v` - Set layout mode: vertical
|
|
93
|
+
- `H` - Set layout mode: horizontal
|
|
94
|
+
- `t` - Set layout mode: stacked (tabbed)
|
|
95
|
+
- `x` - Close current pane
|
|
96
|
+
- `z` - Toggle zoom
|
|
97
|
+
- `s` - Open session picker
|
|
98
|
+
- `]` - Paste from clipboard
|
|
99
|
+
- `r` - Enter resize mode
|
|
100
|
+
- `?` - Toggle keyboard hints
|
|
101
|
+
- `Esc` - Exit prefix mode
|
|
102
|
+
|
|
103
|
+
### Resize Mode
|
|
104
|
+
- `h/l` - Shrink/grow width
|
|
105
|
+
- `j/k` - Grow/shrink height
|
|
106
|
+
- `Enter/Esc` - Exit resize mode
|
|
107
|
+
|
|
108
|
+
## Concepts
|
|
109
|
+
|
|
110
|
+
### Workspaces
|
|
111
|
+
Like i3/sway, openmux supports multiple workspaces (1-9). Each workspace has its own layout tree of panes. The status bar shows populated workspaces dynamically - empty workspaces don't appear unless active.
|
|
112
|
+
|
|
113
|
+
### Layout Modes (Zellij-style)
|
|
114
|
+
Each workspace has a layout mode that determines how panes are arranged:
|
|
115
|
+
- **Vertical** (`│`): Main pane on left, stack panes split vertically on right
|
|
116
|
+
- **Horizontal** (`─`): Main pane on top, stack panes split horizontally on bottom
|
|
117
|
+
- **Stacked** (`▣`): Main pane on left, stack panes tabbed on right (only active visible)
|
|
118
|
+
|
|
119
|
+
### Sessions
|
|
120
|
+
Sessions persist your workspace layouts and pane working directories. Sessions are auto-saved to `~/.config/openmux/sessions/` and can be switched via the session picker (`Alt+s` or `Ctrl+b s`).
|
|
121
|
+
|
|
122
|
+
## Project Structure
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
src/
|
|
126
|
+
├── core/ # Core layout and session management
|
|
127
|
+
│ ├── types.ts # Type definitions (Workspace, Pane, etc.)
|
|
128
|
+
│ ├── config.ts # Configuration and defaults
|
|
129
|
+
│ ├── keyboard-utils.ts # hjkl to Direction conversion
|
|
130
|
+
│ ├── operations/
|
|
131
|
+
│ │ ├── index.ts # Layout operations exports
|
|
132
|
+
│ │ └── master-stack-layout.ts # Master-stack layout calculations
|
|
133
|
+
│ └── session/ # Session persistence
|
|
134
|
+
│ ├── index.ts # Session exports
|
|
135
|
+
│ ├── session-manager.ts # High-level session operations
|
|
136
|
+
│ ├── session-serializer.ts # Serialize/deserialize sessions
|
|
137
|
+
│ └── session-storage.ts # Disk I/O for sessions
|
|
138
|
+
│
|
|
139
|
+
├── components/ # OpenTUI React components
|
|
140
|
+
│ ├── index.ts # Component exports
|
|
141
|
+
│ ├── Pane.tsx # Individual pane with border/focus
|
|
142
|
+
│ ├── PaneContainer.tsx # Layout pane renderer
|
|
143
|
+
│ ├── TerminalView.tsx # Terminal rendering with buffer API
|
|
144
|
+
│ ├── StatusBar.tsx # Bottom status bar
|
|
145
|
+
│ ├── KeyboardHints.tsx # Keyboard shortcuts overlay
|
|
146
|
+
│ └── SessionPicker.tsx # Session selection modal
|
|
147
|
+
│
|
|
148
|
+
├── contexts/ # React contexts for state
|
|
149
|
+
│ ├── index.ts # Context exports
|
|
150
|
+
│ ├── LayoutContext.tsx # Workspace/pane layout state reducer
|
|
151
|
+
│ ├── TerminalContext.tsx # PTY management and lifecycle
|
|
152
|
+
│ ├── KeyboardContext.tsx # Prefix mode and key state
|
|
153
|
+
│ ├── SessionContext.tsx # Session management and persistence
|
|
154
|
+
│ └── ThemeContext.tsx # Theme/styling configuration
|
|
155
|
+
│
|
|
156
|
+
├── terminal/ # PTY and terminal emulation
|
|
157
|
+
│ ├── index.ts # Terminal exports
|
|
158
|
+
│ ├── pty-manager.ts # PTY session lifecycle (bun-pty)
|
|
159
|
+
│ ├── ghostty-emulator.ts # Terminal emulator (ghostty-web WASM)
|
|
160
|
+
│ ├── input-handler.ts # Key/mouse to escape sequence encoder
|
|
161
|
+
│ ├── graphics-passthrough.ts # Kitty Graphics/Sixel protocol
|
|
162
|
+
│ ├── capabilities.ts # Terminal capability detection
|
|
163
|
+
│ └── terminal-colors.ts # Color palette detection
|
|
164
|
+
│
|
|
165
|
+
├── utils/
|
|
166
|
+
│ ├── index.ts # Utils exports
|
|
167
|
+
│ └── clipboard.ts # Clipboard read/write
|
|
168
|
+
│
|
|
169
|
+
├── App.tsx # Main app component with context hierarchy
|
|
170
|
+
└── index.tsx # Entry point (Bun serve + OpenTUI renderer)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Development Status
|
|
174
|
+
|
|
175
|
+
Current status:
|
|
176
|
+
|
|
177
|
+
- [x] Master-stack layout with gaps
|
|
178
|
+
- [x] OpenTUI component layer
|
|
179
|
+
- [x] Keyboard navigation system
|
|
180
|
+
- [x] PTY integration
|
|
181
|
+
- [x] ghostty-web WASM terminal emulation
|
|
182
|
+
- [x] Workspaces (1-9)
|
|
183
|
+
- [x] Layout modes (vertical/horizontal/stacked)
|
|
184
|
+
- [x] Session persistence
|
|
185
|
+
- [x] Pane zoom
|
|
186
|
+
- [x] Mouse support
|
|
187
|
+
- [x] Graphics protocol passthrough (Kitty/Sixel)
|
|
188
|
+
- [x] Scrollback support
|
|
189
|
+
- [ ] Session restore on startup
|
|
190
|
+
- [ ] Configurable keybindings
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|
package/bin/openmux
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# openmux npm bin wrapper
|
|
5
|
+
# Locates and executes the downloaded binary
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
PACKAGE_DIR="$(dirname "$SCRIPT_DIR")"
|
|
9
|
+
DIST_DIR="$PACKAGE_DIR/dist"
|
|
10
|
+
|
|
11
|
+
# Determine library extension based on OS
|
|
12
|
+
case "$(uname -s)" in
|
|
13
|
+
Darwin) LIB_EXT="dylib" ;;
|
|
14
|
+
Linux) LIB_EXT="so" ;;
|
|
15
|
+
*) echo "Unsupported OS" >&2; exit 1 ;;
|
|
16
|
+
esac
|
|
17
|
+
|
|
18
|
+
# Check if binary exists
|
|
19
|
+
if [[ ! -x "$DIST_DIR/openmux-bin" ]]; then
|
|
20
|
+
echo "Error: openmux binary not found at $DIST_DIR/openmux-bin" >&2
|
|
21
|
+
echo "Run 'npm run build' or reinstall the package" >&2
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Set library path and execute
|
|
26
|
+
export BUN_PTY_LIB="${BUN_PTY_LIB:-$DIST_DIR/librust_pty.$LIB_EXT}"
|
|
27
|
+
exec "$DIST_DIR/openmux-bin" "$@"
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openmux",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Terminal multiplexer with master-stack tiling layout",
|
|
5
|
+
"module": "src/index.tsx",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"openmux": "./bin/openmux"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"scripts/postinstall.cjs"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"start": "bun run src/index.tsx",
|
|
16
|
+
"dev": "bun run --watch src/index.tsx",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"build": "./scripts/build.sh",
|
|
19
|
+
"build:release": "./scripts/build.sh --release",
|
|
20
|
+
"install:local": "./scripts/build.sh --install",
|
|
21
|
+
"prepare": "effect-language-service patch",
|
|
22
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"release": "standard-version",
|
|
26
|
+
"release:minor": "standard-version --release-as minor",
|
|
27
|
+
"release:major": "standard-version --release-as major",
|
|
28
|
+
"release:patch": "standard-version --release-as patch",
|
|
29
|
+
"release:first": "standard-version --first-release",
|
|
30
|
+
"publish:npm": "./scripts/publish.sh"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/monotykamary/openmux.git"
|
|
35
|
+
},
|
|
36
|
+
"author": "monotykamary",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"homepage": "https://github.com/monotykamary/openmux#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/monotykamary/openmux/issues"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"terminal",
|
|
44
|
+
"multiplexer",
|
|
45
|
+
"tui",
|
|
46
|
+
"tmux",
|
|
47
|
+
"zellij",
|
|
48
|
+
"bun",
|
|
49
|
+
"opentui"
|
|
50
|
+
],
|
|
51
|
+
"engines": {
|
|
52
|
+
"bun": ">=1.0.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@effect/language-service": "^0.60.0",
|
|
56
|
+
"@effect/vitest": "^0.27.0",
|
|
57
|
+
"@types/bun": "latest",
|
|
58
|
+
"@types/react": "^19.2.7",
|
|
59
|
+
"standard-version": "^9.5.0",
|
|
60
|
+
"vitest": "^4.0.15"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"typescript": "^5.9.3"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@effect/cli": "^0.72.1",
|
|
67
|
+
"@effect/platform": "^0.93.6",
|
|
68
|
+
"@opentui/core": "^0.1.57",
|
|
69
|
+
"@opentui/react": "^0.1.57",
|
|
70
|
+
"bun-pty": "^0.4.2",
|
|
71
|
+
"effect": "^3.19.9",
|
|
72
|
+
"ghostty-web": "^0.3.0",
|
|
73
|
+
"react": "^19.2.1"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* openmux postinstall script
|
|
5
|
+
* Downloads prebuilt binaries from GitHub releases
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const https = require("https");
|
|
11
|
+
const { execSync } = require("child_process");
|
|
12
|
+
|
|
13
|
+
const REPO = "monotykamary/openmux";
|
|
14
|
+
const PACKAGE_ROOT = path.join(__dirname, "..");
|
|
15
|
+
const DIST_DIR = path.join(PACKAGE_ROOT, "dist");
|
|
16
|
+
|
|
17
|
+
function getPlatform() {
|
|
18
|
+
const platform = process.platform;
|
|
19
|
+
const arch = process.arch;
|
|
20
|
+
|
|
21
|
+
let os;
|
|
22
|
+
switch (platform) {
|
|
23
|
+
case "darwin":
|
|
24
|
+
os = "darwin";
|
|
25
|
+
break;
|
|
26
|
+
case "linux":
|
|
27
|
+
os = "linux";
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let cpu;
|
|
34
|
+
switch (arch) {
|
|
35
|
+
case "x64":
|
|
36
|
+
cpu = "x64";
|
|
37
|
+
break;
|
|
38
|
+
case "arm64":
|
|
39
|
+
cpu = "arm64";
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`Unsupported architecture: ${arch}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { os, arch: cpu, target: `${os}-${cpu}` };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getVersion() {
|
|
49
|
+
const packageJson = require(path.join(PACKAGE_ROOT, "package.json"));
|
|
50
|
+
return `v${packageJson.version}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function fetch(url) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
https.get(url, { headers: { "User-Agent": "openmux-installer" } }, (res) => {
|
|
56
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
57
|
+
// Follow redirect
|
|
58
|
+
fetch(res.headers.location).then(resolve).catch(reject);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (res.statusCode !== 200) {
|
|
62
|
+
reject(new Error(`HTTP ${res.statusCode}: ${url}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
resolve(res);
|
|
66
|
+
}).on("error", reject);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function downloadFile(url, destPath) {
|
|
71
|
+
console.log(`Downloading ${url}...`);
|
|
72
|
+
|
|
73
|
+
const response = await fetch(url);
|
|
74
|
+
const writeStream = fs.createWriteStream(destPath);
|
|
75
|
+
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
response.pipe(writeStream);
|
|
78
|
+
writeStream.on("finish", () => {
|
|
79
|
+
writeStream.close();
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
82
|
+
writeStream.on("error", reject);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function main() {
|
|
87
|
+
// Skip in CI or when OPENMUX_SKIP_DOWNLOAD is set
|
|
88
|
+
if (process.env.CI || process.env.OPENMUX_SKIP_DOWNLOAD) {
|
|
89
|
+
console.log("Skipping binary download");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const { target } = getPlatform();
|
|
95
|
+
const version = getVersion();
|
|
96
|
+
|
|
97
|
+
console.log(`Installing openmux ${version} for ${target}...`);
|
|
98
|
+
|
|
99
|
+
const url = `https://github.com/${REPO}/releases/download/${version}/openmux-${version}-${target}.tar.gz`;
|
|
100
|
+
|
|
101
|
+
// Ensure dist directory exists
|
|
102
|
+
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
103
|
+
|
|
104
|
+
const tarballPath = path.join(DIST_DIR, "download.tar.gz");
|
|
105
|
+
|
|
106
|
+
await downloadFile(url, tarballPath);
|
|
107
|
+
|
|
108
|
+
console.log("Extracting...");
|
|
109
|
+
|
|
110
|
+
// Use native tar command to extract
|
|
111
|
+
execSync(`tar -xzf "${tarballPath}" -C "${DIST_DIR}"`, { stdio: "inherit" });
|
|
112
|
+
|
|
113
|
+
// Clean up tarball
|
|
114
|
+
fs.unlinkSync(tarballPath);
|
|
115
|
+
|
|
116
|
+
// Make binary executable
|
|
117
|
+
const binaryPath = path.join(DIST_DIR, "openmux-bin");
|
|
118
|
+
if (fs.existsSync(binaryPath)) {
|
|
119
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Make wrapper executable
|
|
123
|
+
const wrapperPath = path.join(DIST_DIR, "openmux");
|
|
124
|
+
if (fs.existsSync(wrapperPath)) {
|
|
125
|
+
fs.chmodSync(wrapperPath, 0o755);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log("openmux installed successfully!");
|
|
129
|
+
} catch (error) {
|
|
130
|
+
// Don't fail the install if download fails
|
|
131
|
+
// User might be building from source
|
|
132
|
+
console.warn(`Warning: Could not download prebuilt binary: ${error.message}`);
|
|
133
|
+
console.warn("You may need to build from source: bun run build");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
main();
|