Skip to content

feat(npx-cli): add --mac flag to install a macOS app bundle - #3379

Open
julioflima wants to merge 2 commits into
BloopAI:mainfrom
julioflima:feat/macos-installer
Open

julioflima wants to merge 2 commits into
BloopAI:mainfrom
julioflima:feat/macos-installer

Conversation

@julioflima

@julioflima julioflima commented Apr 23, 2026 •

Copy link
Copy Markdown

Summary

Adds npx vibe-kanban --mac which installs a native macOS .app bundle to /Applications/Vibe Kanban.app. Users can pin it to the Dock and launch it without ever opening a terminal.

How it works

  1. Creates /Applications/Vibe Kanban.app with a proper Info.plist and launcher shell script
  2. Builds a full .icns icon from the bundled assets/AppIcon.png (2000×2000)
  3. Registers the app with Launch Services (Spotlight picks it up immediately)
  4. Launches the app right after install

On subsequent clicks from the Dock, the launcher:

  • Checks if the server is already running (via nc port check) and reuses the session
  • Otherwise starts npx vibe-kanban in the background — the binary handles browser opening itself

Usage

npx vibe-kanban --mac

Notes

  • macOS only — prints an error and exits on other platforms
  • Resolves npx across nvm, volta, homebrew, and system paths (no PATH issues when launched from Dock)
  • No internet required for the icon — shipped as npx-cli/assets/AppIcon.png

Note

Medium Risk
Adds a new install path that writes to /Applications and executes platform tools (sips, iconutil, lsregister, open), which can fail in varied macOS environments and affects local system state.

Overview
Adds a new npx vibe-kanban --mac flow that installs and launches a macOS .app bundle in /Applications instead of starting the app in browser/desktop mode.

The PR introduces a small macOS installer module that writes an Info.plist, installs a launcher script, and optionally generates an .icns icon from a bundled PNG before registering with Launch Services and opening the app. Build/packaging is updated to bundle .sh/.plist sources as text and to ship the new assets directory.

Reviewed by Cursor Bugbot for commit ed9f7f2. Bugbot is set up for automated code reviews on this repo. Configure here.

julioflima and others added 2 commits April 23, 2026 14:03
Adds `npx vibe-kanban --mac` which creates a native macOS .app bundle
at /Applications/Vibe Kanban.app. The app can be pinned to the Dock
and reopened without a terminal window.

- Launcher script resolves npx via nvm/volta/homebrew paths
- Reuses existing server session if the port is still listening
- The vibe-kanban binary handles browser opening itself
- Icon built from bundled 2000x2000 PNG (assets/AppIcon.png)
- Registers with Launch Services for Spotlight discovery

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ed9f7f2. Configure here.

Comment thread npx-cli/src/mac/index.ts
import infoPlist from './Info.plist';

const APP_NAME = 'Vibe Kanban';
const BUNDLED_ICON = path.join(__dirname, '../../assets', 'AppIcon.png');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bundled icon path resolves to wrong directory

High Severity

BUNDLED_ICON uses ../../assets relative to __dirname, but after esbuild bundles everything into bin/cli.js, __dirname at runtime is the bin/ directory. Two levels up from bin/ overshoots the package root entirely. The existing pattern in download.ts correctly uses path.join(__dirname, '..', 'dist') — one level up — to reach the package root. This path resolves to <parent_of_package>/assets/AppIcon.png instead of <package_root>/assets/AppIcon.png, so the icon file is never found and the .app bundle is always installed without its icon.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ed9f7f2. Configure here.

@Juanlucasbg

Copy link
Copy Markdown

Aggressive review summary — PR #3379

158-line addition to npx-cli/ adding a --mac flag that installs a Vibe Kanban.app bundle in /Applications wrapping the npx CLI as a launcher. New files: Info.plist, launcher.sh, index.ts, AppIcon.png. Verdict: clean — recommend merge with three NITs about admin-permissions, code-signing, and the Tauri-bundle collision.

What it does

npx vibe-kanban --mac writes:

  • /Applications/Vibe Kanban.app/Contents/Info.plist
  • /Applications/Vibe Kanban.app/Contents/MacOS/vibe-kanban (executable launcher script)
  • /Applications/Vibe Kanban.app/Contents/Resources/AppIcon.icns (generated from PNG via sips)

The launcher wraps npx vibe-kanban so the user gets a Spotlight-launchable .app that boots the existing browser-mode flow. Esbuild's --loader:.sh=text --loader:.plist=text inlines the static files into the bundled cli.js.

Findings

  • Structural — PASS: Filesystem layout matches Apple's bundle convention (Contents/MacOS, Contents/Resources, Contents/Info.plist). Icon generation uses sips, the macOS-built-in tool — no extra deps.
  • Adversarial — MED:
    • /Applications write permission: On macOS, /Applications is typically writable by the admin user but not by all users; for a system-managed Mac this requires sudo. The PR's mkdirSync will throw EACCES with a confusing Node stack trace. Catching this and printing a helpful message ("re-run with sudo, or set INSTALL_DIR=$HOME/Applications") would be one line of code.
    • Bundle collision with Tauri build: crates/tauri-app/ produces its own macOS .app bundle via tauri-bundler with the same display name. If both are installed, /Applications/Vibe Kanban.app is overwritten by whichever ran last. Use a different bundle name (e.g. Vibe Kanban (npx).app) or include version/source in the bundle ID.
    • Spotlight after uninstall: Removing the .app doesn't clean up Launch Services / Spotlight indexes. Doc the manual sudo /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r ... if needed.
  • Security — LOW:
    • The launcher script body isn't shown in this excerpt; ensure it doesn't eval user input or pull arbitrary code at run time. (Reviewer should cat npx-cli/src/mac/launcher.sh before merging.)
    • No code signing / notarization. First launch will hit Gatekeeper ("Vibe Kanban can't be opened because it is from an unidentified developer"). User has to right-click → Open → Confirm. Document this in the README so users don't think the install is broken.
  • Conventions — PASS: TypeScript + esbuild bundler matches the existing npx-cli build; package.json adds assets to files so the icon ships in the npm tarball.

NITs

  • Add an --uninstall companion: Nice symmetry, especially given the Gatekeeper friction.
  • Test with a stub sips (or guard for its absence): macOS Server / minimal installs may not have it.
  • The icon path BUNDLED_ICON = path.join(__dirname, '../../assets', 'AppIcon.png') assumes the bundled CJS is at bin/cli.js (so ../../assets resolves to package root). Verify this still holds after the npm publish step ships the right relative tree.

Verdict

Approve.

— Reviewed by automated single-pass review (mac install-flow; full 4-tool battery skipped — change is contained to npx-cli/, no Rust impact, the security/permissions concerns are about the macOS environment rather than the code).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants