Skip to content

[Feature]: Offline Command Queue for iOS/Android Node App #46664

Description

@sbmilburn

Summary

Add an offline command queue to the OpenClaw mobile node app (iOS/Android) that captures user intents while disconnected and automatically syncs them to the gateway for execution when connectivity is restored.

Problem to solve

Many OpenClaw users operate in environments with intermittent or no cellular connectivity — rural areas, mountain passes, canyons, tunnels, basements, aircraft, etc. Currently, the mobile node app requires an active connection to the gateway to submit any command. This means users in dead zones cannot interact with their AI assistant at all, even for simple tasks like setting reminders, scheduling meetings, or queuing emails.

Real-world scenario: A user drives through a canyon with no cell service for 20-30 minutes on their daily commute. During that time, they think of several things they need their assistant to handle:

  • "Remind me to buy eggs"
  • "Schedule a meeting with John for Tuesday at 2pm"
  • "Email me the monthly sales report"
  • "Don't let me forget to call Mom when I get home"

Today, these thoughts are lost unless the user manually remembers them later. With an offline queue, the user speaks or types these commands while offline, and they execute automatically when the phone reconnects — either via cellular recovery or arriving at a WiFi-connected location (e.g., home).

Proposed solution

Core Behavior

  1. Capture: When the node app detects it has no gateway connectivity, switch to "offline queue" mode. The user can still interact via voice or text. Commands are stored locally on-device.
  2. Store: Persist queued commands in a local database (see Storage section below) with metadata: timestamp, raw input text/audio, priority hints, and queue position.
  3. Sync: When connectivity to the gateway is re-established, automatically flush the queue in FIFO order to the gateway as standard node messages/commands.
  4. Confirm: Provide user feedback on sync status — how many commands queued, how many synced, any that failed.

User Experience

  • Seamless transition: The app should not require the user to do anything special to enter/exit offline mode. It should feel the same as normal usage — speak or type, and trust that it will be handled.
  • Visual indicator: A subtle badge or status indicator showing "X commands queued" and current connectivity state (connected / offline / syncing).
  • Voice input: Critical for hands-free use cases (driving). The app should accept voice input offline, store the audio and/or a local transcription, and forward to the gateway on sync.
  • Queue management: Allow the user to review, edit, reorder, or delete queued commands before they sync.
  • Notification on sync: When the queue flushes successfully, notify the user (e.g., "5 queued commands sent to your assistant").

Alternatives considered

Fall back to using Siri for “Apple Reminders” but then I have to ask openclaw to do those later on.

Impact

  • Use case frequency: Anyone with a commute through dead zones (rural users, mountain/canyon roads, subway commuters)
  • Competitive advantage: Most AI assistants (Siri, Google Assistant, Alexa) have limited or no offline queuing capability — this would be a differentiator
  • Implementation complexity: Medium — the on-device storage and sync logic are straightforward; the main work is UI/UX for queue management and robust sync with retry
  • Dependencies: Requires the iOS/Android node app to have local storage permissions and background sync capability

Evidence/examples

Real-world scenario: A user drives through a canyon with no cell service for 20-30 minutes on their daily commute. During that time, they think of several things they need their assistant to handle:

  • "Remind me to buy eggs"
  • "Schedule a meeting with John for Tuesday at 2pm"
  • "Email me the monthly sales report"
  • "Don't let me forget to call Mom when I get home"

Today, these thoughts are lost unless the user manually remembers them later. With an offline queue, the user speaks or types these commands while offline, and they execute automatically when the phone reconnects — either via cellular recovery or arriving at a WiFi-connected location (e.g., home).

Additional information

Storage Recommendation

SQLite is the natural choice for on-device queue storage:

  • Already the standard embedded database on both iOS (via sqlite3 C library, bundled with the OS) and Android.
  • Zero-configuration, serverless, single-file — perfect for a local queue.
  • ACID-compliant — won't corrupt the queue on app crash or sudden power loss.
  • Handles the expected volume trivially (dozens to low hundreds of commands between syncs).
  • Both Swift (via GRDB, SQLite.swift, or raw C API) and Kotlin (via Room/SQLite) have mature SQLite libraries.

Suggested schema:

CREATE TABLE command_queue (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    created_at  TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
    input_type  TEXT NOT NULL CHECK (input_type IN ('text', 'voice')),
    raw_text    TEXT,              -- user's text input or local transcription
    audio_blob  BLOB,             -- raw audio if voice input (for gateway-side STT)
    priority    INTEGER DEFAULT 0, -- future use: urgent vs normal
    status      TEXT NOT NULL DEFAULT 'queued' 
                CHECK (status IN ('queued', 'syncing', 'sent', 'failed', 'cancelled')),
    synced_at   TEXT,             -- timestamp when successfully sent to gateway
    error       TEXT,             -- error message if sync failed
    retry_count INTEGER DEFAULT 0
);

CREATE INDEX idx_queue_status ON command_queue(status);

Alternatives considered:

  • Flat file / JSON array: Simpler but no crash safety, no concurrent access guarantees, harder to manage partial sync state.
  • Core Data (iOS) / Room (Android): Adds abstraction but both are SQLite under the hood anyway. May be appropriate if the app already uses these frameworks.
  • Realm: Overkill for a simple FIFO queue.

Sync Protocol

When the node detects gateway reachability:

  1. Query all rows with status = 'queued', ordered by created_at ASC.
  2. For each command:
    a. Set status = 'syncing'
    b. Submit to gateway via the existing node→gateway message channel (WebSocket or HTTP, depending on protocol state)
    c. On success: set status = 'sent', record synced_at
    d. On failure: increment retry_count, set status = 'failed' if retries exhausted, otherwise back to queued
  3. Purge sent rows after configurable retention (e.g., 24 hours or on next app launch).

Conflict handling: Commands are inherently append-only and user-initiated, so there are no merge conflicts. The gateway processes them as if they arrived in real-time, in order.

Edge Cases to Consider

  • Stale commands: A reminder queued 2 hours ago saying "in 10 minutes" — the gateway/agent should interpret timestamps relative to when the command was spoken, not when it was received. Include created_at in the sync payload so the agent has context.
  • Duplicate prevention: If the app crashes mid-sync and restarts, the status field prevents re-sending already-sent commands. Consider adding an idempotency key (UUID per command) for gateway-side dedup.
  • Large audio blobs: If voice input is stored as raw audio, queue size could grow. Consider a configurable max queue size or audio compression.
  • Battery considerations: Don't aggressively poll for connectivity. Use OS-level network reachability callbacks (NWPathMonitor on iOS, ConnectivityManager on Android) to trigger sync only when connectivity actually changes.
  • Partial connectivity: The phone might have weak signal that drops mid-sync. Handle partial flushes gracefully — each command is independent.

Additional Ideas (Future Enhancements)

  • On-device triage: Use a small local model (e.g., quantized LLM) to categorize commands by urgency, so time-sensitive items sync first.
  • Geofence triggers: "When I get home" commands could use geofencing to trigger sync + immediate execution when arriving at a known location.
  • Offline acknowledgment: The app could provide basic confirmation like "Got it — I'll handle that when we're back online" using canned responses, without needing the gateway.
  • Batch optimization: Group related commands into a single gateway message for efficiency (e.g., "Here are 5 commands queued while offline, in order").
  • Widget/Complication: iOS widget or Apple Watch complication showing queue count and last sync time.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.enhancementNew feature or requestimpact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions