Last active
April 8, 2026 02:54
-
-
Save Hona/090bf930c95dea76af347b326a8f0e92 to your computer and use it in GitHub Desktop.
dev-opencode.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env pwsh | |
| # Development workflow: build opentui -> copy into opencode -> run opencode dev server | |
| # | |
| # This script does NOT use `bun link` (corrupts global state) or symlinks (breaks module resolution). | |
| # It uses a dedicated Bun cache for this workflow and replaces package directories instead of | |
| # overwriting hardlinked files in place. | |
| # | |
| # Usage: | |
| # .\dev-opencode.ps1 # Full flow: build, copy, run dev server | |
| # .\dev-opencode.ps1 -NoDev # Build and copy only, don't start dev server | |
| # .\dev-opencode.ps1 -Revert # Reinstall npm packages (removes local changes) | |
| param( | |
| [switch]$NoDev, | |
| [switch]$Revert | |
| ) | |
| $ErrorActionPreference = "Continue" | |
| $root = Split-Path -Parent $MyInvocation.MyCommand.Path | |
| $opentuiDir = Join-Path $root "opentui" | |
| $opencodeDir = Join-Path $root "opencode" | |
| $devCacheDir = Join-Path $opencodeDir ".bun-dev-cache" | |
| $env:BUN_INSTALL_CACHE_DIR = $devCacheDir | |
| function Resolve-PackagePath { | |
| param( | |
| [string]$LinkPath | |
| ) | |
| if (-not (Test-Path $LinkPath)) { | |
| return $null | |
| } | |
| $item = Get-Item -LiteralPath $LinkPath -Force | |
| $target = $item.Target | |
| if ($target -is [array]) { | |
| $target = $target[0] | |
| } | |
| if ($item.LinkType -eq "SymbolicLink" -and $target) { | |
| return [System.IO.Path]::GetFullPath((Join-Path (Split-Path -Parent $item.FullName) $target)) | |
| } | |
| return (Resolve-Path -LiteralPath $LinkPath).Path | |
| } | |
| function Get-PackageVersion { | |
| param( | |
| [string]$PackagePath | |
| ) | |
| if (-not $PackagePath) { | |
| return $null | |
| } | |
| $packageJson = Join-Path $PackagePath "package.json" | |
| if (-not (Test-Path $packageJson)) { | |
| return $null | |
| } | |
| return (Get-Content -Path $packageJson -Raw | ConvertFrom-Json).version | |
| } | |
| function Get-StorePackagePath { | |
| param( | |
| [string]$Store, | |
| [string]$Pattern, | |
| [string]$PackagePath | |
| ) | |
| $dir = Get-ChildItem -Path $Store -Directory -Filter $Pattern -ErrorAction SilentlyContinue | | |
| Select-Object -First 1 | |
| if (-not $dir) { | |
| return $null | |
| } | |
| return Join-Path $dir.FullName $PackagePath | |
| } | |
| function Replace-PackagePath { | |
| param( | |
| [string]$Source, | |
| [string]$Target | |
| ) | |
| if (-not (Test-Path $Source)) { | |
| throw "Missing source: $Source" | |
| } | |
| if (Test-Path $Target) { | |
| Remove-Item -Path $Target -Recurse -Force | |
| } | |
| New-Item -ItemType Directory -Path $Target -Force | Out-Null | |
| Copy-Item -Path (Join-Path $Source "*") -Destination $Target -Recurse -Force | |
| } | |
| function Remove-PackagePath { | |
| param([string]$Target) | |
| if (-not $Target -or -not (Test-Path $Target)) { | |
| return $false | |
| } | |
| Remove-Item -Path $Target -Recurse -Force | |
| return $true | |
| } | |
| Write-Host "OpenCode Development Workflow" -ForegroundColor Cyan | |
| Write-Host "=============================" -ForegroundColor Cyan | |
| Write-Host "Using Bun cache: $devCacheDir" -ForegroundColor DarkGray | |
| Write-Host "" | |
| # Revert mode: remove the overlaid package dirs, then reinstall them from the dedicated cache | |
| if ($Revert) { | |
| Write-Host "Reverting local opentui overlays..." -ForegroundColor Yellow | |
| $bunStore = Join-Path $opencodeDir "node_modules\.bun" | |
| $packageNodeModules = Join-Path $opencodeDir "packages\opencode\node_modules" | |
| $coreTarget = Resolve-PackagePath (Join-Path $packageNodeModules "@opentui\core") | |
| $coreVersion = Get-PackageVersion $coreTarget | |
| $targets = @( | |
| $coreTarget, | |
| $(Get-StorePackagePath $bunStore "@opentui+core-win32-x64@$coreVersion*" "node_modules\@opentui\core-win32-x64"), | |
| $(Resolve-PackagePath (Join-Path $packageNodeModules "@opentui\solid")) | |
| ) | |
| foreach ($target in $targets) { | |
| if (Remove-PackagePath $target) { | |
| Write-Host " Removed $target" -ForegroundColor Gray | |
| } | |
| } | |
| Write-Host " Reinstalling restored packages..." -ForegroundColor Gray | |
| Push-Location $opencodeDir | |
| bun install | |
| Pop-Location | |
| Write-Host "" | |
| Write-Host "Done! Reverted to npm packages." -ForegroundColor Green | |
| exit 0 | |
| } | |
| # Step 1: Install opencode dependencies first | |
| Write-Host "Step 1: Installing opencode dependencies..." -ForegroundColor Yellow | |
| Push-Location $opencodeDir | |
| bun install | |
| Pop-Location | |
| # Also install .opencode dependencies if they exist (user config directory) | |
| $dotOpencode = Join-Path $opencodeDir ".opencode" | |
| if (Test-Path (Join-Path $dotOpencode "package.json")) { | |
| Write-Host " Installing .opencode plugin dependencies..." -ForegroundColor Gray | |
| Push-Location $dotOpencode | |
| bun install | |
| Pop-Location | |
| } | |
| Write-Host " Done." -ForegroundColor Green | |
| Write-Host "" | |
| # Step 2: Build opentui | |
| Write-Host "Step 2: Building opentui packages..." -ForegroundColor Yellow | |
| Write-Host " Building @opentui/core native..." -ForegroundColor Gray | |
| Push-Location (Join-Path $opentuiDir "packages\core") | |
| bun run build:native | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Error: Native build failed!" -ForegroundColor Red | |
| Pop-Location | |
| exit 1 | |
| } | |
| Write-Host " Building @opentui/core lib..." -ForegroundColor Gray | |
| bun run build:lib | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Error: Core lib build failed!" -ForegroundColor Red | |
| Pop-Location | |
| exit 1 | |
| } | |
| Pop-Location | |
| Write-Host " Building @opentui/solid..." -ForegroundColor Gray | |
| Push-Location (Join-Path $opentuiDir "packages\solid") | |
| bun run build | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Error: Solid build failed!" -ForegroundColor Red | |
| Pop-Location | |
| exit 1 | |
| } | |
| Pop-Location | |
| Write-Host " Done." -ForegroundColor Green | |
| Write-Host "" | |
| # Step 3: Replace installed package dirs with the local opentui builds | |
| Write-Host "Step 3: Copying opentui dist into bun cache..." -ForegroundColor Yellow | |
| $bunStore = Join-Path $opencodeDir "node_modules\.bun" | |
| $packageNodeModules = Join-Path $opencodeDir "packages\opencode\node_modules" | |
| # Resolve the actual installed @opentui/core path from Bun's isolated symlink | |
| $coreNpmPath = Resolve-PackagePath (Join-Path $packageNodeModules "@opentui\core") | |
| if (-not $coreNpmPath) { | |
| Write-Host "Error: Could not resolve @opentui/core from packages/opencode/node_modules" -ForegroundColor Red | |
| exit 1 | |
| } | |
| $coreVersion = Get-PackageVersion $coreNpmPath | |
| $coreDistPath = Join-Path $opentuiDir "packages\core\dist" | |
| Write-Host " Copying @opentui/core dist files..." -ForegroundColor Gray | |
| Replace-PackagePath $coreDistPath $coreNpmPath | |
| Write-Host " Copied @opentui/core" -ForegroundColor Green | |
| # Also copy native DLL for Windows (the JS code references FFI symbols that must exist in the DLL) | |
| $nativePkg = "@opentui+core-win32-x64@$coreVersion*" | |
| $nativeNpmPath = Get-StorePackagePath $bunStore $nativePkg "node_modules\@opentui\core-win32-x64" | |
| if ($nativeNpmPath) { | |
| $nativeSrcPath = Join-Path $opentuiDir "packages\core\node_modules\@opentui\core-win32-x64" | |
| if (Test-Path $nativeSrcPath) { | |
| Write-Host " Copying @opentui/core-win32-x64 native binary..." -ForegroundColor Gray | |
| Replace-PackagePath $nativeSrcPath $nativeNpmPath | |
| Write-Host " Copied native binary" -ForegroundColor Green | |
| } | |
| } | |
| # Resolve the actual installed @opentui/solid path from Bun's isolated symlink | |
| $solidNpmPath = Resolve-PackagePath (Join-Path $packageNodeModules "@opentui\solid") | |
| if (-not $solidNpmPath) { | |
| Write-Host "Error: Could not resolve @opentui/solid from packages/opencode/node_modules" -ForegroundColor Red | |
| exit 1 | |
| } | |
| $solidDistPath = Join-Path $opentuiDir "packages\solid\dist" | |
| Write-Host " Copying @opentui/solid dist files..." -ForegroundColor Gray | |
| Replace-PackagePath $solidDistPath $solidNpmPath | |
| Write-Host " Copied @opentui/solid" -ForegroundColor Green | |
| Write-Host "" | |
| # Step 4: Run dev server (unless -NoDev) | |
| if (-not $NoDev) { | |
| Write-Host "Step 4: Starting opencode dev server..." -ForegroundColor Yellow | |
| Write-Host "" | |
| Push-Location $opencodeDir | |
| bun dev | |
| Pop-Location | |
| } else { | |
| Write-Host "Step 4: Skipping dev server (-NoDev flag)" -ForegroundColor Yellow | |
| Write-Host "" | |
| Write-Host "Done! To start dev server manually:" -ForegroundColor Green | |
| Write-Host " cd $opencodeDir && bun dev" -ForegroundColor Gray | |
| Write-Host "" | |
| Write-Host "To revert to npm packages:" -ForegroundColor Gray | |
| Write-Host " .\dev-opencode.ps1 -Revert" -ForegroundColor Gray | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment