tsujikiri — 辻斬り
Cut through C++ bindings
tsujikiri parses C++ headers via libclang, filters by namespace and pattern, transforms symbols — rename, remap types, inject code — then renders ready-to-compile bindings through a Jinja2 template. Precise control, zero boilerplate.
Built-in support for LuaBridge3 (Lua bindings), LuaLS (Lua Language Server annotations), pybind11 (Python bindings), and Python type stubs (.pyi). Custom formats are first-class.
How It Works
C++ Header (.hpp)
│
▼ libclang
Intermediate Representation (IR)
│
├─▶ FilterEngine suppress classes / methods / fields by pattern
│
├─▶ Transform Pipeline rename, inject, remap types
│
▼ Jinja2 templates
Target Binding Code
Each phase is independently configurable per input file and per output format.
Documentation
Full documentation is available at tsujikiri.readthedocs.io.
Installation
Using pip:
pip install tsujikiri
Using uv:
uv pip install tsujikiri
Requirements: Python ≥ 3.10
Clang Version
By default tsujikiri installs libclang-ng>=19, which resolves to the latest available version (see https://github.com/kunitoki/libclang-ng for more information). To pin a specific Clang release use an extra:
# pip
pip install "tsujikiri[clang19]"
pip install "tsujikiri[clang20]"
pip install "tsujikiri[clang21]"
pip install "tsujikiri[clang22]"
# uv
uv pip install "tsujikiri[clang21]"
Only one clangXX extra may be active at a time — they are mutually exclusive.
Quick Start
1. Write an input config
# myproject.input.yml
source:
path: myproject.hpp
parse_args: ["-std=c++17"]
include_paths: ["/usr/local/include"]
filters:
namespaces: ["myproject"]
classes:
whitelist: ["Vec3", "Matrix4", "Camera"]
constructors:
include: true
generation:
includes: ["<myproject.hpp>"]
2. Generate bindings
# Print to stdout
tsujikiri -i myproject.input.yml --target luabridge3 -
# Write to file
tsujikiri -i myproject.input.yml --target luabridge3 bindings.cpp
# Generate multiple outputs in one pass
tsujikiri -i myproject.input.yml \
--target luabridge3 bindings.cpp \
--target pybind11 py_bindings.cpp \
--target pyi mymodule.pyi
# Dry-run: parse and filter, print summary
tsujikiri -i myproject.input.yml --target luabridge3 - --dry-run
# List available formats
tsujikiri --list-formats
3. Example output (LuaBridge3)
Given a header with a Vec3 class, tsujikiri emits:
#include <myproject.hpp>
#include <LuaBridge/LuaBridge.h>
void register_myproject(lua_State* L)
{
luabridge::getGlobalNamespace(L)
.beginClass<myproject::Vec3>("Vec3")
.addConstructor<void(*)(float, float, float)>()
.addFunction("length", &myproject::Vec3::length)
.addFunction("dot", &myproject::Vec3::dot)
.addProperty("x", &myproject::Vec3::x)
.addProperty("y", &myproject::Vec3::y)
.addProperty("z", &myproject::Vec3::z)
.endClass();
}
Built-in Formats
luabridge3
Generates C++ registration code for LuaBridge3.
tsujikiri -i project.input.yml --target luabridge3 bindings/lua_bindings.cpp
Handles: classes, constructors, instance/static methods, overloaded methods, properties, enums, free functions, inheritance.
luals
Generates Lua Language Server annotation stubs.
tsujikiri -i project.input.yml --target luals types/myproject.lua
Emits ---@class, ---@field, ---@param, ---@return annotations with C++→Lua type mappings.
pybind11
Generates C++ registration code for pybind11.
tsujikiri -i project.input.yml --target pybind11 src/py_bindings.cpp
Handles: classes with multiple inheritance, constructors, instance/static methods, overloaded methods (via py::overload_cast), read-write/read-only properties, enums (via py::enum_), free functions, doc strings.
pyi
Generates Python type stub files (.pyi) for use alongside pybind11 bindings.
tsujikiri -i project.input.yml --target pyi mymodule.pyi
Emits Python-typed stubs with @overload, @staticmethod, class inheritance, enum stubs as class Foo(int), and C++→Python type mappings.
Custom Formats
Create a myformat.output.yml alongside your templates:
format_name: "myformat"
format_version: "1.0"
description: "My custom binding format"
type_mappings:
"std::string": "String"
"int32_t": "int"
unsupported_types:
- "CFStringRef"
template:
{%- block prologue -%}
# DO NOT EDIT - Auto-generated Python stubs for {{ module_name }} by tsujikiri
from __future__ import annotations
from typing import overload
{{ code_injections | code_at("beginning") }}
{%- endblock %}
# ... finish the template
Point tsujikiri at your format directory:
tsujikiri -i project.input.yml --target myformat out/bindings.cpp -f ./my_formats/
CLI Reference
usage: tsujikiri [-h] [--input FILE] [--target FORMAT FILE] [--formats-dir DIR] [--list-formats] [--dry-run] [--manifest-file FILE]
[--check-compat] [--embed-version] [--trace-transforms] [--dump-ir [FILE]] [--validate-config] [--verbose]
[--api-version VERSION] [--pretty [FORMAT ...]] [--strict] [--jobs N]
辻斬り — Generic C++ Binding Generator
options:
-h, --help show this help message and exit
--input FILE, -i FILE
Input config YAML (e.g. myproject.input.yml)
--target FORMAT FILE, -t FORMAT FILE
Output target: FORMAT is a built-in name (luabridge3) or path to .output.yml; FILE is the output path ('-' for
stdout). Repeatable.
--formats-dir DIR, -f DIR
Additional directory to search for .output.yml format files (repeatable)
--list-formats Print available built-in output formats and exit
--dry-run Parse and filter but do not generate output; print a summary instead
--manifest-file FILE, -m FILE
Write API manifest JSON to FILE; if FILE already exists, compare with new manifest
--check-compat Exit 1 if --manifest-file exists and breaking API changes are detected
--embed-version Embed the API version hash in the generated code (template must support it)
--trace-transforms Print which transform stages ran and on what entities to stderr
--dump-ir [FILE] Dump the post-transform IR as JSON to FILE (default: stdout when flag is given without FILE)
--validate-config Validate the input config YAML (regex patterns, transform stage names) and exit
--verbose, -v Enable verbose output during parsing (currently only applies to Clang diagnostics)
--api-version VERSION
Target API version (semver). Entities with api_since > VERSION or api_until <= VERSION are excluded.
--pretty [FORMAT ...]
Enable pretty printing. With no FORMAT args, enable for all targets. With FORMAT names (e.g. --pretty luabridge3
pybind11), enable only for those targets. Overrides the input.yml `pretty` setting.
--strict Exit 1 if clang reports any errors during parsing; no output is written
--jobs N, -j N Parse sources using N worker processes, or 'auto' for one per CPU. Default: 1 (serial). Output is identical for
any N.
Development
# Install task runner and sync dependencies
pip install just uv
just sync
# Run tests
just test
# Run tests with coverage
just coverage
# Build wheel
just build
The test suite covers parsing, filtering, transforms, generation, CLI integration, and end-to-end compilation with LuaBridge3.
Coverage
License
MIT — see LICENSE.
Metadata
Release files for tsujikiri 0.30.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tsujikiri-0.30.0.tar.gz | 87.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tsujikiri-0.30.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 185.7 kB
Release files / tsujikiri-0.30.0.tar.gz
| Download URL | tsujikiri-0.30.0.tar.gz |
|---|---|
| Size | 87.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7fe35d9c5d6bbef1c106411446b27526e7588355eb82314e55847e18d0e7dae6
|
|
BLAKE2b-256 checksum How to use checksums |
dfb79a4147b4da47a3e694efca14e331cf2e58ee94bad12502fc6295d130dfa1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / tsujikiri-0.30.0-py3-none-any.whl
| Download URL | tsujikiri-0.30.0-py3-none-any.whl |
|---|---|
| Size | 98.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
958f23410d12be5cbfce83c5f1512b93ab749302bec2315c29bfde97b991755d
|
|
BLAKE2b-256 checksum How to use checksums |
f8f03a7cae44e1e39aa04b64f1037c1595e52573dd417b623dbb08d2bce3a930
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency log