Skip to content

Build

Contributor recipes for building Bob Mac Capture. Install, signing identity, updates, and uninstall stay in Install. Architecture boundaries are in Architecture. CI gates are in CI.

Recipes

just format-lint
just build
just test
just bundle

On a host without Xcode, only CaptureCore, RefsCore, and refs-rank build; just portable-check lints every Swift file and builds and tests those targets, but cannot type-check the BobMacCapture* targets.

just typecheck-tests type-checks all test targets on a Mac with only Command Line Tools.

just bundle creates .build/bundle/Bob Mac Capture.app and signs it with the ad-hoc identity -, which is the right default for agent scratch builds. just install instead resolves its identity: an explicit --identity or CODESIGN_IDENTITY wins (including -), otherwise it signs with the stable "Bob Mac Capture Local" identity when the login keychain holds it, and falls back to ad-hoc with a loud warning:

just install ~/Applications
just install ~/Applications "Apple Development: Name (TEAMID)"

just install is the complete update for the selected target: it restarts that installed copy if it was already running, and leaves it stopped otherwise. See Install.

Ad-hoc signatures are useful for local development, but notification permissions, Accessibility grants, and launch-at-login trust are tied to the installed signed bundle. Reinstalling with a new or expired certificate can require reauthorizing those system permissions.

just signing-check runs the identity check without building. just signing-identity creates the stable local signing identity from a GUI Terminal.

Toolchain selection

macOS 26 with Command Line Tools for Xcode 26+ or Xcode 26+. SwiftPM from the selected Apple toolchain. justfile, Scripts/bundle.sh, and CI all route Swift invocations through Scripts/xcode-swift.sh, which resolves swift via xcrun from DEVELOPER_DIR or xcode-select --print-path rather than trusting a bare swift on PATH. This accepts either /Library/Developer/CommandLineTools or a full Xcode developer directory when the selected tools provide a macOS 26+ SDK and Apple Swift executable. It also keeps a Swift.org / Swiftly installation, or any other shadowing swift, from compiling ordinary targets while swift test later fails at import XCTest. Compare what's actually selected:

command -v swift; swift --version           # whatever is first on PATH
./Scripts/xcode-swift.sh --version           # what build/test/bundle actually use

If the two differ, ./Scripts/xcode-swift.sh --version fails, or import XCTest fails to compile, update or select matching Apple developer tools rather than migrating tests off XCTest:

sudo xcode-select --switch /Library/Developer/CommandLineTools
# or:
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
# or, scoped to one shell:
export DEVELOPER_DIR=/Library/Developer/CommandLineTools
# or:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

A swift test failure with no such module 'XCTest' is this toolchain mismatch.

The menu-bar mark is drawn in code (Sources/BobMacCapture/StatusItemGlyph.swift) as a template image. User-visible states are in Diagnostics. To eyeball the real AppKit rendering:

BOB_MAC_CAPTURE_RENDER_DIR=… ./Scripts/xcode-swift.sh test --filter StatusItemGlyphDesignTests

Inspect the PNGs it writes: each state at 1x, 2x, and 3x on light, dark, and accent backgrounds, 8x enlargements, and a pulse filmstrip. CI uploads the directory as the render-fixtures artifact; see CI.

Tested rolling snapshot bob-cli 41afa14 bob-mac-capture 556bb67 bob-plugins af1e691 Built 2026-10-24T22:34:13Z (zensical) build.json