mcpField
C
cpp-systems

cpp-systems

github.com/iliaalDevelopment4565 installsUpdated 3d ago
Repository

About cpp-systems

A skill for implementing and reviewing C++ systems and libraries, using C++17 as its baseline and noting C++20 features where relevant. It emphasizes explicit resource ownership, compatibility, repository conventions, and verification through builds, analysis, and tests.

Key features

  1. 01RAII and ownership guidance
  2. 02C++17 baseline with C++20 notes
  3. 03API and ABI compatibility practices
  4. 04Repository conventions and tooling
  5. 05Build, analysis, and sanitizer checks

Use cases

  1. 01Implement C++ library changes
  2. 02Review resource lifetime and ownership
  3. 03Preserve public API and ABI
  4. 04Verify builds and threaded code

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/iliaal/ai-skills --skill cpp-systems

After installing, type/cpp-systemsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

SPEC.md
references/
api-and-abi.md
cmake-and-tooling.md
concurrency-and-verification.md
legibility-standard.md
value-and-interface-design.md

Details

From the project README

C++ Systems & Libraries

Covers C++17 as the baseline, with C++20 features called out where a project's standard allows them. For plain C (manual lifetimes, status enums, native extensions), see the ia-c-systems skill.

Working rules

  • Make resource ownership explicit and use RAII for release on every exit path.
  • Keep borrowed views within backing-storage lifetimes and review copy/move behavior when special members change.
  • Follow the project's error model and supported language standard.
  • Preserve ABI and avoid invoking unknown callbacks while holding locks or invalidatable container iterators.

Repo conventions outrank this skill

Check CMakeLists.txt for CXX_STANDARD, read .clang-format and .clang-tidy, and read two adjacent translation units before writing. Where they conflict with the rules below, they win.

The conflicts that actually happen:

Local constraintConsequence
-fno-exceptionsError handling is codes or expected-alikes. Constructors cannot report recoverable failure, so use a fallible factory or construct a valid fallback state. new (std::nothrow) only where the project's OOM policy is to observe null and recover; plain new is fine where the policy is termination
Standard pinned below C++17No std::optional/string_view/structured bindings/if constexpr; check before using any
Public header is ABI-stableNo layout changes, no inline-function changes, no added virtuals: load the ABI reference
Embedded or freestanding targetNo RTTI, no dynamic allocation in hot paths, possibly no STL containers

Ownership and RAII

Every resource has exactly one owner, and that owner is an object whose destructor releases it. A raw new or delete in application code is a defect.

  • std::unique_ptr<T> for sole ownership. It is the default; it costs nothing over a raw pointer.
  • std::shared_ptr<T> only where lifetime is genuinely shared and cannot be expressed as "the owner outlives the users". Reach for it third, not first.
  • std::weak_ptr<T> to break ownership cycles. LeakSanitizer does report a cycle that is unreachable from any root, but not one still reachable from a global or other registered root, and detection varies by platform and configuration. Do not rely on the sanitizer to find these.
  • Raw T* and T& mean non-owning observation, and are correct in that role. A parameter taking unique_ptr by value is announcing that it consumes ownership; one taking T* is announcing it does not.
  • std::span<T> (C++20) or a pointer-plus-length pair for a borrowed contiguous range in a new public API, since const std::vector<T>& there refuses every other container. On a C++17 baseline, or for internal code whose callers all hold vectors anyway, const std::vector<T>& is fine and simpler.

Rule of zero: a class that owns nothing declares no destructor, no copy, and no move. Composing members that manage themselves gets all five special members correct for free. Rule of five: declaring any one of destructor, copy constructor, copy assignment, move constructor, or move assignment obliges the author to reason about all five. A user-declared destructor suppresses the implicit move operations, so a class that gained a destructor silently started deep-copying where it used to move.

Discipline

  • Preserve behavior and API compatibility unless a break was requested. A public header change is a decision, not a cleanup.
  • Do not introduce a template, an inheritance hierarchy, or a policy parameter for a single call site.
  • #include what the file uses; do not rely on transitive includes from another header.
  • No using namespace at namespace scope in a header. Fully qualify instead, or scope the using to a function body.
  • When a constraint forces a deviation, comment at the deviation site and state the constraint.

Verify

  • Build clean with -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Werror
  • clang-tidy reports no new findings on the diff
  • Tests pass under -fsanitize=address,undefined with zero reports
  • Any threaded code touched by the change exercised under TSan with zero reports; the warning bundle above does not catch lock misuse
  • clang-format --dry-run --Werror produces no diff
  • No new raw new/delete, no new shared_ptr where unique_ptr suffices
  • Any class that gained a destructor has its move operations reviewed

Task-specific references

Read the relevant reference before implementing or reviewing the matching behavior:

Existing specialized references, when the corresponding topic applies:

Comments

Markdown supported