Remodex

repository·main·Indexed 25 days ago

https://github.com/emanuele-web04/remodex

A local-first, open-source bridge and iOS app that allows users to control the Codex AI runtime from an iPhone. It enables remote coding, git operations, and real-time AI interaction by maintaining a secure, encrypted connection between a Mac and an iOS device. The bridge integrates with the Codex CLI and Codex desktop app, supporting features like end-to-end encryption, workspace-scoped revert operations, and a dedicated relay for pairing.

Tokens
18K
Snippets
35
Records
89
Agent score
85%

What's inside remodex

  1. Understand the Remodex Multi-Provider Architecture

    main

    Remodex is designed as a local-first mobile client that can support multiple AI agent providers (e.g., Codex, OpenCode, Claude, Gemini) via a local bridge.

    While the transport layer (Relay and Secure Transport) is already provider-agnostic, the runtime protocol layer currently expects a 'Codex-shaped' application protocol. To support other providers, a RuntimeAdapter layer must be implemented within the phodex-bridge to normalize provider-specific events into the Remodex canonical format (threads, turns, items, approvals, and model events).

  2. Security: End-to-end encryption in Remodex

    main

    Remodex uses an authenticated end-to-end encrypted channel between the paired iPhone and the Mac bridge.

    Encryption Workflow:

    1. The bridge generates a long-term device identity keypair on the Mac.
    2. The pairing QR shares the connection URL, session ID, bridge device ID, bridge identity public key, and an expiry window.
    3. During pairing, the iPhone and bridge exchange X25519 ephemeral keys and nonces.
    4. The bridge signs the handshake with its Ed25519 identity key; the iPhone verifies this against the QR or trusted record.
    5. The iPhone signs a client-auth transcript with its Ed25519 identity key; the bridge verifies this.
    6. Both sides derive AES-256-GCM keys with HKDF-SHA256 to encrypt application messages with monotonic counters for replay protection.

    Privacy Guarantees:

    • The transport layer (WebSocket) sees connection metadata (session IDs, device IDs, public keys) but cannot see decrypted application payloads (prompts, tool calls, Codex responses, git output, or workspace RPC payloads) once the secure session is established.
    • On-device message history on iPhone is encrypted at rest using a Keychain-backed AES key.
  3. Configure a custom relay endpoint

    main
    If you are self-hosting Remodex on a VPS or a stable private network (such as Tailscale), you must provide your own relay URL. Use the REMODEX_RELAY environment variable to point the application to your custom relay endpoint instead of relying on a built-in default.
  4. Check Turn View performance

    main

    Use the check-turnview-performance.sh script to compare fresh XCTest metrics against a JSON baseline for the Turn View.

    To see the required JSON structure for a baseline file, use the --print-baseline-template flag.

    To run the performance check, provide the path to your baseline file via the BASELINE_PATH environment variable. You can also override SCHEME, DESTINATION, and MAX_REGRESSION_PERCENT using environment variables.

    # Print the required baseline JSON template
    CodexMobile/scripts/check-turnview-performance.sh --print-baseline-template
    
    # Run the performance check with a specific baseline
    BASELINE_PATH=/path/to/TurnView-Performance-Baseline.json \
      CodexMobile/scripts/check-turnview-performance.sh
  5. Refactor SidebarThreadListView for complexity reduction

    main

    The SidebarThreadListView.swift file is a high-complexity SwiftUI component responsible for sidebar navigation and rendering. To maintain performance and readability, follow these refactoring patterns:

    • Extract Subviews: Instead of using computed view fragments within the main body, extract stable, meaningful subviews or row/projection helpers into separate components.
    • State Management: Move complex state (such as project previews, subagent hierarchies, and project expansion state) out of the view and into dedicated state objects like SidebarThreadListState.swift.
    • Complexity Targets: Aim to keep the file under 500 lines of code (LOC) to ensure high-frequency UI/service paths remain easy to reason about.
    • Preserve Behavior: Ensure local-first behavior and existing public APIs are preserved during extraction.
  6. Integrate Cursor as a Remodex Provider

    main

    To integrate Cursor into Remodex, it must be implemented as a separate RuntimeAdapter behind the phodex-bridge. Do not connect Cursor directly to the iOS client or the relay. The adapter's responsibility is to normalize Cursor sessions, prompts, events, command execution, and model metadata into the standard Remodex runtime contract used by other providers like OpenCode.

    Recommended integration hierarchy:

    • Remodex iOS -> relay -> phodex-bridge -> RuntimeAdapter -> Cursor adapter

    Recommended implementation paths:

    1. MVP (Fastest): Use the Cursor CLI in non-interactive/headless mode with stream-json output.
    2. Long-term (Preferred): Use the @cursor/sdk for a typed, programmatic interface.
    3. Optional: Use the Background Agents API for cloud-based, GitHub-backed tasks (treat as a separate cursor-background provider).
  7. Prioritize Remodex codebase cleanup tasks

    main

    Based on the codebase audit, the following high-priority tasks are identified to improve maintainability and reduce technical debt in the Swift/Xcode project:

    P0 - Critical (Fix First)

    • Split message normalization and timeline mutation logic out of CodexMobile/CodexMobile/Services/CodexService+Messages.swift.
    • Shrink turn timeline rendering by extracting row-specific components and data shaping from TurnTimelineView.swift and TurnView.swift.
    • Reduce repeated connection/recovery branching across CodexService extensions (incoming, history, and threads/turns).

    P1 - Significant Technical Debt

    • Address bloated files such as ContentView.swift, SettingsView.swift, CodexService+Account.swift, and CodexService+Connection.swift.

    P2 - Moderate Issues

    • Schedule cleanup for moderate issues identified in the audit.
  8. Install the Remodex Bridge

    main

    To use Remodex, you must install the bridge globally via npm. This allows the remodex CLI to be available in your login-shell PATH, which is required if you want to use the macOS menu bar companion.

    Install the latest version using:

    npm install -g remodex@latest
  9. Enable the deep-link refresh workaround

    main

    If you need to force the Codex desktop app to remount the current thread without interrupting running tasks, you can enable the old deep-link refresh workaround. This triggers a debounced deep-link bounce (codex://settingscodex://threads/<id>).

    # Enable the old deep-link refresh workaround manually
    REMODEX_REFRESH_ENABLED=true remodex up
  10. Implement Cursor Provider Modes

    main

    The integration is divided into three distinct provider modes to maintain clear boundaries between local and cloud execution:

    1. cursor-cli: A local process-based MVP using the Cursor CLI.
    2. cursor-sdk: The preferred programmatic adapter using the @cursor/sdk for typed local/provider interactions.
    3. cursor-background: An explicit cloud mode that runs against a GitHub-backed repository.
  11. Design the Cursor CLI Adapter

    main

    The Cursor CLI adapter is designed for a process-per-turn lifecycle.

    Key Implementation Details:

    • Binary Discovery: Look for agent or cursor-agent in the system path, or use the REMODEX_CURSOR_BIN environment variable.
    • Execution: Spawn the process using flags like -p <prompt> and --output-format stream-json.
    • Parsing: Use a line-by-line JSON parser (CursorCliStreamParser) to handle streaming output.
    • Interrupts: Send SIGINT followed by SIGTERM to stop a turn.
    • History: Since the CLI may lack persistent history, the bridge should maintain its own history using a JSON structure mapping remodex-thread-id to turns.
    // Example: Resolving the Cursor Agent Binary
    async function resolveCursorAgentBinary(config) {
      if (config.cursorBin) return config.cursorBin
      for (const name of ["agent", "cursor-agent"]) {
        if (await commandExists(name)) return name
      }
      throw new Error("Cursor CLI not found. Install Cursor CLI or set REMODEX_CURSOR_BIN.")
    }