VCode — feature documentation
VCode drives claude, codex, opencode and cursor from a phone. This
folder documents every feature, one file each, grouped by area.
New here? Read these in order: run it locally, reach it from a phone, start a thread, send a message, read the transcript. Keep navigation and commands open for the keys and gestures. Before you put it on a public hostname, read approvals are bypassed: anyone who can log in runs code as your user.
Install and security
Get it running on a machine, reach it from a phone, log in, keep it safe.
| Feature | What it does | Status |
|---|---|---|
| Install VCode on Linux with one command | curl -fsSL https://v-code.dev/install | sh installs the newest signed release on a Linux x64 machine, starts it, and links it to your v-code.dev account. |
beta |
| Install VCode on a Mac with one command | The same curl -fsSL https://v-code.dev/install | sh, run in Terminal on an Apple silicon or Intel Mac, installs the newest signed release as a launch agent and links it to your v-code.dev account. |
beta |
| Install VCode on Windows through WSL2 | irm https://v-code.dev/install.ps1 | iex in PowerShell sets up WSL2 and an Ubuntu distro with systemd, then runs the Linux installer inside it. |
beta |
| Install it as systemd user services | bash install.sh install puts VCode on a machine as a systemd --user service, writes its env file with a fresh login token, and starts it. |
stable |
| Log in with the token | Paste the server's AUTH_TOKEN into the sign-in card once per device. |
stable |
| Logs and troubleshooting | Every unit logs to the journal. | stable |
| Memory limits and parking idle tabs | The VCode unit runs inside a cgroup with a hard memory ceiling. | stable |
| Reach it from a phone | Two ways to open VCode on a phone: over a Tailscale tailnet, or over a Cloudflare tunnel with Cloudflare Access in front. | stable |
| Run it locally for a first try | Start VCode on your own machine with one command and open it in a browser. | stable |
| Where state lives, and how to back it up | Everything VCode remembers is plain files under one directory, VCODE_STATE. |
stable |
| The security model | Anything that can log in to VCode runs code as your user, so a login is full trust. | stable |
| The box updates itself | A box installed from a release checks for a new one every hour, installs it while no thread is working, and rolls back if it does not come up. | beta |
| Update an installed machine | bash install.sh update pulls the new code, reinstalls dependencies, migrates the env file, re-renders the units and restarts them. |
stable |
Remote access
Link the box to a v-code.dev account, pair a phone, and use VCode from app.v-code.dev.
| Feature | What it does | Status |
|---|---|---|
| Add a computer from app.v-code.dev | Copy one command from app.v-code.dev; it installs the box, links it to your account and pairs that browser, with no email prompt and no pairing code. | beta |
| Link this box to your v-code.dev account | Link the box with your email and an emailed code from v-code box link; it connects out to the VCode router. |
beta |
| Open this box from a phone or another browser | Sign in to app.v-code.dev and every box on the account opens; v-code box devices lists them, and the box can require a pairing code for new ones. |
beta |
| Use VCode from app.v-code.dev | Log in, pick a box, check its fingerprint, pair, and work through the router. | beta |
| Work on several boxes in one app | Every paired box opens at once: one strip with a badge per box, a box pick in New thread, and a box that is off marks only its own tabs. | beta |
Threads and tabs
Start work in a folder, move between tabs, rename, reorder, close and reopen.
| Feature | What it does | Status |
|---|---|---|
| The back button closes what is open | The phone's back button closes the top open layer — a sheet, a drawer, a viewer, the shell — one press at a time. | stable |
| Close, reopen and delete a tab | Closing a tab stops its agent and takes it out of the strip; the conversation stays on disk and the Threads sheet brings it back. | stable |
| Navigation and commands | Every way to move around and every command VCode runs, the phone way and the desktop way side by side. | stable |
| Open a tab from the composer with /new | Type /new in the composer to open another tab without leaving the composer. |
stable |
| Pick the folder a tab works in | The folder box in the new-thread form is a typeable list of your repos that also completes any path on the machine. | stable |
| Rename a tab | Give a tab a name of your own, either by editing it in the tab list or by typing /rename <name> in the composer. |
stable |
| Reorder tabs | Drag a tab along the strip, or a row up and down in the drawer or the Threads sheet, to put the tabs in the order you want. | stable |
| Start a new thread | Open a new tab: pick which agent runs it and which folder it works in, then tap Start thread. | stable |
| Swipe between tabs | Swipe the transcript sideways to move to the next or previous tab, in strip order. | stable |
| Switch tabs from the strip | The row of tabs across the top (#tabstrip) is every open thread. |
stable |
| Colour a tab | /colour blue paints a tab: the bar under it in the strip, its row's border in the tab lists, and the composer's edge while you are in it. |
stable |
| The tab drawer | Pull in from the left edge of the transcript for a list of the open tabs (#drawer). |
stable |
| A tab's working folder, and moving it | Every tab is rooted in one directory, chosen when the tab is created. | stable |
| The Threads sheet | The full tab manager (#sessions), behind All threads in the new-thread card, /resume, and the status bar's branch segment. |
stable |
Composer
Write and send: queue or steer, slash commands, model and effort, attachments.
| Feature | What it does | Status |
|---|---|---|
| Alt moves and deletes a word | With a hardware keyboard, Alt in the composer does what Ctrl does: a word at a time. | stable |
| Choose where your typing goes — Agent or Shell | Two chips at the top of the screen decide who reads what you type: the agent, or the shell pane. | stable |
| Send a photo or a file with your message | The + under the composer attaches a screenshot. |
stable |
| Clear the context with /clear | /clear starts the agent fresh in this tab. |
stable |
| Escape twice to clear the composer | Press Escape twice in a row and the composer empties. Attachments stay where they are. | stable |
| Each tab keeps its half-written message | Swipe to another tab and back and the text you were typing is still there. | stable |
| Hold backspace to delete whole words | Hold backspace in the composer and after two seconds it starts taking a whole word per repeat instead of one character. | stable |
| Edit, drop or steer a queued message | A message waiting to run has three buttons on its card: steer it into the running turn, pull it back into the composer to rewrite, or drop it. | stable |
| Queue or steer while the agent works | While a turn is running you can still type. | stable |
| Send a message to the agent | You type into the box at the bottom of the screen and send it to the agent running in the open tab. | stable |
| Set how hard the agent thinks | Effort is the reasoning dial: how long the agent is willing to think before it answers. | stable |
| The slash menu | Type / in the composer and a list appears above it: the commands VCode runs itself, and the skills the agent can load. |
stable |
| Type to start a message | With a hardware keyboard, start typing anywhere and the character goes into the composer. | stable |
| Switch the model for a tab | Each tab runs one model. | stable |
| What the CLI's own slash commands do here | A slash command typed here is not a slash command typed into the vendor's own terminal UI. | stable |
| Walk back through the prompts you sent | Press the up arrow in the composer to put the prompt you sent before back in it. | stable |
Transcript
What you read while the agent works: answers, tool output, plan, subagents, errors.
| Feature | What it does | Status |
|---|---|---|
| See what the agent is doing right now | While a turn runs, the last thing in the transcript is a live card that says what the agent is doing, how long the turn has been going, and gives you a way to stop it. | stable |
| Copy a reply, a prompt or an output | Each card has a copy button in its header, and each code block has one of its own. | stable |
| When the agent stops, and retrying | A card at the end of the transcript when the agent process died, a turn logged an error, or the thread is waiting out a usage limit. | stable |
| Formatted answers and coloured code | Replies render as markdown: headings, lists, tables, quotes and fenced code. | stable |
| Screenshots inside the transcript | An agent can show you a picture. | stable |
| Jump back to the latest message | Scroll up and a pill appears above the composer with a down arrow and a count of what arrived while you were away. | stable |
| Page through the transcript | PageUp and PageDown move the conversation a screen at a time, with the caret still in the composer. |
stable |
| Follow the plan strip | A band above the transcript (#planstrip) showing the agent's steps: one dot per step, the step it is on, and how many are done. |
stable |
| Track steps with the todo CLI | v-code todo is a command on every agent's PATH inside a thread. |
stable |
| Read the transcript | The middle of the screen (#thread) is the conversation: your messages, the agent's replies, its thinking, every tool it ran and every file it edited, in the order they happened. |
stable |
| Run a command from a code block | A bash code block carries a run control that sends the block to the tab's shell pane and runs it there. | stable |
| Choose how much of each step shows | The settings sheet sets how much of each step the agent takes shows in the transcript: thinking, tool calls, edits and system notes. | stable |
| Watch the subagents | A strip under the transcript (#subs) that appears when the agent launches subagents. |
stable |
| Terminal colour and one-tap links | Command output keeps the colours the program printed, and every URL in it becomes a link with a copy button beside it. | stable |
Files and changes
Browse the folder, read and edit files, see what a turn changed, review and comment.
| Feature | What it does | Status |
|---|---|---|
| Comment on a line of a file | Tap a line in the viewer, type what is wrong with it, and send it to the agent as a message that names the file, the line and quotes it. | stable |
| Review a diff and accept or revert it | One file's diff, full height, with every edit the turn made to it. | stable |
| Edit a file | Tap Edit in the viewer, change the text, and save it to disk. | beta |
| See which files changed, in the tree | The explorer marks changes the way VS Code does: a changed file's name takes a colour and a letter (M, U, A, D), a folder above it the colour and a dot, and what git ignores is grey. |
stable |
| Browse the thread's folder | A file tree of the folder the thread runs in. | stable |
| Open a file | One file from the explorer, in a sheet over the thread. | stable |
| Find a file by name | Type part of a name into the explorer's filter and the whole folder is walked for matches. | stable |
| Put a file path in your message | One tap in the viewer appends the open file's path to whatever you are typing, and gets both panels out of the way. | stable |
| Make, rename and delete files | Right-click or long-press a row in the explorer for New file, New folder, Rename and Delete. | beta |
| Open or download an attachment | Files you sent with a message stay on the message. | stable |
| Review code line by line | Gather comments across several lines and several files, then send the lot as one message. | stable |
| See the files a turn changed | Every turn that edited files gets a summary: a count in the status bar for the latest turn, a footer under each turn's last reply, and a popup listing the files with their line counts. | stable |
| See what changed in a file | The open file is marked with what has changed since the last commit: new lines are highlighted, and lines that were taken out stand where they used to be. | stable |
Agents and sessions
claude, codex, opencode and cursor: differences, resume, handoff, usage limits, compaction.
| Feature | What it does | Status |
|---|---|---|
| Log in to Claude or Codex from your phone | A logged-out agent's tab offers a login in place of Retry, and the settings sheet lists each agent's login per computer. | stable |
| Log in to Cursor from your phone | Shows a browser login link in the new-thread card when Cursor is not authenticated. | stable |
| Approvals are bypassed — the agent runs as you | Nothing in a VCode thread asks permission. | stable |
| Compact the context automatically | When a turn ends with the context over a token mark, VCode runs a compaction turn of its own before the next message goes in. | stable |
| Background and resumed subagents | An agent can launch helpers that keep working after the call that started them returns, and can pick one back up later. | stable |
| Hand a tab to another agent | Change the agent on a tab and keep the conversation: same tab, same title, same history. | stable |
| Memory headroom and parked agent processes | Every agent runs inside VCode's cgroup. | stable |
| Resume a session you started in a terminal | A claude, codex or cursor session you started in a plain terminal can be picked up in VCode. | stable |
| Work carries on after VCode restarts | When the VCode process goes down mid-turn, the tab does not sit frozen. | stable |
| The status bar | One line under the transcript with the facts about this tab right now: which machine, which branch, how much context, whether you are connected, and what is waiting. | stable |
| Stop a running turn | Cut the agent off mid-answer, with the ■ Stop button or Escape. |
stable |
| The four agents and what each one can do | A tab runs one agent: claude, codex, opencode or cursor. |
stable |
| Wait out a usage limit and resume automatically | When the agent's plan window is full, the tab pauses instead of failing. | stable |
| Read your plan usage | A row of meters above the transcript shows how much of each plan's quota you have spent, and when each window resets. | stable |
| What VCode tells every agent | Every agent started in a tab gets the same short instruction block and the same four environment variables. | stable |
Voice dictation
Talk instead of typing: the mic, the waveform or live text, installing the service.
| Feature | What it does | Status |
|---|---|---|
| Choose how a recording shows | The VCode machine turns every dictation into text; the cog picks a waveform or the words as you speak. | optional |
| Dictate a message | Speak into the composer instead of typing. | optional |
| See the words appear while you speak | With Live text, the words land in the composer as you say them, not after you stop. | optional |
| Dictate, then switch tabs before the words arrive | The words belong to the tab you were on when you recorded. | optional |
| When the mic button is missing or the microphone is refused | Two different failures look alike on a phone: no mic button at all, and a mic button that cannot open the microphone. | optional |
| Install the transcription service on the box | bash install.sh voice builds a python venv, downloads a 482 MB speech model, starts v-code-voice.service on loopback, and points VCode at it. |
optional |
| Point dictation at another service, or turn it off | VCODE_STT_URL is the only coupling between VCode and whatever transcribes a clip. |
optional |
| Retry a dictation that failed | When a transcription fails, the clip you just recorded is kept in memory for five minutes. | optional |
| Stop recording when you stop talking | A recording ends by itself after a set number of seconds of quiet, so you do not have to reach back for the stop button. | optional |
| What happens to the audio you record | Every dictation goes to the VCode machine; the clip is not saved anywhere and the transcript is never written to a log. | optional |
Offline and notifications
Install on the phone, work offline, get told when a thread finishes.
| Feature | What it does | Status |
|---|---|---|
| Install it on a phone | Put VCode on your home screen so it opens in its own window, with its own icon, and keeps working when the server is out of reach. | stable |
| Live updates and reconnect | The open thread streams from the server as it happens, and so does the tab strip. | stable |
| Open the app offline | The app opens and shows your threads with no connection to the server. | stable |
| Queue a message while offline | Send a message with no connection. | stable |
| The notification when a thread finishes | With notifications on, the phone buzzes when a thread settles: the agent finished with nothing queued behind it, it crashed, it is blocked on an approval, or it is waiting out a usage limit. | stable |
| Turn on notifications | Tap the bell to have this device buzz when a thread finishes, fails, or needs an approval. | stable |
| Update to a new build | When the server has a newer version of the app, a button appears in the top bar. | stable |
| Where notifications work | Which browsers can subscribe to push, which need something from you first, and where the bell is not offered at all. | stable |
Shell, machines and layout
Shell mode, the machine name, the wide layout, the icon legend.
| Feature | What it does | Status |
|---|---|---|
| Run one command with ! | Start a message with ! and it runs as a command instead of going to the agent; the card lands in the transcript. |
stable |
| The screen on a phone | Two bands of controls float over the conversation: everything above it in #overhead, everything below it in #underfoot. |
stable |
| What every icon means | Most controls in the app are a drawing with no words. | stable |
| Know which machine you are on | The first segment of the status bar is this machine's name. | stable |
| Send a keystroke to the shell | Keycaps for the keys a phone keyboard does not offer: Tab, Esc, ↑, ↓, ^C, ^L, ⏎ and ^D. |
stable |
| Run shell commands in the tab | Switch the composer from the agent to a shell. | stable |
| Split the window into panes | On a wide window the conversation area splits into panes, up to six across and six down, each holding some of your open tabs and its own status line, with the composer in whichever one has the focus, and you drag a tab from one pane to another. | stable |
| When the app talks back | A short message slides in under the top band when something happened that you cannot already see. | stable |
| The layout on a tablet or desktop | Given a wide enough window the frame fills it, the whole app is scaled up, the tab strip becomes a desktop tab bar, and the file explorer stops being a drawer and stands as a column beside the conversation. | stable |