clang-format-swig 0.0.1

dotnet tool install --global clang-format-swig --version 0.0.1
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local clang-format-swig --version 0.0.1
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=clang-format-swig&version=0.0.1
                    
nuke :add-package clang-format-swig --version 0.0.1
                    

clang-format-swig

clang-format for SWIG .i interface files.

Why

SWIG .i files are mostly C/C++ with a handful of SWIG-specific directives sprinkled in (lines that start with %):

%module mylib

%{
#include "mylib.h"
%}

%include "typemaps.i"

%typemap(in) MyStruct * {
    if (!convert($input, &$1)) return NULL;
}

Running clang-format directly on these files produces broken output because:

  • %{ and %} contain braces that shift clang-format's tracked brace depth, causing everything after them to be indented as if inside a block.
  • %module is parsed as a C++20 module declaration, altering scope state for all subsequent code.

The C/C++ content (the bulk of every .i file) ends up incorrectly indented or not formatted at all.

How it works

Before passing the file to clang-format, each %-prefixed line is swapped for a #pragma placeholder:

Original Placeholder
%module my_lib #pragma SWIG_3F9A12_0
%{ #pragma SWIG_3F9A12_1
%} #pragma SWIG_3F9A12_2

#pragma lines are preserved verbatim by clang-format and have no effect on brace depth or scope, so all surrounding C/C++ is formatted correctly. Afterwards the placeholders are replaced back with the original % lines.

Your .clang-format config is fully respected: clang-format-swig is a thin wrapper, not a reimplementation. It is written in Go and compiles to a single static binary, so it can ship through any package registry without requiring a runtime or build toolchain on the target system.

Installation

Pick whichever channel fits your stack, every install resolves to the same Go binary.
If there's no distribution available for your platform architecture, you can open a feature request.

clang-format must be installed separately and be on PATH. Install it however you'd normally get LLVM tooling on your platform (e.g. apt install clang-format, brew install clang-format, winget install LLVM.LLVM, uv tool install clang-format, npm install -g clang-format, ...).

Go

go install github.com/Avasam/clang-format-swig@latest

Requires Go (see go.mod for the minimum version).

pre-commit

Add to your .pre-commit-config.yaml:

# Requires having clang-format pre-installed and available on PATH
# Has go installation and build overhead
- repo: https://github.com/Avasam/clang-format-swig
  rev: vX.X.X
  hooks:
    - id: clang-format-swig

or

# Has Python installation overhead
- repo: local
  hooks:
    - id: clang-format-swig
      name: clang-format SWIG files
      language: python
      entry: clang-format-swig
      files: \.i$
      additional_dependencies:
        - clang-format-swig==X.X.X
        - clang-format==X.X.X

Python

uv tool install clang-format-swig

The platform binary is bundled in the wheel.

Node.js

npm install -g clang-format-swig

The platform binary is fetched as an optional dependency, so no install-time scripts run.

.NET

dotnet tool install -g clang-format-swig

See clang-format-swig.csproj for the minimum .NET runtime. The platform binary is embedded in the package and extracted to your user cache on first run.

Usage

# Format files in-place
clang-format-swig src/mylibrary.i

# Format multiple files
clang-format-swig **/*.i

# Check without writing (useful in CI)
clang-format-swig --check **/*.i

# Print version
clang-format-swig --version

clang-format-swig exits 0 if no files were changed (or --check found nothing to change), and 1 if any file was reformatted (or would be reformatted under --check).

clang-format itself must be on PATH; the wrapper does not vendor it.

pre-commit usage

Once the hook is configured, it runs automatically on staged .i files:

pre-commit run clang-format-swig --all-files

LLM / Coding Agent disclaimer: This project was initially scaffolded with Claude (Sonnet 4.6 and Opus 4.7). Every change is reviewed by a human before being merged.

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.0.1 171 4/26/2026