AgentStack
SKILL verified MIT Self-run

Coding Guidance Cpp

skill-n-n-code-n-n-code-skills-coding-guidance-cpp · by n-n-code

C++ implementation and review skill. Use when writing, modifying, refactoring, or reviewing C++ code, especially modern C++17/20/23 code that needs strong ownership, type safety, and testable design. Portable across C++ repos and build systems.

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-n-n-code-n-n-code-skills-coding-guidance-cpp

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Coding Guidance Cpp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

C++ Coding Guidance

This skill adds portable C++ implementation, refactoring, and review guidance.

Adjacent Skills

This skill provides portable C++ engineering principles. Compose with:

  • Workflow: thinking (planning), recursive-thinking (stress-testing),

security (threat modeling)

  • Domain overlays: backend-guidance (server-side code),

backend-systems-guidance (stronger backend architecture, reliability, and trust-boundary work), ui-guidance (graphical UI/web frontend), project-core-dev (repo-specific build/test commands)

When Not to Lean on This Skill

  • non-C++ work
  • legacy or bare-metal environments where modern C++ guidance must be adapted

selectively

  • pure architecture or process work with no C++ design or code judgment needed
  • repo-specific style packs or platform policies that should be enforced by

local clang-tidy, compiler, or overlay rules rather than a portable principle skill

Boundary Contract

Keep this skill focused on portable C++ engineering judgment.

  • Put repo-specific exception policy, warning policy, formatter choices, and

include-order rules in repo config or repo docs

  • Put style-pack rules from ecosystems such as Google, LLVM, Abseil, or

platform/vendor bundles in repo config or overlays, not here

  • Put library- or platform-specific API policy in repo config or a domain

overlay

  • When a rule is analyzer-shaped but not portable, keep it in clang-tidy

config or the reference note rather than adding it to the main skill

Implementation Workflow

  1. Read the touched code, build shape, existing tests, and any nearby docs or

shorthand notes before editing.

  1. If the request is partially specified, infer the intended behavior from the

existing code and tests. Ask only when multiple plausible C++ designs would change semantics.

  1. Choose the narrowest change that solves the problem without hiding ownership,

lifetime, or error-handling contracts.

  1. Implement with simple, strongly typed interfaces and modern C++ defaults.
  2. Add or update tests close to the changed behavior.
  3. Run the narrowest relevant format, build, test, sanitizer, and analyzer

targets the repo supports.

Refactoring Workflow

Use this instead of the default implementation workflow when the task is primarily cleanup or restructuring:

  1. Capture current behavior, invariants, side effects, and risky hotspots.
  2. Break the refactor into small slices that preserve behavior.
  3. Remove duplication, long functions, or muddled responsibilities one step at

a time.

  1. Keep tests passing after each slice; add characterization coverage first when

behavior is unclear.

  1. Stop when the code is simpler and safer.

Review Workflow

When reviewing (not implementing), skip the implementation workflow and use this instead:

  1. Read the change in full before commenting.
  2. Identify findings, ordered by severity: Critical > Important >

Suggestion.

  1. Prioritize bugs and regressions, ownership and lifetime errors, exception or

error-path holes, thread-safety issues, security risks, performance mistakes with real impact, and missing tests.

  1. State findings with concrete evidence and the likely consequence.

C++ Rules

Read these by failure theme, not as an exhaustive checklist.

Construction, ownership, and lifetime

  • Treat raw pointers and references as non-owning; never transfer ownership by

raw pointer or reference

  • Avoid new and delete; bind resource lifetime to object lifetime with RAII
  • Prefer std::unique_ptr by default; use std::shared_ptr only for real

shared lifetime and std::weak_ptr to break cycles

  • Prefer values and stack allocation over heap allocation when ownership is

simple

  • Prefer rule-of-zero types; if you write a destructor or custom special member

function, justify it

  • Initialize objects into valid states immediately; construction should

establish invariants instead of relying on later “remember to initialize” steps

  • Do not store or return references, views, iterators, or pointers into

temporaries or short-lived owners; when the lifetime proof is not obvious, return or store an owning value instead

  • Treat moved-from objects as valid but semantically narrow; only destroy,

reassign, or call operations whose post-move contract is explicit

  • Do not cross async, callback, coroutine-suspend, or thread-handoff

boundaries with borrowed state unless the lifetime proof is explicit

Type, bounds, and representation safety

  • Avoid unchecked bounds access; prefer .at(), iterators, range-for, or

std::span when bounds are uncertain

  • Avoid silent narrowing conversions; use explicit casts or narrowing helpers
  • Avoid signed/unsigned comparison traps; use std::cmp_*, std::in_range,

or a deliberate common type when integer domains differ

  • Prefer compile-time checking to runtime checking when the type system can

express the rule

  • Avoid C-style casts; use static_cast, const_cast, reinterpret_cast, and

dynamic_cast deliberately

  • Prefer std::bit_cast or byte-wise copy for object-representation

reinterpretation; do not use reinterpret_cast where aliasing or lifetime rules make the behavior fragile

  • Avoid raw memory APIs, memset/memcpy tricks, or pointer arithmetic on

non-trivial, polymorphic, or lifetime-sensitive types

  • Use const and constexpr by default; mutability should be the exception
  • Prefer enum class over plain enums and nullptr over NULL
  • Prefer std::array over C arrays, std::string_view for non-owning strings,

and std::span for non-owning ranges when lifetime rules are clear

API contracts and call-site clarity

  • Do not mix exception and error-code styles inconsistently inside one path
  • Do not ignore must-check results from allocation, parsing, synchronization,

numeric conversion, or OS/library APIs when failure changes behavior

  • Use [[nodiscard]] when ignoring a result is likely a bug
  • Prefer explicit constructors, conversions, and named types when ownership,

units, or semantics would otherwise be implicit

  • Avoid forwarding, overload, and default-argument combinations that make calls

ambiguous or silently select the wrong overload

  • Treat virtual dispatch boundaries as bug-prone: use override, avoid near

misses, and do not rely on shadowing or signature accidents

  • Keep declarations and definitions consistent across headers and sources:

parameter names, qualifiers, defaults, and ownership cues should not drift

  • Be suspicious of adjacent same-type parameters; named types, parameter

objects, or strong typedefs are often clearer than comments

  • Prefer interfaces that make argument order hard to misuse and bool/int/string

sentinels hard to confuse

  • Prefer APIs that encode units, domains, and nullability in types rather than

relying on comments, magic values, or positional conventions

Headers, globals, and build surface

  • Avoid using namespace std in headers
  • Keep warnings at zero in repo-owned code
  • Keep macros narrow, parenthesized, side-effect-safe, and out of API shaping;

prefer language features unless a macro is the least-bad tool

  • Avoid reserved identifiers, namespace pollution, and definitions in headers

that quietly change ODR or rebuild behavior

  • Prefer include sets that are minimal and explicit; unused includes, include

cycles, and transitive-include dependence are design smells

  • Use constinit for non-local static or thread-local objects that must not

rely on dynamic initialization

  • Prefer compile-time constants, local statics, or explicit startup wiring over

hidden global initialization side effects

Concurrency, async, and testability

  • Prefer structured thread ownership and explicit cancellation over detached

threads or ad hoc stop flags; std::jthread and std::stop_token are good defaults when the codebase already uses standard thread primitives

  • Assume container modifications may invalidate iterators, references, pointers,

and views unless the container contract says otherwise

  • Prefer seams that keep core logic testable without real threads, clocks,

filesystem, process state, or ambient globals when the domain does not require those dependencies

Expressive modern defaults

  • Prefer vocabulary types such as std::optional, std::variant, and

std::expected when they encode real domain states better than sentinels or ad hoc conventions

  • Prefer standard algorithms and ranges over open-coded loops when they make the

intent clearer

  • Prefer standard library and language replacements for deprecated,

legacy-C-leaning, or handwritten utilities when the replacement is clearer and already acceptable in the repo toolchain

Advanced design judgment

Load [references/cpp-advanced-design-judgment.md](references/cpp-advanced-design-judgment.md) when the task involves public APIs, error-model choices, advanced language features, template-heavy interfaces, headers with broad rebuild impact, coroutines, synchronization strategy, ABI/plugin/C interop boundaries, or abstraction design. Keep ordinary feature work in the default rules above.

Clang-Tidy-derived emphasis

Use the full clang-tidy catalog as a source of recurring failure modes, not as a portable checklist to paste into every repo.

  • Treat bugprone, cppcoreguidelines, modernize, performance, misc,

portability, and the CERT/HIC++ aliases as high-signal prompts for code review and refactoring

  • Fold only portable semantics into this principle skill; repo-specific naming,

include order, formatter preferences, test-framework style, platform APIs, and library-pack rules belong in repo config or overlays

  • If a repo ships clang-tidy, read its enabled checks before introducing new

patterns; local suppressions and allowlists often document real constraints

  • When multiple checks point at the same design issue, fix the design cause

instead of satisfying each warning mechanically

Resource map

  • [references/clang-tidy-derived-guidance.md](references/clang-tidy-derived-guidance.md):

triage of the current clang-tidy check catalog into portable principles, repo-level rules, and non-portable families that should stay out of this skill

  • [references/cpp-advanced-design-judgment.md](references/cpp-advanced-design-judgment.md):

deeper guidance for public API design, error models, advanced features, headers, synchronization, and abstraction choices

Decision Heuristics

Use these when the right choice is not obvious:

  • Scope check: if a change touches more than 3 public interfaces, stop and

plan before continuing; the change is bigger than it looks.

  • Ownership clarity: if ownership is not obvious from the type signature,

redesign the interface or add a one-line contract comment.

  • Error-model consistency: do not mix exceptions, error codes, and

expected-style returns within one subsystem unless the boundary is explicit.

  • Exception-safety pressure: when mutating multi-step state, decide whether

the operation offers no-fail, strong, or basic exception safety and structure the code to match.

  • Repo conventions: if the repo has established rules for exceptions,

containers, ownership types, or naming, follow them unless they create a correctness or safety problem.

  • Feature pressure: do not introduce concepts, ranges, coroutines, or

metaprogramming unless they make the code simpler for this repo's likely maintainers.

  • Interface pressure: if a header starts dragging in broad dependencies or

exposing implementation detail, narrow the interface before adding more code.

  • Build-surface pressure: if a design pushes more logic, templates, or

dependencies into public headers, justify the compile-time and rebuild cost.

  • Parameter pressure: when adjacent parameters have the same type, or the

function needs more than 2-3 meaningful inputs, prefer a named type or helper struct.

  • Lifetime pressure: if a non-owning type crosses async, callback, return,

or storage boundaries, prefer an owning type unless the lifetime proof is obvious from the interface.

  • Initialization pressure: if correct behavior depends on a later

“remember to initialize” step, move that requirement into construction or the type itself.

  • Call-site pressure: if two arguments are easy to swap or a call needs

comments to explain literals, redesign the API before adding more call sites.

  • Header pressure: if a header starts accumulating definitions, globals,

unnecessary includes, or hidden initialization, push behavior back behind a source boundary.

  • Testability pressure: if a design forces tests to spin threads, sleep,

touch the real filesystem, or patch globals just to exercise core logic, introduce a seam before adding more behavior.

  • Test setup size: if test setup exceeds about 20 lines, extract a fixture

only when the setup is reused or the test intent becomes unclear.

  • Narrowness vs. quality: implement the narrowest change that solves the

problem. When narrowness conflicts with correctness or safety, prefer correctness. When it conflicts with style alone, prefer narrowness unless the task is explicitly a cleanup.

  • Refactor boundary: outside explicit refactor work, fix at most one small

adjacent issue while you are in the file.

  • Abstraction threshold: three similar code blocks or repeated API-shaping

pain is a pattern; before extracting, check whether a free function, helper type, or composed object is the simpler move.

  • Performance rule: optimize only after measurement, except for obvious

ownership, allocation, or algorithmic mistakes on hot paths.

  • UB-sensitive optimization: treat optimizations that rely on subtle

lifetime, aliasing, or memory-order assumptions as high-risk until proven by evidence and tooling.

Validation

A change is done when:

  • the code compiles without new warnings, unless the repo explicitly treats a

known warning set as baseline debt outside the change

  • existing tests pass
  • new or changed behavior has test coverage, or the lack of coverage is called

out with a concrete reason

  • the repo's formatter has been run
  • configured static analyzers report no new findings
  • available sanitizers are clean for the touched paths when the change affects

memory safety, threading, or undefined-behavior risk

  • performance-sensitive changes are measured instead of justified by intuition
  • review findings at Critical and Important severity are addressed

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.