{
  "title": "Location command (nodes)",
  "content": "* `location.get` is a node command (via `node.invoke`).\n* Off by default.\n* Settings use a selector: Off / While Using / Always.\n* Separate toggle: Precise Location.\n\n## Why a selector (not just a switch)\n\nOS permissions are multi-level. We can expose a selector in-app, but the OS still decides the actual grant.\n\n* iOS/macOS: user can choose **While Using** or **Always** in system prompts/Settings. App can request upgrade, but OS may require Settings.\n* Android: background location is a separate permission; on Android 10+ it often requires a Settings flow.\n* Precise location is a separate grant (iOS 14+ “Precise”, Android “fine” vs “coarse”).\n\nSelector in UI drives our requested mode; actual grant lives in OS settings.\n\n* `location.enabledMode`: `off | whileUsing | always`\n* `location.preciseEnabled`: bool\n\n* Selecting `whileUsing` requests foreground permission.\n* Selecting `always` first ensures `whileUsing`, then requests background (or sends user to Settings if required).\n* If OS denies requested level, revert to the highest granted level and show status.\n\n## Permissions mapping (node.permissions)\n\nOptional. macOS node reports `location` via the permissions map; iOS/Android may omit it.\n\n## Command: `location.get`\n\nCalled via `node.invoke`.\n\nErrors (stable codes):\n\n* `LOCATION_DISABLED`: selector is off.\n* `LOCATION_PERMISSION_REQUIRED`: permission missing for requested mode.\n* `LOCATION_BACKGROUND_UNAVAILABLE`: app is backgrounded but only While Using allowed.\n* `LOCATION_TIMEOUT`: no fix in time.\n* `LOCATION_UNAVAILABLE`: system failure / no providers.\n\n## Background behavior (future)\n\nGoal: model can request location even when node is backgrounded, but only when:\n\n* User selected **Always**.\n* OS grants background location.\n* App is allowed to run in background for location (iOS background mode / Android foreground service or special allowance).\n\nPush-triggered flow (future):\n\n1. Gateway sends a push to the node (silent push or FCM data).\n2. Node wakes briefly and requests location from the device.\n3. Node forwards payload to Gateway.\n\n* iOS: Always permission + background location mode required. Silent push may be throttled; expect intermittent failures.\n* Android: background location may require a foreground service; otherwise, expect denial.\n\n## Model/tooling integration\n\n* Tool surface: `nodes` tool adds `location_get` action (node required).\n* CLI: `openclaw nodes location get --node <id>`.\n* Agent guidelines: only call when user enabled location and understands the scope.\n\n## UX copy (suggested)\n\n* Off: “Location sharing is disabled.”\n* While Using: “Only when OpenClaw is open.”\n* Always: “Allow background location. Requires system permission.”\n* Precise: “Use precise GPS location. Toggle off to share approximate location.”",
  "code_samples": [
    {
      "code": "Response payload:",
      "language": "unknown"
    }
  ],
  "headings": [
    {
      "level": "h2",
      "text": "TL;DR",
      "id": "tl;dr"
    },
    {
      "level": "h2",
      "text": "Why a selector (not just a switch)",
      "id": "why-a-selector-(not-just-a-switch)"
    },
    {
      "level": "h2",
      "text": "Settings model",
      "id": "settings-model"
    },
    {
      "level": "h2",
      "text": "Permissions mapping (node.permissions)",
      "id": "permissions-mapping-(node.permissions)"
    },
    {
      "level": "h2",
      "text": "Command: `location.get`",
      "id": "command:-`location.get`"
    },
    {
      "level": "h2",
      "text": "Background behavior (future)",
      "id": "background-behavior-(future)"
    },
    {
      "level": "h2",
      "text": "Model/tooling integration",
      "id": "model/tooling-integration"
    },
    {
      "level": "h2",
      "text": "UX copy (suggested)",
      "id": "ux-copy-(suggested)"
    }
  ],
  "url": "llms-txt#location-command-(nodes)",
  "links": []
}