This repository is a generic CMake-first C++ project frame optimized for agentic development.
Baseline shape:
- CMake is the only supported build system
- C++23 is the baseline language standard
- Out-of-tree builds are the default workflow
- Repo-owned code should stay portable, local-first, and easy to validate
- One small library target plus one CLI target form the default example shape
- Deterministic
CTest,clang-tidy,clang-format,cppcheck, Doxygen, release-hygiene, Valgrind, and coverage lanes are part of the maintained contract - Qt/Clazy provide the example UI stack, not the baseline assumption
- Public docs are generated from repo-owned headers and
docs/mainpage.md - Feature plans live under
upcoming_features/as tracked Markdown files only (seeupcoming_features/TEMPLATE.mdfor the expected format) - CMake presets provide named configurations for common workflows
Repository principles:
- Keep generated artifacts out of the repository
- Keep publication-facing files free of machine-specific paths and broken local links
- Prefer small explicit abstractions, clear ownership, and incremental changes
- Keep CI, docs, tests, and release scripts aligned with shipped behavior
- Treat vendored third-party code as subtree/vendor content, not normal project code
src/: repo-owned library and CLI codetests/: deterministic example tests, test registration, andframe_test.hmicro-frameworkdocs/: Doxygen config and API-focused main pagescripts/: hygiene, release, and diagnostics helperscontrib/: optional service/desktop integration examplescmake/: reusable analyzer helper scripts.agents/skills/: project-local agent overlays and merged skills.github/workflows/: generic CI and release workflow templatesbenchmarks/: optional chrono-based micro-benchmarks andframe_bench.hharnessupcoming_features/: forward-looking implementation plans
Read README.md first before changing build, setup, or release behavior.
Prefer CMake presets for common workflows:
cmake --preset dev
cmake --build build/dev -j"$(nproc)"Available presets: dev (debug + sanitizers), release (optimized + LTO),
ci (matches GitHub Actions), coverage (gcov instrumentation).
Manual out-of-tree build (when presets are unavailable):
BUILD_DIR="$(mktemp -d /tmp/cpp-frame-build-XXXXXX)"
cmake -S . -B "$BUILD_DIR" -G Ninja
cmake --build "$BUILD_DIR" -j"$(nproc)"If ninja-build is unavailable, omit -G Ninja.
Optional sanitizer lane (included in the dev preset):
cmake -S . -B "$BUILD_DIR" -G Ninja \
-DFRAME_ENABLE_ASAN=ON \
-DFRAME_ENABLE_UBSAN=ONLightweight default validation:
"$BUILD_DIR/frame_cli" --helpUse the smallest validation set that proves the change, then extend as needed:
ctest --test-dir "$BUILD_DIR" --output-on-failurecmake --build "$BUILD_DIR" --target clang-tidycmake --build "$BUILD_DIR" --target clazywhen the project uses the example Qt-based UI stack and the tool is availablecmake --build "$BUILD_DIR" --target format-checkcmake --build "$BUILD_DIR" --target lint(includes clang-tidy and cppcheck when available)cmake --build "$BUILD_DIR" --target docsbash scripts/run-valgrind.sh "$BUILD_DIR"bash scripts/check-release-hygiene.sh
If install layout or shipped assets change, validate a temporary install prefix:
INSTALL_DIR="$(mktemp -d /tmp/cpp-frame-install-XXXXXX)"
cmake --install "$BUILD_DIR" --prefix "$INSTALL_DIR"Run cmake --build "$BUILD_DIR" --target format before committing to keep
source files consistently formatted. CI enforces format-check and will reject
unformatted code. The .clang-format config at the repo root defines the
canonical style.
Build with the coverage preset and run the coverage target:
cmake --preset coverage
cmake --build build/coverage
cmake --build build/coverage --target coverageThis runs tests and collects coverage via gcovr. HTML output lands in
build/coverage/coverage/. New code should maintain or improve line coverage.
Build with -DFRAME_ENABLE_BENCHMARKS=ON and run manually:
cmake --build "$BUILD_DIR" --target example_bench
"$BUILD_DIR/benchmarks/example_bench"Add benchmarks for hot paths, algorithms, and performance-sensitive code.
Use FRAME_BENCHMARK(name, iterations) from benchmarks/frame_bench.h.
When adapting this frame for a new project, use the init script:
./scripts/init-project.sh --name "Your Project Name" # dry-run
./scripts/init-project.sh --name "Your Project Name" --applyThis renames all placeholder targets, namespaces, prefixes, and filenames.
- Keep repo-owned tests deterministic and headless under
CTest - Use the
frame_test.hmicro-framework:FRAME_TEST(name)for registration,FRAME_EXPECT_EQ,FRAME_EXPECT_TRUE,FRAME_EXPECT_FALSE,FRAME_EXPECT_THROWSfor assertions,FRAME_RUN_TESTS()in main - Keep
WHAT/HOW/WHYcommentary near the start of real test bodies; the repo scripts enforce that contract - Prefer pure helper seams and injected fakes over environment-heavy tests
- Prefer parser, config, algorithm, and boundary-helper coverage before device, network, UI, or platform integration coverage
- If Qt GUI or Widgets tests are added, make
CTestregistration itself setQT_QPA_PLATFORM=offscreen
- Keep changes targeted; do not reformat unrelated code
- Prefer small direct classes and explicit ownership/lifetime over broad abstraction layers
- Favor
const,override,explicit,[[nodiscard]], narrow enums, RAII, rule-of-zero types, and clear invariants - Treat raw pointers and references as non-owning observers unless ownership transfer is explicit
- Prefer standard library value types over raw arrays and manual bounds handling
- When helper functions take multiple adjacent same-shaped parameters, prefer a
small request struct if it improves clarity and avoids
bugprone-easily-swappable-parameters - Keep product/project terminology app-owned and consistent; reserve vendor- specific wording for vendor-boundary code
- Treat
clang-tidy, Doxygen, hygiene scripts, and CI as maintained checks, not optional extras - Prefer the repo-owned
clang-tidytarget from a configured build tree so the same compile database drives local and CI analysis - Keep analyzer fixes targeted to repo-owned code; do not churn vendored or generated output
- Prefer fixing code over weakening analyzer configuration
- In Qt-heavy variants, treat
misc-include-cleanerandreadability-redundant-access-specifiersas low-value noise unless the tool behavior improves - Prefer the repo-owned Valgrind runner over ad hoc Memcheck commands so leak policy and target selection stay aligned
- Treat third-party code as vendored/subtree-managed source
- Prefer app-side integration changes before touching vendored code
- If vendored code changes, document why and update provenance/notice files
- Do not commit generated binaries, model artifacts, or large release payloads
- Keep README, release checklist, workflows, install rules, and shipped assets aligned with each other
- Read
README.mdfirst, then the touched files before editing - Prefer targeted changes over speculative cleanup
- Keep
README.md,AGENTS.md,.agents/skills/, scripts, and workflows aligned when the repo workflow changes - Store forward-looking feature plans under
upcoming_features/as tracked Markdown files; update the existing plan rather than scattering notes - Do not leave generated artifacts in the repo tree
- Do not assume the workspace is a valid Git repo; if Git commands fail, continue with file-based validation and note the limitation
- Optimize for the current implementation, not hypothetical future platforms
- Prefer portable, buildable, testable defaults
- Ask before making architectural expansions that widen the frame far beyond a generic C++ project template