Run agents in the cloud. Work as if they’re local.

Run agents locally or natively in the cloud. Keep long sessions going, close your Mac, and return right where you left off.

Coming soon Read the docs

Build your software factory. Give every agent an isolated place to work, repeatable workflows, and the tools to prove the result.

How Neroli makes cloud agents feel local

Main
Your workspace
Your workspace
Pick a session from the sidebar to get started.
+114-41
42<main>
43 <Gallery slides={slides} />
43 <section class="mx-auto w-[1116px] max-w-[calc(100vw-3rem)]">
44 <FlowMockup client:load scene={heroScene} />
45 </section>
68 <section class="grid min-h-[34rem] gap-8 border-t border-[var(--color-rule)] py-16">

One native workspace

Your Mac stays the control center.

Run Claude Code, Codex, OpenCode, and Pi locally or in the cloud, all from one native workspace.

Claude Code v2.1.212
Fable 5 with high effort · Claude Max
~/Library/Application Support/Neroli-dev-78be8359/worktrees/neroli/neroli-update-website-copy~/…/worktrees/neroli/neroli-update-website-copy
tighten the homepage copy and make the cloud workflow easier to understand
I'll trace the current story, update the copy, and verify the layout at desktop and mobile sizes.
Read(index.astro)
Read 286 lines
Read(HomeFeatureCard.astro)
Read 94 lines
Update(index.astro)
Clarified local and cloud positioning
Update(HomeFeatureCard.astro)
Aligned feature copy with product workflows
Bash(npm run check)
0 errors, 0 warnings
Updated the homepage story and verified it at desktop and mobile sizes. The site check passes.
>_ OpenAI Codex (v0.144.5)
model: gpt-5.6-sol medium /model to change
directory: ~/Library/…/neroli/neroli-update-website-copy
wire the command palette shortcuts into the new pane actions
Explored
Read CommandPalette.tsx
Read PaneActions.ts
Edited CommandPalette.tsx (+9 -2)
88 const actions = usePaneActions()
89 -register("Split pane", noop)
89 +register("Split pane right", actions.splitRight)
90 +register("Split pane down", actions.splitDown)
91 register("Close pane", actions.close)
92 +register("Move pane left", actions.moveLeft)
93 +register("Move pane right", actions.moveRight)
Explored
Read CommandPalette.test.tsx
Added CommandPalette.test.tsx (+4 -0)
142 +it("keeps focus in the active pane", async () => {
143 + await user.keyboard("{Meta>}k{/Meta}")
144 + expect(activePane()).toHaveAttribute("data-pane-id", "right")
145 +})
Ran npm run build
1999 modules transformed
8 page(s) built in 1.29s
Updated Plan
Shortcut wiring is in place; checking focus restoration.
Map split commands
Preserve active pane id
Verify palette close behavior
Done. The changes are in place and checks pass.
Ask Codex to do anything
Claude Code v2.1.212
Fable 5 with high effort · Claude Max
~/Library/Application Support/Neroli-dev-78be8359/worktrees/neroli/neroli-update-website-copy~/…/worktrees/neroli/neroli-update-website-copy
make the cloud settings controls match the mac app
I'll compare the native settings rows, then update the shared controls and their states.
Read(CloudSettingsView.swift)
Read 742 lines
Read(SettingsView.tsx)
Read 386 lines
Update(SettingsView.tsx)
Matched runtime and provider controls
Update(SettingsView.test.tsx)
Covered cloud picker state
Bash(npm run check)
0 errors, 0 warnings
The cloud settings now match the native control hierarchy and spacing. The picker state is covered.
>_ OpenAI Codex (v0.144.5)
model: gpt-5.6-sol medium /model to change
directory: ~/Library/…/neroli/neroli-update-website-copy
stop the auth refresh loop when the app wakes from sleep
Explored
Search refreshToken
Read AuthSessionStore.swift
Read AppSleepObserver.swift
Edited AuthSessionStore.swift (+9 -4)
211 guard !Task.isCancelled else { return }
212 -try await refreshToken()
212 +try await refreshTokenIfNeeded(now: clock.now)
213 +lastWakeRefresh = clock.now
214 scheduleNextRefresh()
Added AuthSessionStoreTests.swift (+5 -0)
301 +func testWakeDoesNotDuplicateRefreshTask() async throws {
302 + await store.handleWakeNotification()
303 + await store.handleWakeNotification()
304 + XCTAssertEqual(client.refreshCount, 1)
305 +}
Ran swift test --filter AuthSessionStoreTests
Executed 7 tests
OK
Done. The changes are in place and checks pass.
Ask Codex to do anything
Claude Code v2.1.212
Fable 5 with high effort · Claude Max
~/Library/Application Support/Neroli-dev-78be8359/worktrees/neroli/neroli-update-website-copy~/…/worktrees/neroli/neroli-update-website-copy
keep the active pane and terminal state when a session moves to cloud
I'll trace the handoff snapshot and reconnect path, then cover a round trip.
Read(CloudHandoffCoordinator.swift)
Read 816 lines
Read(SessionSnapshot.swift)
Read 428 lines
Update(CloudHandoffCoordinator.swift)
Restored the active pane after reconnect
Update(CloudHandoffTests.swift)
Added local-to-cloud round-trip coverage
Bash(scripts/build.sh)
** BUILD SUCCEEDED **
Cloud handoff now restores the active pane and terminal scrollback after reconnecting.
>_ OpenAI Codex (v0.144.5)
model: gpt-5.6-sol medium /model to change
directory: ~/Library/…/neroli/neroli-update-website-copy
tighten the feature layout across desktop and mobile
Explored
Read HomeFeatureCard.astro
Read global.css
Edited HomeFeatureCard.astro (+5 -3)
31 -class="feature-card"
31 +class:list={["feature-card", mediaSide]}
32 +data-visual={visual}
33 <div class="feature-media">
Edited global.css (+6 -1)
318 .home-feature-media {
319 - min-height: 460px;
319 + aspect-ratio: 3 / 2;
320 + min-width: 0;
321 + overflow: hidden;
322 }
Ran npm run build
Complete in 1.18s
Done. The changes are in place and checks pass.
Ask Codex to do anything

Isolated by design

Run more work in parallel.

Give every agent its own worktree and environment, so sessions can run side by side.

cloud-handoff-flow
>_ OpenAI Codex (v0.144.5)
model: gpt-5.6-sol medium /model to change
directory: ~/Library/…/neroli/neroli-update-website-copy
stop the auth refresh loop when the app wakes from sleep
Explored
Search refreshToken
Read AuthSessionStore.swift
Read AppSleepObserver.swift
Edited AuthSessionStore.swift (+9 -4)
211 guard !Task.isCancelled else { return }
212 -try await refreshToken()
212 +try await refreshTokenIfNeeded(now: clock.now)
213 +lastWakeRefresh = clock.now
214 scheduleNextRefresh()
Added AuthSessionStoreTests.swift (+5 -0)
301 +func testWakeDoesNotDuplicateRefreshTask() async throws {
302 + await store.handleWakeNotification()
303 + await store.handleWakeNotification()
304 + XCTAssertEqual(client.refreshCount, 1)
305 +}
Ran swift test --filter AuthSessionStoreTests
Executed 7 tests
OK
Done. The changes are in place and checks pass.
Ask Codex to do anything

Local or cloud

Keep agents running.

Work locally or let long sessions run in the cloud, even when your Mac is closed.

Main
Your workspace
Your workspace
Pick a session from the sidebar to get started.
+114-41
42<main>
43 <Gallery slides={slides} />
43 <section class="mx-auto w-[1116px] max-w-[calc(100vw-3rem)]">
44 <FlowMockup client:load scene={heroScene} />
45 </section>
68 <section class="grid min-h-[34rem] gap-8 border-t border-[var(--color-rule)] py-16">

Live validation

Don’t just read the diff. Run it.

Open the app, use the browser or simulator, and verify every result before you merge.

Your software factory starts here.

Coming soon Read the docs