RepoPilotOpen in app →

fmtlib/fmt

A modern formatting library

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 5d ago
  • 24+ active contributors
  • MIT licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 64% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/fmtlib/fmt)](https://repopilot.app/r/fmtlib/fmt)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/fmtlib/fmt on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: fmtlib/fmt

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/fmtlib/fmt shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 5d ago
  • 24+ active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 64% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live fmtlib/fmt repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/fmtlib/fmt.

What it runs against: a local clone of fmtlib/fmt — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in fmtlib/fmt | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 35 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>fmtlib/fmt</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of fmtlib/fmt. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/fmtlib/fmt.git
#   cd fmt
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of fmtlib/fmt and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "fmtlib/fmt(\\.git)?\\b" \\
  && ok "origin remote is fmtlib/fmt" \\
  || miss "origin remote is not fmtlib/fmt (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "include/fmt/core.h" \\
  && ok "include/fmt/core.h" \\
  || miss "missing critical file: include/fmt/core.h"
test -f "include/fmt/format.h" \\
  && ok "include/fmt/format.h" \\
  || miss "missing critical file: include/fmt/format.h"
test -f "src/format.cc" \\
  && ok "src/format.cc" \\
  || miss "missing critical file: src/format.cc"
test -f "include/fmt/base.h" \\
  && ok "include/fmt/base.h" \\
  || miss "missing critical file: include/fmt/base.h"
test -f "include/fmt/format-inl.h" \\
  && ok "include/fmt/format-inl.h" \\
  || miss "missing critical file: include/fmt/format-inl.h"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 35 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~5d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/fmtlib/fmt"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

{fmt} is a modern C++ formatting library that provides a fast, type-safe alternative to C stdio printf and C++ iostreams. It implements C++20 std::format and C++23 std::print with Python-like format string syntax, featuring correct IEEE 754 floating-point rounding via the Dragonbox algorithm and portable Unicode support. Header-only library in include/fmt/ with core types in base.h, core.h, and format.h. Implementation details split across include/fmt/format-inl.h. Optional compiled sources in src/ (fmt.cc, format.cc, os.cc) for non-header builds. Specializations for chrono (chrono.h), ranges (ranges.h), color output (color.h), C compatibility (fmt-c.h), and printf-style (printf.h).

👥Who it's for

C++ developers building performance-critical systems (servers, databases, embedded applications) who need safe, efficient string formatting without the overhead of iostreams or printf vulnerabilities. Also library authors who want to expose a standard-compliant formatting API.

🌱Maturity & risk

Production-ready and actively maintained. The project has OpenSSF Best Practices badge, continuous fuzzing via oss-fuzz, and multi-platform CI (Linux, macOS, Windows). Core API is stable (C++20/C++23 standard-compliant), with frequent commits and releases (Android build shows versionName 7.1.2, versionCode 34).

Very low risk. Single lead maintainer (Victor Zverovich) could create bus factor concerns, but the project is standards-aligned and well-tested. No external dependency bloat visible (it's a self-contained formatting library). Breaking changes are rare post-v7 (semantic versioning followed).

Active areas of work

Active development targeting C++20/C++23 standard library parity. Recent work includes Android NDK integration (visible in support/ and Gradle config targeting API 36). Continuous fuzzing and security hardening ongoing. Documentation and performance benchmarks maintained in doc/ directory.

🚀Get running

git clone https://github.com/fmtlib/fmt.git && cd fmt && mkdir build && cd build && cmake .. && make && make test

Daily commands: For header-only: #include <fmt/core.h> in C++ code. For development: cmake build with -DFMT_TEST=true enables test targets (run via ctest). For Android: use Gradle with external CMake build. For benchmarks: check support/Android.mk and perf-related build flags.

🗺️Map of the codebase

  • include/fmt/core.h — Core formatting API with fundamental types and format() function; foundational abstraction all contributors must understand.
  • include/fmt/format.h — Extended formatting library with format_to, vformat, and formatter specializations; primary public API surface.
  • src/format.cc — Core implementation of format logic and buffer management; where the actual formatting rendering happens.
  • include/fmt/base.h — Low-level base types (buffer, format_error, basic_format_args) that underpin the entire formatting system.
  • include/fmt/format-inl.h — Inline implementation details for format functions and formatters; critical for understanding performance characteristics.
  • CMakeLists.txt — Build configuration defining library structure, test setup, and platform-specific compilation rules.
  • test/format-test.cc — Primary test suite validating formatting correctness; reference for expected behavior and test conventions.

🛠️How to make changes

Add a new formatter for a custom type

  1. Create a specialization of fmt::formatter<YourType> in your header or in include/fmt/format.h (for core types) (include/fmt/format.h)
  2. Implement parse() method to handle format spec (e.g., :d, :x) by advancing the iterator and returning it (include/fmt/format.h)
  3. Implement format() method that writes the formatted output to the context's output iterator and returns it (include/fmt/format.h)
  4. Add test cases in test/format-test.cc to verify parsing and output for various format specifiers (test/format-test.cc)

Add a new chrono type formatter (date/time)

  1. Add fmt::formatter<YourChronoType> specialization in include/fmt/chrono.h (include/fmt/chrono.h)
  2. Implement parse() to handle strftime-like format specs (e.g., %Y-%m-%d) (include/fmt/chrono.h)
  3. Use fmt::format_to() with strftime-compatible logic to write formatted time to output iterator (include/fmt/chrono.h)
  4. Add comprehensive tests including edge cases (leap years, timezones) in test/chrono-test.cc (test/chrono-test.cc)

Add support for a new output backend (e.g., logging system)

  1. Create a new header include/fmt/mylogger.h following pattern from include/fmt/ostream.h or include/fmt/os.h (include/fmt/ostream.h)
  2. Define a formatter operator or format function that converts fmt::format_string to your logger's output format (include/fmt/mylogger.h)
  3. If needed, extend fmt::basic_format_context or create a custom context type for logger-specific state (include/fmt/base.h)
  4. Add integration tests in test/ directory (e.g., test/mylogger-test.cc) to validate end-to-end formatting (test/format-test.cc)

Add a compile-time format string validation

  1. Leverage fmt::compile or constexpr format parsing in include/fmt/compile.h for static checking (include/fmt/compile.h)
  2. Create a constexpr wrapper or type-safe overload in include/fmt/core.h or include/fmt/format.h (include/fmt/core.h)
  3. Add compile-error tests in test/compile-error-test/ to verify that invalid format strings fail compilation (test/compile-error-test/CMakeLists.txt)

🔧Why these technologies

  • C++17 (with C++14/11 compatibility) — Enables compile-time format string validation, variadic templates, and modern type traits while maintaining backward compatibility for legacy codebases.
  • Header-only core + optional compiled library — Allows zero-overhead inlining of hot paths (parse, format_to) while optional shared library (libfmt) reduces binary bloat for large projects.
  • CMake build system — Multi-platform support (Linux, macOS, Windows, Android) with modular targets and straightforward integration via find_package() or add_subdirectory().
  • Type-safe formatter specialization pattern — Avoids printf-style format string bugs via compile-time type checking and enables user-defined type formatters without touching library code.
  • ANSI color/styling via format specs — Integrates terminal coloring as a first-class format specifier (e.g., {0:fg(red)}) rather than external helper functions, improving ergonomics.

⚖️Trade-offs already made

  • Header-only for core vs. compiled library for ostream/color/os

    • Why: Reduces template bloat and simplifies distribution for users who only need basic formatting.
    • Consequence: Users needing advanced features (color, file I/O) must link libfmt or pull in headers, adding ~100KB binary for each new feature module.
  • Compile-time format string validation optional (constexpr path)

    • Why: Maintains compatibility with dynamic format strings and avoids breaking runtime polymorphism.
    • Consequence: Runtime errors on invalid format strings still possible if users bypass compile checks; requires explicit opt-in to static validation.
  • ANSI-only color support (no Windows native API by default)

    • Why: Simplifies cross-platform code and avoids Win32 API complexity.
    • Consequence: Windows 10+ users see ANSI escape codes in terminal; older Windows and some IDEs may not render colors unless manually enabling VT100 mode.
  • Format args stored as type-erased tuples (basic_format_args)

    • Why: Enables printf-style dynamic formatting without losing type information for custom formatters.
    • Consequence: Small runtime overhead for type erasure; not suitable for extreme high-frequency logging in latency-critical code (<1μs/call required).

🚫Non-goals (don't propose these)

  • does not implement localization beyond basic locale-aware number/date formatting via std::locale
  • does not provide runtime format string safety guarantees (must be provided by caller or

🪤Traps & gotchas

Header-only library has long compile times for large projects; prefer compiled build for production (use src/format.cc). constexpr format string validation in compile.h only works with compile-time-constant strings; runtime format strings bypass this safety. Android NDK requires C++17+ and c++_shared STL (see Gradle config); older NDK versions will fail silently. Color support (color.h) uses terminal codes that may not work in all environments—no auto-detection built in.

🏗️Architecture

💡Concepts to learn

  • CRTP (Curiously Recurring Template Pattern) — {fmt} uses CRTP extensively for formatter specialization (custom types inherit from formatter<T>) without virtual dispatch overhead; understanding this is key to extending the library
  • Constexpr format string validation — compile.h provides compile-time parsing of format strings to catch errors before runtime; critical for {fmt}'s safety claims and C++20 parity
  • Dragonbox algorithm — Core floating-point formatting uses Dragonbox for correct rounding and shortest representation; understanding this explains why {fmt} benchmarks well vs std::to_chars
  • Format string specification (Python-like) — The [[fill][align][sign][#][0][width][grouping_option][.precision][type] syntax is non-standard for C++ but intentionally mimics Python's str.format for familiarity
  • Type erasure and format_context — fmt::format_context wraps heterogeneous argument lists and output buffers; essential for understanding how variadic templates are managed internally
  • Memory layout optimization (buffer, output_range) — Custom range-based output handling in format-inl.h avoids temporary string allocations; critical for the performance claims vs iostreams
  • abseil/abseil-cpp — Google's C++ library with StrCat/StrFormat as older-style alternatives; Abseil developers increasingly prefer {fmt} for new code
  • fmtlib/cppformat — Historical predecessor; {fmt} is the modernized continuation (v2+) of the cppformat project
  • python/cpython — Format syntax is intentionally Python-inspired (PEP 3101); useful reference for behavior edge cases
  • LLVM/llvm-project — LLVM's own adoption of {fmt} for internal formatting; signals production-grade quality

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Complete Android NDK Build CI Workflow

The repo has an incomplete Android Gradle configuration (support/gradle/build.gradle with unfinished externalNativeBuild block), but no CI workflow exists to validate Android builds. Adding a GitHub Actions workflow for Android NDK compilation would ensure the library builds correctly for arm64-v8a, armeabi-v7a, and x86_64 targets, catching regressions early. Currently only linux.yml, macos.yml, and windows.yml workflows exist.

  • [ ] Create .github/workflows/android.yml with Android NDK setup (API 36, NDK 28.2.13676358)
  • [ ] Configure matrix builds for the three ABI filters: arm64-v8a, armeabi-v7a, x86_64
  • [ ] Complete the externalNativeBuild cmake block in support/gradle/build.gradle
  • [ ] Verify shared library output (.so files) are generated and artifacts are uploaded

Add C/C++ Memory Safety Tests for fmt-c.h Interface

The C API interface (include/fmt/fmt-c.h and src/fmt-c.cc) exists but there's no dedicated test suite visible for C-specific functionality. The C interface is critical for language interoperability and memory safety (manual buffer management). Adding comprehensive tests would catch issues like buffer overflows, use-after-free, and format string vulnerabilities specific to the C API.

  • [ ] Create test/fmt-c-test.cc with C API unit tests covering format string parsing
  • [ ] Test memory lifecycle: allocation, formatting, and deallocation for C handles
  • [ ] Add AddressSanitizer/MemorySanitizer validation in linux.yml workflow for these tests
  • [ ] Test edge cases: NULL pointers, oversized format strings, invalid format codes

Add Code Coverage Tracking and Reports

With comprehensive test suites across multiple platforms (linux.yml, macos.yml, windows.yml) but no visible coverage integration, adding code coverage reports would identify untested code paths in the formatting library's core logic. This is especially valuable for include/fmt/core.h and include/fmt/format.h which are critical paths. Integration with a service like Codecov would provide per-PR feedback.

  • [ ] Add gcov/lcov or llvm-cov instrumentation flags to CMakeLists.txt (CMAKE_CXX_FLAGS with -fprofile-arcs -ftest-coverage)
  • [ ] Create coverage collection step in linux.yml workflow after test runs
  • [ ] Integrate Codecov GitHub Action to post coverage reports as PR comments
  • [ ] Set coverage thresholds in .github/workflows/lint.yml to fail on significant coverage drops

🌿Good first issues

  • Add format specialization for std::optional<T> in include/fmt/std.h—currently only std::pair, std::tuple, and std::vector are specialized; this is a common type with no custom formatter.
  • Expand doc/syntax.md with side-by-side Python/C++ format string examples for each feature—currently sparse on practical examples, making it hard for newcomers to understand brace-counting edge cases.
  • Create simple benchmark script in support/ comparing {fmt} vs std::format vs iostreams on common types (int, float, string)—perf.svg exists but source and reproducible script are missing.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 9cb8c0f — Fix ambiguous formatter<std::optional<T>> between fmt/std.h and fmt/ranges.h on C++26 (P3168R2) (#4761) (phprus)
  • 5a9a184 — Apply clang-format (vitaut)
  • 7aabdcf — Workaround apt-add-repository timeouts (vitaut)
  • 8f20ee6 — Correct image link in README (vitaut)
  • 522b509 — Fix badge links in README (vitaut)
  • d0e3d20 — chore(IWYU):Remove redundant includes (#4758) (KaganCanSit)
  • 432fda7 — Fix false positive in tsan (fixes #4755) (vitaut)
  • eeff868 — Avoid dropping null byte in format string (#4732) (user202729)
  • 4b50ad7 — Replace try and catch with the FMT_TRY and FMT_CATCH macros (#4751) (st0rmbtw)
  • 2cb3983 — Update link anchor (#4748) (Powerbyte7)

🔒Security observations

The fmtlib/fmt codebase demonstrates generally good security practices with OpenSSF Best Practices compliance and continuous fuzzing. The primary security concerns are related to build configuration: an outdated Android Gradle Plugin, incomplete native build configuration syntax, and debug output in build files. The C++ formatting library itself (the core component) appears well-structured with no obvious injection vulnerabilities or hardcoded secrets in the analyzed files. Recommendations focus on updating dependencies, completing build configuration, and removing debug logging from production builds. The repository should maintain its strong security posture by continuing fuzzing efforts and timely dependency updates.

  • High · Outdated Android Gradle Plugin — support/gradle/build.gradle (buildscript dependencies). The gradle build configuration uses com.android.tools.build:gradle:9.0.0, which may contain known vulnerabilities. Android Gradle Plugin versions should be kept up-to-date with the latest stable releases to receive security patches. Fix: Update to the latest stable version of Android Gradle Plugin. Check Android Developer releases for the current recommended version and update accordingly.
  • Medium · Incomplete External Native Build Configuration — support/gradle/build.gradle (externalNativeBuild section). The externalNativeBuild block in the gradle configuration appears incomplete (missing closing braces and cmake path specification). This could lead to misconfiguration of the native build process and potential build-time vulnerabilities. Fix: Complete the externalNativeBuild configuration block by adding the cmake path and proper closing braces. Example: add 'path "CMakeLists.txt"' and ensure proper syntax.
  • Medium · High Target API Level with Deprecated Features — support/gradle/build.gradle (compileSdk 36, targetSdkVersion 36). The build targets Android API 36 (compileSdk and targetSdkVersion), which is very recent. While staying current is good, there may be compatibility issues with older devices and libraries. The configuration should be validated against all dependencies. Fix: Verify that all native and Java dependencies support API 36. Review Android compatibility matrices and test on supported API levels. Consider a slightly lower targetSdk if there are compatibility concerns.
  • Low · Debug Output in Build Configuration — support/gradle/build.gradle (println statements). The gradle configuration includes println() statements that output cmake flags and arguments during build time. This could expose build configuration details in CI/CD logs. Fix: Remove or comment out debug println() statements, especially in production CI/CD environments. Use gradle's built-in logging mechanisms with appropriate log levels instead.
  • Low · Missing Security Policy for GitHub — Repository root. While the repository has security badges and follows OpenSSF Best Practices, there is no visible SECURITY.md file in the root directory for coordinated vulnerability disclosure. Fix: Create a SECURITY.md file at the repository root documenting responsible disclosure practices and security reporting procedures, as per OpenSSF guidelines.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · fmtlib/fmt — RepoPilot