skills/cpp/SKILL.md
Use when editing C++ files, .cpp, .hpp, .cc, .hh, .cxx, CMakeLists.txt, modern C++ APIs, resource ownership, error handling, concurrency, build systems, or native extension code.
npx skillsauth add cofin/flow cppInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill for modern C++ extension and backend work: safe, maintainable design choices plus a reliable build-and-release pipeline. Covers resource ownership, API boundaries, error handling, concurrency, local builds, git workflow, and CI/CD.
| Principle | Rule |
|---|---|
| Resource management | RAII for all resource lifetimes; no raw new/delete |
| Ownership | std::unique_ptr for exclusive, std::shared_ptr only when truly shared |
| Error handling | Explicit policy per module (exceptions or error codes); never mix ad hoc |
| Immutability | const by default on variables, parameters, and methods |
| API boundaries | Small, stable headers; hide implementation in .cpp files |
| Concurrency | Message passing or clear lock ownership; document thread-safety per type |
| Performance | Measure first; avoid allocations in hot loops; keep data cache-friendly |
cmake_minimum_required(VERSION 3.20)
project(mylib VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Library target
add_library(mylib src/mylib.cpp)
target_include_directories(mylib PUBLIC include)
# Tests
option(BUILD_TESTS "Build tests" ON)
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
| Action | Command |
|---|---|
| Configure (debug) | cmake -B build -DCMAKE_BUILD_TYPE=Debug |
| Configure (release) | cmake -B build -DCMAKE_BUILD_TYPE=Release |
| Build | cmake --build build -j$(nproc) |
| Test | ctest --test-dir build --output-on-failure |
| Tidy check | clang-tidy src/*.cpp -- -I include |
| Sanitizer build | cmake -B build -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined" |
Create CMakeLists.txt with C++20 standard, CMAKE_EXPORT_COMPILE_COMMANDS ON (for tooling), and separate library/executable/test targets.
Define public headers in include/. Keep headers minimal — forward-declare where possible, use the Pimpl idiom for implementation hiding. Document thread-safety guarantees on public types.
Use smart pointers for heap allocations, RAII wrappers for file handles / sockets / locks. Never use raw new/delete. Prefer value types and references over pointers.
Use a testing framework (GoogleTest, Catch2). Write tests alongside implementation. Focus on behavior and edge cases, not line coverage.
Build matrix across supported OS/arch. Run clang-tidy and sanitizers (ASan, UBSan) in CI. Separate fast unit tests from slower integration tests. Cache dependencies/toolchains.
</workflow> <guardrails>new/delete — use std::make_unique / std::make_shared; if you need custom allocation, wrap it in an RAII typestd:: algorithms over hand-written loops — std::ranges::find, std::transform, std::accumulate are safer and often fasterBefore delivering code, verify:
new/delete — all allocations use smart pointers or RAII wrappersCMakeLists.txt sets C++ standard, exports compile commands, and has test targetsCMakeLists.txt and a class demonstrating RAII:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(sensor_reader VERSION 0.1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(sensor_reader src/sensor_reader.cpp)
target_include_directories(sensor_reader PUBLIC include)
// include/sensor_reader/sensor_reader.hpp
#pragma once
#include <cstdint>
#include <memory>
#include <span>
#include <string>
#include <string_view>
/// Thread-safety: NOT thread-safe. Each instance must be used from one thread.
class SensorReader {
public:
/// Opens a connection to the sensor at the given device path.
/// Throws std::runtime_error if the device cannot be opened.
explicit SensorReader(std::string_view device_path);
/// RAII: closes the connection on destruction.
~SensorReader();
// Non-copyable, moveable
SensorReader(const SensorReader&) = delete;
SensorReader& operator=(const SensorReader&) = delete;
SensorReader(SensorReader&&) noexcept;
SensorReader& operator=(SensorReader&&) noexcept;
/// Read up to `buffer.size()` bytes. Returns the number of bytes read.
[[nodiscard]] std::size_t read(std::span<std::uint8_t> buffer) const;
/// Device path this reader is connected to.
[[nodiscard]] std::string_view device_path() const noexcept;
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
// src/sensor_reader.cpp
#include "sensor_reader/sensor_reader.hpp"
#include <fcntl.h>
#include <unistd.h>
#include <stdexcept>
#include <utility>
struct SensorReader::Impl {
std::string device_path;
int fd = -1;
~Impl() {
if (fd >= 0) {
::close(fd);
}
}
};
SensorReader::SensorReader(std::string_view device_path)
: impl_(std::make_unique<Impl>()) {
impl_->device_path = std::string(device_path);
impl_->fd = ::open(impl_->device_path.c_str(), O_RDONLY);
if (impl_->fd < 0) {
throw std::runtime_error("Failed to open device: " + impl_->device_path);
}
}
SensorReader::~SensorReader() = default;
SensorReader::SensorReader(SensorReader&&) noexcept = default;
SensorReader& SensorReader::operator=(SensorReader&&) noexcept = default;
std::size_t SensorReader::read(std::span<std::uint8_t> buffer) const {
const auto n = ::read(impl_->fd, buffer.data(), buffer.size());
if (n < 0) {
throw std::runtime_error("Read failed on device: " + impl_->device_path);
}
return static_cast<std::size_t>(n);
}
std::string_view SensorReader::device_path() const noexcept {
return impl_->device_path;
}
</example>
For detailed guides, refer to the following documents in references/:
testing
Use when syncing Beads state to markdown, checking Flow status, refreshing context docs, validating task markers, or reporting ready/blocked Flow work.
testing
Use when initializing Flow in a repo, configuring .agents, installing or checking Beads bd, setting local-only sync policy, or creating first project context files.
data-ai
Use when drafting PRDs, researching, planning, refining, revising, or creating .agents/specs/<flow_id>/spec.md worksheets for Flow.
testing
Use when implementing Flow tasks from Beads or spec.md, claiming ready work, applying TDD, recording task notes, committing, and syncing after task state changes.