DunneFlow · Start here
Installing
The application for macOS, Windows and Linux, running from source with uv, the languages DunneFlow reads, and where your maps are kept.
There are two ways to run DunneFlow: the application, or from source. Which one you want depends on whether you intend to change it. The application comes in a macOS build, a Windows build and a Linux build, and everything after this page is the same on all three.
macOS#
Open DunneFlow-<version>.dmg, drag DunneFlow to Applications, and double-click it. It opens
your browser on the start page. There is no Python to
install, no terminal, and no configuration file.
The macOS build is universal (Apple silicon and Intel), signed with a Developer ID and notarised by Apple, so Gatekeeper opens it without argument. It asks the system for no special permissions: it reads the directory you point it at, writes its maps, and opens a folder picker when you ask for one.
Windows#
Unzip DunneFlow-<version>-windows-x64.zip anywhere and double-click DunneFlow. It
opens your browser on the start page, exactly as the macOS build does.
There are two programs in that folder:
| Program | Use it for |
|---|---|
DunneFlow.exe | Double-clicking. It opens no console window. |
dunneflow-cli.exe | The command line, from PowerShell or another terminal. |
They are the same program built two ways. A double-clickable Windows program has no console
to print to, so DunneFlow.exe run from a terminal would do the work and show you none of
it. Use dunneflow-cli.exe whenever you want to see output.
The folder picker opens behind your browser. Press Choose… (the button reads Opening… while the chooser starts), then Alt-Tab to it or click its icon in the taskbar. Windows does not let a background program bring a window to the front. Typing the path by hand always works.
Linux#
Unpack the tarball and run its installer:
tar -xzf DunneFlow-<version>-linux-<arch>.tar.gz
./dunneflow/install.sh
That puts the program in ~/.local/lib/dunneflow, the dunneflow command in
~/.local/bin, and a menu entry and icons where your desktop looks for them. Nothing
needs root, and nothing lands outside your home directory. To install somewhere else, use
./dunneflow/install.sh --prefix /some/where.
You can also skip installing and run ./dunneflow/dunneflow from wherever you unpacked it;
you just do not get a menu entry.
There is one program here, not two: on Linux dunneflow is both what the menu launches
and the command line.
To uninstall (your maps are never touched):
~/.local/lib/dunneflow/install.sh uninstall
The installed copy carries its own uninstaller, so this still works after you have deleted the tarball.
Install from source#
Running from source needs Python 3.12 or newer and uv. Clone the DunneFlow repository, then:
git clone https://github.com/aacloudguy/dunneflow.git dunneflow
cd dunneflow
uv sync
uv run dunneflow serve
uv sync installs the dependencies into a project environment, and uv run dunneflow serve opens the start page in your browser. Every command in these docs is written as
uv run dunneflow … for a source checkout. With the application, drop the uv run and
use the program itself (see The command line).
Languages#
| Language | Files | What you need |
|---|---|---|
| Python | .py | Nothing. |
| TypeScript | .ts, .tsx, .mts, .cts (JSX syntax included) | Node.js 20 or newer on the machine. |
| C++ | .cpp, .cc, .cxx, .hpp, .h, .inl and siblings | Nothing. |
| Kotlin | .kt, .kts | Nothing. |
Only TypeScript needs anything installed. DunneFlow reads it by asking TypeScript's own compiler, so a name it resolves is one the compiler resolved rather than one DunneFlow guessed. That compiler runs on Node.js. If Node is missing, DunneFlow says so before it reads anything:
typescript needs `node` ≥ 20.0.0 and nothing answers `node --version` on this machine.
Install it (brew install node, or nodejs.org), or run again with `--without typescript`
and the map will say those files were declined.
Either install Node, or analyse with --without typescript and get a map of everything
else. A declined language is never silent: the run prints how many files you declined, and
About this map records it on its It was told row. If the tree holds no TypeScript,
Node is never looked for. See the tutorial
A mixed-language repository without Node.
C++ and Kotlin are read syntactically, without a compiler. A C++ compiler needs to know how your program is built (every include path and defined symbol) before it reads a file, and most large C++ trees cannot say that without being built first. Asking Kotlin's compiler would put a Java runtime on every machine. So a C++ or Kotlin map tells you every routine, what it touches (files, environment, network, database), every loop, branch, guard and handler, and what registers it. It does not tell you which overload a call meant, where a call goes inside your own program, or what a C++ macro expands to. Calls in these maps are all external, and the run says so with a count.
In Kotlin, a per-element rate hidden inside items.forEach is a call, not a loop, so it is
not drawn as a loop where the same code written with for would be.
Everything else is counted, not read. Plain .js, .json, .yaml and any other suffix
no reader claims appear on an unread: line at the end of the run, so a map smaller than
its directory always has a printed reason.
Where maps are kept#
| Running | Maps go to |
|---|---|
| The application, macOS | ~/Library/Application Support/DunneFlow |
| The application, Windows | %LOCALAPPDATA%\DunneFlow |
| The application, Linux | ~/.local/share/DunneFlow, or $XDG_DATA_HOME/DunneFlow if set |
| From source | output/, beside the checkout |
None of these is your Documents folder, deliberately: a map holds copies of the source it read, and Documents is often synced to iCloud Drive or OneDrive. Because the folder is hard to find, the start page prints the path, and Show me opens it in your file manager.
Maps are not small. As a guide, one snapshot of a program of about 600 files is roughly 160 MB, and each further version of the same program adds roughly 130 MB. Most of that is the per-snapshot graph and document store. The copies of the source and documents that DunneFlow keeps are stored once by content and shared by every snapshot, so they are the cheap part.
Moving your maps#
If maps are filling your startup disk, Move… on the start page points DunneFlow at a different directory and offers to carry your existing maps across.
- The directory must already exist, on a connected disk. DunneFlow will not create it.
- Keep maps on a locally attached disk. They are SQLite databases, and network shares do not lock reliably.
- The move copies, verifies, and only then deletes. If anything fails part-way, your originals are untouched.
If you later start DunneFlow while that disk is disconnected, it says so, names the disk, and falls back to the standard location rather than quietly creating an empty one. See When it refuses.
Something unclear or out of date? Tell us.