A plugin for CodeOnTheGo that turns the IDE into a real-time collaborative editor. Two phones on the same WiFi share one editing session: one device hosts, others join by typing the host's ip:port or scanning its QR code, and from then on edits, cursors, and file opens flow between devices as they happen — no server, no cloud, no signup.
It surfaces as a Pair tab in the editor. Host a session and an invite card shows the address and a QR code; join one and the peer list fills in. When the host types in MainActivity.kt, the guest sees the same file open and the text arrive keystroke by keystroke, with each peer's live position shown in the peer list.
cd pair
./gradlew clean assemblePluginThe .cgp lands in build/plugin/. Install it from inside CodeOnTheGo via the Plugin Manager. Always clean first — the plugin builder copies the built APK into the .cgp and then deletes the source APK, so an incremental build can package an empty artifact.
- Pair tab — contributes an editor tab and sidebar entry via
EditorTabExtension+UIExtension; the whole UI is Jetpack Compose (Home, Host, Guest, and QR-scan screens). - Edit sync — subscribes to the host IDE's
DocumentChangeEventon the EventBus for local edits and replays remote edits throughIdeEditorService.replaceRange(...). A single loopback guard stops an applied remote edit from rebroadcasting as a local one. - File-relative identity — a file's wire identity is its path relative to the project root (
IdeProjectService.getCurrentProject().rootDir). The sender strips the root; the receiver re-anchors to its own, so a session works across two devices whose projects live at different absolute paths. - Presence — cursor positions ride alongside edits; each peer gets a color, shown in the peer list and (with the extended API below) as an inline caret inside the editor.
- Transport — a star topology over
ws://: the host runs aWebSocketServer, each guest opens oneWebSocketClient, and the host echoes messages to the other guests. Messages are compact JSON (hi/edit/cur/fo/fc/ff/sync/bye). - Conflict handling — per-file sequence numbers with the host as authority; a divergence flags the session out of sync rather than dropping the edit, and the host can push an authoritative resync of the full file.
- Session history — past sessions persist as JSON under
IdeEnvironmentService.getPluginDataDirectory(); the Home screen lists them to rename, delete, or reconnect.
pair/
├── build.gradle.kts, settings.gradle.kts, proguard-rules.pro
└── src/main/
├── AndroidManifest.xml plugin id, main class, icons, permissions
├── assets/ icon_day.png, icon_night.png (190×190 interlocking-rings mark)
└── kotlin/com/appdevforall/pair/plugin/
├── PairPlugin.kt IPlugin + EditorTabExtension + UIExtension entry
├── data/ wire protocol, WebSocket server/client, session store
├── domain/ EditBroker orchestrator, observer/applier, path mapping, peer registry
├── ui/ Compose theme, components, and screens
└── util/ LAN discovery, QR decode
../libs/plugin-api.jar— the plugin API surface (IPlugin, extensions,Ide*Service);compileOnly, provided by the IDE at runtime.../libs/gradle-plugin.jar— thecom.itsaky.androidide.plugins.buildGradle plugin that packages the.cgp.../libs/eventbus-events.jar— the editor and file*Eventtypes Pair subscribes to on the EventBus.../libs/shared.jar—com.itsaky.androidide.models.Range, the type ofDocumentChangeEvent.changeRangethat Pair reads.
Jetpack Compose is linked compileOnly (host-provided), not bundled.
Note: Pair requires an extended
plugin-apibeyond the currentstagebaseline —IdeProjectService.openProject(File)(open a project after a pull-model sync) andIdeEditorService.showPeerCursor/hidePeerCursor/clearPeerCursors(inline remote-cursor decoration). These land on thefeat/ADFA-4419-remote-peer-editor-decorationbranch. IfassemblePluginfails with unresolved references to those symbols, the sharedlibs/jars are older than the API Pair needs; refresh them from a CodeOnTheGo build that includes the extensions (../scripts/update-libs.sh --local <path-to-CodeOnTheGo> --ref feat/ADFA-4419-remote-peer-editor-decoration).
Pair is an open-source example plugin for Code on the Go. Its source is licensed per the surrounding plugin-examples repository (see LICENSE at the repo root). It makes no cloud calls — all traffic stays on the local network between the paired devices.