Files
ctdd/AGENTS.md
T
portersky 79d3b92511 chore: add pi skills for tdd, cmake, and git
Create .pi/skills/ with three skills:
- tdd: Red-Green-Refactor workflow, Unity assertions, CMock patterns
- cmake: build commands, adding modules, dependency FetchContent pattern
- git: conventional commits, semver tagging, branching conventions

Update AGENTS.md and README.md to reference the skills and template
project description.
2026-06-15 04:27:39 +02:00

5.9 KiB

AGENTS.md

Project Overview

ctdd is a C23 template project wired for test-driven development using Unity and CMock. Use it as the core template when scaffolding new projects.

For TDD workflows (adding modules, writing tests, mocking), load the tdd skill with /skill:tdd.

For build configuration (dependencies, coverage, sanitizers), load the cmake skill with /skill:cmake.

For committing, tagging, and branching, load the git skill with /skill:git.

Build System

  • Generator: Ninja
  • CMake minimum: 3.21
  • C standard: C23

Commands

Configure (default):

cmake -S . -B build -G Ninja

Configure with coverage:

cmake -S . -B build-cov -G Ninja -DENABLE_COVERAGE=ON

Build:

ninja -C build

Run tests (full Unity output, colored):

ninja -C build check

Run tests (CTest summary only):

ninja -C build test

Run tests and generate coverage HTML:

ninja -C build-cov coverage

Run (Linux/macOS):

./build/main

Run (Windows):

./build/main.exe

Dependencies

Dependencies are managed via custom Find*.cmake scripts in deps/. These scripts use FetchContent under the hood to download and build libraries automatically.

To add a new dependency:

  1. Add the corresponding Find<name>.cmake to deps/
  2. Add find_package(<name> REQUIRED) to CMakeLists.txt
  3. Link with <name>::<name> in target_link_libraries()

CMake Module Path

deps/ is added to CMAKE_MODULE_PATH so find_package() resolves to the custom scripts instead of system-installed packages.

Coding Conventions

C

  • Language: C23
  • East const (e.g. char const* not const char*)
  • 4-space indentation
  • <> includes for system headers (C stdlib, OS, etc.)
  • "" includes for third-party and local headers
  • Naming: snake_case for variables, functions, and structs
  • Naming: SCREAMING_SNAKE_CASE only for macros and constants

C++

  • Trailing return type for function signatures (e.g. auto fn() -> void)
  • auto for obvious types (e.g. auto main(...) -> int)
  • No semicolons after closing braces for namespaces/classes
  • Trailing return type for all function definitions, including operators (e.g. auto operator=(T&&) noexcept -> T&)
  • Public members first in class declarations, private members at the bottom

Include Order

Both C and C++ follow the same include order:

  1. C++ standard library headers (<chrono>, <vector>, etc.)
  2. (blank line)
  3. C standard library headers (<stdlib.h>, <string.h>, etc.)
  4. (blank line)
  5. OS-specific headers (Windows API, POSIX, etc.)
  6. (blank line)
  7. Third-party dependencies ("fmt/core.h", etc.)
  8. (blank line)
  9. Local/project headers

Shell Scripts

  • Always use #!/bin/sh shebang for shell scripts
  • Scripts must be POSIX compliant (no bashisms)
  • When providing commands to users:
    • Windows/PowerShell: use ` for line continuation
    • Unix/Linux/macOS: use \ for line continuation

Commit Messages

  • Follow the 50/72 rule:
    • Subject line: max 50 characters
    • Body lines: wrapped at 72 characters
  • Use conventional commit prefixes (feat:, fix:, docs:, chore:, etc.)
  • Separate subject from body with a blank line
  • Do not add yourself as a co-author (Co-Authored-By: trailers are forbidden)

Example:

feat: add stopwatch timer

Replace Hello World with a live stopwatch that prints elapsed time
in HH:MM:SS.mmm format, updating every 10ms with color output.

Documentation (Markdown)

  • Wrap normal text and lists at max 80 columns (for readability in terminals and editors).

  • Exceptions: Tables and code blocks (```) can exceed 80 columns when formatting requires it (e.g. trees, alignment).

  • Use standard Markdown: **bold**, `inline code`, ## headings, - or numbered lists, fenced code blocks with language hints (```cpp, ```sh).

  • Keep examples concise, up-to-date, and self-documenting.

  • Do not use em dashes (). Use a colon or rewrite the sentence.

  • Each shell command gets its own fenced code block; do not combine multiple commands into one block. Precede each block with a short plain-text label describing what the command does:

    Setup build:

    cmake -S . -B build -G Ninja
    
  • This file (AGENTS.md) follows its own rules.

Source Layout

ctdd/
  str.h / str.c        Pure string utilities (no dependencies)
  report.h / report.c  Formats a value and calls log_message()
  logger.h / logger.c  Real log_message via printf to stdout
main.c                 Entry point
tests/
  test_str.c           Unity state-based tests for ctdd/str
  test_report.c        Interaction-based tests using CMock
deps/
  FindUnity.cmake      Fetches Unity v2.6.1 via ZIP
  FindCMock.cmake      Fetches CMock v2.6.0 via ZIP

Behavioral Guidelines

Reduce common LLM coding mistakes. Bias toward caution over speed. For trivial tasks, use judgment.

Think Before Coding

  • State assumptions explicitly. If uncertain, ask.
  • If multiple interpretations exist, present them, don't pick silently.
  • If something is unclear, stop. Name what's confusing. Ask.

Simplicity First

Minimum code that solves the problem. Nothing speculative.

  • No features beyond what was asked.
  • No abstractions for single-use code.
  • If you write 200 lines and it could be 50, rewrite it.

Surgical Changes

Touch only what you must. Clean up only your own mess.

  • Don't "improve" adjacent code, comments, or formatting.
  • Don't refactor things that aren't broken.
  • Match existing style, even if you'd do it differently.
  • Remove imports/variables/functions that YOUR changes made unused.
  • Don't remove pre-existing dead code unless asked.

Goal-Driven Execution

Transform tasks into verifiable goals:

  • "Add validation" means: write tests for invalid inputs, then pass.
  • "Fix the bug" means: write a test that reproduces it, then pass.
  • "Refactor X" means: ensure tests pass before and after.