h-m-m: a mind map that is one PHP file and a set of Vim keys
h-m-m, or Hackers Mind Map, is a simple, fast, keyboard-centric terminal-based tool for working with mind maps.
At a glance
- What is it?
- A keyboard-centric terminal mind map with sibling-aware navigation, marks, positive and negative ranking, focus modes and HTML export, packaged as a single script with a Nix flake and a Docker image alongside it.
- Who is it for?
- h-m-m is worth trying if you already live in a terminal and want a mind map that costs nothing to start. There is no database, no server and no configuration to complete before your first node, and the whole program is one file you can read top to bottom.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 98 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the project is, and what it is not
The repository description calls h-m-m, short for Hackers Mind Map, a simple, fast, keyboard-centric terminal-based tool for working with mind maps. The readme says the name is pronounced like the interjection hmm, which is a small joke that also solves the discoverability problem, since searching the name does find it.
The single most important fact is structural. The file tree contains h-m-m as one file at the repository root, with no src directory, no build output and no vendor tree. It is a PHP script you run directly, and the language field says PHP. GPL-3.0 licensed, 2291 stars, 64 forks, four open issues, default branch main, most recent push 2026-07-06.
That shape explains the feature list without needing it to be large. There is no account, no sync, no plugin system and no renderer. What there is instead is an unusually dense key map, and the readme is essentially a manual for it organized into named groups: adding, removing and editing nodes, marks, relative navigation and moving, adjusting the view, collapsing and expanding, search, saving and exporting, miscellaneous, and the text editor bindings that apply while you are typing a node title.
The navigation model is the part that makes this more than a text outline. Movement is relative to the previously active node rather than absolute, so h activates the parent of where you just were, l activates the middle child, and j and k move to the lower and higher sibling, falling back to the nearest node in that direction when there is no sibling. That is a deliberate choice for tree-shaped data, and it is the reason the tool feels fast rather than fiddly.
Installation: script, container, or Nix
There are three supported ways to get it, and the tree shows all three without documenting any of them in the readme itself.
The first is running the script. The repository root holds the file, so copying it to your PATH and running it with php is the whole install. Nothing is compiled and nothing is generated.
The second is the container, and its Dockerfile is short enough to read in full.
FROM php:cliRUN apt-get update && \
apt-get install -y --no-install-recommends libonig-dev xclip xsel wl-clipboard && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*RUN docker-php-ext-install mbstringCOPY ./h-m-m .Three details in those lines tell you what the runtime actually needs. The base is the CLI-only PHP image, not an Apache or FPM image, which is the right choice for a terminal program. Three clipboard tools are installed side by side, and they are not redundant, because xclip is X11, xsel is an alternative X11 path, and wl-clipboard is for Wayland, so the image covers both X11 and Wayland sessions. And the mbstring extension is compiled in, which is the one non-default extension the script needs.
The third path is Nix. The tree carries flake.nix, flake.lock and default.nix, so the project is a flake with a conventional default.nix fallback. If you are on Nix or nix-darwin, that is the cleanest install and it is the only one of the three that pins the PHP version rather than inheriting whatever your system has.
One caveat on the container: it is built for a terminal and needs a TTY attached, so run it interactively rather than as a detached service, and mount the file you want to edit since the image contains no working directory of yours.
Marks, ranking and stars are the actual data model
Most outline tools treat a node as a string of text with optional children. h-m-m attaches several small pieces of state to every node, and each has a key.
A mark toggles between three states at the beginning of a title, with custom symbols configurable, so a node can be marked as a decision, a rejection or neither. Numeric prefixes are separate: one key adds or removes sequential numbering across a node and its siblings, which is how you build a numbered outline inside a mind map without writing the numbers by hand.
Then there is ranking, and it is bidirectional. Four keys cover the whole matrix: one increases positive ranking, one decreases positive ranking, one increases negative ranking, one decreases negative ranking. Two stars, one up and one down, let you flag something without committing to either direction. And a hidden flag toggles per node, with a separate key to hide and reveal all hidden nodes at once.
None of this is decoration. Positive and negative ranking on a decision tree is the feature that turns a mind map into a decision record, since a list of options with weights attached is something you can actually revisit later. Hidden nodes are how you collapse work in progress without losing it, and the numbering is how you turn a brainstorm into an ordered list.
Undo is bound to a single key and its depth is configurable, with a default of 24 steps. That number is worth noting if you are restructuring a large map, because restructuring is exactly when you want deep undo and the default will not cover a long series of moves.
Folding, focus and the view controls
The folding model has more than one way in, which is unusual and turns out to be necessary for trees with real depth.
Space toggles the active node. One key collapses everything except the first-level nodes, another collapses all children of the active node. A key expands all nodes. Number keys 1 through 9 collapse the nth level while expanding everything before it, so you can set a working depth with one press.
Then there are three graduated focus modes, and they are the feature that separates this from a plain outline. One collapses everything except the ancestors and descendants of the active node, which leaves you a single branch with its context intact. A second locks that focus so it follows the active node as you move, and a third collapses the other first-level items, leaving only the branch containing the active node.
Focus lock and center lock are meant to be used together. Center lock pins the active node to the middle of the screen, and with focus lock on, moving through a subtree keeps both the viewport and the fold state centered on it. For a large map that turns navigation into something close to a paginated read.
The view itself is adjustable with the same density. Arrow keys with a control modifier pan the viewpoint, one key centers the active node, one increases maximum node width and one decreases it, and one key decreases line spacing while another increases it. A key toggles aligned levels, which is how you either align siblings into columns or let variable-width labels push the layout around. Two keys jump to the highest and lowest element in the map, and two more return to the root, one of them a tilde and one of them m, so both hands can find it.
Search, clipboard and export
Three features here are what you will reach for on a real map rather than a toy one.
Search is bound to slash and also to control-f, with n and N stepping forward and backward through results. On a mind map with hundreds of nodes, being able to jump to a phrase and walk the matches is the difference between the map being a place you work and a picture you made once.
Clipboard is handled through the system, not an internal buffer, and the key map shows how carefully that is thought through. y yanks the active node and its descendants, capital Y yanks only the descendants. d cuts the node and its descendants, capital D cuts only the descendants, and Delete removes a node and its descendants without putting anything on the clipboard at all. p pastes as descendants of the active node and capital P pastes as siblings, so you choose the relationship at paste time rather than finding out afterwards.
There is also an append operation on control-p that puts clipboard text at the end of the current title rather than replacing it, which is how you build a longer phrase incrementally instead of retyping it.
Export comes in three shapes. One key saves under the previous file name, or asks for one if there is none, and another saves under a new name. One key exports as an HTML file. One key exports as a text map straight into the clipboard. And a separate key opens the active node as a file or URL through xdg-open, which is the feature that turns a mind map node into a launch point for the thing you are describing.
Quitting is split the same way, one key quits if changes were saved and another quits ignoring them, so losing work requires a deliberate capital.
The configuration file, read carefully
Everything except the text editor bindings can be changed, and the readme lists the defaults. Here they are as the readme shows them.
max_parent_node_width = 25
max_leaf_node_width = 55
line_spacing = 1
initial_depth = 1
max_undo_steps = 24The width settings are the ones that matter most on a narrow terminal. A parent node wraps at 25 columns and a leaf at 55, and increasing or decreasing maximum node width at runtime with the w and W keys changes it for the session. Line spacing has the same treatment with z and Z, so you can fit more of a map on screen without touching the config.
The colors are terminal escape codes, and the readme says so explicitly. Two of them are configured by default, one for the active node and one for messages, both written as an escape sequence.
active_node_color = \033[38;5;0m\033[48;5;172m\033[1m
message_color = \033[38;5;0m\033[48;5;141m\033[1mThe clipboard is the setting most likely to need editing on a fresh machine, and there are four keys for it.
clipboard = os
clipboard_file = /tmp/h-m-m
clipboard_in_command = ""
clipboard_out_command = ""The default is to use the operating system clipboard, with a file fallback at /tmp/h-m-m. The two command keys let you plug in your own tooling if neither works, which is the escape hatch for Wayland setups where you need a specific tool invocation. That is also why the container installs xclip, xsel and wl-clipboard.
Key bindings use a bind syntax with the command name on the right.
bind a = edit_node_append
bind A = edit_node_replace
bind b = expand_all
bind c = center_active_node
bind C = toggle_center_lockThe naming convention is worth noting before you rebind anything. A lowercase command name is generally the gentle variant and the capital letter is the aggressive one, so append versus replace, expand all versus collapse, move down versus move up. The readme notes that editor bindings are the exception, since those follow readline conventions instead and are not rebindable.
One detail in the editor list is worth flagging rather than repeating. Two bindings are listed for move to beginning of line, with control-p appearing twice in the same line and control-e assigned to move to the end of the line, which does not match readline, where control-a is beginning of line and control-e is end of line. If you rely on readline muscle memory inside a node title, test the keys rather than trusting the list.
Editorial conclusion
h-m-m is worth trying if you already live in a terminal and want a mind map that costs nothing to start. There is no database, no server and no configuration to complete before your first node, and the whole program is one file you can read top to bottom. Two things to settle before you commit. Clipboard integration is delegated to xclip, xsel or wl-clipboard through config keys, so a headless box or a bare container needs one of those installed, which is why the Docker image installs all three. And the readme is a key binding reference rather than a tutorial, so plan on learning it the way you learned Vim, one command at a time, starting with the search and fold keys because those are what make a large map navigable.
Frequently asked questions
What does h-m-m do and who is it for?
h-m-m, short for Hackers Mind Map, is a keyboard-centric terminal mind map written as a single PHP file. You create nodes with sibling and child keys, move through the tree with relative navigation, mark and rank options for decision making, fold branches by depth or focus on one subtree, search phrases across the whole map, and export to a file, to HTML, or as a text map into the clipboard. It has 2291 stars and is licensed GPL-3.0. It suits people who already work in a terminal and want a mind map with no database and no server.
How do I install h-m-m, and what does it need on my system?
The simplest route is to copy the single h-m-m script from the repository root to your PATH and run it with php. The Docker image is based on the CLI-only PHP image and additionally installs libonig-dev, xclip, xsel and wl-clipboard for clipboard support, plus the mbstring PHP extension. For Nix users the repository carries flake.nix, flake.lock and default.nix, which is the option that also pins the PHP version. In every case you need a PHP runtime with mbstring available, and you need one of the three clipboard tools if you want the operating system clipboard to work.
Can I change the key bindings and settings in h-m-m?
Yes, with one exception. Every binding outside the text editor can be changed in the config file using a bind syntax that pairs a key with a command name, for example bind a = edit_node_append or bind C = toggle_center_lock. The readme is explicit that the text editor bindings are the exception and follow readline-style conventions instead, so those are not rebindable. Settings in the same file cover node widths, line spacing, initial depth, undo depth, the active node and message colors, the clipboard mode and its fallback file, custom mark symbols, and auto-save.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nadrad-h-m-m)