Repository navigation
Conversation
Loopable for one Mac, in desktop/: the inbox, loops, connectors and agents as native UI drawn by MyGo, with no account and nothing hosted. Everything that is not a screen is the same TypeScript as the service, bundled into one file (src/desktop/engine.ts) that the app runs as a Node process: the dispatcher, a runner in the same process, and a JSON API on loopback that only the app's per-launch token can call. GitHub connects by device flow, since a public client can keep no secret; Google by a desktop client coming back to the engine's loopback address. The screens draw without a window in tests, and one test loads them from a real engine in a throwaway folder. CI vets, tests and builds the app on macOS. How it fits together is in docs/desktop.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…wning agents. Every page of the desktop app waited on the engine, which detected the three agent CLIs on every inbox and loops request, and a new page could not load while an older refresh was still running. Now the engine takes the agents from this host's runner inventory, which it detects on every heartbeat anyway, and the app loads each page's own data first, a newer refresh outranking an older one. Pages answer in tens of milliseconds. The engine also stops only when its parent is really gone, polling the parent id rather than trusting stdin's end; and the integration test waits for the runner to join before it looks at the pages, which it had reached too soon once they were fast. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Nobody using the desktop app should register an OAuth app, so the client IDs are no longer a Settings section. scripts/build-engine.mjs writes them beside the engine, from the environment when releasing or from the desktop entry of the gitignored config/oauth-app.json when developing, and a build without them says which connector it lacks. The app then shows that connector as not available rather than asking the person to fix it. GitHub's answer for an app with device flow off is device_flow_disabled, which now gets the same plain message as unauthorized_client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The desktop app now connects GitHub in one click with the account gh is signed in as on the Mac, which is the account its git already works as: nothing to register and no code to type. The engine asks gh for its current token every few minutes, so signing in again carries over, and only the desktop engine ever asks; the hosted service never looks. Device flow stays as the fallback when Loopable's app is built in. A connector that is not ready now says what this Mac is missing, in the engine's words, rather than blaming the build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app looked for the newest Node in every folder a version manager had made, including fnm's per-shell folders, of which a machine gathers thousands, and asked each one its version. Starting the engine waited on all of them. Now it takes the first Node along the login shell's PATH that is new enough, as a terminal would, skips fnm's per-shell links, and asks a Node reached by two paths once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app icon, the menu bar icon and the sidebar now use the Loopable mark from brand.tsx, not a gradient ring, a pixel ring and the repeat arrows. Connectors and agents show their real logos, copied from the web app's connector-icon.tsx, in place of two-letter tiles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Loopable for one Mac, in
desktop/. The inbox, loops, connectors and agents as native UI drawn by MyGo in Go: no web page, no webview, no account, nothing hosted.Everything that is not a screen stays the TypeScript the service runs.
src/desktop/engine.tsbundles the dispatcher, a runner in the same process (local-runner.ts, the CLI runner with the HTTP taken out) and a JSON API on loopback into one file the app starts as a Node process. Only the app's per-launch token can call it, and the engine stops when the app's stdin closes.Connecting services
src/connectors/github/device.ts): a public client keeps no secret, and needs no callback address. The OAuth app needs device flow turned on.oauthAppRegistrationtakes a client ID alone whenLOOPABLE_DESKTOP=1.Verified
render_test.go, andengine_test.goloads the screens from a real engine in a throwaway folder, saving a loop through the form.go tool mygo devran the app against the engine on this Mac; the engine restarted cleanly across a rebuild.pnpm test(417),pnpm typecheck,go vet,go tool mygo vet.Not yet
docs/desktop.mdsays where each goes.🤖 Generated with Claude Code