Keep Claude Code Remote Control alive on your machine — many projects, one supervisor, and a desktop app to drive it all. Windows, Linux and macOS.

Product page · Download · Report a bug

Claude Code Remote Control lets you drive a Claude Code session running on your own machine from claude.ai or the Claude mobile app. The catch: it is a foreground process in a terminal. Close the window, hit a crash, reboot the machine — and your phone loses the machine.

LiveClaude turns that into infrastructure:

- Multiple agent products — Claude Code Remote Control and Cursor My Machines workers today, each behind its own late-loaded assembly with product-specific session options.

- One long-lived process per session entry, with product-native flags (Claude spawn/capacity/permission; Cursor --name/--worker-dir/ auth).

- A supervisor that restarts a process when it dies (exponential backoff), at sign-in, and after a reboot — hosted by whatever your operating system offers: a Scheduled Task or a Windows Service, a systemd user or system unit, a LaunchAgent or a LaunchDaemon.

- A desktop app to create, edit and remove sessions, watch their state live, read their logs, and install or remove the supervisor. One Avalonia application, the same on all three systems.

- An embedded terminal — a real pseudo terminal (ConPTY on Windows, a pty pair elsewhere) rendered by a VT emulator written from scratch in C# — so the one-time flows that need a terminal (workspace trust, Remote Control confirmation, agent login) happen inside the app, and so you can attach to a running process and type into it.

Everything is C#. No Node, no Python, no tmux, no browser control.

Everything that has to differ between operating systems — the pseudo terminal, autostart, elevation,

the IPC transport, where files live — sits behind one contract and lives in its own assembly, loaded

by name at run time. Agent products (LiveClaude.Product.Claude, LiveClaude.Product.Cursor) ship

the same way. LiveClaude.Core has no compile-time dependency on either.

Claude Code's real TUI rendered inside the app's terminal tab — the trust prompt, and anything else that needs a terminal.

winget install LeandroCannizzaro.LiveClaude- Download LiveClaude-win-x64.zipfrom the latest release.

- Unblock and extract it anywhere.

- Run LiveClaude.exe.

The -selfcontained zip has no prerequisites. The plain zip needs the .NET 10 Desktop Runtime.

Open LiveClaude.application — it installs for the current user and checks for updates on every launch. The manifests are unsigned, so SmartScreen asks once.

Already running 1.x? That channel is frozen at 1.0.15 and keeps working. 2.0 is published to a channel of its own, so a 1.0.15 install is never carried onto it by an update check — install 2.0 alongside, and remove 1.x once you are happy. They are different applications underneath: 1.x is the Windows-only WPF program, 2.x is the cross-platform one.

curl -fsSL https://leandrocannizzaro.github.io/LiveClaude/install.sh | shPicks the .deb, .rpm or tarball for your machine, installs to /opt/liveclaude, and puts

liveclaude and liveclaude-supervisor on your PATH with a desktop entry. x86_64 and arm64,

self-contained — no .NET runtime needed.

By hand, if you prefer:

sudo apt install ./liveclaude_<version>_amd64.deb # Debian, Ubuntu

sudo dnf install ./liveclaude-<version>-1.x86_64.rpm # Fedora, RHEL, openSUSE

tar -xzf LiveClaude-<version>-linux-x64.tar.gz -C ~/liveclaudecurl -fsSL https://leandrocannizzaro.github.io/LiveClaude/install-macos.sh | shDownloads the .dmg for your Mac, copies the app to /Applications and clears the quarantine flag.

Apple silicon and Intel.

Installing the .dmg by hand works too, but the app is not notarised yet: Gatekeeper refuses a

normal double-click, so right-click the app and choose Open the first time. Clearing that flag is

the only reason the script above is worth having.

git clone https://github.com/LeandroCannizzaro/LiveClaude.git

cd LiveClaude

dotnet build -c Release

dotnet run --project src/LiveClaude.AppBuilding a Windows package needs a Windows machine — LiveClaude.Platform.Windows targets

net10.0-windows — but the Linux and macOS packages cross-build from anywhere.

- Open LiveClaude → Sessions → New session.

- Pick the project directory, give it a name, choose spawn and permission mode. The command preview shows exactly what will run.

- Click Trust this directory… — the embedded terminal opens and runs claudethere so you can accept the one-time workspace-trust prompt, then type/exit.

- Click Run remote-control once… the first time, to accept Enable Remote Control? (y/n).

- Save session, then go to Service & startup → Install / update.

The server now shows up at claude.ai/code and in the Claude mobile app, and comes back on its own after a crash, a sign-out or a reboot.

Every system offers two places to register the supervisor, and LiveClaude uses both. The card on the left of Service & startup is always the recommended one.

Starting before anyone signs in is the one thing that works differently everywhere, and each platform says so in the UI rather than quietly installing something that will not do it:

- Windows only lets an administrator register a task with a boot trigger, so installing asks for elevation. Decline it and the task is installed with the logon trigger only.

- Linux needs lingering (loginctl enable-linger <you>) so systemd runs your user manager without a session. LiveClaude offers to enable it; decline and the unit still starts at login.

- macOS cannot do it with a LaunchAgent at all — an agent belongs to the GUI session. The LaunchDaemon can, but the login Keychain stays locked until somebody signs in, and that is where Claude Code keeps its token.

Both scopes are installed from the app, or from the CLI:

LiveClaude.Service install-autostart # your session

LiveClaude.Service install-autostart --scope system --user you

LiveClaude.Service statusinstall-task and install-service are kept as aliases for --scope user and --scope system, so

the Windows documentation, the winget package and anyone's scripts keep working:

LiveClaude.Service.exe install-task

LiveClaude.Service.exe install-service --account "DOMAIN\you" --password "<windows password>"Why installing may ask for elevation (Windows). Windows only lets an administrator register a task

that triggers at system startup: as a normal user, schtasks answers ERROR: Access is denied. The app

therefore asks for elevation through the supervisor executable — the app itself stays asInvoker, which

also means a ClickOnce install (which cannot be launched elevated) works fine. Decline the prompt and the

task is still installed with the logon trigger only: everything works except starting before anyone signs

in. The task is always registered for your account, even when UAC is answered with a different one.

Elsewhere the same prompt comes from pkexec (or sudo) on Linux and from the standard

authentication sheet on macOS, and declining has the same consequence.

What the Windows service needs. Installation is elevated (UAC, again through the supervisor

executable). Running it under your own account additionally needs the Log on as a service right —

sc create obj= does not grant it, and without it the service is created and then refuses to start

with error 1069. LiveClaude grants it during the elevated install. The account also needs a real

password: Windows never lets a user account log on as a service with a blank one.

Who actually runs. The zip and winget packages register LiveClaude.Service.exe. A ClickOnce

install ships that executable without its runtime configuration — .NET then refuses to start it — so

there LiveClaude registers itself instead (LiveClaude.exe --supervise), which hosts the same

supervisor windowlessly. Only one supervisor runs at a time: a second one stops with a note in

logs\supervisor.log rather than supervising the same directories twice.

Installs that move (Windows only). ClickOnce and winget put the app in a folder that is replaced on every update,

which would leave the task or service pointing at an executable that no longer exists. When LiveClaude

detects such a location it first copies the supervisor to %LOCALAPPDATA%\LiveClaude\supervisor and

registers that copy — one path, so the registration survives updates. Because the supervisor runs

from there and holds its own files open, everything running from that folder is stopped before the

copy is refreshed; without that, an update cannot replace the executable and the registration keeps

running the previous build. Linux and macOS install to paths that do not move — /opt/liveclaude and

the .app bundle — so nothing is copied there.

The app talks to whichever supervisor is running over the platform's own channel, so you can close the

window and the servers keep running — and reopen it later to find them. On Windows that is a named

pipe (\.\pipe\LiveClaude.v1), shared across the machine. On Linux and macOS it is a Unix domain

socket in a private per-user directory, created mode 0700 — which makes the "only one supervisor" rule

per-user there, the right answer on a machine two people share.

Every claude remote-control process registers a bridge environment on Anthropic's side, and the

registration outlives the process. Stop a server and start it again and you get a second entry for the

same directory; do it three times and the picker in Claude Desktop shows the project three times, one

live and the rest dead. Archiving conversations does not touch them — they are environments, not

sessions (claude-code#50884).

LiveClaude handles both ends of that:

- It stops servers the way a person would. Stopping sends Ctrl+C and waits (12 s by default, in Service & startup) before terminating, so the CLI gets its chance to deregister. The previous behaviour — a hard kill — is exactly what creates the dead entries.

- It knows which environment is which. When a server comes up, LiveClaude asks the API which bridge environment it just registered and remembers it, so a live entry can never be mistaken for a leftover. Turn this off with Track which environment each server registers to stay fully offline.

- The Environments tab cleans up the rest. It lists the bridge environments on your account

grouped by directory, marks each one live / stale / untracked, and deletes the ones you pick:

- Select duplicates keeps the live one — or the newest — for each directory and selects the

others. This is the answer to "three doG, one alive".

- Select stale picks the environments whose directory LiveClaude supervises but which have no server behind them.

- An environment in use is never selectable, and deletion always asks first. Protection does not depend on the API lookup succeeding: a directory with a running server protects every registration made during that run, including one the server creates again after a delete. Stop the session in the Dashboard to clear those. Leftovers from earlier runs of the same directory stay deletable while the server runs.

- Select duplicates keeps the live one — or the newest — for each directory and selects the

others. This is the answer to "three

The API answers 409 Conflict when an environment still has session records attached:

Environment has 1 active sessions. Use force=true to delete anyway.

Those sessions are themselves leftovers of servers that were killed rather than stopped. LiveClaude

shows the reason on the row and in a panel above the list — with Anthropic's request-id — and offers

a Force delete button that retries with force=true, deleting the environment together with its

session records. Every call, successful or not, is appended to

%ProgramData%\LiveClaude\logs\environments.log; Open log in the toolbar goes straight there.

Not every entry in the picker is a bridge environment: the ones Claude Code on the web creates are

anthropic_cloud environments and are perfectly alive. Tick Show non-bridge environments to see

them.

The tab uses your own Claude Code sign-in (~/.claude/.credentials.json) against

api.anthropic.com/v1/environments with the environments-2025-11-01 beta header. That API is in

beta and undocumented: if Anthropic changes it, the tab reports the error and the rest of LiveClaude

keeps working.

To keep the count down without any cleanup, restart a server within Remote Control's four-hour window

so --continue reattaches instead of registering a fresh environment.

Each session maps one-to-one onto claude remote-control flags:

About the 4-hour window: claude remote-control --continue can only bring back the sessions a stopped server was serving for about four hours. LiveClaude records the stop time per instance and reattaches when it still can; past that it starts a fresh session. The conversations themselves are never lost — they stay resumable locally with claude --resume.

┌─────────────────────────────┐

claude.ai / mobile ───┤ Anthropic Remote Control │

└──────────────┬──────────────┘

│ outbound HTTPS only

┌────────────────────────────────────┼───────────────────────────────┐

│ your machine │ │

│ ▼ │

│ ┌──────────────┐ pipe / socket ┌─────────────────────────────┐ │

│ │ LiveClaude │◄──────────────►│ LiveClaude.Service │ │

│ │ desktop app │ status, │ (task · service · systemd · │ │

│ │ (Avalonia) │ terminal I/O │ LaunchAgent · LaunchDaemon) │ │

│ │ Dashboard │ │ Supervisor │ │

│ │ Sessions │ │ ├── instance "LivePlatform" │ │

│ │ Terminal ───┼────────────────┼──►│ └── pty ─ claude │ │

│ │ Logs │ │ ├── instance "beELive" │ │

│ │ Settings │ │ │ └── pty ─ claude │ │

│ └──────┬───────┘ └───────────┬─────────────────┘ │

│ │ │ │

│ └──────────► LiveClaude.Platform.<OS> ◄────────────────────┤

│ loaded by name at run time │

│ pty · autostart · elevation · paths · IPC │

└────────────────────────────────────────────────────────────────┘

Nothing references a platform assembly at compile time. PlatformLoader probes for

LiveClaude.Platform.<OS>.dll next to the application and loads it by path — by path, because an

assembly nothing references is absent from deps.json and the default resolver would never find it

sitting right there. Delete that file from a published folder and the app stops with one sentence

naming it, which is the cheapest possible proof that the seam is real.

On Windows, a process that owns a console hands its console to every child it starts, and Windows then ignores the pseudo-console attribute — the child's output never reaches your pipes. That is why the supervisor and the app are both windowless executables there, and why the supervisor only borrows the caller's console for one-shot CLI commands. If you ever host the supervisor yourself from a console process, the dashboard will tell you: "this process owns a console…". POSIX has no such rule, so the supervisor is an ordinary console program on Linux and macOS.

On POSIX, the child is started with posix_spawn, never fork. Forking a multi-threaded .NET

process leaves the child holding locks that nothing will ever release, and any managed code running

before exec can deadlock. posix_spawn does the whole open/dup2/exec sequence inside libc. It also

sets a new session, and opening the pty slave without O_NOCTTY makes it the controlling terminal —

which is what turns the 0x03 byte into a real SIGINT. Without a controlling terminal it would be

just a byte, the server would have to be killed, and killing it is exactly what leaves dead bridge

environments in the session picker.

LiveClaude.Service status prints the paths for the machine you are on. In short:

Inside the log directory: <name>-<id>.log per instance, supervisor.log, and install.log —

which is what the elevated install commands printed, since they run in a window nobody sees.

Why the socket is not with everything else. A Unix domain socket path is limited to 104 bytes on

macOS and 108 on Linux, terminator included — and

/Users/<you>/Library/Application Support/LiveClaude/run/ spends more than half of that before the

file name. So the socket goes in a short per-user directory created 0700, the way tmux does it:

$XDG_RUNTIME_DIR/liveclaude/ on Linux when the session has one, /tmp/liveclaude-<uid>/ otherwise

and on macOS. A directory other users cannot traverse is what protects the socket.

Windows keeps one machine-wide root so a service running under another account reads the same

configuration the app writes. POSIX has no equivalent that both a daemon and a desktop user can

reach, so Linux and macOS are per-user. A system-scope daemon opts into a shared root through

LIVECLAUDE_ROOT, which every platform honours. The systemd system unit pins it to

/var/lib/liveclaude (created by StateDirectory=) only when it runs as root; with a named account

it uses that account's home, the same configuration the app writes.

"Needs attention" on a session. Claude Code is waiting for a human: workspace trust, the Remote Control confirmation, or a sign-in. Open the Terminal tab, attach to the instance and answer it — you are typing straight into the running server.

The server exits immediately. Read the instance log. The usual causes are an untrusted directory, a missing sign-in (claude /login in the embedded terminal, or claude setup-token), ANTHROPIC_BASE_URL pointing somewhere other than api.anthropic.com, or DISABLE_TELEMETRY / DO_NOT_TRACK switched on — Remote Control needs the feature-flag check those disable.

The machine-wide host is installed but nothing starts. It is almost certainly running as the

system account. Reinstall it naming your own (--user you) so it uses your profile, where the Claude

credentials live.

Linux: "Failed to connect to bus". systemctl --user needs a session bus, which does not exist

over ssh or in a container. Run loginctl enable-linger <you> so systemd keeps your user manager

running without an interactive session, or use the system unit instead.

macOS: the Environments tab says you are not signed in. Claude Code keeps its token in the login Keychain there. The first read shows an "allow access" prompt — if it was refused, allow LiveClaude in Keychain Access. A LaunchDaemon cannot read it at all before somebody signs in.

The machine sleeps and the sessions go offline. Remote Control needs the machine awake. Disable sleep — on Windows you can also enable Wake the computer to run this task on the scheduled task.

dotnet build # build everything for this machine

dotnet test # 117 tests, no network needed

dotnet run --project src/LiveClaude.App

dotnet run --project src/LiveClaude.Service -- statusThe build picks the platform assembly for the machine you are on, or for the -r you pass:

dotnet publish -r linux-x64 from a Mac produces a Linux package. The one exception is a Windows

package, which needs a Windows machine — LiveClaude.Platform.Windows targets net10.0-windows, and

the build says so rather than producing something half-right.

LiveClaude --terminal <directory> opens the app straight into the embedded terminal for that folder

— the fastest route to a trust prompt.

Issue #1 is the build log: one comment per phase, from the first question to v1.0.15, including the bugs that reported success while doing nothing. Worth reading before changing the hosting, deployment or environment code — most of those decisions look arbitrary until you know what they are guarding against.

Issue #2 is the plan the cross-platform rework followed, including the traps it was written to avoid.

Issues and pull requests are welcome. Keep the C#-only rule: no Node, no web views, no native

dependencies beyond each platform's own libc or Win32. And keep the seam: new platform code belongs

in a platform assembly, and LiveClaude.Core stays free of operating-system conditionals.

MIT © Leandro Cannizzaro

LiveClaude is an independent project. It is not affiliated with, endorsed by, or sponsored by Anthropic.