Skip to the download

Remote Coder

v0.1.0 · in test

The Mac stays on the desk. You don’t.

Take control of your Mac from your iPhone — its screen, its pointer, its keyboard, its files and its sound, and a real login shell when you want one. Leave an agent running and the Mac buzzes your phone when it stops. Everything is encrypted end to end and goes straight between your own two devices wherever the network allows it.

macOS host and iPhone client today · Windows in progress

iPhone · attached to the Mac

zsh · login

mac ~/remote-coder % git status --short
 M packages/rc_core/../auth/auth_proof.dart

mac ~/remote-coder % claude "fix the flaky pairing test"

  * edit   packages/rc_core/../auth/auth_proof.dart
  * run    dart test test/auth/
  ok     41 passed, 1 failed, 4m 12s

  -- the run stopped, so the Mac rang your phone --
  -- phone locked 2h 07m, the shell kept running --
  -- re-attached, the output you missed replayed --

mac ~/remote-coder % 
[01]

Download

Two installs · one link

There is no signed installer yet — both apps build from the repository, and that is the next piece of work. A build with no relay URL reaches your Mac on your own network only; going further needs the relay, which you put up yourself.

Host

The machine on your desk

  • Available

    macOS — available

    macOS 13 or newer · Intel and Apple silicon

    Build the macOS host

    Screen, pointer, shells, files and the Mac's audio

  • Not ready

    Windows — not ready

    Windows 10 or newer · terminal, screen and input are written

    Notify me

    Not yet built on a real PC · no installer

Client

The phone in your hand

  • Available

    iPhone & iPad — available

    iOS and iPadOS 16 or newer

    Build the iOS client

    Several shells at once, search, and every key an iPhone lacks

  • Not ready

    Android — not ready

    Not started — there is no Android project in the repository

    Notify me

    Nothing to install today

[02]

What it does

Six things · all shipping

[03]

How it works

Four steps

  1. 01

    Install both

    The host on the Mac you want to reach, the client on your phone.

  2. 02

    Pair them once

    On your own Wi-Fi, or by scanning the code the Mac shows. Either way the Mac asks you to approve the phone, by hand.

  3. 03

    Open a shell from anywhere

    A real login shell on the Mac, over a link only your two devices can read. On your own network out of the box; further afield once you have put up the relay.

  4. 04

    Put your phone away

    Your agent keeps working on the Mac. When it finishes, or stops to ask you something, the Mac buzzes your phone.

[04]

Security

Five claims

This is the part of Remote Coder worth checking, so here is enough to check it. Each claim below names the file it lives in. The whole model is written down in docs/AUTH.md, including what is still weak.

What it is built from

  • Password verifierArgon2id · 64 MiB · 3 passes
  • Handshake proofHMAC-SHA256, both ways
  • Identity keyX25519, pinned on the phone
  • Session sealXChaCha20-Poly1305
  • Wrong passwords5 per key · 50 total · 15 min
[1]

The password is never sent

The Mac holds the access password, and one tap has it generate a fresh one — twelve random symbols, 60 bits. It is kept only as an Argon2id hash, 64 MiB of memory and three passes per guess, and the phone proves it knows the password by answering with an HMAC instead of handing it over.

packages/rc_core/lib/src/auth/auth_proof.dart

[2]

Both ends have to prove it

The phone proves it knows the password and the Mac proves it back, under a separate label so neither answer can be replayed as the other. Each proof is bound to both identity keys and to a value derived fresh for that session, so a recorded handshake is useless against another Mac, another phone, or the same pair tomorrow. Proofs are compared in constant time.

packages/rc_core/lib/src/auth/auth_proof.dart

[3]

Everything is sealed twice

Each side keeps a long-lived X25519 identity key and mints a throwaway one for every session; both agreements are HKDF-expanded into one key per direction, so a frame cannot be reflected back at the end that sent it. Signaling is sealed with XChaCha20-Poly1305, and the control and terminal payloads carry a second seal on top of WebRTC's own encryption.

packages/rc_core/lib/src/crypto/cipher.dart

[4]

A correct password is not enough

The first time an unknown phone reaches the Mac, the Mac stops and asks whoever is sitting at it — device name, key fingerprint, approve or decline, and the request expires on its own. A password can be read off a screen or forwarded, so it never attaches a new phone by itself: you cannot pair one to a Mac you are not standing at.

apps/host/lib/ui/host_pairing_approval.dart

[5]

The phone remembers which Mac

On the first connection the phone pins the Mac's identity key and refuses a different one afterwards, behind a full-screen warning whose primary button is Do not connect. Scanning the code the Mac puts up — it carries the key and takes itself down after 90 seconds — removes that first unpinned connection altogether.

apps/client/lib/auth/identity_warning_page.dart

What this does not protect against

Your unlocked phone, or your open Mac

Someone holding your unlocked phone has whatever the phone has, exactly as with any saved credential; someone sitting at your Mac does not need the phone at all. Neither is a thing encryption can answer.

“Direct” is not unconditional

Off your own network the session tries for a direct path between your two devices and falls back to a TURN relay when the network refuses one. The relay carries sealed bytes and cannot read the session — but the path is not always direct, so do not read the word as a guarantee.

The model is not finished

An attacker present for a first, unpinned connection still captures the proof and can attack it offline, and the value stored on the Mac is enough to authenticate with. A PAKE would close both and is not built.

The whole threat model, row by row, is in docs/AUTH.md — including the parts it says are still weak.

[05]

One payment, once

Founding lifetime · $59 · not yet on sale

Your screen and your keystrokes go straight between your own two devices, wherever the network allows it — and stay sealed end to end when it doesn’t. Every remote-desktop service that bills monthly is paying to carry your pixels, so the longer you work the more you cost it. Nothing here recurs, so the price doesn’t either.

Founding lifetime

$59

One payment · no subscription

The intended price, held for the first 500 people. Not on sale yet — the apps build from source.

There is nothing to buy here yet. Both apps build from the repository today, and no payment of any kind is taken on this site. This is the price the founding lifetime will be on the day building them stops being the way in — held for the people who ask for it before then.

Hold the founding price

One line by email · nothing is charged

What the licence covers

  • [1]Both apps — host and clientYes
  • [2]macOS host · iPhone & iPad clientNow
  • [3]Windows · Linux · AndroidWhen they land
  • [4]Every future updateYes

What isn’t there yet

  • No installerBoth apps build from the repository
  • Mac and iPhone onlyWindows is close; Android has not started
  • Off your network needs a relayYou put up the Worker and build with its URL
  • An account on first launchBoth apps ask you to sign in before the first connection
  • v0.1.0, in testVerified on my hardware, not yet on many people's

Tell me where to send it

Say which platform you are waiting for and whether you want the founding price held. You get one message back when there is something to install, and nothing else, ever.

Send one line