From 2a8e24f1442784913f99f0e3edf697e1795ce5ea Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sun, 1 Nov 2026 22:42:14 +0700 Subject: [PATCH] The macOS app ships craft-anything-cli beside its executable The DMG's app had only craft-anything, so the app couldn't start its MCP server and every Claude Code build failed with no tools (#91, #96). The CLI is now copied into Contents/MacOS, signed like its zip, and run from the finished DMG before release. --- docs/pitfalls.md | 4 ++++ docs/releasing.md | 3 ++- packaging/macos/package.sh | 14 +++++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/pitfalls.md b/docs/pitfalls.md index 9bbdcf55..b77b7a36 100644 --- a/docs/pitfalls.md +++ b/docs/pitfalls.md @@ -115,6 +115,10 @@ after a live run check that the command returned and nothing it started is still was copied as `cli-r25.exe`; the CLI finds itself by name (`craft-anything-cli`) to start the builder's MCP server, so Claude Code saw no tools and stopped. Copy it under its own name into a folder of its own. +It happened again in a release: the macOS app bundle had only `craft-anything`, with the CLI in +a separate zip, so every Claude Code build from the 0.2.0 DMG failed the same way (#91). Every +package that ships the app ships the CLI beside its executable, and the packaging script runs +the CLI from the finished package before it's published. **A Windows path with forward slashes read as nothing.** rtl_433 decoded a recording in the shell but found no messages, and exited 0, when the test passed `C:/…/x.cu8`; it only reads Windows diff --git a/docs/releasing.md b/docs/releasing.md index 68930027..d90f997f 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -41,7 +41,8 @@ Plus `SHA256SUMS.txt`. scheme on any platform. It appears in Windows' "Open with" list and accepts paths on the command line. Projects (`*.cany`) are folders. - **The macOS executable** is `Craft Anything.app/Contents/MacOS/craft-anything`. Only the bundle - carries the display name. + carries the display name. `craft-anything-cli` sits beside it, as it does in the Windows zip: the + app starts it as the coding agents' MCP server, so an app without it can't build (#91). - **Windows portable mode:** the portable zip ships `portable.txt`. While it sits next to the exe, settings live in `CraftAnythingData\` (`crates/engine/src/settings.rs`). - **Flatpak** grants `--share=network` (AI backends, engine downloads) and `--filesystem=home:ro` diff --git a/packaging/macos/package.sh b/packaging/macos/package.sh index 3f587eb3..730ffac4 100755 --- a/packaging/macos/package.sh +++ b/packaging/macos/package.sh @@ -106,6 +106,9 @@ echo "==> assembling $APP" mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" # The executable keeps the machine name (CFBundleExecutable); the bundle carries the display name. cp "$WORK/bin/craft-anything" "$APP/Contents/MacOS/craft-anything" +# The CLI goes beside it: the app starts it as the MCP server its coding agents use, and finds it +# next to its own executable (`self_cli_path`). Without it every Claude Code build fails (#91). +if [ "$HAS_CLI" = 1 ]; then cp "$WORK/bin/craft-anything-cli" "$APP/Contents/MacOS/craft-anything-cli"; fi cp "$ICNS" "$APP/Contents/Resources/craft-anything.icns" # Licences of the embedded fonts (assets/fonts, OFL-1.1). mkdir -p "$APP/Contents/Resources/Licenses" @@ -117,7 +120,11 @@ plutil -lint "$APP/Contents/Info.plist" printf 'APPL????' >"$APP/Contents/PkgInfo" # Sign inside-out: nested code first, then the bundle itself (no --deep on the final signature). -# Today the only nested code is the main executable; frameworks/helpers would be signed here too. +# The nested code is the main executable and the CLI; frameworks/helpers would be signed here too. +# The CLI keeps the identifier its zip has. +if [ "$HAS_CLI" = 1 ]; then + sign --options runtime --identifier ai.storyteller.craft-anything-cli "$APP/Contents/MacOS/craft-anything-cli" +fi sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP/Contents/MacOS/craft-anything" sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP" codesign --verify --strict --deep --verbose=2 "$APP" @@ -172,6 +179,11 @@ if ! codesign --verify --strict --deep --verbose=2 "$MOUNT/Craft Anything.app"; hdiutil_retry detach detach "$MOUNT" >/dev/null || true exit 1 fi +if [ "$HAS_CLI" = 1 ] && ! "$MOUNT/Craft Anything.app/Contents/MacOS/craft-anything-cli" --version; then + echo "error: the app in the DMG has no working craft-anything-cli beside its executable" >&2 + hdiutil_retry detach detach "$MOUNT" >/dev/null || true + exit 1 +fi hdiutil_retry detach detach "$MOUNT" >/dev/null if [ "$NOTARIZE" = 1 ]; then notarize "$DMG"