agentsclimarketplace

Stdlib audit

Skill ultimatile/development-skills/skills/languages/Cpp/stdlib-audit

Audit C++ source for known-bad standard library defaults (std::function, std::regex, std::list, std::map, std::unordered_map, std::async, std::vector<bool>, etc.) using a TSV-driven rule table that is extended by appending lines. Wraps a ripgrep-based shell script; reports per-rule hit counts and sample locations, exits non-zero on configurable severity (for CI). Targets C++17+ codebases.From its SKILL.md

Install
npx -y skills add ultimatile/development-skills --skill stdlib-audit

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.9 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it

stdlib-audit

Static audit of C++ source for the catalogue of "do not use this, use that instead" standard library entries (the C++26-era walk-back catalogue plus the structurally-frozen container defaults). Rule table is data, not code — add a check by appending one TAB-separated line.

Layout

stdlib-audit/
├── SKILL.md          this file
├── stdlib-audit.sh   executable; reads the TSV, runs ripgrep, formats output
└── stdlib-rules.tsv  extensible rule table (id / severity / regex / note)

Running

# audit current directory (excludes external/** by default)
./stdlib-audit.sh

# audit a different project, with project-specific exclude
./stdlib-audit.sh -e '**/third_party/**' /path/to/project

# show more samples per rule, never exit non-zero
./stdlib-audit.sh -n 10 -f none .
FlagMeaningDefault
-r FILERule TSV pathstdlib-rules.tsv next to script
-e GLOBripgrep exclude glob**/external/**
-n NDetail samples per rule5
-f LISTSeverities that fail with exit 1, comma-separated, or nonecrit,high
-t TYPEripgrep --type filter (limits search to one of rg's known types)cpp

Exit code is 0 (no failing hits), 1 (at least one rule in -f severity matched), or 2 (usage / missing dependency error, malformed rule regex, bad search path, or other ripgrep IO failure). Exit 2 always takes precedence over 1 so CI distinguishes "audit ran and found issues" from "audit could not complete".

The default exclude **/external/** matches any directory named external anywhere in the search tree. If the search root is itself named external (e.g. ./stdlib-audit.sh /tmp/external), pass -e '!' (or another non-matching glob) to disable the default.

The default -t cpp restricts search to ripgrep's built-in C++ source list. As of this writing (rg --type-list | grep '^cpp:') that covers *.cpp, *.cc, *.cxx, *.hpp, *.hh, *.hxx, *.inl, *.h, *.C, *.H (and .in variants). It does NOT cover pure-C sources (*.c) or CUDA (*.cu) — pass -t all or a custom rg type if you need them.

Rule table format

stdlib-rules.tsv is TAB-separated, four columns:

id<TAB>severity<TAB>regex<TAB>note
  • id — short label printed in the summary table (also used as the section header in details)
  • severity — one of crit | high | mid | low
  • regex — Rust-regex (ripgrep) pattern; supports \b, \s, alternation, groups
  • note — one-line replacement / rationale; printed under the detail samples

Lines starting with # and blank lines are ignored. To add a new check, append one line. The script does not need editing.

Severity scale

SeverityMeaningExamples
critRemoved by current standard; any hit is a real bugstd::auto_ptr, std::random_shuffle, gets(), trigraphs
highActive footgun with a documented better replacementstd::function, std::regex, std::list, std::async
midStructural smell; needs case-by-case judgementstd::map, std::unordered_map, std::vector<bool>
lowAcceptable in many cases but worth flaggingstd::deque, std::cout / std::cerr / std::clog

The default -f crit,high is appropriate for CI gating. Pin mid / low to advisory.

Interpreting output

Summary table (one row per rule). Non-zero rules are then expanded into a detail block with up to -n sample path:line:content entries.

For each hit, decide:

  1. Is this in hot-path code? If yes, treat mid-severity matches as high. If no (test, parser, one-shot init), the structural smell often does not need fixing.
  2. Does the project's C++ standard offer the documented replacement? Examples: std::move_only_function only exists in C++23+; std::format only in C++20+. For C++17 projects, the realistic replacements are external libraries (Abseil / Boost / fmt / CTRE / RE2).
  3. Is the smell at an API boundary? std::vector<bool> as a struct field is local; std::vector<bool>& as a function parameter leaks proxy semantics across translation units.

C++17 replacement quick reference

RuleC++17-available replacement
std::functiontemplate parameter; tl::function_ref (header-only, non-owning — only for function-parameter use, not for storage); boost::function2
std::regexCTRE (header-only, compile-time pattern); RE2; Boost.Regex
std::liststd::vector (default); std::deque; boost::intrusive::list
std::asyncthread pool (custom or BS::thread_pool); std::thread directly
std::valarrayEigen; xtensor; Blaze
std::vector<bool>std::vector<std::uint8_t>; boost::dynamic_bitset
std::map / std::setabsl::btree_map; boost::container::flat_map
std::unordered_map / std::unordered_setabsl::flat_hash_map; boost::unordered_flat_map (Boost 1.81+); ankerl::unordered_dense
std::aligned_storagealignas(T) std::byte[sizeof(T)]
std::iterator basedefine the five typedefs (iterator_category, value_type, difference_type, pointer, reference) directly
std::cout / std::cerr in hot codefmt::print; gate diagnostic output behind a verbose flag

Tuning a project's rule set

Two common adjustments:

  • Demote a rule the project has already triaged. Edit the severity column to low; matches remain visible but no longer fail CI under the default -f.
  • Restrict a rule's scope. Replace the regex with a more specific pattern. Example: only flag std::list declarations, not the comment // std::list:
    std::list	high	^[^/]*\bstd::list\s*<	Almost always wrong; ...
    

To suppress one site without changing the rule, add an inline comment the regex won't match (e.g. wrap the type in a typedef in a separate header). The audit is line-level — it does not parse C++.

CI integration sketch

- name: C++ stdlib audit
  run: |
    ./skills/languages/Cpp/stdlib-audit/stdlib-audit.sh \
      -e '**/external/**' \
      src include

The default -f crit,high returns 1 on any matching hit, failing the job. Lower the bar by passing -f crit (only fail on removed-by-standard hits) or raise it by passing -f crit,high,mid.

What this audit does not catch

  • Misuse of a non-flagged type. std::vector used in a way that triggers reallocation in a hot loop is not in the table.
  • Semantic issues. std::map<int,int> keyed by dense 0..n-1 should be a std::vector<int>. The audit flags the type, not the access pattern.
  • Implementation differences. std::deque block size differs across libstdc++ / libc++ / MSVC STL; the audit is source-level only.
  • Generated code. ripgrep only excludes paths matching the -e glob (default **/external/**) and whatever the user's .gitignore / .ignore files mark. A build/ directory that is not gitignored will be searched. Pass -e '{**/external/**,**/build/**}' (or add build/ to .gitignore) to exclude it.
  • Comments and string literals. The audit is line-level regex; a comment such as // std::function<void()> or a string "std::regex" will match the same patterns as real code. Review the detail samples before treating a CI failure as authoritative; allowlist by tightening the rule regex or by demoting severity for the affected file class.

For semantic-level analysis, pair this audit with a code review pass focused on the call sites of the flagged types.

What ships with it: 2 files

13.2 KB alongside SKILL.md, 1 of them executable

Keep looking

Skills are one crate of 326,790. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.