ai-factory.build-automation
Build Automation Generator
Generate or enhance a build automation file for any project. Supports Makefile, Taskfile.yml, Justfile, and Magefile.go.
Two modes:
- Generate — No build file exists → create one from scratch using best-practice templates
- Enhance — Build file already exists → analyze gaps, add missing targets, fix anti-patterns, preserve existing work
Step 0: Load Project Context
Read the project description if available:
Read .ai-factory/DESCRIPTION.md
Store the project context (tech stack, framework, architecture) for use in later steps. If the file doesn't exist, that's fine — we'll detect everything in Step 2.
Step 1: Detect Existing Build Files & Determine Mode
1.1 Scan for Existing Build Files
Before anything else, check if the project already has build automation:
Glob: Makefile, makefile, GNUmakefile, Taskfile.yml, Taskfile.yaml, taskfile.yml, justfile, Justfile, .justfile, magefile.go, magefiles/*.go
Build a list of EXISTING_FILES from the results.
1.2 Determine Mode
Mode A — Enhance Existing (if EXISTING_FILES is not empty):
- Set
MODE = "enhance" - Set
TARGET_TOOLautomatically from the detected file (Makefile →makefile, Taskfile.yml →taskfile, etc.) - If multiple build files exist AND
$ARGUMENTSspecifies one, use the argument to pick which one to enhance - If multiple build files exist AND no argument, ask which one to enhance:
AskUserQuestion: This project has multiple build files. Which one should I improve?
Options (dynamic, based on what exists):
1. Makefile — Enhance the existing Makefile
2. Taskfile.yml — Enhance the existing Taskfile
...
- Read the existing file content — this is the baseline for enhancement
- Store as
EXISTING_CONTENT
Mode B — Generate New (if EXISTING_FILES is empty):
- Set
MODE = "generate" - Parse
$ARGUMENTSto determine tool:
| Argument | Tool | Output File |
|---|---|---|
makefile or make |
GNU Make | Makefile |
taskfile or task |
Taskfile | Taskfile.yml |
justfile or just |
Just | justfile |
mage or magefile |
Mage | magefile.go |
- If
$ARGUMENTSis empty or doesn't match, ask the user interactively:
AskUserQuestion: Which build automation tool do you want to generate?
Options:
1. Makefile — GNU Make (universal, no install needed)
2. Taskfile.yml — Task runner (YAML, modern, cross-platform)
3. justfile — Just command runner (simple, fast, ergonomic)
4. magefile.go — Mage (Go-native, type-safe, no shell scripts)
Store the chosen tool as TARGET_TOOL.
Step 2: Analyze Project
Detect the project profile by scanning the repository. Run these checks using Glob and Grep:
2.1 Primary Language
Check for these files (first match wins):
| File | Language |
|---|---|
go.mod |
Go |
package.json |
Node.js / JavaScript / TypeScript |
pyproject.toml or setup.py or setup.cfg |
Python |
Cargo.toml |
Rust |
composer.json |
PHP |
Gemfile |
Ruby |
build.gradle or pom.xml |
Java/Kotlin |
*.csproj or *.sln |
C# / .NET |
2.2 Package Manager
Check lock files:
| File | Package Manager |
|---|---|
bun.lockb |
bun |
pnpm-lock.yaml |
pnpm |
yarn.lock |
yarn |
package-lock.json |
npm |
poetry.lock |
poetry |
uv.lock |
uv |
Pipfile.lock |
pipenv |
2.3 Framework Detection
For Node.js projects, check package.json dependencies for:
next→ Next.jsnuxt→ Nuxt@remix-run/node→ Remixexpress→ Expressfastify→ Fastifyhono→ Hono@nestjs/core→ NestJS
For Python projects, check pyproject.toml or imports for:
fastapi→ FastAPIdjango→ Djangoflask→ Flask
For PHP projects, check composer.json require for:
laravel/framework→ Laravelsymfony/framework-bundle→ Symfonyslim/slim→ Slimcakephp/cakephp→ CakePHP
For Go projects, check go.mod for:
gin-gonic/gin→ Ginlabstack/echo→ Echogofiber/fiber→ Fibergo-chi/chi→ Chi
2.4 Docker (Deep Scan)
Glob: Dockerfile, Dockerfile.*, docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml, .dockerignore
If any exist, set HAS_DOCKER=true and perform a deeper analysis:
Read the Dockerfile(s) to detect:
- Multi-stage builds (separate
dev/prodstages) →DOCKER_MULTISTAGE=true - Exposed ports →
DOCKER_PORTS(e.g.,3000,8080) - Base image →
DOCKER_BASE(e.g.,node:20-alpine,golang:1.22) - Entrypoint/CMD → understand how the app is started inside the container
Read docker-compose / compose file to detect:
- Service names →
DOCKER_SERVICES(e.g.,app,db,redis,worker) - Volume mounts → understand dev vs prod setup
- Profiles (if any) →
dev,production,test - Dependency services (postgres, redis, rabbitmq, etc.) →
DOCKER_DEPS
Store as DOCKER_PROFILE:
has_compose: booleanhas_multistage: booleanservices: list of service namesdeps: list of infrastructure services (db, cache, queue)ports: exposed portshas_dev_stage: boolean (Dockerfile has adevordevelopmentstage)
2.5 CI/CD
Glob: .github/workflows/*.yml, .gitlab-ci.yml, .circleci/config.yml, Jenkinsfile, .travis.yml
Note which CI system is in use.
2.6 Database & Migrations
Search for migration tools:
Grep: prisma|drizzle|knex|typeorm|sequelize|alembic|django.*migrate|goose|migrate|atlas|sqlx
Check for:
prisma/schema.prisma→ Prismadrizzle.config.ts→ Drizzlealembic/directory → Alembicmigrations/directory → Generic migrations
2.7 Test Framework
| Language | Check For |
|---|---|
| Node.js | jest, vitest, mocha, ava in package.json |
| Python | pytest in pyproject.toml/requirements, unittest imports |
| Go | Go has built-in testing; check for testify in go.mod |
| Rust | Built-in; check for integration test directory tests/ |
2.8 Linters & Formatters
Glob: .eslintrc*, eslint.config.*, .prettierrc*, biome.json, .golangci.yml, .golangci.yaml
Grep in pyproject.toml: ruff|black|flake8|pylint|isort
2.9 Monorepo Detection
Glob: turbo.json, nx.json, lerna.json, pnpm-workspace.yaml
Summary
Build a PROJECT_PROFILE object with:
language: primary languagepackage_manager: detected PMframework: detected framework (if any)has_docker: booleandocker_profile:DOCKER_PROFILEobject (ifhas_docker)ci_system: detected CI (if any)has_migrations: boolean + tool nametest_framework: detected test runnerlinters: list of detected lintersis_monorepo: booleanhas_dev_server: boolean (framework with dev server)
Step 3: Read Best Practices
Read the best practices reference for the chosen tool:
Read skills/build-automation/references/BEST-PRACTICES.md
Focus on the section matching TARGET_TOOL:
- Makefile → Section 1
- Taskfile → Section 2
- Justfile → Section 3
- Magefile → Section 4
Also read the "Cross-Cutting Concerns" section for standard targets.
Step 4: Select & Read Template
Pick the closest matching template based on language + TARGET_TOOL:
| Tool | Go | Node.js | Python | PHP | Other |
|---|---|---|---|---|---|
| Makefile | makefile-go.mk |
makefile-node.mk |
makefile-python.mk |
makefile-php.mk |
Use closest match |
| Taskfile | taskfile-go.yml |
taskfile-node.yml |
taskfile-python.yml |
taskfile-php.yml |
Use closest match |
| Justfile | justfile-go |
justfile-node |
justfile-python |
justfile-php |
Use closest match |
| Magefile | magefile-basic.go |
magefile-full.go |
magefile-full.go |
N/A (use Makefile) | magefile-basic.go |
For Magefile: use magefile-full.go if HAS_DOCKER or has_migrations is true, otherwise magefile-basic.go.
For PHP + Magefile: Mage is Go-specific and not applicable to PHP projects. If the user explicitly requested mage for a PHP project, explain this and suggest Makefile as the closest alternative (universal, no install needed). Ask via AskUserQuestion whether to proceed with Makefile instead.
Read the selected template:
Read skills/build-automation/templates/<selected-template>
Step 5: Generate or Enhance File
Mode B — Generate New File
Using the PROJECT_PROFILE, best practices, and template as reference, generate a customized build file from scratch.
Generation Rules
- Start with the tool's required preamble (from best practices)
- Include all standard targets: help/default, build, test, lint, clean, dev, fmt
- Add conditional targets based on project profile:
- Docker targets → only if
has_docker - Database targets → only if
has_migrations(use correct migration tool) - Deploy targets → only if CI/CD detected
- Generate target → only if code generation detected
- Typecheck target → only if TypeScript or mypy detected
- Docker targets → only if
- Use correct package manager commands (not hardcoded npm/pip/go)
- Include CI aggregate target that runs lint + test + build
- Follow the template's structure for organization and grouping
- Adapt variable names to match the actual project (module name, binary name, source dirs)
- Include version/commit/build-time detection via git
- Docker-aware targets — if
has_docker, generate a dedicated Docker section (see below)
Docker-Aware Target Generation
When has_docker is true, generate two layers of commands:
Layer 1 — Container lifecycle (always when Docker detected):
| Target | Purpose |
|---|---|
docker-build or docker:build |
Build the Docker image |
docker-run or docker:run |
Run the container |
docker-stop or docker:stop |
Stop running containers |
docker-logs or docker:logs |
Tail container logs |
docker-push or docker:push |
Push image to registry |
docker-clean or docker:clean |
Remove images and stopped containers |
Layer 2 — Dev vs Production separation (when compose or multistage detected):
##@ Docker — Development
docker-dev: ## Start all services in dev mode (with hot reload, mounted volumes)
docker-dev-build: ## Rebuild dev containers
docker-dev-down: ## Stop dev environment and remove volumes
##@ Docker — Production
docker-prod-build: ## Build production image (optimized, multi-stage)
docker-prod-run: ## Run production container locally for testing
docker-prod-push: ## Push production image to registry
Generation logic:
- If
has_compose→ usedocker composecommands (notdocker-compose) - If compose has profiles → use
--profile dev/--profile production - If
has_multistage→ use--target devfor dev builds, no target (or--target production) for prod - If
docker_profile.depsexist (db, redis, etc.) → addinfra-up/infra-downtargets to start/stop only infrastructure services without the app - If compose detected →
docker-devshould rundocker compose upwith correct profile/services - If no compose but Dockerfile →
docker-devshould rundocker build --target dev+docker runwith volume mounts
Layer 3 — Container-based commands (mirror host commands via container):
When the project is Docker-based, also generate container-exec variants so that users who run everything in Docker can use the same targets:
# Run tests inside the container
docker-test: ## Run tests inside the Docker container
docker compose exec app [test command]
# Run linter inside the container
docker-lint: ## Run linter inside the Docker container
docker compose exec app [lint command]
# Open shell in the container
docker-shell: ## Open a shell inside the running container
docker compose exec app sh
Only generate docker-* exec variants if the project appears to be Docker-first (compose file mounts source code as volumes, or no local language runtime setup is apparent).
Customization from Project Profile
- Binary name: Use the actual project name from
go.mod,package.json, or directory name - Source directory: Use actual src dir (e.g.,
src/,app/,cmd/) - Dev server command: Match the framework's dev server (e.g.,
next dev,uvicorn --reload,air) - Test command: Match the detected test runner
- Lint command: Match the detected linters
- Migration commands: Match the detected migration tool exactly
- Port numbers: Use framework defaults (3000 for Node, 8000 for Python, 8080 for Go)
Mode A — Enhance Existing File
When MODE = "enhance", do NOT replace the file from scratch. Instead, analyze it and improve it surgically.
5A.1 Analyze Existing File
Compare EXISTING_CONTENT against the PROJECT_PROFILE and best practices. Build a gap analysis:
Missing preamble/config — Check if the file has the recommended preamble:
- Makefile:
SHELL := bash,.ONESHELL,.SHELLFLAGS,.DELETE_ON_ERROR,MAKEFLAGS - Taskfile:
version: '3',output:,dotenv: - Justfile:
set shell,set dotenv-load,set export - Magefile:
//go:build mage, proper imports
Missing standard targets — Check which of these are absent:
help/default(self-documenting)build,test,lint,clean,dev,fmtci(aggregate target)
Missing project-specific targets — Based on PROJECT_PROFILE, check for:
- Docker targets (if
has_dockerbut no docker targets in file) - Database/migration targets (if
has_migrationsbut no db targets) - Typecheck target (if TypeScript/mypy detected but no typecheck target)
- Generate target (if code generation tools detected)
- Coverage target (if test target exists but no coverage variant)
Quality issues — Check for anti-patterns from best practices:
- Targets without descriptions/documentation
- Missing
.PHONYdeclarations (Makefile) - Hardcoded tool paths that should be variables
- Missing version/commit detection
- No self-documenting help target
5A.2 Plan Changes
Build a list of specific changes to make:
CHANGES = [
{ type: "add_preamble", detail: "Add .SHELLFLAGS and .DELETE_ON_ERROR" },
{ type: "add_target", name: "docker-build", detail: "Dockerfile detected but no docker target" },
{ type: "add_target", name: "help", detail: "No self-documenting help target" },
{ type: "fix_quality", detail: "Add ## comments to 3 targets missing descriptions" },
{ type: "add_variable", detail: "Add VERSION/COMMIT detection via git" },
...
]
5A.3 Apply Changes
- Preserve the existing structure — Keep the user's ordering, naming, and style
- Preserve existing targets exactly — Do NOT modify working targets unless fixing a clear bug or adding a missing description
- Add new targets in the appropriate section — Follow the existing grouping pattern (if the file uses
##@sections, add to matching section; if no sections, append logically) - Add missing preamble lines at the top, before existing content
- Add missing variables near existing variable declarations
- Use the template as reference for the syntax of new targets, but adapt to match the style already present in the file (e.g., if existing Makefile uses tabs + simple recipes, don't introduce complex multi-line scripts)
Quality Checks (Both Modes)
Before writing the file, verify:
- All targets have descriptions/documentation (## comments, desc:, [doc()], doc comments)
- No hardcoded paths that should be variables
- Package manager detection is correct
- Self-documenting help target is included
-
.PHONYdeclarations for all non-file targets (Makefile only) - Dangerous operations have confirmations (Justfile) or warnings
Step 6: Write File & Report
6.1 Write the File
Mode B (Generate New):
Write the generated content using the Write tool:
| Tool | Output Path |
|---|---|
| Makefile | Makefile |
| Taskfile | Taskfile.yml |
| Justfile | justfile |
| Magefile | magefile.go |
Mode A (Enhance Existing):
Write the enhanced content to the same path where the existing file was found (preserving the original filename casing and location). The file is updated in-place — no need to ask about overwriting since we're improving, not replacing.
6.2 Display Summary
Mode B (Generate New) — show what was created:
## Generated: [Filename]
### Targets
| Target | Description |
|--------|-------------|
| build | Compile the project binary |
| test | Run test suite |
| lint | Run golangci-lint |
| ... | ... |
### Project Profile Used
- Language: Go
- Package Manager: go modules
- Framework: Chi
- Docker: yes
- Migrations: goose
- Linters: golangci-lint
### Quick Start
[tool-specific run command, e.g., "make help", "task --list", "just", "mage -l"]
Mode A (Enhance Existing) — show what was changed:
## Enhanced: [Filename]
### What Changed
- Added missing preamble: `.SHELLFLAGS`, `.DELETE_ON_ERROR`
- Added `help` target with self-documenting pattern
- Added `docker-build` and `docker-push` targets (Dockerfile detected)
- Added `db-migrate` target (Prisma detected)
- Added `##` descriptions to 3 existing targets
- Added VERSION/COMMIT variables via git
### New Targets Added
| Target | Description |
|--------|-------------|
| help | Show available targets |
| docker-build | Build Docker image |
| db-migrate | Run Prisma migrations |
### Existing Targets (unchanged)
| Target | Description |
|--------|-------------|
| build | Build the project |
| test | Run tests |
| ... | ... |
6.3 Installation Hint (both modes)
If the tool requires installation, include a note:
### Installation
[install instructions for task/just/mage if not already installed]
Installation hints:
- Task:
go install github.com/go-task/task/v3/cmd/task@latestorbrew install go-task - Just:
cargo install justorbrew install just - Mage:
go install github.com/magefile/mage@latestorbrew install mage - Make: Usually pre-installed;
brew install makeon macOS for GNU Make 4+
Step 7: Project Documentation Integration
After writing the build file, integrate the quick commands into the project's documentation. This step ensures that developers can discover commands not just via make help / task --list / just / mage -l, but also in the docs they already read.
Build a QUICK_REFERENCE block — a compact markdown table or code block listing the most important commands:
## Quick Commands
| Command | Description |
|---------|-------------|
| `make dev` | Start development server |
| `make test` | Run tests |
| `make lint` | Run linters |
| `make build` | Build for production |
| `make docker-dev` | Start dev environment in Docker |
| `make docker-prod-build` | Build production Docker image |
| `make clean` | Remove build artifacts |
Adapt the command prefix (make / task / just / mage) to match TARGET_TOOL.
7.1 Update Existing Markdown Files
Scan for markdown files that already contain command/usage sections:
Grep in *.md: "## Commands\b|## Quick Start\b|## Usage\b|## Development\b|## Getting Started\b|## How to Run\b|```sh|```bash"
For each matching file:
- Read the file and find the relevant section
- Check if it already lists commands for the generated tool — if so, update the command list to match the new/enhanced build file
- If the section exists but doesn't mention our build tool, append the quick reference block after the existing commands
- Do NOT delete or rewrite existing content — only add or update the command references
Be conservative: only touch files that clearly have a "commands" or "getting started" section. Don't inject commands into unrelated markdown files.
7.2 Update Project README
Glob: README.md, README.rst, readme.md
If a README exists:
- Check if it has a commands/usage/development section (same grep patterns as 7.1)
- If yes → update/append the quick reference there
- If no → add a
## Quick Commandssection before the last section (typically "License" or "Contributing"), or at the end if no such section exists - Keep it concise — link to the build file for the full list:
Run \make help` for all available targets.`
7.3 AGENTS.md Integration
Glob: AGENTS.md, agents.md, CLAUDE.md, claude.md, .github/copilot-instructions.md, .cursorrules, .cursor/rules/*.md
If an agent instruction file exists (AGENTS.md, CLAUDE.md, etc.):
- Read it and check if it already has a build/commands section
- If no build section → append a section with quick commands that AI agents should use:
## Build & Development Commands
This project uses [Makefile|Taskfile|justfile|Magefile] for build automation.
Common commands:
- `make test` — always run tests before committing
- `make lint` — run linters, fix issues before pushing
- `make build` — verify the project builds cleanly
- `make docker-dev` — start the full dev environment
Run `make help` for all available targets.
- If a build section already exists → update it to reflect the current targets
If NO agent instruction file exists, suggest creating one:
AskUserQuestion: This project doesn't have an AGENTS.md (AI agent instructions). Should I create one with build commands?
Options:
1. Create AGENTS.md — Add build commands and basic project instructions for AI agents
2. Skip — Don't create agent instructions
If the user chooses to create it, generate a minimal AGENTS.md with:
- Project name and brief description (from
PROJECT_PROFILEor.ai-factory/DESCRIPTION.md) - Build commands section (as above)
- Key project conventions (language, test framework, linter — so AI agents run the right commands)
7.4 Summary of Documentation Changes
After all doc updates, append to the Step 6 summary:
### Documentation Updated
- README.md — Added Quick Commands section
- AGENTS.md — Created with build commands
- docs/getting-started.md — Updated command examples
More from lee-to/ai-factory
aif-skill-generator
Generate professional Agent Skills for AI agents. Creates complete skill packages with SKILL.md, references, scripts, and templates. Use when creating new skills, generating custom slash commands, or building reusable AI capabilities. Validates against Agent Skills specification.
37aif-implement
Execute implementation tasks from the current plan. Works through tasks sequentially, marks completion, and preserves progress for continuation across sessions. Use when user says "implement", "start coding", "execute plan", or "continue implementation".
36aif-security-checklist
Security audit checklist based on OWASP Top 10 and best practices. Covers authentication, injection, XSS, CSRF, secrets management, and more. Use when reviewing security, before deploy, asking "is this secure", "security check", "vulnerability".
34aif-plan
Plan implementation for a feature or task. Two modes — fast (single quick plan) or full (richer plan with optional git branch/worktree flow). Use when user says "plan", "new feature", "start feature", "create tasks".
33aif
Set up agent context for a project. Analyzes tech stack, installs relevant skills from skills.sh, generates custom skills, and configures MCP servers. Use when starting new project, setting up AI context, or asking "set up project", "configure AI", "what skills do I need".
32aif-commit
Create conventional commit messages by analyzing staged changes. Generates semantic commit messages following the Conventional Commits specification. Use when user says "commit", "save changes", or "create commit".
32