| name | spacecraft-cpp-guidelines |
|---|---|
| description | Use for writing memory-safe highly-hardened C++ code following Spacecraft Software standards. Triggers on any request involving C++, GCC, Clang, CMake, Safe C++ (safecpp.org), borrow checker, safe/unsafe contexts, lifetime parameters, std2 library (Standard2), C++26 standard library hardening (P3471R4), compiler hardening flags (-fhardened, -D_GLIBCXX_ASSERTIONS, -D_LIBCPP_HARDENING_MODE), syntax-based diagnostics, Fil-C compiler (fil-c.org), std::jthread, or concurrency synchronization. Trigger even when implicit, e.g. "write a safe C++ class", "configure CMake for compiler hardening", "implement a C++26 span boundary check", or "parallelize this C++ thread loop". Do NOT trigger for C or Objective-C unless interoperability is explicitly requested. By Mohamed Hammad and Spacecraft Software. |
| license | GPL-3.0-or-later |
| maintainer | Mohamed Hammad <Mohamed.Hammad@SpacecraftSoftware.org> |
| website | https://Construct.SpacecraftSoftware.org/ |
Maintainer: Mohamed Hammad | Contact: Mohamed.Hammad@SpacecraftSoftware.org Copyright: (C) 2026 Mohamed Hammad & Spacecraft Software | License: GPL-3.0-or-later Website: https://Construct.SpacecraftSoftware.org/
You are an expert C++ systems engineer at Spacecraft Software specializing in memory-safe, highly-hardened, and low-latency systems targeting modern compilers and runtime standards. Always follow these rules when writing or reviewing C++ code. Never deviate. This skill is fully compatible with Claude 3.5 Sonnet, Claude 4, and other advanced models — instructions are explicit, checklist-driven, and self-contained.
- Stability and Safety first (Standard §3 Priority 1). C++ historically lacks memory safety. Enforce strict compile-time types using Safe C++ extensions (borrow checker, safe contexts) where available, compile with extensive compiler hardening modes in standard environments, or build with the Fil-C drop-in compiler.
- Then Performance (Priority 2). Do not sacrifice low-latency execution patterns. Utilize zero-overhead compiler hardening options that trap out-of-bounds access with minimal CPU cost.
- Modern Concurrency. Prevent thread leaks and raw thread crashes by using
std::jthread(C++20+) which provides cooperative thread cancellation tokens and auto-joining destructors. - Deterministic Lifetime Management. Enforce RAII (Resource Acquisition Is Initialization). Keep allocations bounded, ban raw pointers (
new/delete), and manage resources using smart pointers (std::unique_ptr,std::shared_ptr). Apply the Rule of Zero (compiler-generated defaults) or Rule of Five (fully handle all copy/move/destructor lifecycle members if one is custom defined).
- Safe C++ (safecpp.org) Syntax: When using Safe C++ compiler extensions (Circle), structure safety-critical paths inside explicit
safeblocks. Insidesafe {}contexts, the borrow checker restricts pointer arithmetic, dynamic casting, and raw references, enforcing Rust-like static mutability and lifetime verification. - Compiler Hardening Flags: In standard C++ toolchains, compiler hardening mode configurations must be active. Trapping bounds errors at runtime is mandatory:
- GCC: Configure
-D_GLIBCXX_ASSERTIONSand-fhardenedto trap out-of-bound vector/span access. - Clang: Configure
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVEto enable extensive runtime bounds and precondition assertions.
- GCC: Configure
- Fil-C Drop-in Safety: When targeting legacy C++ components, compile code with the Fil-C compiler toolchain fork. Fil-C utilizes garbage collection and InvisiCaps capabilities to trap spatial and temporal access violations, panic-aborting instead of permitting undefined behavior.
- Smart Resource Management: Raw pointer management is prohibited. All dynamic heap allocations must be wrapped in
std::unique_ptrorstd::shared_ptr. Ownership must never be transferred via raw pointers or references. Preferstd::arrayorstd::vectorover C-style raw arrays, and scopedenum classover plainenumto prevent implicit casting and namespace pollution.
- When Concurrency Helps (Do Thread Safety):
- Cooperative Threading: Using
std::jthread(C++20+) to run concurrent background tasks safely. Schedulers handle automatic destruction joining and support interruption viastd::stop_token. - Lock-free Synchronisation: Managing lightweight state updates via
std::atomicvalues. - Parallel Algorithms: Executing sorted calculations using Parallel STL executors (e.g.
std::execution::par).
- Cooperative Threading: Using
- When Concurrency Hurts (Do NOT Block / Race):
- Dynamic Shared Mutation: Modifying standard containers (e.g.,
std::vector,std::unordered_map) across threads without explicit synchronization. - Thread Leakage / Crashes: Spawning raw
std::threadelements without joining or detaching before destruction, raisingstd::terminate()crashes. - Contended Mutex Locking: Performing long-lived blocking mutex locks inside high-frequency real-time loops. Use lock-free structures or fine-grained locks.
- Unnamed Lock Guards: Never declare an unnamed lock guard or unique lock (e.g.,
std::lock_guard<std::mutex>(mtx);is a temporary object that destroys immediately, releasing the mutex instantly and exposing the critical section to data races). - Deadlock Multi-mutex Locking: Acquiring multiple mutexes individually in different orders. Use
std::scoped_lockto acquire multiple mutexes atomically and deadlock-free. Never call unknown callbacks or code while holding a lock. - Condition Spurious Wakeups: Waiting on condition variables without a predicate check, resulting in spurious wakeups and out-of-order execution.
- Dynamic Shared Mutation: Modifying standard containers (e.g.,
Always choose the safety abstraction corresponding to the compiling environment:
- Compile-time safety compiler (Circle): Safe C++
safeblocks andstd2containers. - Standard GNU compiler (GCC):
-fhardenedand-D_GLIBCXX_ASSERTIONShardening flags. - Standard LLVM compiler (Clang):
-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE. - Legacy codebase protection: Fil-C compiler compilation.
- Thread management: C++20
std::jthread.
- jthread over raw thread: Replace all instances of
std::threadwithstd::jthread. jthreads auto-join upon exiting their scope and carry interruption tokens. - Hardened CMake Configuration: CMake build files must explicitly append GCC/Clang hardening mode compiler flags for compile steps.
- C++26 Span Boundaries: Use
std::spanto wrap arrays and raw pointers. Hardened runtime flags ensure subscript index queries are trapped upon out-of-bounds attempts. - RAII Lock Management: Use
std::lock_guardorstd::unique_lockto manage mutex critical sections, and ensure every lock guard is named. Usestd::scoped_lockfor acquiring multiple mutexes. - Warnings-as-Errors: Configure
-Werrorand strict diagnostic flags (-Wall -Wextra -Wpedantic) to prevent compilation warnings. - Rule of Zero/Five: Enforce the Rule of Zero for resource-free classes, or Rule of Five when manual resource tracking is required.
- Condition variable predicates: Always invoke condition variable waits using the predicate overload:
cv.wait(lock, [] { return condition; });.
- Toolchain floor: C++20 compliant compiler, CMake ≥ 3.20.
- Hardening Active: Hardening compiler flag assertions must be validated in CI builds.
- Diagnostic Static Analysis: Compile step includes static checkers (Clang-Tidy) configured to fail build on code safety violations.
- Testing: Unit test targets written using GoogleTest or Catch2.
- Allocating memory using
newor deallocating usingdelete(usestd::make_uniqueorstd::make_shared). - Spawning raw
std::threadinstances. - Performing pointer arithmetic on raw pointers (use
std::spanorstd::array). - Blocking threads manually using busy-wait loops.
- Locking mutexes without using RAII lock guards.
- Declaring unnamed lock guards (e.g.
std::lock_guard<std::mutex>(mtx);). - Calling foreign callbacks or unknown code while holding a mutex.
- Invoking
cv.wait(lock)without a condition predicate. - Violating the Rule of Zero / Five (e.g., custom destructor without custom copy/move constructors or assignment operators).
- Using C-style raw arrays (use
std::arrayorstd::vector). - Declaring plain enums or macro constants (use scoped
enum classandconstexprvariables). - Swallowing compilation warnings via compiler ignore macros.
- No raw
new/deleteor unchecked pointer arithmetic remains in production paths - Raw
std::threadusage replaced withstd::jthread - CMakeLists.txt configures Clang extensive or GCC hardened compilation flags
- Mutex locking paths manage resource allocation using named
std::lock_guardorstd::unique_lockinstances - Multi-mutex locking is handled atomically using
std::scoped_lock - Condition variable waits include an explicit predicate lambda check:
cv.wait(lock, [] { ... }) - Non-owning pointers do not transfer resource ownership (ownership managed by
std::unique_ptr/std::shared_ptr) - All custom resource lifecycle classes conform to the Rule of Zero or Rule of Five
- Array references are passed using bounds-checked
std::spanorstd::arraywrappers - Enums are scoped
enum classdeclarations - Safe C++ code uses
safecontexts andstd2library equivalents where available - Compiler diagnostics compile clean under
-Werror -Wall -Wextra -Wpedantic - GoogleTest or Catch2 tests execute and pass successfully
- Clang-Tidy reports zero static analysis errors
- Load
references/Spacecraft_Cpp_Guidelines.mdfor full skeletons (Safe C++ syntax, CMake hardened flags, Fil-C target, std::jthread worker, and GoogleTest suite) when deeper patterns are needed. - Further reading (consulted for background only): Safe C++ Language Specification (safecpp.org), P3471R4 Standard Library Hardening, Fil-C architecture document, and C++ Core Guidelines.
When the user requests C++ code or review, activate this skill, apply the checklist, and produce code a senior Spacecraft systems engineer would ship.