TL;DR

Why a selector (not just a switch)

OS location permissions are multi-level. Precise location is a separate OS grant too (iOS 14+ "Precise", Android "fine" vs "coarse"). The in-app selector drives the requested mode, but the OS still decides the actual grant.

Settings model

Per node device:

UI behavior:

Permissions mapping (node.permissions)

Optional. The macOS node reports location via the permissions map on node.list/node.describe; iOS/Android may omit it.

Command: location.get

Called via node.invoke, or the CLI helper:

apus nodes location get --node <idOrNameOrIp>
apus nodes location get --node <idOrNameOrIp> --accuracy precise --max-age 15000 --location-timeout 10000

Params:

{
  "timeoutMs": 10000,
  "maxAgeMs": 15000,
  "desiredAccuracy": "coarse|balanced|precise"
}

CLI flags map directly: --location-timeout -> timeoutMs, --max-age -> maxAgeMs, --accuracy -> desiredAccuracy.

Response payload:

{
  "lat": 48.20849,
  "lon": 16.37208,
  "accuracyMeters": 12.5,
  "altitudeMeters": 182.0,
  "speedMps": 0.0,
  "headingDeg": 270.0,
  "timestamp": "2026-01-03T12:34:56.000Z",
  "isPrecise": true,
  "source": "gps|wifi|cell|unknown"
}

Errors (stable codes):

Background behavior

Linux node host

The bundled Linux Node plugin adds location.get to the CLI apus node service, including headless hosts without the Linux desktop app. Location defaults to off. Enable it under the plugin entry, then restart the node service:

{
  plugins: {
    entries: {
      "linux-node": {
        config: {
          location: { enabled: true },
        },
      },
    },
  },
}

Install GeoClue2 and its where-am-i demo (geoclue-2-demo on Debian and Ubuntu). The node-service user must be allowed by the host's GeoClue policy and authorization agent.

The plugin uses where-am-i instead of a sequence of busctl calls. GeoClue ties client creation, properties, start, updates, and stop to one D-Bus client connection; the demo keeps that lifecycle together while separate busctl subprocesses do not. No npm dependency is added.

Linux maps coarse, balanced, and precise to GeoClue accuracy levels 4, 6, and 8. It validates maxAgeMs against the returned timestamp. GeoClue's demo does not expose the selected provider, so source is unknown; isPrecise is true only when reported accuracy is 100 meters or better.

Linux uses the same stable errors: LOCATION_DISABLED, LOCATION_TIMEOUT, and LOCATION_UNAVAILABLE.

Model/tooling integration

UX copy (suggested)

Related