git-agent for C/C++Conventional commits for C and C++ projects
git-agent understands C/C++ header and implementation separation, CMake project structure, and modern C++ patterns, producing atomic conventional commits for systems and embedded codebases.
diff example
diff --git a/src/io/file_reader.cpp b/src/io/file_reader.cpp
index 3d1b8c2..7a9e4f6 100644
--- a/src/io/file_reader.cpp
+++ b/src/io/file_reader.cpp
@@ -1,14 +1,22 @@
#include "file_reader.h"
+#include <memory>
+#include <system_error>
-FileReader::FileReader(const char* path) : file_(fopen(path, "r")) {
- if (!file_) throw std::runtime_error("failed to open file");
+FileReader::FileReader(const std::filesystem::path& path)
+ : file_(std::fopen(path.c_str(), "r")) {
+ if (!file_) {
+ throw std::system_error(errno, std::generic_category(),
+ path.string());
+ }
}
-FileReader::~FileReader() { if (file_) fclose(file_); }
+FileReader::~FileReader() = default;
-FileReader::FileReader(FileReader&& other) noexcept
- : file_(std::exchange(other.file_, nullptr)) {}
+FileReader::FileReader(FileReader&&) noexcept = default;
-std::string FileReader::ReadLine() {
+std::expected<std::string, FileReader::Error> FileReader::ReadLine() {
+ if (!file_) return std::unexpected(Error::NotOpen);
std::array<char, 256> buf;
if (auto* p = std::fgets(buf.data(), buf.size(), file_)) {
return std::string(p);
diff --git a/src/io/file_reader.h b/src/io/file_reader.h
index 5c2a1b4..8d3f7e9 100644
--- a/src/io/file_reader.h
+++ b/src/io/file_reader.h
@@ -1,8 +1,14 @@
#pragma once
+#include <expected>
+#include <filesystem>
#include <string>
+#include <memory>
class FileReader {
public:
+ enum class Error { NotOpen, ReadError, Eof };
+
explicit FileReader(const std::filesystem::path& path);
~FileReader();
FileReader(FileReader&&) noexcept;git-agent output
refactor(io): modernise FileReader with RAII, std::expected, and filesystem path
- replace raw fopen/fclose with RAII via unique_ptr custom deleter (defaulted destructor)
- migrate from const char* to std::filesystem::path for Unicode path support
- switch return type from string to std::expected<string, Error> for explicit error handling
- replace std::runtime_error with std::system_error preserving errno context
- default move constructor/assignment instead of manual exchange
The old API leaked file descriptor ownership semantics into callers and
threw exceptions on I/O errors; std::expected makes failures part of the
return type, and the modernised path handling supports Unicode filenames
on all platforms.Why it works for C/C++
- Understands header (.h/.hpp) and implementation file pairs for atomic grouping
- Recognises CMakeLists.txt and Makefile build configuration changes as chore commits
- Separates C++ template metaprogramming changes from runtime code changes
- Handles embedded C projects with platform-specific #ifdef blocks correctly
install
brew install gitagenthq/tap/git-agent
# inside your C/C++ project
git-agent init # detects CMakeLists.txt / Makefile structure for scopesFAQ
Does git-agent handle C++ template metaprogramming diffs?Yes. The LLM understands template specialisation, SFINAE, constexpr, and concepts. Template-related changes are grouped together and described in terms of their effect on the type system.
How does git-agent handle C++ preprocessor directives and conditional compilation?Preprocessor changes are kept with the code they guard. The LLM understands #ifdef / #endif blocks and will note platform-specific additions in the commit message.
Can git-agent work with CMake presets and vcpkg/conan dependency management?Yes. CMakePresets.json, vcpkg.json, and conanfile.txt changes are detected as build configuration changes and committed separately from source code changes.