jaygupta17/otto

Run agents on a cloud machine. Steer them from your desktop or phone.

TypeScript

11

33 commits

updated Oct 16, 2026

See the code

See what people are saying

SourceMessageScoreDate

I built a desktop and phone app for OpenCode v2 that runs your sessions on a cloud machine (r/coolgithubprojects)

I wanted to run coding agents on hardware I control and still use them from my phone, so I built Otto. \- Connect to an agent server you run, with its URL and password. The app talks to it directly over HTTPS. No Otto backend, account or telemetry. \- Or let Otto set one up for you on Boat, boxd,…

8

Oct 13, 2026

Show HN: Run your agents across E2B, Daytona and more. steer them from anywhere

1

Oct 13, 2026

README

Otto

Otto

Run coding agents on a cloud machine and steer them from your laptop or phone.

Website · Download · Changelog

An agent adds link expiry to a small URL shortener, writes tests and gets them passing


Otto is a desktop and mobile app for OpenCode v2. Paste a sandbox API key and Otto starts a Linux machine, installs OpenCode, keeps it running as a service and connects to it over HTTPS. Your agents keep working when your laptop sleeps, and you can check in from your phone.

It runs on macOS, Windows, Linux, iOS and Android, built with Tauri 2.

What you can do

  • Start a workspace in one step. Choose Boat, boxd, E2B or Daytona, paste a key, and Otto sets up the machine. Or connect any OpenCode v2 server you already run.
  • Work with agents in a live conversation. Replies stream as they are written, and every file read, edit and command the agent runs is listed step by step. Stop or steer a run at any time.
  • Approve risky steps. When an agent asks for permission or has a question, it shows up inline and in a system notification.
  • Manage agents and their permissions. Create agents, set their model and instructions, and decide per tool, per skill and per MCP server what each agent may do: allow, ask or deny, with path and command patterns.
  • Add tools. Manage MCP servers, skills and slash commands from the app.
  • Schedule work. Have an agent run your tests every night or summarize changes every morning. Schedules run on the agent machine, so they fire even when Otto is closed.
  • Browse files. Open the project tree and read files with syntax highlighting.
A finished task: the agent's summary of what changed and the tests it ran
Three agents working at once
Several agents at once, each in its own session.
The file editor next to the conversation
Read the code the agent wrote, next to the conversation.
Choosing a cloud provider: Boat, boxd, E2B, Daytona or your own server
Pick a cloud, paste a key.
Otto on a phone: the sessions list and a conversation
Check in from your phone.

How it works

 Otto (Tauri app)                       Cloud machine (Boat sandbox or your server)
 ─────────────────                      ───────────────────────────────────────────
 React UI                               systemd: otto-opencode.service
   │  REST + Server-Sent Events  ───►   opencode serve  (OpenCode v2 API)
   │  over HTTPS, password-protected      ├─ sessions, agents, tools, MCP
 Rust side                                └─ ~/.otto  (scheduled tasks, cron)
   ├─ HTTP client (no CORS, streaming)
   ├─ OS keychain for secrets
   └─ notifications
  1. Setup. Otto uses the sandbox provider's API to create a machine, install OpenCode v2, write a systemd unit with a random password, and expose the port on the provider's HTTPS proxy.
  2. Connect. The app talks to OpenCode's own API: REST for actions and one Server-Sent Events stream for live updates. If the machine is asleep, Otto wakes it and repairs the service when needed.
  3. Storage.
    • Your device: app choices (theme, last model per workspace).
    • The OS keychain: secrets (API keys, server passwords).
    • The agent machine: everything shared (sessions, agents, config, schedules), so every device sees the same state.

Download

On macOS, one command installs the latest version into Applications (script):

curl -fsSL https://jaygupta.dev/otto/install.sh | sh

Everything else is on Releases.

PlatformFile
macOS (Apple silicon)Otto_<version>_aarch64.dmg
macOS (Intel)Otto_<version>_x64.dmg
WindowsOtto_<version>_x64-setup.exe or .msi
Linux.AppImage, .deb or .rpm
AndroidOtto_<version>_android.apk

The builds aren't code-signed yet, so your OS will warn you the first time:

  • macOS: the install command above avoids this. With the .dmg, Otto isn't notarized yet, so the first launch is blocked. Move it to Applications and open it once, then go to System Settings → Privacy & Security and click Open Anyway. If macOS says Otto "is damaged" instead, run xattr -dr com.apple.quarantine /Applications/Otto.app.
  • Windows: on the SmartScreen prompt, choose More info, then Run anyway.
  • Android: open the APK from your phone's browser or Files app and allow Install unknown apps for it when asked.
  • iOS: Apple doesn't allow installing apps from a download. Build it yourself with Xcode (see Mobile).

Getting started

To build from source.

Prerequisites

  • Bun 1.3+
  • Rust (stable) and the Tauri prerequisites for your OS
  • For mobile builds: Xcode (iOS) or Android Studio with the NDK (Android)

Run the desktop app

bun install
bun run app:dev

Try it without a cloud account

Run a local OpenCode v2 server with an isolated config, so nothing touches your own ~/.config/opencode:

bun run oc:local

Then in Otto choose Your own server, enter http://127.0.0.1:4917, and use the password printed in .dev/password. Free models work without any provider key.

Mobile

bun run tauri ios init       # once
bun run ios:dev
bun run tauri android init   # once
bun run android:dev

Build

bun run app:build

Release

Bump version in package.json, src-tauri/tauri.conf.json and src-tauri/Cargo.toml, then push a matching tag:

git tag v0.1.0 && git push origin v0.1.0

The Release workflow builds macOS, Windows, Linux and Android into a draft release. Check it, then publish. To sign the Android APK with a stable key, set the repository secrets ANDROID_KEYSTORE_BASE64, ANDROID_KEY_ALIAS and ANDROID_KEY_PASSWORD; without them each build is signed with a throwaway key.

Project layout

src/
  components/      UI: shell, chat, settings, schedules, onboarding, mobile
  lib/opencode/    OpenCode v2 client, event stream, timeline projection, config files
  lib/providers/   Sandbox providers (Boat) and the setup/repair flow
  lib/schedules.ts Scheduled tasks (cron + runner script on the agent machine)
  lib/permissions.ts  Agent permission rules editor model
  state/           Zustand stores (connection, chat, workspaces, extensions, ui)
src-tauri/         Rust side: plugins, keychain commands, app config, icons
scripts/           Local development helpers
DESIGN.md          Design system: tokens, type, color roles, motion

Security

  • Sandbox API keys and server passwords are stored in the OS keychain on macOS and Windows, and in the app's private storage elsewhere. They are never logged.
  • Each workspace gets its own random server password. The OpenCode server is only reachable through the provider's token-gated HTTPS URL.
  • Scheduled tasks keep their credentials in ~/.otto/server.env on the agent machine, readable only by the agent user.

Found a vulnerability? Please open a private security advisory on GitHub instead of an issue.

Roadmap

  • Terminal (PTY) panel
  • Diff review and one-click commits
  • Push notifications for mobile

Contributing

See CONTRIBUTING.md.

License

MIT. Parts of the permission editor are adapted from OpenChamber (MIT); see THIRD_PARTY_NOTICES.md.

agents
ai-agents
boat
boxd
coding-agents
daytona
developer-tools
e2b
harness
mobile
mobileagent
opencode
opencode-v2
remote-access
remote-control
remote-desktop
sandbox
self-hosted
tauri

jaygupta17/otto

Run agents on a cloud machine. Steer them from your desktop or phone.

TypeScript

11

33 commits

updated Oct 16, 2026

See the code

See what people are saying

SourceMessageScoreDate

I built a desktop and phone app for OpenCode v2 that runs your sessions on a cloud machine (r/coolgithubprojects)

I wanted to run coding agents on hardware I control and still use them from my phone, so I built Otto. \- Connect to an agent server you run, with its URL and password. The app talks to it directly over HTTPS. No Otto backend, account or telemetry. \- Or let Otto set one up for you on Boat, boxd,…

8

Oct 13, 2026

Show HN: Run your agents across E2B, Daytona and more. steer them from anywhere

1

Oct 13, 2026

README

Otto

Otto

Run coding agents on a cloud machine and steer them from your laptop or phone.

Website · Download · Changelog

An agent adds link expiry to a small URL shortener, writes tests and gets them passing


Otto is a desktop and mobile app for OpenCode v2. Paste a sandbox API key and Otto starts a Linux machine, installs OpenCode, keeps it running as a service and connects to it over HTTPS. Your agents keep working when your laptop sleeps, and you can check in from your phone.

It runs on macOS, Windows, Linux, iOS and Android, built with Tauri 2.

What you can do

  • Start a workspace in one step. Choose Boat, boxd, E2B or Daytona, paste a key, and Otto sets up the machine. Or connect any OpenCode v2 server you already run.
  • Work with agents in a live conversation. Replies stream as they are written, and every file read, edit and command the agent runs is listed step by step. Stop or steer a run at any time.
  • Approve risky steps. When an agent asks for permission or has a question, it shows up inline and in a system notification.
  • Manage agents and their permissions. Create agents, set their model and instructions, and decide per tool, per skill and per MCP server what each agent may do: allow, ask or deny, with path and command patterns.
  • Add tools. Manage MCP servers, skills and slash commands from the app.
  • Schedule work. Have an agent run your tests every night or summarize changes every morning. Schedules run on the agent machine, so they fire even when Otto is closed.
  • Browse files. Open the project tree and read files with syntax highlighting.
A finished task: the agent's summary of what changed and the tests it ran
Three agents working at once
Several agents at once, each in its own session.
The file editor next to the conversation
Read the code the agent wrote, next to the conversation.
Choosing a cloud provider: Boat, boxd, E2B, Daytona or your own server
Pick a cloud, paste a key.
Otto on a phone: the sessions list and a conversation
Check in from your phone.

How it works

 Otto (Tauri app)                       Cloud machine (Boat sandbox or your server)
 ─────────────────                      ───────────────────────────────────────────
 React UI                               systemd: otto-opencode.service
   │  REST + Server-Sent Events  ───►   opencode serve  (OpenCode v2 API)
   │  over HTTPS, password-protected      ├─ sessions, agents, tools, MCP
 Rust side                                └─ ~/.otto  (scheduled tasks, cron)
   ├─ HTTP client (no CORS, streaming)
   ├─ OS keychain for secrets
   └─ notifications
  1. Setup. Otto uses the sandbox provider's API to create a machine, install OpenCode v2, write a systemd unit with a random password, and expose the port on the provider's HTTPS proxy.
  2. Connect. The app talks to OpenCode's own API: REST for actions and one Server-Sent Events stream for live updates. If the machine is asleep, Otto wakes it and repairs the service when needed.
  3. Storage.
    • Your device: app choices (theme, last model per workspace).
    • The OS keychain: secrets (API keys, server passwords).
    • The agent machine: everything shared (sessions, agents, config, schedules), so every device sees the same state.

Download

On macOS, one command installs the latest version into Applications (script):

curl -fsSL https://jaygupta.dev/otto/install.sh | sh

Everything else is on Releases.

PlatformFile
macOS (Apple silicon)Otto_<version>_aarch64.dmg
macOS (Intel)Otto_<version>_x64.dmg
WindowsOtto_<version>_x64-setup.exe or .msi
Linux.AppImage, .deb or .rpm
AndroidOtto_<version>_android.apk

The builds aren't code-signed yet, so your OS will warn you the first time:

  • macOS: the install command above avoids this. With the .dmg, Otto isn't notarized yet, so the first launch is blocked. Move it to Applications and open it once, then go to System Settings → Privacy & Security and click Open Anyway. If macOS says Otto "is damaged" instead, run xattr -dr com.apple.quarantine /Applications/Otto.app.
  • Windows: on the SmartScreen prompt, choose More info, then Run anyway.
  • Android: open the APK from your phone's browser or Files app and allow Install unknown apps for it when asked.
  • iOS: Apple doesn't allow installing apps from a download. Build it yourself with Xcode (see Mobile).

Getting started

To build from source.

Prerequisites

  • Bun 1.3+
  • Rust (stable) and the Tauri prerequisites for your OS
  • For mobile builds: Xcode (iOS) or Android Studio with the NDK (Android)

Run the desktop app

bun install
bun run app:dev

Try it without a cloud account

Run a local OpenCode v2 server with an isolated config, so nothing touches your own ~/.config/opencode:

bun run oc:local

Then in Otto choose Your own server, enter http://127.0.0.1:4917, and use the password printed in .dev/password. Free models work without any provider key.

Mobile

bun run tauri ios init       # once
bun run ios:dev
bun run tauri android init   # once
bun run android:dev

Build

bun run app:build

Release

Bump version in package.json, src-tauri/tauri.conf.json and src-tauri/Cargo.toml, then push a matching tag:

git tag v0.1.0 && git push origin v0.1.0

The Release workflow builds macOS, Windows, Linux and Android into a draft release. Check it, then publish. To sign the Android APK with a stable key, set the repository secrets ANDROID_KEYSTORE_BASE64, ANDROID_KEY_ALIAS and ANDROID_KEY_PASSWORD; without them each build is signed with a throwaway key.

Project layout

src/
  components/      UI: shell, chat, settings, schedules, onboarding, mobile
  lib/opencode/    OpenCode v2 client, event stream, timeline projection, config files
  lib/providers/   Sandbox providers (Boat) and the setup/repair flow
  lib/schedules.ts Scheduled tasks (cron + runner script on the agent machine)
  lib/permissions.ts  Agent permission rules editor model
  state/           Zustand stores (connection, chat, workspaces, extensions, ui)
src-tauri/         Rust side: plugins, keychain commands, app config, icons
scripts/           Local development helpers
DESIGN.md          Design system: tokens, type, color roles, motion

Security

  • Sandbox API keys and server passwords are stored in the OS keychain on macOS and Windows, and in the app's private storage elsewhere. They are never logged.
  • Each workspace gets its own random server password. The OpenCode server is only reachable through the provider's token-gated HTTPS URL.
  • Scheduled tasks keep their credentials in ~/.otto/server.env on the agent machine, readable only by the agent user.

Found a vulnerability? Please open a private security advisory on GitHub instead of an issue.

Roadmap

  • Terminal (PTY) panel
  • Diff review and one-click commits
  • Push notifications for mobile

Contributing

See CONTRIBUTING.md.

License

MIT. Parts of the permission editor are adapted from OpenChamber (MIT); see THIRD_PARTY_NOTICES.md.

agents
ai-agents
boat
boxd
coding-agents
daytona
developer-tools
e2b
harness
mobile
mobileagent
opencode
opencode-v2
remote-access
remote-control
remote-desktop
sandbox
self-hosted
tauri