arashi 1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arashi Contributors
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,351 @@
1
+ # Arashi
2
+
3
+ > 嵐 - The eye of the storm for your development workflow
4
+
5
+ Arashi is a Git worktree manager for meta-repositories that automatically manages worktrees across multiple related repositories. When working on features that span multiple repositories, Arashi simplifies the workflow by ensuring all related repositories maintain synchronized worktrees.
6
+
7
+ ## Documentation
8
+
9
+ 📋 **For complete design documents, specifications, and planning, see the [Arashi Specifications Repository](https://github.com/corwinm/arashi-arashi).**
10
+
11
+ ## Status
12
+
13
+ 🚧 **Under Active Development** - Phase 1 Complete
14
+
15
+ This project is currently in early development. See the [Design Document](https://github.com/corwinm/arashi-arashi/tree/main/setup/.specify/memory/design.md) in the specs repository for the complete feature roadmap and implementation plan.
16
+
17
+ ## Installation (Coming Soon)
18
+
19
+ ### npm (Recommended)
20
+
21
+ ```bash
22
+ npm install -g arashi
23
+ ```
24
+
25
+ The npm package includes everything you need for full fzf compatibility.
26
+
27
+ ### Direct Binary Download
28
+
29
+ Download and extract the latest release for your platform from [GitHub Releases](https://github.com/corwinm/arashi/releases):
30
+
31
+ **macOS (Apple Silicon)**
32
+ ```bash
33
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi-macos-arm64.tar.gz -o arashi.tar.gz
34
+ tar xzf arashi.tar.gz
35
+ cd arashi-macos-arm64
36
+ sudo cp arashi arashi.bin /usr/local/bin/
37
+ ```
38
+
39
+ **Linux (x64)**
40
+ ```bash
41
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi-linux-x64.tar.gz -o arashi.tar.gz
42
+ tar xzf arashi.tar.gz
43
+ cd arashi-linux-x64
44
+ sudo cp arashi arashi.bin /usr/local/bin/
45
+ ```
46
+
47
+ **Windows (x64)**
48
+ - Windows support coming soon (wrapper script needs PowerShell equivalent)
49
+
50
+ ## Vision
51
+
52
+ Arashi will enable developers to:
53
+ - Create coordinated worktrees across multiple repositories with a single command
54
+ - Automatically manage branch synchronization across related repos
55
+ - Simplify setup and teardown of development environments
56
+ - Maintain clean git state across meta-repository structures
57
+
58
+ ## Quick Start (Coming Soon)
59
+
60
+ ```bash
61
+ # Initialize arashi in your meta-repository
62
+ arashi init
63
+
64
+ # Add repositories to manage
65
+ arashi add git@github.com:user/frontend.git
66
+ arashi add git@github.com:user/backend.git
67
+
68
+ # Create a new feature worktree across all repos
69
+ arashi create feature-new-api
70
+
71
+ # Check status across all repos
72
+ arashi status
73
+
74
+ # Remove worktree when done
75
+ arashi remove feature-new-api
76
+ ```
77
+
78
+ ## Planned Commands
79
+
80
+ - `arashi init` - Initialize arashi in current repository
81
+ - `arashi add <git-url>` - Add a repository to the repos folder
82
+ - `arashi create <branch>` - Create coordinated worktrees
83
+ - `arashi list` - List all worktrees
84
+ - `arashi remove <branch>` - Remove worktrees and branches
85
+ - `arashi setup` - Run setup scripts
86
+ - `arashi status` - Show status of all repositories
87
+
88
+ ## Integration with fzf, tmux, and sesh
89
+
90
+ The `arashi list` command outputs clean, full paths perfect for piping to tools like fzf. Here are powerful workflow integrations:
91
+
92
+ ### Basic: Change Directory with fzf
93
+
94
+ Navigate to any worktree interactively:
95
+
96
+ ```bash
97
+ # Interactive worktree selection
98
+ cd $(arashi list | fzf)
99
+ ```
100
+
101
+ **Add as a shell keybinding** for instant access:
102
+
103
+ #### Bash/Zsh
104
+
105
+ Add to your `~/.bashrc` or `~/.zshrc`:
106
+
107
+ ```bash
108
+ # Ctrl+G to select and navigate to worktree
109
+ bind '"\C-g":"cd \$(arashi list | fzf)\n"' # Bash
110
+ bindkey -s '^g' 'cd $(arashi list | fzf)\n' # Zsh
111
+ ```
112
+
113
+ Press `Ctrl+G` from anywhere to fuzzy-find and jump to a worktree.
114
+
115
+ #### Fish
116
+
117
+ Add to your `~/.config/fish/config.fish`:
118
+
119
+ ```fish
120
+ # Ctrl+G to select and navigate to worktree
121
+ function __arashi_worktree_jump
122
+ set -l worktree (arashi list | fzf)
123
+ and cd $worktree
124
+ commandline -f repaint
125
+ end
126
+ bind \cg __arashi_worktree_jump
127
+ ```
128
+
129
+ ### Advanced: tmux Session Management
130
+
131
+ Create or switch to a tmux session for a worktree:
132
+
133
+ ```bash
134
+ # Function to create/attach tmux session for worktree
135
+ arashi-tmux() {
136
+ local worktree=$(arashi list | fzf)
137
+ if [ -n "$worktree" ]; then
138
+ # Create session name from last path component
139
+ local session_name=$(basename "$worktree")
140
+
141
+ # Create session if it doesn't exist
142
+ if ! tmux has-session -t "$session_name" 2>/dev/null; then
143
+ tmux new-session -d -s "$session_name" -c "$worktree"
144
+ fi
145
+
146
+ # Switch to or attach session
147
+ if [ -n "$TMUX" ]; then
148
+ tmux switch-client -t "$session_name"
149
+ else
150
+ tmux attach-session -t "$session_name"
151
+ fi
152
+ fi
153
+ }
154
+
155
+ # Bind to Ctrl+G
156
+ bind '"\C-g":"arashi-tmux\n"' # Bash
157
+ bindkey -s '^g' 'arashi-tmux\n' # Zsh
158
+ ```
159
+
160
+ **What this does:**
161
+ 1. Fuzzy-find a worktree with fzf
162
+ 2. Create a named tmux session for that worktree (if needed)
163
+ 3. Switch to the session, preserving your current context
164
+
165
+ ### Simplified: Using sesh
166
+
167
+ [sesh](https://github.com/joshmedeski/sesh) is a smart session manager for tmux. Integrate arashi with sesh for the ultimate workflow:
168
+
169
+ #### Setup
170
+
171
+ ```bash
172
+ # Install sesh
173
+ brew install joshmedeski/sesh/sesh
174
+
175
+ # Add arashi as a sesh source
176
+ # ~/.config/sesh/sesh.toml
177
+ [sources]
178
+ arashi = "arashi list"
179
+ ```
180
+
181
+ #### Usage
182
+
183
+ ```bash
184
+ # Select from all sessions + arashi worktrees
185
+ sesh connect $(sesh list | fzf)
186
+
187
+ # Or create a keybinding (Ctrl+A)
188
+ bind '"\C-a":"sesh connect \$(sesh list | fzf)\n"'
189
+ ```
190
+
191
+ **Benefits of sesh:**
192
+ - Unified list of existing tmux sessions + arashi worktrees
193
+ - Smart session naming and path handling
194
+ - Automatic tmux session creation
195
+ - Works seamlessly with zoxide and other tools
196
+
197
+ ### Fish + tmux Integration
198
+
199
+ For Fish shell users, here's a complete solution:
200
+
201
+ ```fish
202
+ # ~/.config/fish/functions/arashi_session.fish
203
+ function arashi_session
204
+ set -l worktree (arashi list | fzf \
205
+ --preview 'cd {} && git status' \
206
+ --preview-window=right:60% \
207
+ --height=80%)
208
+
209
+ if test -n "$worktree"
210
+ set -l session_name (basename $worktree)
211
+
212
+ if not tmux has-session -t $session_name 2>/dev/null
213
+ tmux new-session -d -s $session_name -c $worktree
214
+ end
215
+
216
+ if set -q TMUX
217
+ tmux switch-client -t $session_name
218
+ else
219
+ tmux attach-session -t $session_name
220
+ end
221
+ end
222
+ end
223
+
224
+ # Bind to Ctrl+G
225
+ bind \cg arashi_session
226
+ ```
227
+
228
+ This includes:
229
+ - Live git status preview in fzf
230
+ - Automatic session creation with smart naming
231
+ - Works both inside and outside tmux
232
+
233
+ ### Comparison Table
234
+
235
+ | Method | Setup Complexity | Features | Best For |
236
+ |--------|-----------------|----------|----------|
237
+ | **Basic fzf** | Low | Quick navigation | Simple cd workflows |
238
+ | **tmux function** | Medium | Session management | Multi-project work |
239
+ | **sesh** | Low-Medium | Unified session list | Power users with multiple sources |
240
+
241
+ ### Tips
242
+
243
+ - **Preview window:** Add `--preview 'cd {} && git status'` to fzf for live status
244
+ - **Layout:** Try `--preview-window=right:60%` for side-by-side preview
245
+ - **Height:** Use `--height=80%` to avoid fullscreen fzf
246
+ - **Multi-select:** Add `--multi` to fzf for batch operations
247
+
248
+ ### Example Workflow
249
+
250
+ ```bash
251
+ # Morning routine:
252
+ 1. Press Ctrl+G
253
+ 2. Type "feature" to filter worktrees
254
+ 3. Select your feature branch worktree
255
+ 4. tmux session is created/attached
256
+ 5. Start coding immediately!
257
+
258
+ # No more:
259
+ cd ~/projects/repo
260
+ cd ../feature-worktree
261
+ tmux new -s feature-branch
262
+ cd ~/projects/repo/feature-worktree
263
+ ```
264
+
265
+ ## Development
266
+
267
+ ### Prerequisites
268
+
269
+ - [Bun](https://bun.sh/) >= 1.3.0 (for development)
270
+ - Node.js >= 18.0.0 (for npm installation)
271
+
272
+ ### Setup
273
+
274
+ ```bash
275
+ # Clone the repository
276
+ git clone https://github.com/corwinm/arashi.git
277
+ cd arashi
278
+
279
+ # Install dependencies
280
+ bun install
281
+
282
+ # Run in development mode
283
+ bun run dev
284
+
285
+ # Build single-file executable
286
+ bun run build
287
+
288
+ # Build for all platforms
289
+ bun run build:all
290
+
291
+ # Run tests (coming soon)
292
+ bun test
293
+
294
+ # Type check
295
+ bun run lint
296
+ ```
297
+
298
+ ### Contributing
299
+
300
+ We welcome contributions! Please see our [Specifications Repository](https://github.com/corwinm/arashi-arashi) for:
301
+ - [Design Document](https://github.com/corwinm/arashi-arashi/tree/main/setup/.specify/memory/design.md) - Feature roadmap and technical design
302
+ - [Contributing Guide](https://github.com/corwinm/arashi-arashi/blob/main/setup/CONTRIBUTING.md) - Specs-first development workflow
303
+
304
+ **Quick Summary:**
305
+ 1. Specs are created in the [arashi-arashi repository](https://github.com/corwinm/arashi-arashi) first
306
+ 2. Implementation happens in this repository
307
+ 3. Use conventional commits
308
+ 4. All PRs require review
309
+ 5. Squash merge with conventional commit message
310
+
311
+ **Commit Message Format:**
312
+ We use [Conventional Commits](https://www.conventionalcommits.org/):
313
+ ```
314
+ feat: add interactive mode for repo selection
315
+ fix: handle worktrees with uncommitted changes
316
+ docs: update installation instructions
317
+ ```
318
+
319
+ ## Architecture
320
+
321
+ Arashi is built with:
322
+ - **Runtime:** Bun (single-file executable)
323
+ - **Language:** TypeScript
324
+ - **CLI Framework:** Commander.js
325
+ - **User Prompts:** @inquirer/prompts
326
+
327
+ ## Roadmap
328
+
329
+ See the [Design Document](https://github.com/corwinm/arashi-arashi/tree/main/setup/.specify/memory/design.md) in the specs repository for the complete feature roadmap organized by implementation phases.
330
+
331
+ ### Current Phase: Foundation (Phase 1)
332
+ - [x] Project setup and structure
333
+ - [x] Type definitions
334
+ - [ ] Utility libraries (git, config, filesystem, logger, prompts)
335
+
336
+ ### Next Phase: Core Commands (Phase 2)
337
+ - [ ] `init` command
338
+ - [ ] `add` command
339
+ - [ ] `create` command
340
+
341
+ ## Why "Arashi"?
342
+
343
+ 嵐 (Arashi) means "storm" in Japanese. This tool aims to be the calm center - the eye of the storm - that brings order to the chaos of managing multiple repositories and worktrees.
344
+
345
+ ## License
346
+
347
+ MIT
348
+
349
+ ---
350
+
351
+ **Note:** This project is under active development. Features and APIs may change.
package/bin/arashi ADDED
@@ -0,0 +1,42 @@
1
+ #!/bin/bash
2
+ # Wrapper for arashi to fix fzf compatibility
3
+ # Bun's compiled executables don't properly close stdin, which blocks fzf
4
+ # from accessing /dev/tty for keyboard input. This wrapper closes stdin (0<&-)
5
+ # before executing the binary.
6
+
7
+ # Resolve the actual script path, following symlinks
8
+ SCRIPT_SOURCE="${BASH_SOURCE[0]}"
9
+ while [ -L "$SCRIPT_SOURCE" ]; do
10
+ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
11
+ SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")"
12
+ [[ "$SCRIPT_SOURCE" != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE"
13
+ done
14
+ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
15
+ BINARY="$SCRIPT_DIR/arashi.bin"
16
+
17
+ # Use platform-specific binary if main binary doesn't exist
18
+ if [ ! -f "$BINARY" ]; then
19
+ PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
20
+ ARCH=$(uname -m)
21
+
22
+ case "$PLATFORM-$ARCH" in
23
+ darwin-arm64)
24
+ BINARY="$SCRIPT_DIR/arashi-macos-arm64"
25
+ ;;
26
+ linux-x86_64)
27
+ BINARY="$SCRIPT_DIR/arashi-linux-x64"
28
+ ;;
29
+ *)
30
+ echo "Error: Unsupported platform $PLATFORM-$ARCH" >&2
31
+ exit 1
32
+ ;;
33
+ esac
34
+ fi
35
+
36
+ if [ ! -f "$BINARY" ]; then
37
+ echo "Error: arashi binary not found at $BINARY" >&2
38
+ exit 1
39
+ fi
40
+
41
+ # Execute with stdin closed (0<&-) for fzf compatibility
42
+ exec "$BINARY" "$@" 0<&-
package/bin/arashi.bat ADDED
@@ -0,0 +1,22 @@
1
+ @echo off
2
+ REM Wrapper for arashi.exe to support piping to tools like fzf on Windows
3
+ REM This closes stdin before executing the binary
4
+
5
+ REM Get the directory where this script is located
6
+ set "SCRIPT_DIR=%~dp0"
7
+ set "BINARY=%SCRIPT_DIR%arashi.bin.exe"
8
+
9
+ REM Use platform-specific binary if main binary doesn't exist
10
+ if not exist "%BINARY%" (
11
+ set "BINARY=%SCRIPT_DIR%arashi-windows-x64.exe"
12
+ )
13
+
14
+ REM Check if binary exists
15
+ if not exist "%BINARY%" (
16
+ echo Error: arashi binary not found at %BINARY% 1>&2
17
+ exit /b 1
18
+ )
19
+
20
+ REM Execute the binary with stdin closed
21
+ REM In Windows, we use <NUL to close/redirect stdin
22
+ "%BINARY%" %* <NUL
package/bin/arashi.ps1 ADDED
@@ -0,0 +1,21 @@
1
+ # PowerShell wrapper for arashi.exe to support piping to tools like fzf
2
+ # This closes stdin before executing the binary
3
+
4
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
5
+ $Binary = Join-Path $ScriptDir "arashi.bin.exe"
6
+
7
+ # Use platform-specific binary if main binary doesn't exist
8
+ if (-not (Test-Path $Binary)) {
9
+ $Binary = Join-Path $ScriptDir "arashi-windows-x64.exe"
10
+ }
11
+
12
+ # Check if binary exists
13
+ if (-not (Test-Path $Binary)) {
14
+ Write-Error "Error: arashi binary not found at $Binary"
15
+ exit 1
16
+ }
17
+
18
+ # PowerShell way to close stdin and execute
19
+ # We redirect stdin from $null which effectively closes it
20
+ $process = Start-Process -FilePath $Binary -ArgumentList $args -NoNewWindow -Wait -PassThru -RedirectStandardInput $null
21
+ exit $process.ExitCode
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "arashi",
3
+ "version": "1.1.0",
4
+ "description": "Git worktree manager for meta-repositories - The eye of the storm for your development workflow",
5
+ "type": "module",
6
+ "bin": {
7
+ "arashi": "./bin/arashi"
8
+ },
9
+ "files": [
10
+ "bin/arashi",
11
+ "bin/arashi.bat",
12
+ "bin/arashi.ps1",
13
+ "scripts/postinstall.js",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "os": [
18
+ "darwin",
19
+ "linux",
20
+ "win32"
21
+ ],
22
+ "cpu": [
23
+ "x64",
24
+ "arm64"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "scripts": {
30
+ "dev": "bun run src/index.ts",
31
+ "build": "bun build src/index.ts --compile --minify --sourcemap --outfile bin/arashi.bin",
32
+ "build:all": "bun run build:mac && bun run build:linux && bun run build:windows",
33
+ "build:mac": "bun build src/index.ts --compile --target=bun-darwin-arm64 --outfile bin/arashi-macos-arm64",
34
+ "build:linux": "bun build src/index.ts --compile --target=bun-linux-x64 --outfile bin/arashi-linux-x64",
35
+ "build:windows": "bun build src/index.ts --compile --target=bun-windows-x64 --outfile bin/arashi-windows-x64.exe",
36
+ "test": "bun test",
37
+ "lint": "tsc --noEmit",
38
+ "postinstall": "node scripts/postinstall.js"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/corwinm/arashi.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/corwinm/arashi/issues"
46
+ },
47
+ "homepage": "https://github.com/corwinm/arashi#readme",
48
+ "keywords": [
49
+ "git",
50
+ "worktree",
51
+ "meta-repo",
52
+ "monorepo",
53
+ "cli",
54
+ "development",
55
+ "git-worktree",
56
+ "multi-repo",
57
+ "development-tools"
58
+ ],
59
+ "author": "",
60
+ "license": "MIT",
61
+ "devDependencies": {
62
+ "@inquirer/prompts": "^7.2.0",
63
+ "@semantic-release/changelog": "^6.0.3",
64
+ "@semantic-release/git": "^10.0.1",
65
+ "@types/bun": "latest",
66
+ "bun-types": "latest",
67
+ "chalk": "^5.3.0",
68
+ "commander": "^12.1.0",
69
+ "conventional-changelog-conventionalcommits": "^8.0.0",
70
+ "js-yaml": "^4.1.1",
71
+ "ora": "^8.1.1",
72
+ "semantic-release": "^24.2.0",
73
+ "typescript": "^5.9.3"
74
+ }
75
+ }
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-install script to download the platform-specific arashi binary from GitHub releases
5
+ * This keeps the npm package size small while providing pre-compiled binaries
6
+ */
7
+
8
+ import { createWriteStream, chmodSync } from "node:fs";
9
+ import { mkdir, access, constants } from "node:fs/promises";
10
+ import { get } from "node:https";
11
+ import { join, dirname } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+
17
+ const PACKAGE_NAME = "arashi";
18
+ const GITHUB_REPO = "corwinm/arashi";
19
+
20
+ // Determine platform and binary name
21
+ function getPlatformInfo() {
22
+ const platform = process.platform;
23
+ const arch = process.arch;
24
+
25
+ let binaryName;
26
+ if (platform === "darwin" && arch === "arm64") {
27
+ binaryName = `${PACKAGE_NAME}-macos-arm64`;
28
+ } else if (platform === "linux" && arch === "x64") {
29
+ binaryName = `${PACKAGE_NAME}-linux-x64`;
30
+ } else if (platform === "win32" && arch === "x64") {
31
+ binaryName = `${PACKAGE_NAME}-windows-x64.exe`;
32
+ } else {
33
+ throw new Error(
34
+ `Unsupported platform: ${platform}-${arch}. Please build from source or file an issue at https://github.com/${GITHUB_REPO}/issues`
35
+ );
36
+ }
37
+
38
+ return { binaryName, isWindows: platform === "win32" };
39
+ }
40
+
41
+ // Download file from URL
42
+ function downloadFile(url, dest) {
43
+ return new Promise((resolve, reject) => {
44
+ console.log(`Downloading ${url}...`);
45
+
46
+ const file = createWriteStream(dest);
47
+ const request = get(url, (response) => {
48
+ // Handle redirects
49
+ if (
50
+ response.statusCode === 301 ||
51
+ response.statusCode === 302 ||
52
+ response.statusCode === 307
53
+ ) {
54
+ file.close();
55
+ downloadFile(response.headers.location, dest)
56
+ .then(resolve)
57
+ .catch(reject);
58
+ return;
59
+ }
60
+
61
+ if (response.statusCode !== 200) {
62
+ file.close();
63
+ reject(
64
+ new Error(
65
+ `Failed to download: ${response.statusCode} ${response.statusMessage}`
66
+ )
67
+ );
68
+ return;
69
+ }
70
+
71
+ response.pipe(file);
72
+
73
+ file.on("finish", () => {
74
+ file.close(resolve);
75
+ });
76
+ });
77
+
78
+ request.on("error", (err) => {
79
+ file.close();
80
+ reject(err);
81
+ });
82
+
83
+ file.on("error", (err) => {
84
+ file.close();
85
+ reject(err);
86
+ });
87
+ });
88
+ }
89
+
90
+ // Main installation logic
91
+ async function install() {
92
+ try {
93
+ // Skip postinstall in development (when installing from the repo)
94
+ // Check if we're in development by looking for src/ directory
95
+ const srcDir = join(__dirname, "..", "src");
96
+ try {
97
+ await access(srcDir, constants.F_OK);
98
+ console.log("✓ Development environment detected, skipping binary download");
99
+ console.log(" Run 'bun run build:all' to build binaries locally");
100
+ return;
101
+ } catch {
102
+ // Not in development, continue with download
103
+ }
104
+
105
+ // Get version from package.json
106
+ const packageJsonPath = join(__dirname, "..", "package.json");
107
+ const { readFile } = await import("node:fs/promises");
108
+ const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
109
+ const { version } = packageJson;
110
+
111
+ const { binaryName, isWindows } = getPlatformInfo();
112
+ const binDir = join(__dirname, "..", "bin");
113
+ const binaryPath = join(binDir, binaryName);
114
+
115
+ // Check if binary already exists
116
+ try {
117
+ await access(binaryPath, constants.F_OK);
118
+ console.log(`✓ Binary already exists at ${binaryPath}`);
119
+ return;
120
+ } catch {
121
+ // Binary doesn't exist, continue with download
122
+ }
123
+
124
+ // Ensure bin directory exists
125
+ await mkdir(binDir, { recursive: true });
126
+
127
+ // Download binary from GitHub releases
128
+ const downloadUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${version}/${binaryName}`;
129
+
130
+ await downloadFile(downloadUrl, binaryPath);
131
+
132
+ // Make binary executable (Unix-like systems)
133
+ if (!isWindows) {
134
+ chmodSync(binaryPath, 0o755);
135
+ }
136
+
137
+ console.log(`✓ Successfully installed ${PACKAGE_NAME} v${version}`);
138
+ console.log(` Binary location: ${binaryPath}`);
139
+ } catch (error) {
140
+ console.error(`✗ Failed to install ${PACKAGE_NAME}:`, error.message);
141
+ console.error(
142
+ `\nYou can manually download binaries from: https://github.com/${GITHUB_REPO}/releases`
143
+ );
144
+ process.exit(1);
145
+ }
146
+ }
147
+
148
+ install();