skills/format-cpp/SKILL.md
Formats C++ code according to 21 specific style rules covering whitespace, braces, preprocessor directives, namespaces, types, formatting, and semantic transformations. Use when user asks to "format my C++ code", "apply C++ style rules", "clean up this C++ file", or "run format-cpp on X". Run refactor-cpp before this skill. Do NOT use for explaining C++ code, debugging, or writing new C++ code from scratch.
npx skillsauth add armandli/get-skilled format-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.
If $ARGUMENTS is provided, use it as the target path. Otherwise, ask the user which files to format.
.cpp, .cc, .cxx, .h, .hpp, .hxx files recursivelyDetect the C++ standard version for the project. Check these sources in order:
CMakeLists.txt: look for CMAKE_CXX_STANDARD, target_compile_features(... cxx_std_17), or similarMakefile / Makefile.*: look for -std=c++17, -std=c++20, etc. in CXXFLAGS or compiler flags.clang-format, compile_commands.json, or other tooling configRules D3, G1, and G3 require C++17 or later. If the project targets C++14 or earlier, skip those rules and note it in the report.
Apply rule groups A through G in order. For each file:
"header.h" to <header.h>, note the header for Step 3 (build file updates)Safety principle: When uncertain whether a transformation is safe, skip it and warn the user. Never break compilation for style.
If any G2 conversions turned project-local "header.h" into <header.h>, search for Makefile, CMakeLists.txt, or BUILD files in the project:
-I include paths so the converted angle-bracket includes resolveSummarize what was changed:
A1 — No tabs. Replace all tab characters with spaces.
A2 — 2-space indent. All indentation uses 2 spaces per level. Convert any other indent width.
A3 — Namespace body not indented. Content inside namespace blocks sits at the same indentation level as the namespace declaration itself.
A4 — 80-character target. Break lines that exceed 80 characters. Prefer breaking at logical points (after commas, before operators). This is a target, not a hard limit — don't break lines if it would harm readability.
B1 — Same-line opening brace. Opening { goes on the same line as the declaration:
if (x) { // yes
void foo() { // yes
class Bar { // yes
B2 — Multi-line signature exception. When a function signature spans multiple lines, the opening brace goes on its own line, aligned with the function declaration:
void very_long_function(
int param1,
int param2)
{
// body
}
C1 — Header guards, not #pragma once. Use #ifndef/#define/#endif guards. The guard name is the filename in UPPER_SNAKE_CASE with _H suffix. Replace any existing #pragma once.
C2 — Tidy includes. Sort #include directives in this order, separated by blank lines:
.cpp files)<cstdlib>, <cstring>, etc.)<string>, <vector>, etc.)Remove duplicate includes.
D1 — No global using namespace. Remove any using namespace X; at file/namespace scope. Replace affected unqualified names with qualified names or namespace aliases.
D2 — Namespace aliases. When removing using namespace or when a qualified name like std::chrono::seconds appears 3+ times, introduce a short alias near the top of the function or file scope. Use the predefined alias mapping in references/namespace-aliases.md.
D3 — Nested namespace syntax. (C++17) When namespace blocks are nested, collapse them into a single declaration using namespace A::B::C {. Apply this to all consecutive nested namespaces. Add a closing comment reflecting the full path: } // namespace A::B::C. Skip this rule if the project targets C++14 or earlier.
E1 — struct over class. Use struct instead of class. Adjust access specifiers accordingly — what was implicit private: in a class must become explicit if needed.
E2 — Default access first. In a struct, put public members first (since that's the default), then protected, then private. Within each section, order: types/aliases, static members, constructors/destructor, methods, data members.
E3 — protected over private for methods. Use protected instead of private for member functions, to allow overriding in derived types. Data members may remain private.
E4 — typename in templates. Use typename instead of class in template parameter lists:
template<typename T> // yes
template<class T> // no
E5 — Inline small methods. Methods with 3 or fewer statements should be defined inline in the struct/class body. Move longer methods out-of-line.
E6 — Enum underlying type. Every enum class, enum struct, and plain enum declaration must include an explicit underlying fundamental type. If none is specified, add : int as the default. Only use a type other than int when the enum values demonstrably require it (e.g., a flags enum needing more than 32 bits uses : uint64_t, an enum that must fit in a byte uses : uint8_t). If the declaration already has an explicit underlying type, leave it unchanged.
F1 — One item per line at 80 chars. When a function call, declaration, initializer list, or template parameter list exceeds 80 characters, put each item on its own line with a trailing indent.
F2 — Trailing commas. Add trailing commas in initializer lists, enum values, and macro argument lists where the language permits. This makes diffs cleaner.
F3 — break; case compound style. In switch statements, place break; on the same line as the next case or default label (e.g., break; case State::Init:). The first case after switch { has no break; prefix. The last case/default has no trailing break;. Put a blank line between case blocks. When multiple cases share the same handler, group them: break; case X: case Y: — the break; joins the first label, additional labels follow on the same line.
F3a — Mandatory default label. Every switch statement must have a default label. If the original code has no default, add one with assert(false); // should never get here as the body.
F4 — Alternative operators. Use not, and, or, xor instead of !, &&, ||, ^. Do NOT convert & (binary), |, ~, !=, unary address-of &, or pointer dereference *.
G1 — string to string_view. (C++17) Convert const std::string& parameters to std::string_view when the function does not:
const std::string& or std::string.c_str() or .data() on it and pass to C APIs expecting null-terminated stringsAlso convert local const std::string variables that are only read to std::string_view. Add #include <string_view> if not already present. Skip when safety is uncertain.
G2 — Angle-bracket includes. Convert all #include "header.h" to #include <header.h>, including project-local headers. When converting project-local headers, note them for build file updates in Step 3 — the build system needs -I paths added so angle-bracket includes resolve.
G3 — No raw-pointer returns to optional. (C++17) Convert functions returning raw pointers (T*) to return std::optional<T> (for value types) or std::optional<std::reference_wrapper<T>> (when reference semantics are needed). Update all callers to use .value() or .has_value() instead of null checks.
Exceptions — do NOT convert when:
virtual, override, or part of a polymorphic hierarchyunique_ptr instead)Add #include <optional> if not already present.
After the skill's primary task completes, run (record both the dependency and this skill):
python3 ${PWD}/.claude/skills/skill-stat/scripts/record-stat.py "refactor-cpp"
python3 ${PWD}/.claude/skills/skill-stat/scripts/record-stat.py "format-cpp"
tools
--- name: update-readme description: Updates a project README.md with build instructions, unit test instructions, and a mermaid architecture diagram. Use when a project README needs to be created or refreshed. Trigger phrases: "update readme", "generate readme", "create readme", "refresh readme docs". Emphasizes project interfaces, extension points, and customization hooks in the diagram — not concrete implementations. Do NOT use for documentation sites, wikis, or non-project READMEs. argument-h
business
--- name: skill-stat description: Records skill usage statistics and issue reports into .claude/skill-stats.md. Increments the Uses count for a skill name, and optionally logs an issue report that increments the Issues count and appends a row to the Issue Reports table. Use when tracking how often a skill is invoked, when a user reports a problem with a skill, or when another skill needs to log its own usage. Trigger phrases: "record skill stat", "log skill usage", "report skill issue". Do NOT u
testing
--- name: revert description: Reverts ALL git changes in the working directory: staged changes, unstaged modifications, and new untracked files. Use when user asks to "revert all changes", "undo all changes", "discard all changes", "reset all git changes", or "clean working directory". Do NOT use for reverting a specific file or a specific commit — those need targeted git commands. disable-model-invocation: true --- Revert all git changes in the working directory. This is destructive and cannot
tools
Scans a Python codebase for duplicate or near-duplicate logic patterns across functions, classes, and files, then extracts those patterns into typed utility classes in a shared module. Use when the user asks to "refactor this Python code", "find duplicate logic", "extract shared utilities", "apply DRY to Python", "deduplicate Python code", or "find repeated patterns in Python". Groups extracted helpers by the object type they operate on (strings, numbers, dates, collections, etc.). Do NOT use for performance optimization (use optimize-python), for debugging logic errors, or for explaining code. Do NOT extract code that appears only once. Run this skill before optimize-python.