Bento is an open-source developer cockpit built with Tauri. A modular desktop workspace where you can open and arrange developer panels — Git worktrees, terminals, code review, databases, containers, scripts, and more — side by side, with a persistent layout that survives restarts.
Runs natively on macOS, Linux, and Windows.
| Panel | What it does |
|---|---|
| Tasks | Git worktrees per task — branch, changes, commit, PR, rebase, merge. Linear integration. Multi-repo. Docker devcontainer support. |
| Terminal | Real shell via xterm.js + PTY. Multiple terminals, profiles, themes, search, zoom, cwd restore on reopen. Terminals survive app restarts — they live in the background daemon. |
| Tech Review | AI-assisted code review. Set a base branch, browse changed files, open PRs, diff split/tree view, inline comments, chat with an AI agent. |
| Diff | Browse Git history or worktree changes. File list on the left, rendered patch on the right. Grouped log view per commit. |
| DB | Database explorer. Connect to SQLite, PostgreSQL, MySQL. Tree view of schemas and tables, query editor with results. |
| Docker | Container manager grouped by project. Start/stop individual containers or entire project groups. Logs and terminal per container. |
| Jira | Jira board inside Bento. Multiple accounts, board view, backlog, issue search, create and edit issues. |
| Scripts | Script runner. Scan folders for shell scripts, run them in an embedded terminal. Filter by folder. |
| Notes | Markdown notes as .md files. Categories, tags, preview, Ask-AI from sidebar. |
| HTTP | REST client. Methods, headers, body (JSON, form, raw), saved collections. Imports OpenAPI / Swagger specs as a browsable collection. |
| TV | IPTV player with HLS.js. M3U channel list (iptv-org), favourites, YouTube/Twitch embeds. |
| Web | Embedded browser (native WebView). Bookmarks and history per project. |
| Phone Remote | Control any terminal from your phone over Wi-Fi or Tailscale. Toggle a token-gated HTTP server, scan the QR code on your phone — full xterm.js with arrow keys, reconnect and resize. Optional Tailscale mode for remote access outside your local network. |
Bento detects running AI agent sessions (Claude Code, Codex, OpenCode) and shows their status in the sidebar. When you reopen a workspace, agents that were running are automatically resumed — no copy-pasting session IDs.
Session detection and resume:
- Claude Code — herdr IPC socket reports the session ID;
--resume <id>is verified against~/.claude/projects/before use - Codex — herdr IPC socket; stale thread-writer lock cleaned up automatically so
codex resumenever fails - OpenCode — SQLite session DB at
~/.local/share/opencode/opencode.db, matched by cwd + creation time
No API key required on Bento's side. Each agent manages its own credentials.
Terminals and the phone remote server live in bento-daemon, an out-of-process background service. The GUI and the CLI both connect to it over localhost TCP.
┌─────────────────────────────────────────┐
│ bento-daemon │
│ PTY manager · Phone HTTP/WS server │
│ IPC: TCP 127.0.0.1:7877 │
└──────────┬──────────────────┬───────────┘
│ │ │
bento (CLI) Bento.app 📱 Phone
Benefits:
- Terminals survive restarts — reopen Bento and your shells are still there
- Phone remote without the app —
bento daemon startis enough - CLI access — list, open and attach to terminals from any shell
Terminals do not live in the desktop app or in the CLI: they live in the daemon. Each client is a window onto the same thing, so a terminal opened in one shows up in the others — same id, same title, same scrollback.
bento daemon start # 1. the daemon — everything else talks to it
bento # 2. the CLI, no arguments: the terminal panel (TUI)
npm run tauri:dev # 3. the desktop appThe phone has no command of its own: turn its server on from the desktop's Phone Remote panel, which is what asks the daemon to start it.
The desktop app starts the daemon itself when none is answering. The CLI does
not: run bento daemon start first, or bento daemon install once and let
launchd/systemd keep it up — that is also what brings it back if it dies.
After rebuilding the daemon, bento daemon restart: otherwise the old binary
keeps serving. Restarting it kills every terminal it holds — the shells are its
child processes.
Inside the TUI, Tab switches between terminals and tech review, and every
pane's footer lists its keys.
bento # open the terminal panel (TUI)
bento daemon status # show daemon status
bento daemon start # start the daemon in the background
bento daemon restart # stop and start it again (after rebuilding)
bento daemon install # register as a login service (launchd / systemd)
bento daemon uninstall # remove the login service
bento terminals # list open terminals
bento open [--cwd <dir>] # open a new terminal
bento attach <id> # attach stdin/stdout to a terminal
bento review branches # recent branches of this repo
bento review files [--base <ref>] # files changed vs base
bento review file <path> [--base <ref>] # one file's diff
bento review run [--agents claude,codex] # a full AI reviewbento --help lists the rest: tasks, docker, notes and agent sessions.
bento daemon install writes a launchd plist on macOS or a systemd user service on Linux so the daemon starts at login — independent of the Bento app.
The binaries are not on your PATH until you install them. From the repo:
cargo build --release --manifest-path daemon/Cargo.toml
./daemon/target/release/bento # the CLI
./daemon/target/release/bento daemon start # the daemon
# or put it on your PATH:
ln -s "$PWD/daemon/target/release/bento" /usr/local/bin/bentoThe Phone Remote panel lets you control any open terminal from your phone browser — no app install required.
Local network (Wi-Fi)
- Open the Phone Remote panel in Bento
- Toggle Activar servidor WiFi — the server binds to your LAN IP
- Scan the QR code with your phone (must be on the same Wi-Fi)
Remote access via Tailscale
Works on macOS, Linux and Windows. Install Tailscale on your desktop:
| Platform | Command |
|---|---|
| macOS | brew install --cask tailscale |
| Linux | curl -fsSL https://tailscale.com/install.sh | sh |
| Windows | Download from tailscale.com/download |
- Sign in to Tailscale on your desktop
- Install Tailscale on your phone and sign in to the same account
- In Bento, toggle Usar Tailscale (fuera de casa) — the server binds to your
100.x.x.xTailscale IP - Scan the QR code from anywhere with an internet connection
The two modes are mutually exclusive at the TCP bind level. LAN mode only accepts connections from your local network; Tailscale mode only accepts connections through the Tailscale VPN.
- Rust (stable)
- Node.js 20+
- On Linux:
libwebkit2gtk-4.1,libgtk-3,libayatana-appindicator3(see Tauri Linux deps)
git clone https://github.com/R0MADEV/bento
cd bento
npm installnpm run tauri:devnpm run tauri:buildProduces a native binary (.dmg on macOS, .AppImage/.deb on Linux, .msi/.exe on Windows). The bento-daemon and bento CLI binaries are built from the daemon/ workspace alongside.
npm run dev # frontend only (Vite, no Tauri shell)
npm run typecheck # TypeScript — zero errors required
npm run lint # ESLint
npm test # Vitest (unit tests, no browser)
npm run ci:local # full local CI: lint + typecheck + test + bindings + buildGenerated Rust → TypeScript bindings live in src/generated/bindings/. Regenerate after changing Tauri DTOs:
npm run bindings:generate
npm run bindings:check # CI fails if bindings are staleDaemon workspace tests:
cd daemon && cargo test| Layer | Technology | Why |
|---|---|---|
| App framework | Tauri 2 | Native binaries 5–15 MB; system WebView; Rust backend |
| Backend | Rust | PTY, native filesystem, DB drivers, Docker IPC |
| Daemon | Rust + Tokio | Out-of-process PTY manager; IPC over TCP localhost |
| CLI | Rust | bento binary — thin client for the daemon |
| Frontend | TypeScript + Vite | Type safety, fast HMR, first-class Tauri support |
| Layout | dockview-core | Tile panels + tabs, drag-and-drop, serialisable layout |
| Terminal | xterm.js + portable-pty | Real shell emulator; PTY spawned in the daemon |
| Phone remote | Axum + xterm.js | Token-gated HTTP + WebSocket bridge to daemon terminals |
| Streaming | hls.js | Adaptive HLS for the TV panel |
| Tests | Vitest + cargo test | Frontend unit tests; Rust unit tests in the daemon workspace |
| Persistence | JSON in ~/.config/bento/ |
No database; human-readable; versionable |
| License | MIT | Maximum permissiveness |
bento/
├── src/ # Frontend (TypeScript)
│ ├── main.ts # Composition root — registers panels, mounts app
│ ├── app/ # createSessionManager, createWorkspaceView, home
│ ├── core/ # Pure, tested logic (git, docker, http, notes…)
│ ├── panels/ # One folder per panel (tasks/, terminal/, diff/, remote/…)
│ ├── ui/ # Shared UI: collapsibleSidebar, icons, commandPalette, aiChat…
│ ├── adapters/ · ports/ # Repository implementations and interfaces
│ ├── i18n/ # en.json / es.json
│ └── styles.css
├── src-tauri/ # Tauri backend (Rust)
│ ├── Cargo.toml
│ ├── tauri.conf.json
│ └── src/
│ ├── main.rs # Tauri commands + app setup
│ ├── pty.rs # Thin daemon client (spawn, kill, IPC relay)
│ ├── agent_sessions.rs # Session restore for Claude / Codex / OpenCode
│ ├── agent_socket.rs # herdr IPC socket (session ID reporting)
│ ├── git.rs # Git operations
│ ├── docker.rs # Docker container management
│ ├── db.rs # Database connections
│ ├── workspace_io.rs # Workspace state persistence
│ └── …
├── daemon/ # Background daemon workspace (Rust)
│ ├── bento-core/ # Shared PTY manager (no Tauri dependency)
│ ├── bento-daemon/ # TCP IPC server + phone HTTP/WS server
│ └── bento-cli/ # `bento` CLI binary
├── tests/ # Vitest — unit tests for src/core and src/ui
└── scripts/ # Dev scripts (bindings, i18n audit)
Pull requests are welcome. Before opening one:
- Run
npm run ci:local— it must pass with zero errors. - Run
cd daemon && cargo test— must pass. - Follow the commit convention:
feat: added …/fix: corrected … - Branch names:
feat/short-descriptionorfix/short-description
About to touch the bundling code? docs/pendiente.md
records what was open, how each point was closed and — just as usefully — what
was looked at and deliberately left alone, so nobody relitigates it.
MIT — free to use, modify and distribute.





