skyhook is a headless macOS CLI that reads this Mac's current location with CoreLocation and prints it.
skyhook --locationExpected output (TUI mode):
Location
────────────────────────
Latitude 40.78286°
Longitude -73.96536°
Accuracy 65 m
Timestamp 2026-05-30T10:00:55.195Z
Or in JSON mode (--json):
{"accuracy":65,"latitude":40.78286,"longitude":-73.96536,"timestamp":"2026-05-30T08:15:27.123Z"}git clone <repo>
cd skyhook
make install # build + bundle + install to ~/.local/bin/skyhook
export PATH="$HOME/.local/bin:$PATH" # add to ~/.zshrc once
skyhook --request-permissions # grant location permission (dialog appears)
skyhook --location # print locationIf you don't want to install skyhook into PATH, you can build and run directly
from the .app bundle in the project directory:
# Build, bundle, and sign
make sign-bundle
# Run directly
./skyhook.app/Contents/MacOS/skyhook --request-permissions
./skyhook.app/Contents/MacOS/skyhook --location
# Or using the convenience wrapper
./bin/skyhook --request-permissions
./bin/skyhook --location
# Or using make (rebuilds if needed)
make run ARGS="--request-permissions"
make run ARGS="--location"- macOS 13+
- Swift 5.9+ / Swift Package Manager
- Location Services enabled in macOS
- No Xcode GUI and no external dependencies
Built with Apple Swift 6.1 on arm64 macOS 15.
| Command | Output |
|---|---|
skyhook |
TUI box with location |
skyhook --location / -l / -loc |
TUI box with location |
skyhook --json / -j |
JSON location (error as JSON too) |
skyhook --request-permissions / -rp |
Grant permission (stdout: JSON status) |
skyhook --help / -h |
Usage info |
| Target | Description |
|---|---|
make run ARGS="..." |
Build → bundle → sign → execute |
make install |
Build → bundle → sign → link to ~/.local/bin/skyhook |
make sign-bundle |
Build → bundle → sign only |
make sign |
Sign standalone binary (no CoreLocation) |
make run-direct ARGS="..." |
Run standalone binary (no CoreLocation) |
Create a .env file at the project root to fake coordinates. Useful for
testing without real GPS or a location fix:
cp .env.example .env
# edit .env with your test coordinates
skyhook --location.env is git-ignored. See .env.example for the variables.
skyhook --request-permissions triggers the macOS permission dialog. Grants persist across rebuilds because macOS matches by bundle ID (dev.local.skyhook), not code hash.
macOS does not show location permission dialogs for standalone CLI binaries. The binary is wrapped in a minimal .app bundle (skyhook.app/Contents/MacOS/skyhook) so CoreLocation prompts work correctly.
CLLocationManager lives on a dedicated thread with an active CFRunLoop — the @main async entrypoint doesn't provide the run loop that CLLocationManager delegate callbacks require.
Hexagonal (ports & adapters):
Sources/Domain/Location.swift— entitySources/Domain/LocationRepository.swift— portSources/Application/GetLocationUseCase.swift— use caseSources/Infrastructure/CoreLocationRepository.swift— CoreLocation adapterSources/Output/JSONLocationPresenter.swift— JSON output portSources/Output/TUILocationPresenter.swift— TUI output portSources/Skyhook.swift— CLI entrypoint
- Current: CLI mode that prints location and exits.
- Later: HTTP server mode on
localhost:PORTexposingGET /locationusingNetwork.framework.