Communitygithub.com

C++ 코딩 표준 (C++ Core Guidelines 기반)

C++ Core Guidelines(isocpp.github.io)에 기반한 C++ 코딩 표준입니다. C++ 코드를 작성, 검토, 리팩토링할 때 현대적이고 안전하며 관용적인 방식을 적용합니다.

C++ 코딩 표준 (C++ Core Guidelines 기반)란 무엇인가요?

이 스킬은 C++ Core Guidelines에서 파생된 포괄적인 C++ 코딩 표준을 제공하며, C++17/20/23과 같은 최신 표준을 대상으로 타입 안전성, 리소스 안전성, 불변성, 코드 명확성을 강조합니다. 새로운 C++ 코드(클래스, 함수, 템플릿)를 작성하거나 기존 C++ 코드를 검토/리팩토링할 때, C++ 프로젝트의 아키텍처 결정이나 일관된 스타일 적용이 필요할 때 사용합니다. 또한 `enum` vs `enum class`, raw 포인터 vs 스마트 포인터 같은 언어 기능 선택 시에도 유용합니다. 주요 원칙으로 RAII, 기본 불변성, 타입 안전성, 의도 표현, 복잡도 최소화, 값 의미론을 강조하며, 각 분야(P.*, F.*, C.*, R.*, ES.*, E.*, Con.*, CP.*)별 구체적인 규칙과 권장 패턴, 금지 패턴을 코드 예제와 함께 제시합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/cpp-coding-standards

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

C++ 코딩 표준 (C++ Core Guidelines)

C++ Core Guidelines에서 도출된 최신 C++(C++17/20/23)용 포괄적 코딩 표준입니다. 타입 안전성, 리소스 안전성, 불변성 및 명확성을 적용합니다.

사용 시기

  • 새 C++ 코드(클래스, 함수, 템플릿) 작성
  • 기존 C++ 코드 검토 또는 리팩토링
  • C++ 프로젝트의 아키텍처 결정
  • C++ 코드베이스에 걸쳐 일관된 스타일 적용
  • 언어 기능 선택(예: enum vs enum class, raw 포인터 vs 스마트 포인터)

사용하지 말아야 할 경우

  • C++ 이외의 프로젝트
  • 최신 C++ 기능을 도입할 수 없는 레거시 C 코드베이스
  • 특정 가이드라인이 하드웨어 제약과 충돌하는 임베디드/베어메탈 환경(선별적으로 적용)

교차 절단 원칙

다음 주제는 전체 가이드라인에 걸쳐 반복되며 기초를 형성합니다:

  1. 모든 곳에서의 RAII (P.8, R.1, E.6, CP.20): 리소스 수명을 객체 수명에 결합
  2. 기본 불변성 (P.10, Con.1-5, ES.25): const/constexpr로 시작, 가변성은 예외
  3. 타입 안전성 (P.4, I.4, ES.46-49, Enum.3): 타입 시스템을 사용하여 컴파일 타임에 오류 방지
  4. 의도 표현 (P.3, F.1, NL.1-2, T.10): 이름, 타입 및 개념이 목적을 전달해야 함
  5. 복잡도 최소화 (F.2-3, ES.5, Per.4-5): 단순한 코드가 올바른 코드
  6. 포인터 의미론보다 값 의미론 (C.10, R.3-5, F.20, CP.31): 값 반환 및 범위 기반 객체 선호

철학 및 인터페이스 (P., I.)

주요 규칙

규칙요약
P.1아이디어를 코드로 직접 표현하세요
P.3의도를 표현하세요
P.4이상적으로 프로그램은 정적으로 타입 안전해야 합니다
P.5런타임 검사보다 컴파일 타임 검사를 선호하세요
P.8리소스를 누수하지 마세요
P.10가변 데이터보다 불변 데이터를 선호하세요
I.1인터페이스를 명시적으로 만드세요
I.2비-const 전역 변수를 피하세요
I.4인터페이스를 정확하고 강력하게 타입화하세요
I.11raw 포인터나 참조로 소유권을 전송하지 마세요
I.23함수 인자 수를 적게 유지하세요

권장

// P.10 + I.4: 불변, 강력하게 타입화된 인터페이스
struct Temperature {
    double kelvin;
};

Temperature boil(const Temperature& water);

금지

// 취약한 인터페이스: 소유권 불명, 단위 불명
double boil(double* temp);

// 비-const 전역 변수
int g_counter = 0;  // I.2 위반

함수 (F.*)

주요 규칙

규칙요약
F.1의미 있는 연산을 신중하게 이름 지어진 함수로 패키징하세요
F.2함수는 단일 논리 연산을 수행해야 합니다
F.3함수를 짧고 단순하게 유지하세요
F.4함수가 컴파일 타임에 평가될 수 있다면 constexpr로 선언하세요
F.6함수가 예외를 던지지 않아야 한다면 noexcept로 선언하세요
F.8순수 함수를 선호하세요
F.16"in" 매개변수의 경우 저렴하게 복사되는 타입은 값으로, 나머지는 const&로 전달하세요
F.20"out" 값의 경우 출력 매개변수보다 반환 값을 선호하세요
F.21여러 "out" 값을 반환하려면 구조체 반환을 선호하세요
F.43지역 객체에 대한 포인터나 참조를 절대 반환하지 마세요

매개변수 전달

// F.16: 저렴한 타입은 값으로, 나머지는 const&로
void print(int x);                           // 저렴함: 값으로
void analyze(const std::string& data);       // 비쌈: const&로
void transform(std::string s);               // 싱크: 값으로 (이동됨)

// F.20 + F.21: 출력 매개변수 대신 값 반환
struct ParseResult {
    std::string token;
    int position;
};

ParseResult parse(std::string_view input);   // 좋음: 구조체 반환

// 나쁨: 출력 매개변수
void parse(std::string_view input,
           std::string& token, int& pos);    // 피하세요

순수 함수와 constexpr

// F.4 + F.8: 가능한 경우 순수, constexpr
constexpr int factorial(int n) noexcept {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

static_assert(factorial(5) == 120);

안티 패턴

  • 함수에서 T&& 반환 (F.45)
  • va_arg / C 스타일 가변 인자 사용 (F.55)
  • 다른 스레드로 전달되는 람다에서 참조로 캡처 (F.53)
  • 이동 의미론을 억제하는 const T 반환 (F.49)

클래스 및 클래스 계층 구조 (C.*)

주요 규칙

규칙요약
C.2불변 조건이 있으면 class를, 데이터 멤버가 독립적으로 변하면 struct를 사용하세요
C.9멤버 노출을 최소화하세요
C.20기본 연산 정의를 피할 수 있다면 피하세요 (Rule of Zero)
C.21복사/이동/소멸자 중 하나를 정의하거나 =delete하면 모두 처리하세요 (Rule of Five)
C.35기반 클래스 소멸자: public 가상 또는 protected 비가상
C.41생성자는 완전히 초기화된 객체를 생성해야 합니다
C.46단일 인자 생성자는 explicit으로 선언하세요
C.67다형 클래스는 public 복사/이동을 억제해야 합니다
C.128가상 함수: virtual, override, final 중 정확히 하나만 지정하세요

Rule of Zero

// C.20: 컴파일러가 특수 멤버를 생성하도록 함
struct Employee {
    std::string name;
    std::string department;
    int id;
    // 소멸자, 복사/이동 생성자 또는 할당 연산자 불필요
};

Rule of Five

// C.21: 리소스를 관리해야 한다면 다섯 가지 모두 정의
class Buffer {
public:
    explicit Buffer(std::size_t size)
        : data_(std::make_unique<char[]>(size)), size_(size) {}

    ~Buffer() = default;

    Buffer(const Buffer& other)
        : data_(std::make_unique<char[]>(other.size_)), size_(other.size_) {
        std::copy_n(other.data_.get(), size_, data_.get());
    }

    Buffer& operator=(const Buffer& other) {
        if (this != &other) {
            auto new_data = std::make_unique<char[]>(other.size_);
            std::copy_n(other.data_.get(), other.size_, new_data.get());
            data_ = std::move(new_data);
            size_ = other.size_;
        }
        return *this;
    }

    Buffer(Buffer&&) noexcept = default;
    Buffer& operator=(Buffer&&) noexcept = default;

private:
    std::unique_ptr<char[]> data_;
    std::size_t size_;
};

클래스 계층 구조

// C.35 + C.128: 가상 소멸자, override 사용
class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;  // C.121: 순수 인터페이스
};

class Circle : public Shape {
public:
    explicit Circle(double r) : radius_(r) {}
    double area() const override { return 3.14159 * radius_ * radius_; }

private:
    double radius_;
};

안티 패턴

  • 생성자/소멸자에서 가상 함수 호출 (C.82)
  • 비-사소한 타입에 memset/memcpy 사용 (C.90)
  • 가상 함수와 재정의자에 다른 기본 인자 제공 (C.140)
  • 데이터 멤버를 const 또는 참조로 만들어 이동/복사 억제 (C.12)

리소스 관리 (R.*)

주요 규칙

규칙요약
R.1RAII를 사용하여 리소스를 자동으로 관리하세요
R.3raw 포인터(T*)는 소유권이 없습니다
R.5범위 기반 객체를 선호하세요, 불필요하게 힙 할당하지 마세요
R.10malloc()/free()를 피하세요
R.11new와 delete를 명시적으로 호출하는 것을 피하세요
R.20소유권을 나타내려면 unique_ptr 또는 shared_ptr을 사용하세요
R.21소유권을 공유하지 않는 한 unique_ptr을 shared_ptr보다 선호하세요
R.22shared_ptr을 만들려면 make_shared()를 사용하세요

스마트 포인터 사용

// R.11 + R.20 + R.21: 스마트 포인터를 사용한 RAII
auto widget = std::make_unique<Widget>("config");  // 고유 소유권
auto cache  = std::make_shared<Cache>(1024);        // 공유 소유권

// R.3: Raw 포인터 = 소유권 없는 관찰자
void render(const Widget* w) {  // w를 소유하지 않음
    if (w) w->draw();
}

render(widget.get());

RAII 패턴

// R.1: 리소스 획득은 초기화
class FileHandle {
public:
    explicit FileHandle(const std::string& path)
        : handle_(std::fopen(path.c_str(), "r")) {
        if (!handle_) throw std::runtime_error("Failed to open: " + path);
    }

    ~FileHandle() {
        if (handle_) std::fclose(handle_);
    }

    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;
    FileHandle(FileHandle&& other) noexcept
        : handle_(std::exchange(other.handle_, nullptr)) {}
    FileHandle& operator=(FileHandle&& other) noexcept {
        if (this != &other) {
            if (handle_) std::fclose(handle_);
            handle_ = std::exchange(other.handle_, nullptr);
        }
        return *this;
    }

private:
    std::FILE* handle_;
};

안티 패턴

  • 맨 new/delete (R.11)
  • C++ 코드에서 malloc()/free() (R.10)
  • 단일 표현식에서 여러 리소스 할당 (R.13 -- 예외 안전성 위험)
  • unique_ptr로 충분한 곳에 shared_ptr 사용 (R.21)

표현식 및 문장 (ES.*)

주요 규칙

규칙요약
ES.5범위를 작게 유지하세요
ES.20항상 객체를 초기화하세요
ES.23{} 초기화 구문을 선호하세요
ES.25수정이 의도되지 않은 경우 객체를 const 또는 constexpr로 선언하세요
ES.28const 변수의 복잡한 초기화에는 람다를 사용하세요
ES.45매직 상수를 피하고 기호 상수를 사용하세요
ES.46좁혀지는/손실이 있는 산술 변환을 피하세요
ES.470이나 NULL 대신 nullptr을 사용하세요
ES.48캐스트를 피하세요
ES.50const를 캐스트하여 제거하지 마세요

초기화

// ES.20 + ES.23 + ES.25: 항상 초기화, {} 선호, 기본적으로 const
const int max_retries{3};
const std::string name{"widget"};
const std::vector<int> primes{2, 3, 5, 7, 11};

// ES.28: 복잡한 const 초기화에 람다 사용
const auto config = [&] {
    Config c;
    c.timeout = std::chrono::seconds{30};
    c.retries = max_retries;
    c.verbose = debug_mode;
    return c;
}();

안티 패턴

  • 초기화되지 않은 변수 (ES.20)
  • 포인터에 0 또는 NULL 사용 (ES.47 -- nullptr 사용)
  • C 스타일 캐스트 (ES.48 -- static_cast, const_cast 등 사용)
  • const를 캐스트하여 제거 (ES.50)
  • 이름 있는 상수 없는 매직 넘버 (ES.45)
  • 부호 있는/부호 없는 산술 혼합 (ES.100)
  • 중첩된 범위에서 이름 재사용 (ES.12)

오류 처리 (E.*)

주요 규칙

규칙요약
E.1설계 초기에 오류 처리 전략을 개발하세요
E.2함수가 할당된 작업을 수행할 수 없음을 알리기 위해 예외를 던지세요
E.6RAII를 사용하여 누수를 방지하세요
E.12던지는 것이 불가능하거나 허용되지 않을 때 noexcept를 사용하세요
E.14목적에 맞게 설계된 사용자 정의 타입을 예외로 사용하세요
E.15값으로 던지고, 참조로 잡으세요
E.16소멸자, 해제, swap은 절대 실패해서는 안 됩니다
E.17모든 함수에서 모든 예외를 잡으려고 하지 마세요

예외 계층 구조

// E.14 + E.15: 사용자 정의 예외 타입, 값으로 던지고, 참조로 잡기
class AppError : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
};

class NetworkError : public AppError {
public:
    NetworkError(const std::string& msg, int code)
        : AppError(msg), status_code(code) {}
    int status_code;
};

void fetch_data(const std::string& url) {
    // E.2: 실패를 알리기 위해 던짐
    throw NetworkError("connection refused", 503);
}

void run() {
    try {
        fetch_data("https://api.example.com");
    } catch (const NetworkError& e) {
        log_error(e.what(), e.status_code);
    } catch (const AppError& e) {
        log_error(e.what());
    }
    // E.17: 여기서 모든 것을 잡지 마세요 -- 예상치 못한 오류는 전파되도록 두세요
}

안티 패턴

  • int나 문자열 리터럴 같은 내장 타입 던지기 (E.14)
  • 값으로 잡기 (슬라이싱 위험) (E.15)
  • 조용히 오류를 삼키는 빈 catch 블록
  • 흐름 제어에 예외 사용 (E.3)
  • errno 같은 전역 상태 기반 오류 처리 (E.28)

상수 및 불변성 (Con.*)

모든 규칙

규칙요약
Con.1기본적으로 객체를 불변으로 만드세요
Con.2기본적으로 멤버 함수를 const로 만드세요
Con.3기본적으로 포인터와 참조를 const로 전달하세요
Con.4생성 후 변경되지 않는 값에 const를 사용하세요
Con.5컴파일 타임에 계산 가능한 값에 constexpr을 사용하세요
// Con.1 ~ Con.5: 기본 불변성
class Sensor {
public:
    explicit Sensor(std::string id) : id_(std::move(id)) {}

    // Con.2: 기본적으로 const 멤버 함수
    const std::string& id() const { return id_; }
    double last_reading() const { return reading_; }

    // 변경이 필요한 경우에만 비-const
    void record(double value) { reading_ = value; }

private:
    const std::string id_;  // Con.4: 생성 후 절대 변경되지 않음
    double reading_{0.0};
};

// Con.3: const 참조로 전달
void display(const Sensor& s) {
    std::cout << s.id() << ": " << s.last_reading() << '\n';
}

// Con.5: 컴파일 타임 상수
constexpr double PI = 3.14159265358979;
constexpr int MAX_SENSORS = 256;

동시성 및 병렬성 (CP.*)

주요 규칙

규칙요약
CP.2데이터 경합을 피하세요
CP.3쓰기 가능한 데이터의 명시적 공유를 최소화하세요
CP.4스레드보다 작업 단위로 생각하세요
CP.8동기화를 위해 volatile을 사용하지 마세요
CP.20RAII를 사용하고 절대 lock()/unlock()을 직접 사용하지 마세요
CP.21여러 뮤텍스를 획득하려면 std::scoped_lock을 사용하세요
CP.22락을 보유한 상태에서 알 수 없는 코드를 호출하지 마세요
CP.42조건 없이 기다리지 마세요
CP.44lock_guard와 unique_lock의 이름을 기억하세요
CP.100절대적으로 필요하지 않다면 락-프리 프로그래밍을 사용하지 마세요

안전한 락킹

// CP.20 + CP.44: RAII 락, 항상 이름 지정
class ThreadSafeQueue {
public:
    void push(int value) {
        std::scoped_lock lock(mutex_);  // CP.20: RAII 락
        queue_.push(value);
    }

    std::optional<int> pop() {
        std::scoped_lock lock(mutex_);
        if (queue_.empty()) return std::nullopt;
        int value = queue_.front();
        queue_.pop();
        return value;
    }

private:
    std::queue<int> queue_;
    mutable std::mutex mutex_;
};

조건 변수

// CP.42: 조건과 함께 대기
std::condition_variable cv;
std::mutex cv_mutex;
bool ready{false};

void worker_thread() {
    std::unique_lock lock(cv_mutex);
    cv.wait(lock, [] { return ready; });  // CP.42: 조건부 대기
    // 작업 수행...
}

void signal_thread() {
    {
        std::scoped_lock lock(cv_mutex);
        ready = true;
    }
    cv.notify_one();
}

안티 패턴

  • 동기화에 volatile 사용 (CP.8)
  • std::lock_guard 없이 lock()/unlock() 직접 호출 (CP.20)
  • 락을 보유한 상태에서 사용자 콜백 호출 (CP.22 -- 데드락 위험)
  • 조건 없이 wait() 사용 (CP.42 -- 가짜 깨움)
  • 원자적 연산만으로 동시성 문제 해결 시도 (CP.100)

템플릿 및 제네릭 프로그래밍 (T.*)

주요 규칙

규칙요약
T.10모든 템플릿에 대한 개념을 지정하세요
T.20"추상"과 "구체적인" 의미론 간의 관계를 개념으로 표현하세요
T.40연산자 오버로딩을 통해 알고리즘 인자를 개념적으로 사용하세요
T.41템플릿에서는 프로토타입 요구 사항만 충분히 설명하세요
T.42더 나은 가독성과 정확성을 위해 템플릿 별칭을 사용하세요
T.43using을 사용하여 typedef보다 선호하세요
T.44함수 템플릿을 특수화하는 것보다 오버로딩을 사용하세요
T.46템플릿 인자는 const 참조로 전달하세요
T.47높은 컴파일 시간 비용이 드는 템플릿을 피하세요
T.48컴파일 타임 계산에는 constexpr 템플릿을 사용하세요
T.60인터페이스로서의 특성(traits)보다 템플릿 별칭을 선호하세요
T.65태그 디스패치를 사용하여 대체 구현을 선택하세요
T.120템플릿 메타프로그래밍에는 개념만 사용하세요

개념 (C++20)

// T.10: 개념으로 템플릿 제약
template <typename T>
concept Hashable = requires(T a) {
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};

template <Hashable T>
void process(const T& value) {
    std::size_t hash = std::hash<T>{}(value);
    // ...
}

// T.40: 연산자 오버로딩을 통한 개념적 사용
template <typename T>
concept Streamable = requires(std::ostream& os, T value) {
    { os << value } -> std::same_as<std::ostream&>;
};

template <Streamable T>
void print(const T& value) {
    std::cout << value << '\n';
}

템플릿 메타프로그래밍

// T.48: 컴파일 타임 계산을 위한 constexpr 템플릿
template <int N>
struct Factorial {
    static constexpr int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static constexpr int value = 1;
};

static_assert(Factorial<5>::value == 120);

안티 패턴

  • 템플릿 인자 제약 부족 (T.10): 의미 없는 오류 메시지 발생
  • 오버로딩 대신 템플릿 특수화 사용 (T.44): 예상치 못한 동작 발생 가능
  • 고비용 템플릿 컴파일 (T.47): 빌드 시간 증가
  • 비-타입 템플릿 인자에 raw 포인터 사용 (T.53): 더 나은 대안 존재

소스 코드 구성 및 네임스페이스 (SF., NL.)

파일 구성

규칙요약
SF.1.h / .cpp 파일 쌍을 사용하여 선언과 정의를 분리하세요
SF.2.h 파일은 #include를 제외한 다른 것을 포함해서는 안 됩니다
SF.3모든 .h 파일에 #include 가드를 사용하세요
SF.4필요한 경우에만 .h 파일에 인라인 함수를 포함하세요
SF.5.cpp 파일은 필요한 헤더만 포함해야 합니다
SF.6using namespace를 전역 범위가 아닌 함수/네임스페이스 범위로 제한하세요
SF.7헤더가 자기 충족적이도록 만드세요 (필요한 모든 헤더를 포함)
SF.8의존성 그래프를 비순환적으로 유지하세요
SF.21헤더에 익명 네임스페이스를 사용하지 마세요

네임스페이스 사용

// SF.6: using namespace를 제한된 범위로 제한
namespace MyLibrary {
    namespace Detail {
        void internal_helper();
    }

    class PublicAPI {
    public:
        void do_something();
    };
} // namespace MyLibrary

// 개인 구현 파일에서
void example() {
    using namespace std::chrono_literals;  // OK: 함수 범위
    auto timeout = 30ms;
}

// SF.21: 헤더가 아닌 .cpp 파일에서 익명 네임스페이스 사용
namespace {  // .cpp 파일 내부에서만
    int internal_counter = 0;

    void helper_function() {
        // 여기서만 접근 가능
    }
}

명명 규칙

규칙요약
NL.1코드에서 의도를 표현하세요
NL.2주석에서 의도를 기술하세요
NL.5타입 이름은 대문자로 시작하고 함수 이름은 소문자로 시작하세요
NL.7이름을 발음할 수 있고 검색 가능하게 만드세요
NL.9줄당 하나의 선언만 사용하세요
NL.10_ 접두사나 접미사를 피하세요
NL.15주석을 적게 사용하되, 사용하는 경우 품질을 유지하세요
NL.16일반적인 코딩 스타일을 사용하세요
NL.17간결한 주석보다 설명적인 이름을 사용하세요
NL.18C 스타일 주석보다 C++ 스타일 주석을 사용하세요
NL.19기본적인 명명 규칙을 따르지 않은 이름을 피하세요
NL.20이름 외에는 공백을 사용하지 마세요
NL.25매개변수로 전달된 포인터를 nullptr에 대해 테스트하지 마세요
NL.26일반적인 규칙을 재정의할 때만 주석을 사용하세요
NL.27주석이 아닌 코드를 주석 처리하세요
NL.31일관된 들여쓰기를 사용하세요
NL.35함수, 클래스 및 네임스페이스 주위에 빈 줄을 사용하세요

권장 개발 환경 설정

CMake 구성 (C++17 이상)

cmake_minimum_required(VERSION 3.15)
project(MyProject LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)          # SF.1: 표준 C++만 사용

# 경고 수준 높이기
if(MSVC)
    add_compile_options(/W4 /permissive-)
else()
    add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()

add_executable(my_app main.cpp)

clang-tidy 구성

# .clang-tidy
Checks: >
    clang-*,
    cpp-coreguidelines-*,
    modernize-*,
    performance-*,
    readability-*,
    -modernize-use-trailing-return-type
WarningsAsErrors: '*'
HeaderFilterRegex: '.*'

참고 자료

라이선스

이 문서는 C++ Core Guidelines를 기반으로 합니다. C++ Core Guidelines는 CC-BY-4.0 라이선스에 따라 배포됩니다.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

관련 스킬