Install
Download the .dmg from the
latest release, open it, and drag
dira.app into Applications. The app fetches updates on its own.
What you need
Two things. Even if you have neither right now, following the order below gets you there.
1. An Apple Silicon Mac
The app runs here and nowhere else. Open the Apple menu at the top left and choose
About This Mac. If Chip starts with Apple M, you are fine. On an Intel Mac the app will
not run, and your route is
Running the engine without the app below.
2. Setting up an engine
To drive dira you need one LLM engine you can call from the CLI. That is what a worker starts
when it takes a ticket, so without it a ticket never moves out of Open. The default is
claude.
Open the dira.app you just moved and press Settings at the far right of the header. Look at
the top line of Authentication › claude. If the engine is installed, claude CLI — is
followed by the path the app found. If it is not, the line reads
No claude CLI here — workers can't start a session.
Once you have installed the engine, quit the app, open it again, and look at the same line. The list of paths the app searches for programs is decided once, at launch. When that line has turned into a path, you are ready.
While a worker holds a ticket and runs this engine, macOS may ask you for permission or for
keychain access. The name in the dialog shows up as a number (2.1.222, say) rather than dira,
because the worker is running exactly the CLI engine you just configured. Nothing unfamiliar
has appeared. The engine itself needs that dialog, so go ahead and allow it.
python3 and bash already ship with macOS. The engine itself uses nothing but the standard
library of those two. The apm command that installs persona and protocol packages is something
dira installs on its own when it needs it (§Installing packages on a new machine below).
Installing packages on a new machine
Personas, squads and protocols live as packages under .dira/team/ inside the queue folder, and
which ones at which version is pinned by .dira/team/apm.yml and .dira/team/apm.lock.yaml. The
whole of .dira is gitignored, so this folder is never committed to the project repository.
Operational information is kept apart from the project's code. That also means cloning the
repository on a new machine does not bring the team folder along.
This folder used to sit in the project repository as dira-team/, and it was committed. For such a
project, the 0003-team-into-queue migration moves the old dira-team/ to .dira/team/ during an
update and makes one commit that removes the committed dira-team/ from the repository. It does not
push; do that yourself (The screen blurs after an update).
If you brought the queue folder over from another machine or deleted .dira/team/apm_modules/,
install the packages once. It is one command.
cd ~/Library/Application\ Support/dira/engine # the engine inside the app; with the repo, your clone
python3 dira_apm.py install <project root><project root> is the repository folder that contains .dira, not the .dira folder itself. With
the app you will rarely type this yourself: before claiming a ticket, a worker checks the install
and, if it differs from the lock, installs once on its own. The command does four things.
- If there is no
apmcommand yet, it installs one first. The version is the one line in the engine'sapm-versionfile (0.33.0today), and the place is~/.config/dira/tools/apm/<version>/. Withuvit installs throughuv; without it, it makes a virtual environment there with apython3.xof 3.10 or later. Anapmyou put on your own PATH is not used. - It installs from the lock, at the repository root if there is an
apm.ymlthere, and in.dira/team/if there is a.dira/team/apm.yml. - It checks the result (
check). - It rewrites the queue's
.dira/protocols/(Protocols).
If the last lines show no error, you are done. To only look at the current state, put check where
install is. It installs nothing, prints one line per mismatch, and exits with rc 1 if there is any.
With neither uv nor a python3.x of 3.10 or later, it stops with
apm 설치 실패: uv도 python3.10 이상도 없다 (apm install failed: no uv and no python3.10 or later).
The python3 that ships with macOS is 3.9 and does not count. Install uv and run it again.
Stalled: Package install differs from the lock
Before a worker claims a ticket, it checks that the project's packages match the lock. If they do
not, it tries one install from the lock; if they still differ, it claims no ticket in that
project. That is when Stalled: Package install differs from the lock and a one-line detail attach
after the Next dispatch clock in the status bar at the bottom of the screen. The project's
runner.log gets this line.
SKIP apm 설치 상태가 lock과 다르다 - <one-line detail>It tries the install only once per lock, so this does not clear by itself.
- Run the command from §Installing packages on a new machine above, as is. That fixes most cases, and the worker claims tickets again on the next tick.
- If the same line stays, read the lines
checkprinted. Each starts with one of these four.스킬 이름 충돌: <skill> <- <package>, <package>(skill name clash) - two packages ship a skill by the same name. Drop it from one, or rename it.페르소나 <name>: skills.md의 <skill>가 패키지 폐포에 없다(not in the package closure) - that skill is installed by another package but not by this persona package or its dependencies. Put it in the persona package's.apm/skills/, add the package that has it as a dependency, or delete that line fromskills.md.apm_modules 사본이 원본과 다르다: <package>or원본 없음: <package>(copy differs from the source, source missing) - a local package was edited or moved and not installed again. Run the command in 1 again.team: apm audit rc 1: ...- the installed files differ from the lock. Often someone changed.dira/team/apm.ymland did not write a new lock, so check.dira/team/apm.lock.yaml. If the dependency change is intended, run~/.config/dira/tools/apm/<version>/bin/apm installin that folder to write a new lock. There is nothing to commit.
- After fixing, run the command in 1 once more.
To keep the worker from trying an install, as in tests, set the environment variable
DIRA_APM_NO_INSTALL=1 (Worker environment variables). How
this ranks against other stall reasons is in the table in Troubleshooting.
The screen blurs after an update
As of 2026-10-16 this screen is still being built. The
migrate.pycommands below already work.
Some updates change the file format inside your project folders. When that happens, the whole
screen blurs the next time you open the app, and an Updating dira window sits on top. Nothing
is broken. dira is moving each registered project to the new format one at a time, and the window
closes by itself when it is done. Leave it alone until then. While it runs, no worker in any
project picks up a new ticket.
The window has one row per project. A grey dot means the project is waiting its turn, a spinner
shows the item being applied right now, and a check mark means it is done. If a row says
Waiting for {n} running sessions to finish, that project still has sessions running. dira does
not cut them off; it waits for them to end and then moves the project. After 20 minutes two buttons
appear. Press Wait 20 more minutes if the sessions look close to done, or Skip this project to
deal with it later.
If a row fails, it shows a one-line cause, the log path and the backup path. The failed project
has already been put back the way it was before, and the other projects carry on. If the cause is
something you can fix (a full disk, say), fix it and press Retry. If you cannot tell what went
wrong, or do not want to spend the time now, press Skip this project. A skipped project's row
reads Skipped - this project will not dispatch, and nobody picks up its tickets until you apply it.
The other projects run as usual.
Backups stay in each project under
<project>/.dira/migrations/backup/<item ID>/<time>/. The files from before the change are there
as they were, not zipped, at the same paths they had inside the project. dira never deletes this
folder, so remove it yourself once you no longer need it. What was done is written one line at a
time, with timestamps, in <project>/.dira/migrations/migrate.log.
To apply a skipped project later, run the following in a terminal. The engine inside the app
lives in ~/Library/Application Support/dira/engine/. <root> is that project's .dira folder.
cd ~/Library/Application\ Support/dira/engine
python3 migrate.py list --root <root> # find the item IDs left as skipped
python3 migrate.py apply --root <root> --id <item ID> # apply that itemIf several items were skipped, run it once per ID. apply without --id leaves skipped items as
they are. Once every remaining item is applied, that project dispatches again. The full command
list is in CLI.
Running the engine without the app
For when you do not need the screen, or you are running on Linux. This route clones the repo directly.
git clone https://github.com/proofer-tech/dira.git ~/Projects/diraWriting the worker file by hand and putting it on cron is in the appendix,
Running the engine alone. Using the app alongside it is fine. The app carries its
own copy of the engine inside the bundle. As long as both are looking at the same queue root
(<project>/.dira), they can tend one project without ever knowing about each other.
Next is Create your first project.