diff --git a/Casks/orca.rb b/Casks/orca.rb index 53a98c54c..6b97b27d5 100644 --- a/Casks/orca.rb +++ b/Casks/orca.rb @@ -27,6 +27,13 @@ cask "orca" do app "Orca.app" + # Why: expose the bundled `orca` CLI on PATH at install time (Homebrew symlinks + # this into its already-on-PATH bin dir). Without it, the CLI is only registered + # by the in-app "Install CLI" action, which a headless host can never trigger — + # so `orca serve` on a server would be unreachable from the shell. The shim + # resolves the real app by walking symlinks, so the Homebrew symlink works. + binary "#{appdir}/Orca.app/Contents/Resources/bin/orca" + # Why: Orca writes user data under ~/.orca (worktrees, agent state) and # Electron's standard userData directories. Zap removes everything the app # creates during normal use so `brew uninstall --zap` is a clean slate. diff --git a/Casks/orca@rc.rb b/Casks/orca@rc.rb index f3782f7db..63bc843b6 100644 --- a/Casks/orca@rc.rb +++ b/Casks/orca@rc.rb @@ -35,6 +35,13 @@ cask "orca@rc" do app "Orca.app" + # Why: expose the bundled `orca` CLI on PATH at install time (Homebrew symlinks + # this into its already-on-PATH bin dir). Without it, the CLI is only registered + # by the in-app "Install CLI" action, which a headless host can never trigger — + # so `orca serve` on a server would be unreachable from the shell. The shim + # resolves the real app by walking symlinks, so the Homebrew symlink works. + binary "#{appdir}/Orca.app/Contents/Resources/bin/orca" + # Why: Orca writes user data under ~/.orca (worktrees, agent state) and # Electron's standard userData directories. Zap removes everything the app # creates during normal use so `brew uninstall --zap` is a clean slate. diff --git a/config/electron-builder.config.cjs b/config/electron-builder.config.cjs index 68913b8ff..f6d983062 100644 --- a/config/electron-builder.config.cjs +++ b/config/electron-builder.config.cjs @@ -286,7 +286,13 @@ module.exports = { // Why: xvfb lets the bundled `orca serve` CLI run browser panes on a headless // Linux host — Chromium needs a display server even for offscreen rendering, // and serve starts Xvfb itself when present (see ensure-virtual-display.ts). - depends: ['python3', 'python3-gi', 'gir1.2-atspi-2.0', 'at-spi2-core', 'xdotool', 'xclip', 'xvfb'] + depends: ['python3', 'python3-gi', 'gir1.2-atspi-2.0', 'at-spi2-core', 'xdotool', 'xclip', 'xvfb'], + // Why: symlink the bundled CLI onto PATH at install time so `orca-ide serve` + // works on a headless host. The in-app CLI registration (CliInstaller) is + // GUI-triggered and can never run on a server, so without this the CLI is + // unreachable from the shell on exactly the hosts that need it. + afterInstall: 'resources/linux/packaging/after-install.sh', + afterRemove: 'resources/linux/packaging/after-remove.sh' }, rpm: { packageName: 'orca-ide', @@ -300,7 +306,10 @@ module.exports = { 'xdotool', 'xclip', 'xorg-x11-server-Xvfb' - ] + ], + // Why: same headless CLI-on-PATH registration as deb; rpm runs these via fpm. + afterInstall: 'resources/linux/packaging/after-install.sh', + afterRemove: 'resources/linux/packaging/after-remove.sh' }, beforeBuild: electronBuilderNativeRebuild, // Why: must be true so that electron-builder rebuilds native modules diff --git a/resources/linux/packaging/after-install.sh b/resources/linux/packaging/after-install.sh new file mode 100755 index 000000000..393bfb6a8 --- /dev/null +++ b/resources/linux/packaging/after-install.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Why: register the bundled `orca-ide` CLI on PATH at package-install time. +# The in-app "Install CLI" action (CliInstaller) can never run on a headless +# server, so without this symlink `orca serve` is unreachable from the shell on +# the exact hosts that need it most. deb/rpm both run this after unpacking. +# +# The shim resolves the real app by walking up from its own location, so a +# symlink works. We discover the install dir instead of hardcoding /opt/Orca +# because electron-builder's directory name can vary by productName sanitization. +set -e + +link="/usr/bin/orca-ide" + +for dir in /opt/Orca /opt/orca-ide /opt/orca; do + shim="$dir/resources/bin/orca-ide" + if [ -x "$shim" ]; then + # Only manage our own symlink; never clobber an unrelated /usr/bin/orca-ide. + if [ ! -e "$link" ] || [ -L "$link" ]; then + ln -sf "$shim" "$link" + fi + break + fi +done + +exit 0 diff --git a/resources/linux/packaging/after-remove.sh b/resources/linux/packaging/after-remove.sh new file mode 100755 index 000000000..0f4970246 --- /dev/null +++ b/resources/linux/packaging/after-remove.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Why: remove the PATH symlink that after-install.sh created, but only if it +# still points into an Orca install dir — never delete an unrelated +# /usr/bin/orca-ide a user or other package may own. +set -e + +link="/usr/bin/orca-ide" + +if [ -L "$link" ]; then + target="$(readlink "$link" || true)" + case "$target" in + /opt/Orca/*|/opt/orca-ide/*|/opt/orca/*) + rm -f "$link" + ;; + esac +fi + +exit 0