Introduction
Unlock the full potential of your Makefiles.
makefile2doc is a CLI tool that turns your raw Makefiles into clear, categorized, and visual documentation.
The Problem
Makefiles are powerful, but they often become “Black Boxes” as projects grow:
- The “Bus Factor”: Often, only the author knows all the available commands.
- Partial Onboarding: New developers usually learn just the 2 or 3 commands needed to start, missing out on powerful utility scripts.
- Cryptic Syntax: Reading a raw Makefile requires mentally parsing bash syntax, which is inefficient.
The Solution
Treat your Makefile as the Single Source of Truth.
By adding simple comments (The Convention), you generate a MAKEFILE.md that is always up-to-date with your code.
Why use it?
- 🧠 Kill the “Makefile Anxiety”: No more scrolling through 300 lines of obscure Bash at 2 AM just to find the right deploy command.
- 🚀 Instant Onboarding: Give new developers a “Cheat Sheet” that actually makes sense, letting them use the project before they fully understand its internals.
- 🤖 AI Optimization: Provides clean context for LLMs, saving tokens and preventing hallucinations (see AI Context).
Why NOT use it?
- 🦀 You don’t like Rust for some reason.
- 😨 You are afraid to re-open your Makefile because it currently works and you don’t want to jinx it.
Real-World Example
The best way to understand makefile2doc is to see it in action.
Below is the Result (the generated Markdown) and the Input (the raw Makefile) from our internal test suite.
Makefile Documentation
Auto-generated by makefile2doc
Cheat Sheet
| Command | Category | Description |
|---|---|---|
make up | Development Environnement | Start the full development environment (Docker) |
make down | Development Environnement | Stop all containers |
make logs | Development Environnement | Show live logs for all services |
make shell-back | Development Environnement | Open a shell inside the PHP container (Laravel) |
make shell-front | Development Environnement | Open a shell inside the Node.js container |
make shell-db | Development Environnement | Open a shell inside the PostgreSQL container |
make install-back | Setup & Initialization | Install backend (Composer) |
make install-front | Setup & Initialization | Install frontend (NPM) dependencies |
make install | Setup & Initialization | Run both backend and frontend installations |
make migrate | Database | Run database migrations |
make seed | Database | Reset the DB and run seeds (Test data) Warning: This deletes all data! |
make test-back | Code Quality | Run unit tests (Pest/PHPUnit) |
make lint-front | Code Quality | Lint frontend code (ESLint) |
make lint-back | Code Quality | Lint backend code (PHP-CS-Fixer dry-run) |
make fix-front | Code Quality | Fix frontend code style and format |
make fix-back | Code Quality | Fix backend code style |
make lint | Code Quality | Run all linters (front & back) |
make fix | Code Quality | Fix all code style issues (front & back) |
make build-front | Deployment | Compile Frontend assets (Vite/Mix) |
make deploy | Deployment | Deploy to Production 1. Build frontend assets 2. Optimize Laravel cache 3. Run migrations force |
Workflow Graph
flowchart LR
subgraph Development_Environnement[Development Environnement]
up(up)
down(down)
logs(logs)
shell-back(shell-back)
shell-front(shell-front)
shell-db(shell-db)
end
style Development_Environnement fill:transparent,stroke-dasharray: 5 5
classDef cat0 fill:#E1F5FE,stroke:#01579B,stroke-width:2px,color:#000;
class up cat0
class down cat0
class logs cat0
class shell-back cat0
class shell-front cat0
class shell-db cat0
subgraph Setup_&_Initialization[Setup & Initialization]
install-back(install-back)
install-front(install-front)
install(install)
end
style Setup_&_Initialization fill:transparent,stroke-dasharray: 5 5
classDef cat1 fill:#E8F5E9,stroke:#1B5E20,stroke-width:2px,color:#000;
class install-back cat1
class install-front cat1
class install cat1
subgraph Database[Database]
migrate(migrate)
seed(seed)
end
style Database fill:transparent,stroke-dasharray: 5 5
classDef cat2 fill:#FFF3E0,stroke:#E65100,stroke-width:2px,color:#000;
class migrate cat2
class seed cat2
subgraph Code_Quality[Code Quality]
test-back(test-back)
lint-front(lint-front)
lint-back(lint-back)
fix-front(fix-front)
fix-back(fix-back)
lint(lint)
fix(fix)
end
style Code_Quality fill:transparent,stroke-dasharray: 5 5
classDef cat3 fill:#F3E5F5,stroke:#4A148C,stroke-width:2px,color:#000;
class test-back cat3
class lint-front cat3
class lint-back cat3
class fix-front cat3
class fix-back cat3
class lint cat3
class fix cat3
subgraph Deployment[Deployment]
build-front(build-front)
deploy(deploy)
end
style Deployment fill:transparent,stroke-dasharray: 5 5
classDef cat4 fill:#FFEBEE,stroke:#B71C1C,stroke-width:2px,color:#000;
class build-front cat4
class deploy cat4
logs --> up
shell-back --> up
shell-front --> up
shell-db --> up
install --> install-back
install --> install-front
migrate --> up
migrate --> install
seed --> migrate
test-back --> install
lint-front --> install-front
lint-back --> install-back
fix-front --> install-front
fix-back --> install-back
lint --> lint-front
lint --> lint-back
fix --> fix-front
fix --> fix-back
build-front --> install
deploy --> build-front
deploy --> migrate
Section Details
Development Environnement
| Command | Description | Dependencies | Required Variables |
|---|---|---|---|
make up | Start the full development environment (Docker) | - | PORT |
make down | Stop all containers | - | - |
make logs | Show live logs for all services | up | - |
make shell-back | Open a shell inside the PHP container (Laravel) | up | - |
make shell-front | Open a shell inside the Node.js container | up | - |
make shell-db | Open a shell inside the PostgreSQL container | up | - |
Setup & Initialization
| Command | Description | Dependencies | Required Variables |
|---|---|---|---|
make install-back | Install backend (Composer) | - | - |
make install-front | Install frontend (NPM) dependencies | - | - |
make install | Run both backend and frontend installations | install-back, install-front | - |
Database
| Command | Description | Dependencies | Required Variables |
|---|---|---|---|
make migrate | Run database migrations | up, install | - |
make seed | Reset the DB and run seeds (Test data) Warning: This deletes all data! | migrate | SEED_CLASS |
Code Quality
| Command | Description | Dependencies | Required Variables |
|---|---|---|---|
make test-back | Run unit tests (Pest/PHPUnit) | install | - |
make lint-front | Lint frontend code (ESLint) | install-front | - |
make lint-back | Lint backend code (PHP-CS-Fixer dry-run) | install-back | - |
make fix-front | Fix frontend code style and format | install-front | - |
make fix-back | Fix backend code style | install-back | - |
make lint | Run all linters (front & back) | lint-front, lint-back | - |
make fix | Fix all code style issues (front & back) | fix-front, fix-back | - |
Deployment
| Command | Description | Dependencies | Required Variables |
|---|---|---|---|
make build-front | Compile Frontend assets (Vite/Mix) | install | - |
make deploy | Deploy to Production 1. Build frontend assets 2. Optimize Laravel cache 3. Run migrations force | build-front, migrate | APP_KEY, SSH_USER |
2. The Input (Makefile)
This is the source Makefile using The Convention.
Pro Tip: We recommend using visual separators (like the # === lines below) to clearly delimit your categories. This keeps the raw file readable for humans, while the parser simply ignores them.
# ==============================================================================
## @category Development Environnement
# ==============================================================================
## @description Start the full development environment (Docker)
## @env PORT
up:
# docker compose up -d
## @description Stop all containers
down:
# docker compose down
## @description Show live logs for all services
## @depends up
logs:
# docker compose logs -f
## @description Open a shell inside the PHP container (Laravel)
## @depends up
shell-back:
# docker compose exec app bash
## @description Open a shell inside the Node.js container
## @depends up
shell-front:
# docker compose exec app bash
## @description Open a shell inside the PostgreSQL container
## @depends up
shell-db:
# docker compose exec app bash
# ==============================================================================
## @category Setup & Initialization
# ==============================================================================
## @description Install backend (Composer)
install-back:
# docker compose run --rm app composer install
## @description Install frontend (NPM) dependencies
install-front:
# docker compose run --rm app npm install
## @description Run both backend and frontend installations
## @depends install-back, install-front
install: install-back install-front
# ==============================================================================
## @category Database
# ==============================================================================
## @description Run database migrations
## @depends up, install
migrate:
# docker compose exec app php artisan migrate
## @description Reset the DB and run seeds (Test data) \n Warning: This deletes all data!
## @depends migrate
## @env SEED_CLASS
seed:
# docker compose exec app php artisan migrate:refresh --seed
# ==============================================================================
## @category Code Quality
# ==============================================================================
## @description Run unit tests (Pest/PHPUnit)
## @depends install
test-back:
# docker-compose exec app php artisan test
## @description Lint frontend code (ESLint)
## @depends install-front
lint-front:
# docker compose exec app npm run lint
## @description Lint backend code (PHP-CS-Fixer dry-run)
## @depends install-back
lint-back:
# docker compose exec app php-cs-fixer
## @description Fix frontend code style and format
## @depends install-front
fix-front:
# docker compose exec app npm run lint-fix && npm run format
## @description Fix backend code style
## @depends install-back
fix-back:
# docker compose exec app php-cs-fixer --fix
## @description Run all linters (front & back)
## @depends lint-front, lint-back
lint: lint-front lint-back
## @description Fix all code style issues (front & back)
## @depends fix-front, fix-back
fix: fix-front fix-back
# ==============================================================================
## @category Deployment
# ==============================================================================
## @description Compile Frontend assets (Vite/Mix)
## @depends install
build-front:
# npm run build
## @description Deploy to Production \n 1. Build frontend assets \n 2. Optimize Laravel cache \n 3. Run migrations force
## @depends build-front, migrate
## @env APP_KEY, SSH_USER
deploy:
# git pull
# docker compose exec app php artisan config:cache
# docker compose exec app php artisan migrate --force
Installation
1. Recommended: Download Binary
The easiest way to install makefile2doc is to download the latest executable for your operating system.
- Go to the GitHub Releases page.
- Download the file matching your OS and architecture (e.g.,
makefile2doc-linux-amd64). - Follow the setup instructions below for your operating system.
2. Setup
Linux & macOS
To use the command globally, make it executable and move it to a folder in your system $PATH.
Assuming you are in the folder where you downloaded the file:
# 1. Give execution permissions
chmod +x makefile2doc-*
# Note: Ensure you only have one version of the file in the folder to avoid errors.
sudo mv makefile2doc-* /usr/local/bin/makefile2doc
Windows
- Create a folder for your CLI tools (e.g.,
C:\Tools) - Move the downloaded file (e.g.,
makefile2doc-windows-amd64.exe) into this folder. - Rename the file to
makefile2doc.exe. - Add this folder to your PATH environment variable:
- Search “Env” in the Start Menu
- Open Edit the system environment variables
- Select Path → Edit → New
- Paste the path to your folder
3. Verify Installation
Open a new terminal and verify that the tool is correctly installed:
makefile2doc --help
If you see the help menu, you are ready to use it!
4. Developer Installation (via Cargo)
If you already have Rust and Cargo installed on your machine, you can install the tool directly from the source code.
cargo install --git https://github.com/Merlin-Clos/makefile2doc --locked
This will compile the project and place the binary in your ~/.cargo/bin folder.
Usage
1. The Command Line Interface
The tool is designed to be smart about paths. You don’t always need to specify arguments.
Basic Usage
Run the command in the folder containing your Makefile:
makefile2doc
- Input: Looks for
Makefilein the current directory. - Output: Generates
MAKEFILE.mdin the same directory.
Custom Input (-i)
If your Makefile is in a subfolder:
makefile2doc -i backend/Makefile
- Input: Reads
backend/Makefile. - Output: Automatically targets
backend/MAKEFILE.md.
Custom Output (-o)
If you want to save the documentation somewhere specific:
makefile2doc -i Makefile -o docs/development.md
- Input: Reads
Makefilefrom the current directory. - Output: Generates the documentation in
docs/development.md.
2. Important Note: Output is Empty?
makefile2doc only documents targets that have a ## @description tag. If your Makefile doesn’t follow The Convention, the generated file will be empty.
Try adding a description to one of your targets and run the tool again:
## @description A simple hello world
hello:
echo "hello"
The Convention
To generate documentation, makefile2doc parses specific comments in your Makefile. We call this “The Convention”.
It is designed to be unobtrusive and readable, even without the tool.
Core Rules
- Description is Mandatory: Any target without a description is considered private and is ignored.
- Stateful Categories: A category tag applies to all subsequent commands until a new one is defined.
Supported Tags
## @description (Required)
Describes what the command does.
- Usage: Must be placed immediately before the target.
- Effect: Adds the command to the documentation.
- Multi-line support: You can use
\nor the<br>tag to force a line break in the generated Markdown tables.
## @description Starts the server \n Warning: check your .env first!
start:
...
## @category (Optional)
Groups commands into a section.
- Usage: Can be placed anywhere. It acts as a switch.
- Default: If omitted, commands go into a “General” category.
## @category Database
# ... all commands below are now in "Database" ...
## @depends (Optional)
Lists the dependencies of a command (what must run before).
- Usage: Comma-separated list of other make targets.
- Effect: Draws arrows in the generated Workflow Graph and lists them in the “Dependencies” column of the detailed tables.
## @description Run database migrations
## @depends up, install
migrate:
...
## @env (Optional)
Documents required environment variables.
- Usage: Comma-separated list of variables.
- Effect: Adds a “Required Variables” column in the details table.
## @description Starts the server
## @env PORT, NODE_ENV
start:
...
Automation & CI/CD
Documentation is misleading if it is not up-to-date.
Instead of remembering to run makefile2doc manually after every change, you should let your CI pipeline handle it.
The logic is simple: if Makefile is modified, regenerate MAKEFILE.md and commit the result.
GitHub Actions Example
Here is a ready-to-use workflow using checkout and the git-auto-commit Action (check links for latest versions).
Create .github/workflows/update-docs.yml:
name: Update Makefile Doc
on:
push:
paths:
- "Makefile" # Trigger only when the Makefile changes
permissions:
contents: write # Required to push the new commit
jobs:
update-doc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install makefile2doc
env:
# Check the latest version: https://github.com/Merlin-Clos/makefile2doc/releases
VERSION: v0.1.2
run: |
curl -L -o makefile2doc https://github.com/Merlin-Clos/makefile2doc/releases/download/${VERSION}/makefile2doc-linux-amd64
chmod +x makefile2doc
sudo mv makefile2doc /usr/local/bin/
- name: Generate Documentation
run: makefile2doc
- name: Commit & Push changes
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: "docs: auto-update MAKEFILE.md"
file_pattern: MAKEFILE.md
AI-Ready Documentation
makefile2doc bridges the gap between raw code and AI comprehension.
1. Context Window Efficiency
When you provide a raw Makefile to an LLM (ChatGPT, Claude, etc.), it has to parse implementation details like docker compose flags, sed commands, or complex environment variable expansions.
By providing the generated MAKEFILE.md, you offer a high-level summary:
- Token Savings: Only the intent and dependencies are sent, not the bash implementation.
- Better Reasoning: LLMs can understand the Workflow Graph (Mermaid) to see how commands relate, preventing it from suggesting commands in the wrong order.
2. Accuracy Enforcement
Using makefile2doc acts as a Forcing Function for your team:
- If the documentation is wrong, your AI will hallucinate.
- This incentivizes developers to keep
## @descriptionand## @dependstags accurate.
3. How to use with LLMs
To give your AI the full context, don’t copy-paste files one by one.
👉 Click here for the Full Context (Print View)
Copy the content of that page and paste it into your AI. It contains the entire documentation in one go.