Shows where this Mac is: street address, what's around, coordinates and time
zone. It calls CoreLocation directly through the objc2 crates, with no
third-party location tools.
$ whereami
whereami 1 Apple Park Way, Cupertino
⌂ Address 1 Apple Park Way
Cupertino CA 95014
United States
◍ Area Santa Clara · California
★ Landmark Apple Park
▦ Building 50+ businesses listed here · likely a shared office
incl. Caffè Macs · Apple Fitness Center
⌖ Around The Ring 40 m Landmark
Visitor Center Café 310 m Cafe
Apple Park Visitor Center 320 m Store
Main Street Cupertino 900 m Food market
+12 more (--json lists all)
◎ Position 37.334900, -122.009020 ±35 m
house number is approximate
◷ Time zone America/Los_Angeles UTC−7
↗ Maps Open in Apple Maps
fix just now · 2026-10-23T08:38:11ZThe example output above is illustrative. whereami keeps no history. Its only
network calls are to Apple: the address lookup and the nearby places search.
--offline skips both.
In a terminal it shows a live spinner while it locates you and looks up the
address, then the styled view above. "Open in Apple Maps" is a clickable link
in Ghostty. Colour is off with NO_COLOR or when output isn't a terminal.
whereami [--json] [--offline] [--no-nearby] [--radius METRES] [--timeout SECONDS]
whereami --status [--json]
-j, --jsonprints JSON. This is the default when stdout isn't a terminal, as withspeed.-n, --offlineprints coordinates only and skips the address and nearby lookups, which both need the network.--no-nearbyskips the nearby places lookup.-r, --radiussets how far to look for nearby places (default 150 m). MapKit returns at most 50 places, so in dense areas a larger radius doesn't reach further.-t, --timeout(default 15 s) applies to the location fix and, separately, to the address lookup. The permission prompt has its own 120 s allowance, so a first run doesn't time out while you read the dialog.--statusshows whether Location Services is on and whether whereami is authorized, without requesting anything. After a rebuild it reportsnot_determineduntil the next real run (see Rebuilds below).
{
"latitude": 37.3349, "longitude": -122.00902, "horizontal_accuracy_m": 35.0,
"timestamp": "2026-10-23T08:38:11Z",
"place": {
"address": "1 Apple Park Way\nCupertino CA 95014\nUnited States",
"name": "1 Apple Park Way",
"street": "Apple Park Way", "house_number": "1",
"neighbourhood": null, "postal_code": "95014",
"city": "Cupertino", "district": "Santa Clara", "region": "California",
"country": "United States", "country_code": "US",
"points_of_interest": ["Apple Park"],
"timezone": { "id": "America/Los_Angeles", "abbreviation": "PDT", "utc_offset_seconds": -25200 }
}
}place.addressis formatted the way addresses are written in that country, usingCNPostalAddressFormatter. Formatting an address doesn't need Contacts permission.- Missing fields are
null.place,nearbyandbuildingarenullwhen their lookup is skipped. nearbylists venues (cafés, shops, transit, landmarks and so on), nearest first, each withname,category,distance_m, coordinates,phone,urlandin_building.buildingdescribes what's listed at your exact spot:listed(count),at_least(MapKit's cap of 50 was hit),likely_shared_officeand asampleof names.- If a lookup fails, its field is
null,geocode_errorornearby_errorexplains why, and the exit code is 6.
Macs locate themselves from nearby Wi-Fi networks, typically within ±35 m. That is enough to get the street right, but the house number is only the nearest guess and can change between runs. The view adds a note when the house number is approximate, and another when accuracy is worse than 100 m.
Nearby places come from MapKit's points-of-interest search. Offices and coworking spaces list every tenant company at the same spot, and these would crowd out everything else. whereami handles this in three steps:
- It counts what's listed within 25 m. Ten or more businesses without a category is reported as "likely a shared office" in the Building row, with a few tenant names.
- Venues that are probably inside your building are tagged
in_buildingand kept out of the Around list. These are listings that share exact coordinates with others, or anything within 20 m of a shared office. - The Around list shows the 8 nearest places, at most 2 per category, with EV chargers, toilets and parking only filling leftover slots. JSON keeps everything.
Errors go to stderr: a one-line message (with a link to Location Services
settings where relevant), or {"error": "<code>", "message": "..."} in JSON
mode.
| exit | error codes |
|---|---|
| 1 | location_error |
| 2 | usage |
| 3 | denied, restricted |
| 4 | location_services_disabled |
| 5 | timeout, authorization_timeout |
| 6 | geocode_error, nearby_error: the location is still printed, but a lookup failed |
Requires the Rust toolchain and Xcode command-line tools (codesign).
make install # cargo build --release, assemble + ad-hoc sign the bundle, install
make lint # cargo clippy -D warningsThis installs:
~/Applications/whereami.app: a minimal bundle (io.sezer.whereami,LSUIElement,NSLocationUsageDescription), ad-hoc signed and registered with Launch Services.~/.local/bin/whereami: a two-lineshwrapper thatexecswhereami.app/Contents/MacOS/whereami.
Override locations with make install APP_DIR=... BIN_DIR=....
locationd identifies location clients by the calling executable, not by the
TCC "responsible process" (the terminal). When the executable lives inside a
bundle, locationd resolves it to the bundle identifier. Verified with
/usr/bin/log stream --predicate 'process == "locationd"':
- bundled binary → client
io.sezer.whereami, prompt posted forbundlepath = ~/Applications/whereami.app - bare
target/release/whereami→ client keyed by its executable path
Neither is attributed to Ghostty, so the wrapper uses plain exec rather than
open -W --stdout/--stderr. That keeps stdin/stdout, exit codes and Ctrl-C
working normally.
Ad-hoc signatures have no stable signing identity, so every make install
changes the code hash. The grant stays keyed to the bundle ID, but locationd
checks it again on the next run, which may show the prompt again.
Denial can't be simulated without changing settings. To test it yourself:
- System Settings > Privacy & Security > Location Services, switch whereami off.
whereami; echo $?. Expect{"error":"denied","message":"Location access was denied. Enable whereami in System Settings > Privacy & Security > Location Services, then run it again."}and exit 3.- Switch it back on.
To test the services-off path, turn off the main Location Services switch in
the same pane. Expect location_services_disabled and exit 4.
make uninstall # unregister from Launch Services, remove the bundle and wrapperThe permission entry is kept by locationd. To revoke it, switch whereami
off in System Settings > Privacy & Security > Location Services (or remove it
there if your macOS version offers that). tccutil doesn't manage Location
Services.
MIT