Skip to content

Lody

A workspace where a team shares the coding agents it already runs: connect a machine, bring Claude Code, Codex, Kimi or any other agent that speaks the protocol, and dispatch work from desktop, phone, web or terminal while sessions delegate to each other and the code stays on the machine its owner connected.

Screenshot of Lody
Editor screenshot, 30 Sep 2026Lody ↗

What it is

A shared workspace for the coding agents a team already runs. A machine joins by starting a daemon from the command line, which opens a sign-in link and then stays available; the machine remains private until its owner shares it. Work is dispatched as a session from desktop, phone, web or terminal, and each session hands the conversation to an agent over the Agent Client Protocol, so Claude Code, Codex, Kimi, OpenCode or another compatible agent keeps the subscription, login, model and permission mode it was configured with. Sessions can be given their own git worktrees to work in parallel or forked into a second conversation, and inspected through per-turn or whole-session diffs with line-level comments and pull-request status next to the conversation. Agents are also given tools to create, read, message and cancel other sessions, which lets one conversation act as the coordinator of several; a running web application can be opened inside a session so element-level annotations can be sent back, and permission requests can be approved from a phone notification.

Who built itThe repository belongs to the LodyAI organisation rather than to a person, and the commit record reads like a team with automation in front of it. Of 1,201 commits, 296 are attributed to lodystage[bot], 274 to zxch3n, 262 to Leeeon233 and 223 to wibus-wee; 40 further accounts follow them, and the contributor list holds 44. The repository guidelines single those three logins out as the ones to count as the Lody team and treat everything else as community.

How it is put together

The parts · 6

One shared workspace, several surfaces, and the work itself left on the machines the team owns. A session runs a coding agent through the Agent Client Protocol, so the product does not implement agents — it supervises them: a per-machine daemon keeps them known and reachable, the session layer gives each one a git worktree and a durable history, and the desktop, phone, web and terminal clients are views onto the same conversation state rather than four applications. The state is the interesting part: collaborative state is represented with CRDTs and synchronised over the Loro stack, and the README is explicit that the direction is local-first and that the project has not arrived — the same foundation is meant to extend from conversations to documents. Two boundaries shape the code as much as the architecture does. The published source is only the two applications and their packages, with the hosted backend, operator configuration, private records and the web and mobile sources excluded, and the open-source desktop is local-only, so authenticated product-cloud requests are forbidden inside it. And the isolation is per session rather than per user: worktrees keep parallel agents from mixing changes, which is why so much of the command-line surface is git plumbing and process supervision.

apps/cli/
736 files and 11.2 MB: the daemon, the session layer, the agent layer, the tool surface and the git plumbing. The weight sits in a few files — a session execution service at 267,883 bytes, an agent client at 113,265, a session dispatch watcher at 110,836, a session manager at 95,959, a worktree manager at 61,447, a managed-runtime resolver at 55,841 and an authentication module at 47,025 — beside eight runtime manifests for the bundled adapters and a development build script of 12,071 bytes.
apps/electron/
226 files and 8.7 MB for the desktop application: main, preload and renderer processes, a separate developer toolbar with its own test file, a packaging script of 6,942 bytes with a 12,469-byte after-pack hook, four icon sizes and two macOS entitlement files, and a build that copies the command-line interface into the application instead of requiring it separately.
packages/
Thirteen workspace packages behind the two applications. components is the largest at 2,565 files and 33.7 MB — routes, the provider layer, stories, benchmarks and the conversation scroll engine; ui is 110 files of primitives and StyleX design tokens whose rule document alone is 52,835 bytes; shared holds schemas, protocols and session data; code-review-helper and code-review-viewer the diff and review surface; loro-streams-rpc the transport; cloud-api only the protocol names and types for the optional hosted composition. Eight acp-extension-* directories are git submodules with their own repositories, and two of them sit outside the root workspace graph entirely, consumed as separately built and checksummed artifacts.
specs/ and .agents/
The written system: 162 specification files in 595 KB with Chinese twins, 846 notes in 4.2 MB organised by lifecycle stage and category, and 28 explanatory documents. Every scope — the root, each application, each package, the site and the scripts — carries an instruction file under eight kilobytes, and each of those has a nine-byte CLAUDE.md symlink beside it, which is how one set of rules serves two different agent tools.
e2e/ and .github/
108 source files of browser-driven acceptance: twenty feature files with matching step definitions and page objects, scripted protocol fixtures standing in for real agents, a 52,485-byte journey registry, a failure-analysis scout, a load runner and an artifact convention. Around it sit fourteen workflows and 23 policy scripts, the largest of which selects the continuous-integration scope at 22,053 bytes and another of which authors test journeys at 18,174.
site-docs/
The website, documentation, blog and changelog, prerendered to static files with its own post-processing and a 23,059-byte browser verification script, plus generators for the sitemap, the feed, the documentation search index and the machine-readable summary files that sit in the public assets directory. 246 content files, two language trees, and roughly 39 MB of images under public/.

Choices, and what they beat

  • Supervise agents behind one protocol instead of building each integration over a separate first-party implementation for every assistant

    The README answers the question the same way in its first paragraph: connect any machine and bring any coding agent through the Agent Client Protocol. The consequence is written down for contributors — the adapter packages are public submodules with their own repositories, and adapter behaviour is to be fixed in those package sources first, not in the application that consumes them.

  • Publish the applications and their packages, and not the rest over releasing the whole product as open source

    The repository guidelines define the boundary explicitly: the public source is the two applications and their packages, while the hosted backends, operator and billing configuration, private secrets and records, and the web and mobile application sources are excluded. Captured user or agent transcripts must never be committed and fixtures must be synthetic, and the open-source desktop is local-only, where authenticated product-cloud requests are forbidden.

  • Collaborative state on CRDTs, moving toward local-first over a server-owned document that clients merely render

    The README states the intent and the unfinished part in the same section: the project wants the entire workspace, not only conversations, to become local-first, it uses the Loro stack including Loro and Flock to represent and synchronise collaborative state, and it says plainly that it is still moving toward full local-first support. The transport is therefore its own small package rather than a hidden detail of the server.

  • DeepSeek Harness deliberately stays out of the managed-runtime set over giving it the bundled adapter plus managed native runtime treatment

    The command-line overview lists Claude, Codex and Grok as bundled adapters with managed native runtimes and Kimi as a managed Node package, then separates DeepSeek Harness on purpose: it consumes a pinned profile from its own submodule, launches through an isolated package cache, and loads a bundled adapter, so the extension owns the model, reasoning-effort and permission selectors while the harness keeps ownership of model execution, sandbox enforcement and one-shot approvals.

  • Electron 43 rather than the newest major over jumping to Electron 44 while the upgrade was being done

    The pull request gives both reasons in full: 43 keeps the oldest supported macOS release and the synchronous clipboard call, while 44 drops that release, requires an atomic clipboard migration the project has only specified, and carries an open start-up crash. Upgrading at all was justified by the older line being out of support and by a feature flag it forced on every process.

Read fromapps/cli/scripts/dev-build.mjs, .agents/docs/cli-overview.md, the twenty-eight documents under .agents/docs/, the root AGENTS.md, specs/ and its Chinese twins, .agents/notes/implemented/process/*, the pull-request bodies for numbers 1154, 1155, 1156, 1157, 1168, 1171, 1176 and 1177, README.md (8,701 characters), and the complete 6,135-file tree with sizes and the two-level directory summary.

Build log

6 stages
  1. 01

    A public history that begins with a seeding commit

    The repository was created on 2026-08-07, and its oldest commit — dated twenty minutes later, 02:29 UTC the same day — is chore: prepare public source history [risk:high]: the published source history was prepared rather than accumulated. From there it ran for just under eight weeks and 1,201 commits, 437 of them in August and 764 in September, ending on 2026-09-30 with the commit that moved the desktop runtime to Electron 43. It is Apache-2.0 and 115,592 KB, and at the time of the report had 1,158 stars, 133 forks, 4 watchers and 146 open issues. Against that volume sits an unusually thin release surface: four tags — v0.88.0, v0.93.3, v0.100.0 and v0.102.0 — and only three GitHub releases, the last on 2026-09-30. What fills the gap is a changelog, apps/cli/CHANGELOG.md at 392,802 bytes and the desktop one at 115,024. The README sets out the mechanism and its limits in one paragraph: pushing a stable tag creates a draft pull request that synchronises every application version, followed by a release with generated notes, and no installers or auto-update files are built or uploaded, and the original tag is never moved. A note in the record directory is called changelog-only-releases.

  2. 02

    Who commits, and the trailer that names the model

    A bot is the largest single committer — lodystage[bot] with 296 of the 1,201 commits — and the three named maintainers follow at 274, 262 and 223, with 40 other accounts behind them. The co-author trailers are the part worth reading: 470 of them, of which 136 name a Claude model. The largest single group is Claude Opus 5.5 (1M context) at 50, then Claude Opus 5 (1M context) at 39, Claude Opus 5 at 16, Claude Opus 5.5 at 14, Claude Fable 5 at 10, Claude Fable 5.1 at 5, and one line each for Claude Sonnet 5.5 and for Claude alone. The second agent identity in the history is Cursor, twelve trailers in two spellings — nine Cursor and three Cursor Agent. After those come Devin on 10, Amp on 5 and copilot-swe-agent[bot] on 3. The remainder credit people: Zixuan Chen on 106, Leeeon233 on 56, Leon Zhao on 50, an account called Lody Dev on 35, and a Test User on 22. The trailers are not the only convention: the repository guidelines require that artificial-intelligence commits end with a Model: <runtime-model-id> line, and the pull request that prepared the 0.103.0 changelog shows three commits carrying Model: gpt-6.

  3. 03

    Three kinds of document, and the rule that keeps them apart

    The project draws a line and then obeys it: specs express intent, docs explain implementation, notes record decisions, each in its own tree. specs/ holds 162 files in 595 KB and almost every one has a Chinese twin — session-files.md at 28,420 bytes beside 25,131, ui-primitives.md at 30,289, session-sharing.md at 15,365, session-history-writes.md at 15,051. .agents/notes/ is larger still, 846 files and 4.2 MB, and it behaves like a state machine rather than an archive: implemented/ splits into architecture, bug-fix, feature, process, simplification and testing, with proposed/ and rejected/ beside it and a dated archived/ underneath, and the file name carries its own date — 2026-09-27-conversation-scroll-engine.md is 58,940 bytes. Twenty-eight further documents sit in .agents/docs/, and a single skill directory under .claude/skills/ holds a 9,988-byte document about the synchronisation stack. The enforcing rule is one sentence: non-trivial work must add or update the owning note in the same pull request, and only mechanical or local edits are exempt. The bilingual pairing is itself a written decision — a process note from 2026-09-12 is named agent-authored-notes-ship-both-languages — and instruction files are kept under eight kilobytes per scope, each with a nine-byte CLAUDE.md beside it that is a symlink rather than a copy.

  4. 04

    What a community pull request has to look like

    The contribution policy is carried by scripts: check-pr-body.mjs is 11,783 bytes, pr-policy.mjs is 18,897, and the pull-request template is 4,366. The text the template carries is blunt about forks and size: fork-based contributions must reference an issue, all policy findings share one seven-day correction period, a community pull request over 1,000 changed lines needs a maintainer assignment on the linked issue, and one over 200 with no prior issue adds what it calls a size-specific finding. Same-repository branches are exempt from opening an issue at all. On 2026-09-30 the account Jackey-Z filed six issues in one afternoon — 1170 through 1174 and 1178 — each with version, operating system and agent runtime. Dante-dan answered two of them with the mechanism rather than a promise: the reply to 1171 names the pre-provider halt path, the field promptStarted, why ordinary user turns keep their failure acknowledgement while post-start deliveries do not, and links a fixed comparison branch. Review is also partly automated: a Codex reviewer is wired to the repository and its brief tells it to report only the two highest severities, security first. The smallest thread is a feature request from Gabyran, who wanted @ to open the mention menu mid-sentence in a language written without spaces, and who called it a personal habit he dared to turn into a contribution.

  5. 05

    A build whose layout is load-bearing

    A developer document explains why the command-line build looks as it does, and most of the reasons are failures already paid for. Development bundles with esbuild in about three seconds and runs built JavaScript; there is no on-demand TypeScript loader fallback, so a development start cannot run from source. The output layout has to match production exactly, because the worker pools and the workspace watcher all locate their child by file name next to the module they were imported from; running from source would leave only TypeScript siblings, and the pools would fall back to the main thread with the reason recorded as worker_missing. The build script asserts after every build that no worker-resolving module was hoisted into the shared chunk directory, which would reintroduce the same fallback. Two further choices are marked load-bearing: dependencies stay external by absolute path, because the strict package layout has no entry for its transitive dependencies; and code splitting stays on so a dynamic import remains a real lazy boundary, without which a statically imported generated manifest would break even the version flag. The version number comes from a build-time alias, because importing the package manifest by relative path once baked a stale version into the published bundle, and it gives the evidence plainly: a published lody@0.82.1 printed 0.76.0.

  6. 06

    Measured rather than argued: the desktop, the poller, the frame budget

    Several pull requests carry numbers instead of adjectives. Moving the desktop runtime from Electron 39.5.1 to 43.7.6 came with the reasoning written out: 39 is out of support and force-disabled the system window-occlusion tracking; version 44 was refused because it drops the oldest supported macOS release, needs an atomic clipboard migration the project has only specified, and has an open start-up crash — so 43, which keeps the old macOS floor and the synchronous clipboard call. The next pull request is a performance measurement in its own body: with a window visible but not focused, four working marks and two spinners left the compositor drawing a frame every vertical sync — 120 Hz on that display — at 11.4 per cent renderer, 20.4 per cent graphics process and 46 per cent window server, against 2.2, 0.8 and 8.0 with every animation paused. Pausing on blur was rejected outright because the application often sits on a second display and would look frozen, so a frame budget was added that quantises every infinite animation to 30 frames per second while unfocused. The same habit shows on the daemon side: the pull-request reconciler is a compensation path for a broken hosted webhook, polls in a fast lane at 20 seconds and a slow one at 5 minutes, discovers unlinked pull requests every 20 minutes, has no turn-end hook at all, and keeps its scheduling state under the user home directory with an environment variable as the kill switch.

Adjacent records

All records →