01 Documentation

Everything SofaCode does, and how to make it do it.

SofaCode is a remote control for the coding agent already running on your computer — Claude Code, GitHub Copilot Chat or OpenAI Codex, inside VS Code. This page covers the whole thing: installing it, pairing a phone, every screen in the app, running it over the internet, the SofaNode, and the command line behind all of it.

Written against the shipping code. Where a feature is on one phone and not the other, it says so. Prefer to watch? The Guides walk through install, pairing, everyday use, and flashing a SofaNode on video — with the steps written out beside each one.

01 · The three pieces

Nothing about SofaCode runs in a cloud we own. There is no accounts server and no relay in the middle — the phone talks to your computer directly.

  • The daemon runs on the computer where your code and your agent live. It watches Claude Code's transcripts, talks to VS Code, synthesizes speech, and is the only thing a phone ever connects to.
  • The VS Code extension is how the daemon reaches the editor: which window has focus, which session is running where, and the commands that type a prompt or answer a chat. It is installed for you and it is not optional in practice.
  • The app — Android or iOS — is the remote control. The Android build is also the one that runs on an Android TV Android; it is the same app at the same version, not a separate product. Optionally a SofaNode, the round desk device, which speaks the same protocol.
Requirements

Python 3.10+ on the computer, VS Code, and your own Claude Code, GitHub Copilot Chat or Codex subscription — SofaCode is the remote control, not the agent. The app needs Android 8.0+ or iOS 16+. On a television, Android 8.0+ with a D-pad remote; no camera and no microphone are needed, so pairing is by 8-digit code and you type with the remote.

02 · Install and pair

One command on the computer, then one scan on the phone.

  1. 1

    Install the daemon

    macOS and Linux:

    curl -fsSL https://dl.codedatda.casa/sofacode/install.sh | bash

    Windows, in PowerShell:

    irm https://dl.codedatda.casa/sofacode/install.ps1 | iex

    The installer sets up a Python virtualenv, puts sofacode on your PATH, installs the SofaCode extension into every supported editor it finds — VS Code, and, in beta, VS Code Insiders, VSCodium, Cursor, Devin Desktop and Antigravity — wires Claude Code's hooks, opens ports 17845/tcp and 5353/udp on a firewall you are already running, and registers it to start at login. Open a new terminal afterwards, then check it took:

    sofacode --version sofacode doctor
  2. 2

    Reload VS Code

    The extension is installed but a running window has not loaded it yet: Ctrl+Shift+P → Reload Window. The installer only reaches an editor whose command is on your PATH, so if your editor was missed — a fork like Cursor or Antigravity often is — run Ctrl+Shift+P → Shell Command: Install '<editor>' command in PATH (that's code, cursor, codium, and so on) and re-run the installer.

  3. 3

    Pair the phone

    Install the app first — out now on Google Play (Android 8.0+), and on the App Store (iOS 16+). A pairing window opens by itself the first time. To bring it back at any point:

    sofacode pair

    That prints a QR code and a numeric code in the terminal and opens the same thing in a browser at http://127.0.0.1:17846/pair. In the app: Machines → Scan QR code, or Enter pairing code if the phone has no camera. Scanning it with the phone's own camera app works too — the link is a sofacode://pair deep link. Every device gets its own token, revocable on its own.

    Scan QR Enter code Scan network Add by IP
  4. 4

    Grant the microphone

    Push-to-talk needs it. The setup guide asks on first run; you can re-run it any time from Settings → Help → Setup guide.

Pair more than one

Pair as many machines as you like and as many devices as you like — two phones to one computer, or one phone to several computers. Trust is keyed to the machine's identity, not its IP address, so a new DHCP lease or a router reboot changes nothing.

Pairing a television

On an Android TV Android the 8-digit code is the only pairing route, and the app does not offer a Scan QR button there — a TV has no camera. Open Machines → Add machine → Enter pairing code, then type the 8 digits from the pairing window with the remote. Most televisions have no microphone either, so the microphone step is skipped and you type rather than dictate.

Terminal running the SofaCode installer
Step 1. The one-line installer fetches the daemon, verifies it and sets up its own environment.
VS Code with the Command Palette open and SofaCode connected in the status bar
Step 2. After a reload, the status bar reads SofaCode · Connected.
The Machines screen: scan QR code, enter pairing code, linked machines, add by IP
Step 3. Machines: scan the QR, type the 8-digit code, or add a machine by address.
The onboarding step asking for microphone access
Step 4. Grant the microphone once; dictation and push-to-talk both use it.

03 · The deck

The home screen. A state ring you can read across a room, and everything else arranged around it. It is one drawn canvas rather than a stack of widgets, so it reflows the same way from a tablet down to a two-inch screen.

The ring

  • TapDictate on the phone into the deck's response box — or stream to the computer's mic bridge, if you turned that on in Settings.
  • Tap the boxType or edit what is in it with the keyboard.
  • HoldSend what is in the box.
  • Two tapsMove to the next VS Code window.
  • Three tapsClear the box and start over.

Swipes

  • Swipe upOpen the session — the same as the open session pill. A drag that starts inside the quick look scrolls it instead.
  • Swipe downClear the box — the same as three taps.
  • Swipe rightThe session picker — everything running in the current project.
  • Swipe leftThe menu.
  • Drag the quick lookScroll back through the replies; open session or a swipe up is the whole conversation.
  • Tap ⓘBottom right — tooltip mode: tap anything to learn what it does. Tap ⓘ again to leave.

What else is on it

  • The machine pill at the top switches computers, with a badge counting sessions that need you anywhere.
  • The window pill picks which VS Code window prompts land in. A pick aims every app, the node and the computer at it, and the next switch — by anyone, on any device or at the computer — moves everyone together.
  • The quick look under the ring follows the aimed session as it streams and shows the whole transcript the way the chat does — replies with code, tool calls with their output, tasks — drag it to scroll back — and the prompt box under that holds what you dictated or typed until you hold the ring.
  • The ⓘ button at the bottom right puts the deck in tooltip mode: tap anything for a one-line explanation of what it does; tap ⓘ again to leave.
  • The open session pill at the bottom opens the whole conversation.
  • Attention bubbles float between the machine pill and the ring for sessions elsewhere that need you (amber) or just finished (green). Tap one to jump straight into that conversation.
  • Approve and deny appear in their own reserved slot when a permission prompt is waiting, so the ring never jumps.
Small screens

Node mode Android strips the deck to ring, state, machine and chat, and turns the outer edge into a rim dial that scrubs sessions. It switches itself on for watch-class screens; Settings → Node → Node mode overrides either way.

The big screen, and the remote

On an Android TV Android the deck opens in the same landscape layout a phone gets on its side: the session rail down one edge, the ring in the middle, the reading bands beside it. Because the deck is one drawn canvas rather than a stack of widgets, there is nothing for a remote to tab through — so the D-pad moves a focus ring between exactly the controls a finger would tap, and drawing that ring is the only thing the TV adds. OK presses the focused control, holding OK is the long-press (submit, or a row's actions), and Back steps out of whatever the last press opened.

Two things a television does not have, and the app does not pretend otherwise: no microphone, so the ring reads TAP TO TYPE and there is no dictation — talk to the same session from your phone instead; and no browser worth opening, so a link shows you the address to type somewhere else rather than launching one.

The deck in the WORKING state
Working. The ring breathes while the agent is busy; the last line of its reply runs under it.
The deck in the NEEDS YOU state with a check and a cross
Needs you. The badge on the machine pill, the amber ring, and the inline check / cross.
The Machines screen
The machine pill. Tap it for the Machines list: pair, switch, or pin one.

04 · Chat

The running session, live. Code blocks render properly, the agent's task list ticks off as it goes, and its thinking is there if you want it.

  • Sending. Tap send to steer the running turn. Long-press send for Interrupt and send now or Type into input only.
  • The microphone in chat is the phone's own dictation — it types into the box for you to read before sending. The deck's ring is the wireless voice mode that goes straight into the editor. They are deliberately different things.
  • Attachments. Take a photo, choose an image, or add a file as text. Images are re-encoded down to the machine's size cap before they are sent, which strips their location data on the way.
  • Long-press any message for Read aloud from here, Speak this and Copy text. Select text inside a message and you get Speak too.
  • The Tasks pill in the action row opens the agent's checklist; swipe down or back to return.
  • Skills. Type / at the start of a prompt and the machine's skills and commands appear above the composer without taking the keyboard — your skills, the project's, installed plugins' and Claude's built-ins, pulled from the computer you are aimed at. On all three assistants: Claude Code and Copilot Chat's own commands insert as typed, and Codex's skills insert typed with a leading $. Tap one to insert it (nothing is sent until you do), long-press to pick several and insert them together, star the ones you use so they sit at the top. Type / then a space and the menu gets out of the way. The Skills pill in the action row opens the same list with search.
  • The bar across the very bottom is how much of the context window is gone — amber at 80%, red at 95%. Tap it for the full stats. It is hidden entirely for Copilot, which does not report context accounting, rather than shown as zero.
  • The action row holds files, terminal, approve/deny, stop, the permission mode, compact, and the speaker toggle. Anything the machine cannot do is absent, not grayed out.
  • The menu (top left) has switch session, provider, model, slash commands, skills, the system prompt, stats, usage (Claude Code and Codex — Copilot has none to show), and windows & projects.
Models

For Copilot the picker lists the models VS Code actually offers on that machine and switches with a real command. For Claude Code it types /model <name> at the session, because that is the only lever Claude Code exposes. For Codex the picker lists its models and sets the default it uses for new sessions.

Models from your own hardware — LM Studio, Ollama, any OpenAI-compatible server — land in the same Copilot list once you turn on Local LLM (beta) in the extension. The full guide covers each server from install to first reply.

The chat transcript with the action row
The transcript. Streaming reply, the Stop · Mode · Compact row, mic and attachments under it.
The Switch model list: default, fable, sonnet, opus, haiku
Models. Tap the model name in the header to switch — the same list /model gives you.
The session stats screen
Session stats. Tap the context bar: elapsed, prompts, model, the token breakdown and context window.

05 · Sessions

Every session on every paired computer, in one tree: machine, then folder, then session. Sort by recent, by what needs you, or by name. Search does not persist between visits; your sort and your collapsed folders do.

  • Star a session to pin it to the top and exempt it from the auto-archive sweep.
  • Archive hides a session everywhere — it is machine state, so every device paired to that computer agrees. There is a seven-second undo, and an Archived sessions screen that scans by an allowlist, so something archived months ago is still findable and unarchivable.
  • New session asks which computer, where, and which assistant. It can open a project or launch an empty VS Code window and wait for it to come up.
The sessions list grouped by machine and project
Every session, every machine. Filter, sort, star, archive, or start a new one.

06 · Files and terminal

Both are confined to the session's project root by the daemon, not by the app — .. and symlink escapes are refused on the computer's side.

  • File browser. Browse, upload, download a file or a whole folder as a zip, rename and move. Controls the machine has not enabled are absent rather than disabled.
  • Code editor. A text editor, not an IDE: line numbers, find, wrap, undo. A save carries the checksum the file had when you opened it, so if something else changed it underneath you get a conflict with Overwrite / Reload / Cancel instead of a silent clobber. Files over 512 KB open read-only.
  • Terminal. Runs in that session's VS Code window or refuses — it is routed by session, never by "whatever was focused". There is a curated set of common commands, your own favorites, command recall, and a real interrupt button.
The project file browser
File browser. The project on the machine; tap a file for reference-in-chat, editor, or download.
The code editor open on CHANGELOG.md
Code editor. Line numbers, find, wrap, undo — saves straight into the project.
The terminal with saved command shortcuts
Terminal. A real shell on the machine, with saved command shortcuts.

07 · Permissions

When the agent asks to run something, Claude Code blocks and the daemon holds the question open until somebody answers it. The answer can come from the phone, the SofaNode, or the computer — first answer wins, and the others are told it was already decided.

The full-screen card names the machine, the folder, the tool and the exact command, with a countdown. Nothing is auto-approved: if no device answers before the timeout, the request is denied.

Bypass mode

Settings → Permissions is the only place a machine's default can be set to a mode that stops asking, and it applies to new sessions only — nothing can push a running session into another mode from outside. When a machine is in bypass, the approvals screen says so plainly instead of just looking empty.

A permission card: Bash npm test -- --coverage with 234 seconds left, Allow and Deny
The card. Machine, session, the exact command, a countdown — Allow or Deny.

08 · Remote access — using it away from home

On your own network, nothing is exposed to the internet at all. Remote access is the opt-in that lets the same app reach the same computer from anywhere: a coffee shop, a hotel, a phone on mobile data. It is off until you turn it on, and it is turned on from the computer's command line — a paired phone deliberately cannot enable it.

At your own risk

Remote access exposes, over the internet, the ability to type into your editor, run commands, read and change your files and approve what an AI agent asks to do — remote code execution by design. Attacks on exposed endpoints are increasingly automated and AI-driven; SofaCode's protections reduce the exposure and nothing eliminates it. We accept no liability for use of SofaCode beyond your own local network (Terms of Use, section 4). So it asks twice: sofacode remote start shows the warning and waits for you to type I ACCEPT (once per Terms version; --accept-risk for scripts), and each phone, tablet, TV and watch keeps to your own network until it has accepted the same warning — in the remote-access wizard, or when the deck offers it because a paired machine has remote access on. A SofaNode set up from a phone that has not accepted is provisioned LAN-only.

What actually gets published

Exactly two routes: the device socket and the gateway relay. Pairing, the local API, /status, /config and file transfers live on a different listener that is not published at all, so a forwarded port cannot expose them even by accident.

Pairing never goes over the internet

Pair on your own network first, once, per device. A pairing request arriving from outside is refused, and there is no setting to loosen that. It also means you cannot finish setup while you are already away — do it before you travel.

Turning it on

  1. 1

    Pair on the LAN

    If the phone is already paired, this is done.

    sofacode pair
  2. 2

    Pick a way in

    Print the walkthrough with the details for your machine at any time:

    sofacode remote setup

    A Cloudflare tunnel is the usual answer: nothing to forward, nothing to open on the router, and the certificate is a real one. Install cloudflared, then either take the throwaway hostname:

    sofacode remote start # prints the risk warning; type I ACCEPT to continue (once per Terms version)

    …or use a named tunnel you own, so the hostname survives a restart:

    sofacode remote token <TUNNEL_TOKEN> sofacode config --set remote.hostname=sofa.example.com sofacode remote start

    Or forward a port yourself and let the daemon serve TLS from a certificate it generates once. The app is given that certificate's fingerprint over your own network and refuses anything else afterwards:

    sofacode config --set remote.mode=direct sofacode config --set remote.hostname=sofa.example.com sofacode remote start

    Then forward TCP 17847 to that machine.

  3. 3

    Check it

    sofacode remote status

    It prints the address clients will dial, the certificate fingerprint in direct mode, and — when the tunnel is not running — the last error and the last few lines cloudflared printed.

Your phone does not need re-pairing

The moment remote access comes up, the address is pushed to every device that is already paired, over the connection it already has. A phone or a SofaNode paired months ago simply learns the way in. Away from home it tries the local addresses first and falls back to the remote one.

Two rough edges, honestly

Use sofacode remote token for a tunnel token. Setting it through sofacode config --set remote.tunnel_token=… works until the next restart and then silently drops you back to a throwaway hostname — secrets are kept out of the config file on purpose, and only the dedicated command writes them where they survive.

Do not add a Cloudflare Access service token yet. The config keys exist, but no SofaCode client sends those headers — putting Access in front of the tunnel locks out your own phone.

One door for a whole house of machines

If you have several computers, you do not need a tunnel for each. Turn one of them into a gateway and the others are reachable through it:

sofacode remote gateway on # then restart the daemon — it reads this at startup

A device still authenticates to the machine it is actually talking to; the gateway only carries bytes. Android + SofaNode — the iOS app has no relay path yet, so an iPhone needs a direct address for each machine.

How it is kept safe

  • A connection from outside must use the mutual challenge-response handshake. A device offering a plain token is rejected, not quietly accepted — the token never crosses the internet in either direction.
  • "Is this connection remote?" is decided by the daemon, from the socket, and every signal it uses can only push a connection towards remote. A client cannot claim to be local.
  • In direct mode the app pins the exact certificate, handed to it on your own network. A swapped certificate fails.
  • Every device has its own token. Revoke one without touching the others: sofacode paired revoke.

Turning it off

sofacode remote stop sofacode remote status

The tunnel is terminated and the listener goes back to loopback only. Status will say it is disabled — the mode you chose is remembered for next time, but nothing is listening.

Terminal: sofacode remote status reporting OFF
sofacode remote status — off by default; nothing is published until you turn it on.

09 · The SofaNode

The optional round-screen desk device. It is not required — the app is the full product — and it runs on the same SofaCode subscription. Buying one includes 3 months free: a 3-month subscription code for Google Play or the App Store arrives with your order confirmation. The product page has the full story; this is how to drive it.

Setting one up

  • Flash it with the web flasher — Chrome and a USB-C cable, no terminal. It can set the Wi-Fi and the clock's timezone at the same time.
  • Or join its own Wi-Fi network and configure it from a browser.
  • Then scan the QR it shows from Settings → Node → Set up a SofaNode. Every machine you have paired is pushed to it at once, each with its own revocable credentials. A valid scan burns the code, so a failed setup needs a fresh QR rather than a retry.
  • It updates itself from then on — at boot, or from its own menu.

Its screens

  • DeckThe state ring, and a small bar above the SOFANODE label that counts sessions needing you and replies you have not heard — yellow when something needs you, ember when it is only audio waiting. Tap the bar to jump to the next one; when they are all visited a tap opens Sessions.
  • Swipe upThe transcript. Swipe up again for the task list.
  • Swipe rightSessions.
  • Swipe leftThe menu — machines, pairing, Wi-Fi, assistant, update, power. Swipe down inside it for your usage; swipe right to put it away.
  • Turn the rimMove between VS Code windows; roll past either end to switch to the next paired computer.

Every control

  • DeckTap: mic on or off. Hold: send. Swipe up: transcript. Swipe down: clear the prompt box. Left: menu. Right: Sessions. Rim: next or previous VS Code window; past either end, the next paired machine. While Claude Code is waiting on a prompt, a tap steps through its options and a hold confirms. If the deck says NEEDS YOU with no card up, swipe up allows and swipe down denies the session it is following. On a permission card, swipe up or hold allows, swipe down denies. The bottom arc says what tap, hold and swipe do right now.
  • State ringREADY — dim orange, solid. WORKING — amber, breathing, with an orbiting comet. NEEDS YOU — yellow, hard blink. ERROR and OFFLINE — red pulse. LIVE — a waveform while the mic is open. SPEAKING — a small waveform in place of the word. A white flash marks a chime.
  • Notification barSolid and pulsing while some flagged sessions are unvisited; hollow once you have seen them all but they still wait on you. Reaching the Sessions screen by any route clears it.
  • ChatTap: jump to the newest line and follow live again. Hold: voice on or off — one switch, for every session. Left or right: page three lines. Up: Tasks. Down: deck. Rim: one line per notch.
  • TasksThe title counts done / total. Tap: next page of six, wrapping. Up, left, right or the rim: scroll. Down: back to Chat.
  • SessionsGrouped by VS Code window under a > WINDOW header; up to twenty-four rows, five on screen. The right edge shows ◉ on the followed row, a pip for a held reply (solid unheard, hollow once played), otherwise the session's permission mode. Tap: the row's action list. Hold: follow it. Up or left: next row. Right: previous. Down: deck. Rim: one row per notch.
  • Session actionsFollow · Allow and Deny (only while it needs you) · Mode (tap cycles it on Claude; Copilot and Codex set it on the phone) · New session (in that window, with that assistant) · Play reply while unheard, Clear reply once heard. Swipe down returns to the list.
  • New sessionMenu > New session starts a fresh session in the window you are working in (the daemon's usual routing) for the Provider you chose. A sessions row's New session starts one in that row's window. Needs a live link; the answer is a toast.
  • MenuSwipe left opens it — from the deck, and from the setup, search and pairing screens. Rim: move. Tap: pick. Down: back up one level, or Usage from the top level. Right: close, from any depth. Rows, in order: Silent (shown first) · Machines · Pair from app · Pair by code · Wi-Fi · Chime vol · Voice vol · Voice · Provider · Color · Time zone · Clock · Screen · Charge lit · Wake tap · Usage · Update · Auto update · Held replies · Touchpad · Open touchpad · Screensaver · Saver idle · Update check · New session · Sleep · Power off.
  • SilentMenu > Silent mutes chimes and spoken replies on this Node only — the phones and any other Node are untouched. The ring still flashes, and when no node can hear, the replies it would have read are held as dots on SESSIONS until you turn it off. Sleep and Power off are unaffected: a silent Node still sleeps, wakes and powers off the same way.
  • UsageMenu > Usage, or swipe down from the top of the menu. The 5-hour window as a ring (yellow from 75%, red from 90%) with the reset countdown, the 7-day bar, and a bar for the scoped model when there is one. Tap: refresh. Right: deck. Up: back to the menu.
  • TouchpadMenu > Open touchpad — the row appears once Touchpad is on and the machine can move a cursor. Drag moves. Tap: click. Hold: right click. Rim: scroll. Pull down from the band at the top to exit.
  • ScreensaverNight rain (the default), Heat shimmer, Rose window, Console, Drafting, Build pass, Murmuration, or Off. Saver idle sets the wait, 1 to 30 minutes (5 by default). It never starts while a session is working or waiting on you, or over the setup and pairing screens. Any touch dismisses it and does nothing else.
  • Sleep vs Power offMenu > Sleep turns the screen off and stays connected; the function button wakes it — a tap on the glass too, once Wake tap is on. Power off is deep sleep with Wi-Fi off; only the button wakes it, as a fresh boot. The button on its own: tap sleeps or wakes the screen, hold two seconds powers off.
  • Pair from appThe QR carries the Node's address and a 16-character code, printed under it as two groups of eight — scan it, or type both into the app after tapping Enter code instead. It lives ten minutes and dies after five wrong codes or when Wi-Fi drops; raise a fresh one from Menu > Pair from app.
  • Pair by codeNo phone handy? Menu > Pair by code scans your network for machines; tap one, the computer shows an 8-digit code, and you dial it on the Node.
  • Wi-Fi portalWith no network stored the Node raises its own open one, SofaNode-XXXX (the last four of its MAC). Join it and open http://192.168.4.1; the join is tested before it is saved. Later it lives under Menu > Wi-Fi > Setup network.

Speaking, with more than one agent running

Only the session the Node is following is read aloud as it arrives — a dozen agents talking over each other is not a feature. When one of the others stops, it holds its last reply and raises a pip on the SESSIONS screen.

  • Tap a pip rowOpens its action list; pick Play reply.
  • Once heardThe same list offers Clear reply.
  • Hold a rowFollows that session — ring, transcript, tasks and spoken replies — and stays there until you go back to your keyboard.

Turn the voice off and the pips go with it; they are an offer to play something. A tap during playback stops it, the way you would interrupt a person.

The Node pairing screen with QR and 16-character code
Pairing. The QR, the address and the 16-character code, the moment it is on Wi-Fi.
The Node deck at rest
The deck. Clock, state, the session and machine it follows.
The Node chat transcript
Swipe up. The transcript on the circle.
The Node task list
Swipe up again. The task list.
The Node sessions list with an unheard-reply pip
Swipe right. Sessions, with the unheard-reply pip.
The Node root menu
Swipe left. The menu — machines, pairing, Wi-Fi, voice, assistant, update, sleep and power.

10 · Settings

Whole sections are hidden rather than grayed out when nothing you have paired supports them, so the list is only ever as long as it is useful.

  • LookSix themes — Ember (the default, matched to the SofaNode), Ice, Phosphor, Plasma, Volt and Console. App language: English, 繁體中文, 简体中文, or follow the phone. "Assistant replies in" is separate and off by default, because both agents already mirror the language you write in.
  • SpeechRead replies aloud on the phone, with voice, rate and pitch. This is the phone's voice; the SofaNode's is set on the Node.
  • NodeNode mode Android, SofaNode setup, and the firmware version of every Node your machines can see.
  • XR glassesAndroid A heads-up display on USB-C glasses the phone already sees as an external screen. Placement, text size, and head tracking with a recenter.
  • FloatingAndroid A draggable orb over other apps: tap to talk, hold for mic, send, approve, deny and stop.
  • TransfersUpload and download limits, and where downloads land.
  • Remote accessThe guided setup, and the remote address per machine. Appears once a machine is paired.
  • PermissionsPer-machine default permission mode. See 07.
  • SessionsAuto-archive age, whether starred sessions are exempt, and the archived list.
  • AccountSubscription status, restore purchases, manage subscription.
The Settings screen
Settings. Identity, SofaNode, Look, Sound + touch — sections hide when nothing paired needs them.
The theme picker with six themes
Look → Theme. Ember, Ice, Phosphor, Plasma, Volt and Console.

11 · The command line

Everything the app does is available on the computer too, and a few things are only available there.

  • sofacode runRun the daemon in the foreground. Normally it is started for you at login.
  • sofacode pairOpen a pairing window: QR, code, and every address a device can reach this machine on.
  • sofacode pairedList paired devices; revoke one by name without disturbing the rest.
  • sofacode doctorCheck the install — Python, the extension, the hooks, the audio bridge, the ports — and print how to fix whatever is wrong.
  • sofacode remotesetup, start, stop, status, token, gateway. See 08.
  • sofacode configRead and write the config file — --set section.key=value to change one thing, no arguments to print it all. A secret (a tunnel token) is routed to the credentials sidecar automatically.
  • sofacode install-hooksRe-wire Claude Code's hooks (and uninstall-hooks to remove them). They are merged into your existing settings, which are backed up first.
  • sofacode install-serviceStart at login.

Where things live

  • Config~/.config/sofacode/config.toml — secrets are kept in a separate file with tighter permissions, never in here.
  • Paired devices~/.config/sofacode/paired.json
  • The daemon~/.sofacode/ (Windows: %LOCALAPPDATA%\SofaCode)
  • Ports17845 devices · 17846 local API, loopback only · 17847 remote ingress, loopback until you turn remote access on
Config from the phone

Most config sections can be read and written from the app. Remote access and voice cannot — remote because turning on internet access should need a hand on the computer, and voice because the SofaNode's own menu owns it.

Terminal: sofacode doctor with every check OK
sofacode doctor — every check, and the status endpoint.
Terminal: sofacode paired list
sofacode paired list — every phone, watch and Node that holds a token.
Terminal: sofacode config output
sofacode config — the effective configuration, secrets masked.

12 · When it goes wrong

The app cannot find my computer+

Run sofacode doctor on the computer — it checks the ports, the extension and the hooks, and prints the fix for whatever it finds. If discovery is the problem (some networks block mDNS), use Machines → Add by IP with the address sofacode pair printed.

It connects, but prompts do not land in VS Code+

That is the extension. Reload the window (Ctrl+Shift+P → Reload Window) and check the window appears in the app's window picker. A window that is not listed has no extension loaded.

Remote access worked, then stopped after a reboot+

Almost always a tunnel token set the wrong way. Use sofacode remote token <TOKEN> rather than config --set, then sofacode remote start. Confirm with sofacode remote status, which names the hostname clients will actually dial.

I cannot pair while I am away from home+

Correct, and deliberate — pairing is refused over the internet and there is no setting to change that. Pair on your own network before you travel.

The SofaNode says OFFLINE, or sits on SEARCH / finding daemon+

It cannot reach any address it knows for the machine. Check the daemon is running, and re-run Settings → Node → Set up a SofaNode to push a fresh list of addresses — that is also how it learns a remote address after you have turned remote access on.

The Node is not speaking+

Speech is synthesized on the computer, so the computer needs a synthesizer installed — piper-tts or espeak-ng. Without one the Node stays silent rather than erroring, and the unheard-reply pips do not appear at all. Check the voice switch in the Node's own menu too.

Is any of my code sent anywhere?+

No. The phone talks directly to the daemon on your own machine. There is no server of ours in the loop — there isn't one. With remote access on, the traffic goes through an encrypted tunnel you own to the same daemon.

Still stuck? Report it — the form asks for the versions, the steps and a screenshot, and if a SofaNode is involved it opens a second set of questions about the device itself. Include what sofacode doctor printed and it will be a much shorter conversation. Prefer to just talk? Get in touch.

Nothing broken, but it does not do the thing you need? Ask for it — the apps, the watches, the desktop side and the SofaNode hardware all take requests through the same form.

13 · Direct downloads

The only thing you install by hand is the computer half, and the one-line installer in Install & pair does it for you. These direct downloads are here for air-gapped machines, custom setups, and the curious.

SofaCode daemon

The small background process that bridges the app and VS Code. Python, cross-platform — Windows, macOS, Linux, and arm64 boards like a Raspberry Pi.

Get the daemon ⟩

VS Code extension

Streams the live session, terminal output and window info back to the daemon. The daemon installer drops it into every supported editor it finds — VS Code, and, in beta, Insiders, VSCodium, Cursor, Devin Desktop and Antigravity — or grab the .vsix to sideload.

Get the extension ⟩