MaJerle/c-code-style: A Style Document That Ships With Its Own Enforcer
Recommended C code style and coding rules for standard C99 or later. Comes with AI agent skill to write, edit and format the code.
At a glance
- What is it?
- Tilen MAJERLE's C style guide is a Markdown rulebook plus a matching .clang-format file and an AI agent skill. The interesting part is not the rules, it is that the rules and the formatter are meant to be copied together.
- Who is it for?
- Adopt this if you maintain a C library or embedded firmware tree and want a written standard that a formatter can actually enforce, since the repository pairs CODING_RULES.md with a .clang-format file it says matches it. Do not adopt it if your existing codebase has a different house style and you are unwilling to reformat, because the document itself tells you to imitate surrounding code first.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem is not a missing style, it is a style nobody enforces
Most C projects have a style guide that exists as tribal knowledge or as a wiki page nobody reads. This repository takes a different position: the rules are written down in CODING_RULES.md using RFC 2119 keywords, and the same repository ships a .clang-format file that the document says matches those rules. The stated audience is contributors to Tilen MAJERLE's projects and libraries, where the document is described as the recommended guideline for all contributions. That is a narrow audience, but the artifact is portable. Any C project can copy the rules file and the formatter configuration and get a written standard plus a tool that applies part of it mechanically.
The scope is stated plainly: standard C99 or later, with the general rules section asking for the C11 standard. This is not a guide to writing portable C89, and it is not a guide to C++. It is aimed at people who write C libraries and firmware, which shows in rules such as the advice to avoid initializing global variables with default values, because embedded startup code and linker scripts may not initialize custom memory sections.
How the rules and the formatter are supposed to stay in sync
The mechanism is a pair of files rather than a program. CODING_RULES.md holds the prose rules. A .clang-format file in the repository root holds the machine-readable subset. The README states that this repository always contains an up-to-date .clang-format file that matches the rules described there, and that you can place it in your repository root or in a shared project root for multiple repositories. There is no generation step described, no script that derives one from the other. The consistency claim rests on the maintainer keeping both current.
That is a real design choice with a real consequence. Rules that clang-format can express (indent width, brace placement, spacing around operators) are enforced on save or in CI. Rules that it cannot express are enforced only by review. The document is explicit that clang-format is not limited to VSCode and is a standalone tool usable from any editor or the command line, so the enforcement path is not tied to one IDE.
clang-format's own lookup behaviour matters here. If it cannot find a .clang-format file in the current directory, it searches upward until it finds one, and if none is found it falls back to its default rules. A contributor working inside a nested directory of a repository without a .clang-format file will silently get default formatting rather than an error.
What the rules actually pin down, and where they go beyond formatting
The formatting subset is conventional: no tabs, 4 spaces per indent level, one space between a keyword and its opening parenthesis, no space between a function name and its opening bracket, opening curly bracket on the same line as the keyword, single spaces around comparison and assignment operators, and a single space after every comma. The document gives OK and Wrong code blocks for each of these, which is the right format for a rule that will be argued about.
The naming rules are stricter than most C guides and are worth reading before you copy the file. Lowercase only for variables, functions and types, with optional underscores. Variable names should be at least 3 characters long. The double underscore and leading underscore prefixes are banned outright as reserved for the language itself. The document proposes three specific prefixes instead: prv_ for strictly module-private static functions, and libname_int_ or libnamei_ for library-internal functions that must be shared across internal modules but must not be called by the user application.
Two rules are unusual enough to flag. First, local variables of the same type must be declared on the same line, and declaring a second char after a char has already been declared in the same function is marked Wrong. Second, local variables must be declared in a specified order beginning with custom structures and enumerations. Both rules are about reading a function's prologue quickly. Both also conflict with some teams' habits, and neither is something clang-format will fix for you.
Getting it into a repository, and the symlink trap
The README gives the adoption step directly: to adopt these rules in your own project, copy this file, CODING_RULES.md, into your repository. It then warns, in the same paragraph, not to copy the repository's README.md, because that file is only a symlink to CODING_RULES.md so that it renders on the GitHub front page. Copying README.md would overwrite your project's own README. This is a small detail that would otherwise cost someone a file, and the document calls it out rather than leaving it to be discovered.
The second file to copy is the .clang-format file from the repository root. The general rules state that clang-format should be used with the included .clang-format file, and that version 20.x or later is required.
For editor integration, the README describes VSCode invoking clang-format on save, with the formatting rules coming from the .clang-format file, and points to an image of the settings that should be enabled. The image is referenced but its contents are not reproduced in the text, so the exact setting names are not something this review can state.
For CI, the table of contents lists a Continuous integration (GitHub Actions) subsection under Clang format integration. The README text available here does not include that subsection's body, so the workflow file name and its steps cannot be confirmed from the material at hand.
The agent skill and AGENTS.md: the newest and least specified part
The repository ships a Claude Code skill at .claude/skills/c-code-style/ plus an AGENTS.md. According to the README note, these check that clang-format is available and then run it on relevant files using the repository's .clang-format rules, with the skill's SKILL.md holding the details. That is the whole description available here.
What can be said is what this design implies. The skill does not reimplement formatting; it delegates to clang-format and to the same configuration file a human contributor would use. That is the correct instinct, because a second formatter would drift from the first. The gap is that the README does not state which files the skill considers relevant, how it decides, or what it does when clang-format is absent beyond checking for it. If you are adopting this for an agent workflow rather than for human contributors, SKILL.md is the file to read before trusting the behaviour, not the README.
The most important rule is also the one that limits adoption
The document opens with a quote from a GNOME developer: check the surrounding code and try to imitate it. The paragraph that follows is blunt about patches that arrive in a different style from the code around them. The rule is then stated in its strongest form: whatever this document recommends, if there is already existing code and you are patching it, keep its current style consistent even if it is not your favorite style.
This is an honest position and it is also the reason the project is a poor fit for some teams. If you have a large C codebase with a different house style, adopting this document does not mean running clang-format across the tree. It means either accepting two styles indefinitely or committing to a reformat that will bury every other change in a diff. The document does not offer a migration path, and given its own opening rule, it would be inconsistent for it to recommend one.
The other limitation is the sync problem described earlier. The claim that the .clang-format file matches the rules is a maintenance promise, not a checked invariant. Nothing in the material describes a test that fails when the two diverge. A rule added to the Markdown in a pull request can land without a corresponding formatter change, and the only signal would be a reviewer noticing.
Compared with .editorconfig plus a formatter you configure yourself
The obvious alternative is to skip the document and configure your own tooling: an .editorconfig for indentation and line endings, a .clang-format you write yourself, and whatever naming conventions your team already uses. The difference in approach is where the decisions live. With a self-configured setup, every spacing and brace decision is a value in a config file with no prose explaining why, and naming rules have no home at all because .editorconfig and clang-format do not enforce them.
This repository inverts that. The prose is primary and the formatter is the enforcement layer for the subset it can handle. Naming prefixes like prv_ and libname_int_, the ban on leading underscores, the same-line declaration rule and the local variable ordering all exist as written rules with examples, which is something a bare .clang-format cannot give you. The cost is that you inherit another maintainer's opinions wholesale, including the ones you disagree with, and you take on the job of tracking upstream changes to CODING_RULES.md and .clang-format together.
Licence, maintenance and what to check before copying
The repository is MIT licensed, which permits copying, modification and redistribution provided the copyright notice and permission notice are retained. That makes lifting CODING_RULES.md and .clang-format into a proprietary firmware tree straightforward from a licensing standpoint. This is a description of the licence text, not legal advice; if the notice-retention requirement matters for how your project distributes source, get that checked properly.
On maintenance cost, the material supports a limited but concrete answer. There are no releases retrieved for this repository, so there is no versioned artifact to pin. Adoption means tracking a moving file on the main branch. The last push recorded is 2026-09-09, and the README states the .clang-format file is kept up to date with the rules, so upstream changes are expected rather than exceptional. If you copy the files, you own the divergence from that point on, and the two things most likely to drift are the formatter configuration and the rules that clang-format cannot express.
Before copying, confirm your clang-format version, since 20.x or later is required by the general rules, and confirm that CODING_RULES.md is the file you are copying rather than the README symlink. If your existing code does not already look like this style, decide first whether you are willing to follow the document's own opening rule and leave it alone.
Editorial conclusion
Adopt this if you maintain a C library or embedded firmware tree and want a written standard that a formatter can actually enforce, since the repository pairs CODING_RULES.md with a .clang-format file it says matches it. Do not adopt it if your existing codebase has a different house style and you are unwilling to reformat, because the document itself tells you to imitate surrounding code first. Before copying anything, verify two things: that your clang-format is version 20.x or later, as the general rules require, and that copying CODING_RULES.md rather than README.md is what you intend, since README.md is only a symlink and copying it would overwrite your project's own README.
Community notes