Ensemblr
Agents that drive the app, not just the code.
A macOS orchestrator for the Pi agent harness or the Claude Code CLI you already have installed. I build it, and I use it to build everything else, including this site.
or brew install --cask ensemblr-hq/tap/ensemblr
- Platform
- macOS, Apple silicon
- License
- Apache-2.0
- Agent runtimes
- Pi · Claude Code
- Languages
- English · Russian · Greek
What it is
Ensemblr drives a coding-agent CLI you installed yourself, either the Pi harness or the Claude Code CLI, on one chat surface. Shared timeline, tool cards, model and thinking pickers, tool-approval prompts, git-backed checkpoints, session branching. Either runtime on its own is enough. The app ships no agent binary at all, which is about 260 MB of Agent SDK I left out deliberately.
There is no account to create and nothing syncs off the machine. State lives in a local SQLite database
on Node 24's built-in node:sqlite. Secrets go to the macOS Keychain instead of a file or an
environment variable, and GitHub tokens stay with gh, so there is no second copy to leak. No
Ensemblr backend sits in the path, and there is no telemetry.

Isolation is the product
Every stream of work is a workspace: a git worktree with its own branch, working tree, agent sessions, run state and review path. A fan-out of agents cannot collide, because none of them shares a checkout. A workspace either adopts an existing branch or cuts a fresh one, and either way Ensemblr fetches and fast-forwards the base branch first. Retargeting it later leaves the worktree alone.
Workspaces start from an existing branch, a GitHub pull request, or a Linear issue, and they live on a board: Backlog, In progress, In review, Done, Canceled. Backlog holds work with no workspace yet, which means unstarted Linear issues and unassigned open GitHub issues. Drag one rightward and it becomes a workspace. Nothing goes back to the tracker. Dismissing an issue hides it locally, and its status stays yours to change.
Agents drive the app
Ensemblr Control is the permission-gated surface that lets an agent drive the app it is running inside. It can spawn conversations, launch harnesses, run terminals, open file and diff tabs, read the workspace diff and leave review comments on it, read and write Linear issues, ask a multiple-choice question, and move its own workspace across the board. Pi reaches it through a shipped extension; Claude Code and any MCP-capable harness reach the same operations through an embedded MCP server. One set of operations behind two transports, so the surfaces cannot drift.
The part I care most about is orchestration. A root agent delegates one unit of work per sub-agent, each in its own tab and its own context, then blocks until they report back rather than hand-rolling a polling loop. Sub-agents do their own work and never delegate onward, so the tree stays one level deep. Depth, spawn count and spawn rate are all capped.
Code enforces those limits, not a prompt. Sub-agents get no Linear writes at all, and nothing at any depth can move an issue to a completed or canceled state. Agent work stops at In Review, and a human decides whether it is done. Plan mode holds an agent to read-only tools until it submits a plan, checks that on every tool call, and passes it down to every sub-agent it spawns.
Review that ends in GitHub
Review happens locally and ends in GitHub. One panel carries Files, Changes and Checks: source-scoped
diffs, per-file discard, a live file tree, and review comments anchored to specific lines. Agents read
those comments, answer them and resolve them; they are the same comments a human leaves. From there it
is an inline PR editor, commit and push, per-check status through gh, and a two-step merge. Work that
does not survive review gets its workspace archived instead.
Terminals sit under all of it: an xterm.js dock over real PTYs, restored across restart. A repository
declares any number of named run scripts in a committed .ensemblr/settings.toml, each with a command
and an icon, one of them the ⌘R default. Setup and archive scripts run on the same lifecycle, and setup
is fingerprinted so an unchanged workspace skips it.
What it took
Electron 43 and Electron Forge with Vite and Fuses hardening; React 19 and strict TypeScript; TanStack
Router and Query; Jotai for state; Lexical for the composer; xterm.js over node-pty for the terminal
dock; Zod at every boundary; SQLite through node:sqlite. Agent control runs on loopback HTTP plus MCP.
Tests are Vitest and electron --test.
I keep fifty-two architecture decision records in the repository. A codebase this opinionated is only navigable if the reasoning is written down, for the humans and for the agents reading it. The app ships in English, Russian and Greek, and any change that adds a user-facing string ships it translated in the same change.
Distribution is the unglamorous half: Developer ID signing, hardened runtime, Apple notarization and stapling, so the build opens without a Gatekeeper prompt and validates offline. Every release goes out as a Homebrew cask and a signed DMG.
Stack
The product site, with the full feature tour and the current download, is ensemblr.dev.