Overview
This guide outlines the standards and best practices for contributing to the dotfiles repository. These guidelines ensure consistency, scalability, and maintainability across the project.These guidelines are particularly important for AI agents working on this project, but apply to all contributors.
Project Architecture
Data-Driven Ansible Setup
This repository uses a data-driven Ansible architecture to avoid role proliferation.How to Add New Software
Follow these steps to add new packages:-
Open
ansible/group_vars/all.yml -
Add custom repository (if needed)
If the software requires a custom APT repository:
The
commonrole will automatically:- Download the GPG key
- De-armor it
- Configure the APT source
-
Add package name
Add the package to the appropriate list:
-
Update tests
Add the package to
tests/test-packages.sh:
When to Create Dedicated Roles
Only create dedicated Ansible roles for software that requires:- Complex configuration files
- Multi-step templating
- Non-APT package managers (e.g., Snap, Flatpak)
- Extensive system modifications
gnome role handles GNOME desktop settings via dconf, which can’t be managed through simple package lists.
Secrets Management
Never Commit Unencrypted Secrets
Secrets Storage Strategy
This project uses Bitwarden CLI (bw) and age encryption:
| Secret Type | Storage Location | Access Method |
|---|---|---|
| SSH private keys | Bitwarden Secure Notes | bitwarden template function or run_once_ scripts |
| AWS credentials | Bitwarden Custom Fields | bitwardenFields template function |
age private key | Bitwarden Secure Note | Retrieved during bootstrap |
| Config files with secrets | Git repo (.age encrypted) | Decrypted by chezmoi |
Adding Encrypted Files
To add encrypted files to the repository:Tool Calling Conventions
When modifying files (especially important for AI agents):1. Use Precise Editing Tools
Best Practices
Best Practices
- Prefer: Native file editing tools with exact
StartLineandEndLineparameters - Avoid: Shell commands like
echo "text" >> fileorsed - Reason: Precise tools prevent accidental overwrites and make changes reviewable
2. Don’t Duplicate Existing Workflows
Example:- ❌ Don’t write a custom script to install packages
- ✅ Add packages to
ansible/group_vars/all.yml
3. Respect Existing Tools
Use the project’s existing tools:- chezmoi for dotfile management
- Ansible for system configuration
- Bitwarden CLI for secrets
Testing Requirements
Update Tests When Adding Features
Always update
tests/test-packages.sh when adding new packages to ansible/group_vars/all.yml.Run Tests Before Committing
Run the integration test suite locally:- ✅ Packages are installed
- ✅ Dotfiles are applied
- ✅ Age key is configured correctly
Ansible Linting
Setup Local Linting
Before pushing Ansible changes, ensure they passansible-lint:
Critical Lint Rules
Rule 1: Pipes in Shell Tasks (risky-shell-pipe)
When using pipes (|) in ansible.builtin.shell tasks:
Rule 2: YAML Truthy Values (yaml[truthy])
Use standard YAML booleans:
Always use lowercase
true or false. Do not use yes, no, on, off, Y, or N.Rule 3: Collection Dependencies
Custom modules require their collections to be installed:Idempotence
Ansible Tasks
Ansible tasks are idempotent by design. Follow best practices:Chezmoi Scripts
When writingrun_once_ scripts for chezmoi, use guard clauses:
Pull Request Checklist
Before submitting a pull request:- Added packages to
ansible/group_vars/all.yml(not new roles) - Updated
tests/test-packages.shfor new packages - Ran
bash tests/run-all.shlocally - Ran
ansible-lint ansible/site.ymlsuccessfully - Used
true/falseinstead ofyes/noin YAML - Added
set -o pipefailto shell tasks with pipes - Ensured scripts are idempotent
- No unencrypted secrets committed
- Followed existing code style and conventions
Repository Structure
Understand the project structure before making changes:Getting Help
If you’re unsure about:- Whether to create a new role
- How to structure a configuration
- Test requirements
Thank you for helping maintain a clean, scalable, and secure dotfiles environment!