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.
Read .ai-factory/skill-context/aif-build-automation/SKILL.md
— MANDATORY if the file exists.
This file contains project-specific rules accumulated by
from patches,
codebase conventions, and tech-stack analysis. These rules are tailored to the current project.
How to apply skill-context rules:
- Treat them as project-level overrides for this skill's general instructions
- When a skill-context rule conflicts with a general rule written in this SKILL.md,
the skill-context rule wins (more specific context takes priority — same principle as nested CLAUDE.md files)
- When there is no conflict, apply both: general rules from SKILL.md + project rules from skill-context
- Do NOT ignore skill-context rules even if they seem to contradict this skill's defaults —
they exist because the project's experience proved the default insufficient
- CRITICAL: skill-context rules apply to ALL outputs of this skill — including the generated
build files (Makefile, Taskfile, justfile, magefile). Templates in this skill are base structures.
If a skill-context rule says "build file MUST include target X" or "MUST follow convention Y" —
you MUST comply. Generating build automation that violates skill-context rules is a bug.
Enforcement: After generating any output artifact, verify it against all skill-context rules.
If any rule is violated — fix the output before presenting it to the user.
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
from the results.
1.2 Determine Mode
Mode A — Enhance Existing (if
is not empty):
- Set
- Set automatically from the detected file (Makefile → , Taskfile.yml → , etc.)
- If multiple build files exist AND specifies 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
Mode B — Generate New (if
is empty):
- Set
- Parse to determine tool:
| Argument | Tool | Output File |
|---|
| or | GNU Make | |
| or | Taskfile | |
| or | Just | |
| or | Mage | |
- If is 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
.
Step 2: Analyze Project
Detect the project profile by scanning the repository. Run these checks using
and
:
2.1 Primary Language
Check for these files (first match wins):
| File | Language |
|---|
| Go |
| Node.js / JavaScript / TypeScript |
| or or | Python |
| Rust |
| PHP |
| Ruby |
| or | Java/Kotlin |
| or | C# / .NET |
2.2 Package Manager
Check lock files:
| File | Package Manager |
|---|
| bun |
| pnpm |
| yarn |
| npm |
| poetry |
| uv |
| pipenv |
2.3 Framework Detection
For Node.js projects, check
dependencies for:
- → Next.js
- → Nuxt
- → Remix
- → Express
- → Fastify
- → Hono
- → NestJS
For Python projects, check
or imports for:
- → FastAPI
- → Django
- → Flask
For PHP projects, check
require for:
- → Laravel
- → Symfony
- → Slim
- → CakePHP
For Go projects, check
for:
- → Gin
- → Echo
- → Fiber
- → Chi
2.4 Docker (Deep Scan)
Glob: Dockerfile, Dockerfile.*, docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml, .dockerignore
If any exist, set
and perform a deeper analysis:
Read the Dockerfile(s) to detect:
- Multi-stage builds (separate / stages) →
- Exposed ports → (e.g., , )
- Base image → (e.g., , )
- Entrypoint/CMD → understand how the app is started inside the container
Read docker-compose / compose file to detect:
- Service names → (e.g., , , , )
- Volume mounts → understand dev vs prod setup
- Profiles (if any) → , ,
- Dependency services (postgres, redis, rabbitmq, etc.) →
- : boolean
- : boolean
- : list of service names
- : list of infrastructure services (db, cache, queue)
- : exposed ports
- : boolean (Dockerfile has a or stage)
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
- → Drizzle
- directory → Alembic
- directory → Generic migrations
2.7 Test Framework
| Language | Check For |
|---|
| Node.js | , , , in package.json |
| Python | in pyproject.toml/requirements, imports |
| Go | Go has built-in testing; check for in go.mod |
| Rust | Built-in; check for integration test directory |
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
- : primary language
- : detected PM
- : detected framework (if any)
- : boolean
- : object (if )
- : detected CI (if any)
- : boolean + tool name
- : detected test runner
- : list of detected linters
- : boolean
- : 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
:
- 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
+
:
| Tool | Go | Node.js | Python | PHP | Other |
|---|
| Makefile | | | | | Use closest match |
| Taskfile | | | | | Use closest match |
| Justfile | | | | | Use closest match |
| Magefile | | | | N/A (use Makefile) | |
For Magefile: use
if
or
is true, otherwise
.
For PHP + Magefile: Mage is Go-specific and not applicable to PHP projects. If the user explicitly requested
for a PHP project, explain this and suggest Makefile as the closest alternative (universal, no install needed). Ask via
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
, 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
- Database targets → only if (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
- 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 , generate a dedicated Docker section (see below)
Docker-Aware Target Generation
When
is true, generate
two layers of commands:
Layer 1 — Container lifecycle (always when Docker detected):
| Target | Purpose |
|---|
| or | Build the Docker image |
| or | Run the container |
| or | Stop running containers |
| or | Tail container logs |
| or | Push image to registry |
| or | 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 → use commands (not )
- If compose has profiles → use /
- If → use for dev builds, no target (or ) for prod
- If exist (db, redis, etc.) → add / targets to start/stop only infrastructure services without the app
- If compose detected → should run with correct profile/services
- If no compose but Dockerfile → should run
docker build --target dev
+ with 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
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 , , or directory name
- Source directory: Use actual src dir (e.g., , , )
- Dev server command: Match the framework's dev server (e.g., , , )
- 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
, do NOT replace the file from scratch. Instead, analyze it and improve it surgically.
5A.1 Analyze Existing File
Compare
against the
and best practices. Build a gap analysis:
Missing preamble/config — Check if the file has the recommended preamble:
- Makefile: , , , ,
- Taskfile: , ,
- Justfile: , ,
- Magefile: , proper imports
Missing standard targets — Check which of these are absent:
- / (self-documenting)
- , , , , ,
- (aggregate target)
Missing project-specific targets — Based on
, check for:
- Docker targets (if but no docker targets in file)
- Database/migration targets (if but 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 declarations (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:
Step 6: Write File & Report
6.1 Write the File
Mode B (Generate New):
Write the generated content using the
tool:
| Tool | Output Path |
|---|
| Makefile | |
| Taskfile | |
| Justfile | |
| Magefile | |
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
Display summary using format from
references/SUMMARY-FORMAT.md
. Shows targets table, project profile used, and quick start command for Mode B (generate), or what changed + new/existing targets for Mode A (enhance). Include installation hints if the tool requires setup.
Step 7: Project Documentation Integration
After writing the build file, integrate quick commands into project docs.
For detailed integration procedures (README, AGENTS.md, existing markdown) → read
references/DOC-INTEGRATION.md
Brief: scan for existing command sections, update or append quick reference, suggest AGENTS.md creation if missing.
Artifact Ownership and Config Policy
- Primary ownership: generated or enhanced build automation files (, , , ).
- Allowed companion updates: quick command snippets in existing docs or when directly tied to the generated build workflow.
- Config policy: config-agnostic by design. This skill uses repository detection and fixed AI Factory context files rather than .