An AI coding editor that runs on your own models and goes where you go. You work with an agent on a PC, and you can pick up the same session from a phone or iPad, at home or across the internet.
Dart + FlutterWindows · Linux · iPad · iPhonelocal or hosted LLMsend-to-end encrypted remote
The whole system
How the pieces fit
The PC is the host: it runs the agent, touches the files and calls the model. The phone is a remote control for that session. NomadCore is the engine both host apps are built on.
end-to-end encrypteddepends on / callsruns on one machine
The four repositories
What each one does
Move your pointer over a drawing to play with it.
ben/NomadEditor · Flutter app
NomadEditor
The app you see: a VS Code-style editor with an agent chat panel. Runs on desktop, and on phone or iPad as the remote control.
Code editorTabs, split view, syntax highlighting for ~40 languages, find in files, command palette.
Agent chatPlan and Implement modes, multiple conversations, @file mentions, slash commands, images for vision models.
You stay in chargeEdits wait for your review, down to single hunks. Shell commands need approval unless a rule allows them.
Git and terminalBranches, diffs, commit, pull, push, and a built-in terminal, locally or over SSH.
Fits any screenThree panes on desktop, a drawer on tablets, bottom tabs on phones.
ben/NomadCLI · command-line host
NomadCLI
The same agent without the GUI. cd into a project, run nomadcli, and chat in the terminal. Leave it running so a phone can connect.
Terminal chatType a message; approve commands and edits with y / a / n. Ctrl+C stops a turn.
Hosting/remote or --remote opens the session to phones on the LAN and through a relay.
One per projectEach folder gets its own Device ID and port, so several can run at once.
Setup commandsconfig, devices, status, init: set the model, relay, browser and paired devices.
ben/NomadCore · shared Dart package
NomadCore
The engine. Everything that does real work lives here, with no Flutter dependency, so the editor and the CLI behave the same.
Agent loopCalls the model, runs tools, pauses for your decisions, compacts long chats, keeps a to-do list and memory.
Built-in toolsRead, write, edit and search files; git; shell and background processes; diagnostics; web; sub-agents.
Model clientsAny OpenAI-compatible server, plus Anthropic's native API. MCP client for extra tools.
WorkspacesOne interface for files, git and shell, with local and SSH versions.
Project rules.nomad/project.json: allow/deny lists, check and format commands, hooks.
Remote hostDevice identity, pairing and encryption for the host side of a session.
ben/NomadRelay · small server, Docker
NomadRelay
An optional meeting point for when the phone and PC are on different networks, such as cellular. You host it yourself.
MatchmakerThe PC registers as a listener, the phone asks for that Device ID, and the relay joins them.
Blind forwardingTraffic is already encrypted end to end. The relay passes bytes along and can't read them.
No stateNo accounts, no database, no logs. A restart just makes both sides reconnect.
No port forwardingBoth sides make normal outbound WebSocket connections. Put a TLS proxy in front for wss://.
In motion
Two things that happen all the time
Connecting a phone
Modelled on RustDesk: devices trust each other, not an account.
Every host has an identity. An Ed25519 key pair, shown as a Device ID.
Pair once. The phone enters the host's address and a PIN (or scans a QR code). Next time it reconnects without one.
Agree on a key. X25519 and HKDF give a session key, and every frame is sealed with AES-GCM.
Pick a route. On the same Wi-Fi it connects directly. Otherwise both sides go through your NomadRelay.
Mirror the session. The phone shows the chat, edit reviews, command approvals and the to-do list, and can press Stop.
One agent turn
What happens between your message and the answer, on the editor, the CLI or the phone.
You ask. The message goes out with the project's AGENTS.md, the to-do list and any files you mentioned.
The model picks tools. It reads and searches the code, runs git, opens a browser page, and so on.
It pauses for you. Proposed edits show as a diff to accept in full, in part or not at all. Unlisted shell commands wait for Approve / Always allow / Deny.
Checks run. Formatters run on changed files and the project's check command reports errors, which go back to the model to fix.
Done. You get the answer and the changes, with undo or a one-click revert of the whole turn.