A native macOS app that puts Claude Code, Codex, Google's Antigravity CLI and Apple's on-device model behind one chat window, with approval cards for every tool call and a pull request review loop.
This repository holds the released builds and the Sparkle update feed. The application is not open source; the source lives in a private repository.
Download the latest .dmg from Releases, open it and drag the app to Applications. The app is signed with a Developer ID certificate and notarized by Apple. It checks this feed for updates once a day and never installs one without asking.
Add a repository, start a thread, type. Kulula runs the command line tools you already have — claude, codex and agy — as background processes and renders what they do in a single transcript: text, collapsible reasoning, tool calls with their output and exit code, and diffs per file. Apple's on-device model answers the short turns itself.
Threads sit in the sidebar under their repository, each showing which engine answered last, a spinner while a turn runs and a badge while something is waiting on you.
Every turn is routed on device: quick questions stay local, edits go to Claude Code, second opinions go to Codex. The route and the reason for it show above the composer, and one click sends the same turn elsewhere.
To choose yourself, name the engine: @claude, @codex, @agy or @local. Add a model to pin it for the thread, as in @claude:opus.
Nothing is written, run, committed or posted without a decision, and the app makes that decision itself rather than handing the question to the engine. By default it is yours: a card shows what was actually asked for, the command and its arguments, the paths it touches, the diff it wants to apply, and you allow it, allow it for the session, allow it from now on, or deny it. The security level below sets how many of those cards you see.
A standing grant covers the program and the paths it reaches rather than the text you approved, so approving one command does not let a differently spelled one through. Commands that provably only read need no approval. Grants stay listed and revocable in Settings.
When an engine wants to ask you something rather than ask permission, that arrives as its own card and waits for a real answer.
One control in the composer sets how much the app answers on your behalf.
| Level | What it does |
|---|---|
| Always Ask | Asks for every call. Your grants are kept but not consulted. |
| Approval Mode | The default. Asks for everything except commands that provably only read, and the rules you made with "Always allow". |
| Auto Mode | Allows anything confined to the repository, including file writes and local git. Discarding uncommitted work still asks, and so does anything that leaves the machine. |
| Trust Mode | Answers every request with no card at all, pushing and publishing and merging included. Confirmed once, by name, before it takes effect. |
Below Trust Mode, merging a pull request, releasing and any request to widen the app's own permissions always ask. Trust Mode is the level that answers those, for when you have decided to let an engine finish a job unattended. It stores nothing and touches none of the rules you have made, so leaving it takes every answer back from the next request onward, and each answer it gives appears in the transcript naming the level that gave it.
A question card is the exception: it appears at every level, Trust Mode included, since there is no answer the app could invent on your behalf. Commands the app runs unattended stay confined to the repository by the operating system at every level, so a stray script cannot reach your home directory or another checkout.
Set an OpenAI API key in Settings and Auto Mode gains a step: a shell command it cannot place inside your repository goes to a model for an assessment rather than straight to a card, and that one call is allowed if it comes back safe enough. Anything less, an error, or an answer it cannot read still shows you the card.
Some things never reach the model. Any program the app already has a rule about is one, so no assessment can allow curl, sudo, git push or a package install; so is anything whose arguments reach outside the repository, and any command line carrying what looks like a credential. Nothing is remembered either way, and every assessment appears in the transcript with the result it gave. None of this runs until you set the key.
The inspector's Review tab turns a review into a worklist. Kulula watches the open pull requests on the current repository, and when a review arrives it groups the findings by severity with a file and line for each, including the ones left in replies and in the body of the review itself.
Per finding: fix it with an engine, ask Codex for a second opinion, reply only, or dismiss it. "Fix all" works a severity at a time. Fixes run in the thread you are already in, with the usual cards, and the diffs render inline.
Shipping is one card: a commit message drafted on device, the push, and a reply on each finding. Approve, edit or skip each line, and the exact git and gh commands are shown before anything runs. A shipped fix resolves its review thread, so GitHub stays the record of what is still open and a thread someone reopens brings its findings back. Asking for a fresh review is the last step.
Open, Fixed, Dismissed and All filters each carry a count, and merged pull requests stay hidden until you ask for them.
The same loop left to run, with a cap on rounds and on minutes that both count down on screen. A round is fix, build, test, and optionally a fresh review. It stops on either cap, on a round that changed nothing, or on a build that fails. It works within the permissions you have already given and never grants itself anything, so on a machine with no grants it is exactly as interactive as clicking Fix yourself.
A thread is bound to the branch it works on and, when the work came from a review, to its pull request. Before a fix, commit, push, reply or merge, Kulula checks that the branch, the pull request and the checkout agree. If they do not it blocks the action and offers a way back rather than acting on the wrong code. Reading and discussing another pull request stays safe.
Switching the checkout needs a clean tree and no running turn, and is previewed first. Work you have not committed is never stashed or discarded for you.
When a thread moves to another engine, the on-device model writes a short brief — the goal, the files touched, what was decided, what is still open — and hands it over, since neither engine can see the other's context. The brief appears in the transcript.
Everything is stored locally. Quit and reopen, and threads, transcripts, grants and both CLI sessions resume.
The Status tab lists each engine, whether it is available, the plan usage it reports, and a warning when an installed tool has drifted from the version the build was tested against.
- macOS 26 or later with Apple Intelligence enabled.
- The
claude,codexandagycommand line tools installed and logged in.
Kulula runs on the plans you already have and adds no subscription of its own. Antigravity needs a one-time approval hook, which Settings installs for you.
The binaries are provided as is, for personal use, all rights reserved. No warranty.