Aws code habits
A library with Make targets, Ansible playbooks, Jinja templates (and more) designed to boost common software development tasks and enhance governance.
A library of Make targets, Ansible playbooks, and Jinja templates that you add to a project as a Git submodule to standardize common development tasks. The project is written primarily in Makefile, distributed under the MIT No Attribution license, first published in 2022. Key topics include: ansible, aws, code, development, governance.

AWS Code Habits
A library of Make targets, Ansible playbooks, and Jinja templates that you add to a project as a Git submodule to standardize common development tasks.
![]() |
|---|
| Installing AWS Code Habits |
Overview
AWS Code Habits is a reusable library you embed in your own repository. It groups everyday development tasks behind consistent make targets so that every contributor runs the same commands to install tools, format code, run linters, manage infrastructure, and generate documentation.
The library has three parts:
- Make targets under
lib/make/provide the commands you run, such asterraform/plan,python/test, anddoc/build. - Ansible playbooks under
lib/ansible/perform multi-step actions, such as scaffolding.github/directories and rendering the README. - Jinja templates render files such as
README.mdfrom data indoc/habits.yaml.
You add the library to a project as a Git submodule (or as a vendored copy) and include its Make targets from your own Makefile. It is intended for teams that want a shared, version-controlled set of development commands across many repositories.
The following diagram shows how your project consumes the library:
mermaidflowchart LR project["Your project"] makefile["Your Makefile<br/>includes lib/make/*/*.mk<br/>and lib/make/*.mk"] targets["make targets<br/>(terraform/plan, python/test, doc/build)"] tools["Tools<br/>(Terraform, AWS CDK, Python, Node.js, Go)"] ansible["Ansible playbooks<br/>(lib/ansible/)"] project --> makefile makefile -->|include .mk glob| targets targets -->|run a tool directly| tools targets -->|multi-step actions| ansible
Features
- Run common tasks through consistent
maketargets across repositories. - Install and pin developer tools (Terraform, AWS CDK, Python, Node.js, Go, and more) through dedicated targets.
- Generate
README.mdfrom a single source file,doc/habits.yaml. - Scaffold project files:
.gitignore, pre-commit configuration, and.github/directories for actions, workflows, issues, and pull requests. - Gate destructive targets behind a confirmation prompt and verify downloaded binaries with optional SHA256 checks. See docs/HARDENING.md.
Prerequisites
The library supports Linux, macOS, and Windows (with some limitations). Many targets include cross-platform detection and use the appropriate installation method for the host.
You need the following installed before you use the library:
- Python 3 — used by several targets and by the documentation tooling.
- pip — the Python package installer.
- GNU Make — runs the targets the library defines.
Installation
You use AWS Code Habits as a Git submodule. From the root directory of your project, run:
bashgit submodule add --name habits -b main https://github.com/awslabs/aws-code-habits.git habits
This clones the library into a habits/ directory that tracks the main branch.
Pin the submodule to a release. Tracking main exposes you to unannounced changes. After you add the submodule, check out a tagged release (or a specific commit SHA) and commit the resulting submodule pointer:
bashgit -C habits fetch --tags git -C habits checkout v1.5.0 # or any tag from CHANGELOG.md git add habits && git commit -m "chore: pin habits to v1.5.0"
See CHANGELOG.md for available releases. To move to a newer release later, repeat the checkout step against a newer tag.
When you next clone your repository, pass --recurse-submodules so the submodule is fetched:
bashgit clone --recurse-submodules <your-repository-url>
If you already cloned the repository without --recurse-submodules, initialize and fetch the submodule with:
bashgit submodule update --init --recursive
To automate the installation steps, use the helper scripts in the scripts/ directory.
Getting started
-
Add the submodule with the command in Installation.
-
Create a
Makefilein your project root (or add these lines to an existing one):makefileexport WORKSPACE = $(shell pwd) export HABITS = $(WORKSPACE)/habits include $(WORKSPACE)/tools.env # pin the version of your tools include $(HABITS)/lib/make/*/*.mk include $(HABITS)/lib/make/*.mk -
List the available targets:
bashmake helpYou see a list of targets with one-line descriptions:
textAvailable targets: doc/build Builds documentation doc/init Initialize documentation habits/check Performs checks ...
Usage
List every target with the default help target:
bashmake help
For the full target reference, see Makefile.md.
Several technology-specific Makefiles add their own help target:
bashmake terraform/help make nodejs/help make python/help make go/help make gitignore/help
Initialize pre-commit configuration
Create a .pre-commit-config.yaml in your working directory:
bashmake pre-commit/init
Run all pre-commit hooks against every file:
bashmake pre-commit/run
Maintain documentation
-
Initialize the documentation files. This creates a
doc/directory containinghabits.yaml:bashmake doc/init -
Edit
doc/habits.yaml, then rebuild the README:bashmake doc/build
README.md is rendered from doc/habits.yaml. Do not edit README.md by hand — your changes are overwritten on the next make doc/build.
Compose your own targets
Add aggregate targets to your Makefile that call library targets. For example, to combine documentation and pre-commit checks:
makefile.PHONY: hygiene hygiene: doc/build pre-commit/run
To drive an AWS CloudFormation workflow:
makefile.PHONY: hygiene hygiene: aws/cloudformation/hygiene .PHONY: plan plan: aws/cloudformation/create-change-set .PHONY: discard discard: aws/cloudformation/delete-change-set .PHONY: apply apply: aws/cloudformation/execute-change-set
Use technology-specific targets
Each technology groups its targets under a common prefix.
Terraform:
bashmake terraform/install make terraform/init make terraform/plan make terraform/apply make terraform/workspace/list make terraform/workspace/new WORKSPACE_NAME=dev
AWS Cloud Development Kit (AWS CDK):
bashmake aws/cdk/install make aws/cdk/bootstrap make aws/cdk/deploy make aws/cdk/synth
Python:
bashmake python/install make python/virtualenv/init make python/poetry/install make python/poetry/init make python/test
Node.js:
bashmake nodejs/install make nodejs/init/express make nodejs/init/react make nodejs/init/vue make nodejs/add PACKAGE=express make nodejs/add/dev PACKAGE=jest
Go:
bashmake go/install make go/app/build OUTPUT=myapp make go/app/test
Gitignore:
bashmake gitignore/init/web make gitignore/init/python make gitignore/init/node
Run checks
Verify that a project has the files the library expects:
bashmake habits/check
Run technology-specific tests:
bashmake python/test make python/test/coverage make nodejs/test make go/app/test make go/app/test/coverage
Configuration
You configure the library through environment files that your Makefile includes and through variables you pass on the command line.
tools.env— pins tool versions. Every*_VERSIONvariable uses?=, so a value you set intools.envoverrides the default.*_SHA256variables — when set, the matching tool installer verifies the downloaded archive withsha256sum -cand aborts on mismatch. When unset, the installer prints a warning and proceeds.CONFIRM— setCONFIRM=yesto skip the confirmation prompt on destructive targets, for example in continuous integration.
Destructive targets are gated behind a confirmation prompt: terraform/apply, terraform/destroy, aws/cdk/destroy*, nuke/run, docker/remove-images, docker/remove-volumes, and docker/prune. For the full list of safety variables and recommended values, see docs/HARDENING.md.
How it works
You include the library's .mk files from your Makefile. Each .mk file under lib/make/ defines targets for one tool or technology. Targets that perform multi-step actions, such as doc/build and doc/init, delegate to Ansible playbooks under lib/ansible/.
README.md is generated. The doc/build target runs an Ansible playbook that renders the Jinja template lib/ansible/templates/readme.j2 using the data in doc/habits.yaml, then writes the result to README.md.
The following diagram shows the documentation render pipeline:
mermaidflowchart LR cmd["make doc/build"] target["doc/build target<br/>(lib/make/doc.mk)"] playbook["Ansible playbook<br/>(lib/ansible/playbooks/doc/build.yaml)"] data["doc/habits.yaml<br/>(source data)"] template["readme.j2<br/>(lib/ansible/templates/)"] readme["README.md<br/>(generated)"] cmd --> target target --> playbook data --> playbook template --> playbook playbook -->|render| readme
Contributing
See Contributing.
Security
See Security to report a vulnerability. Do not file public GitHub issues for security reports.
License
This project is licensed under the MIT-0 License. See the LICENSE file.
Copyright
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Contributors
Showing top 5 contributors by commit count.

