Getting an algorithm right is paramount. Yet it's rarely the bottleneck. Turning it into shippable code — a tested C library, a Python binding, a build system, packaging, and a public C API that Rust or C++ can also link — is the tedious, exacting work that repeats on every project.
just-makeit new scaffolds the whole thing in one command: core C library, thin
Python binding, CMake build system, and full test coverage — all passing before
you write a single line of your algorithm.
Click the badge to launch a pre-built sandbox in your browser — no install, no
compiler, no Docker required. You'll land in a GitHub Codespaces environment
with just-makeit installed, all nine bundled examples already scaffolded and
compiled, and a terminal ready to go. Run an example end-to-end, browse the
generated C and Python source, or start a fresh project with
just-makeit new.
curl (auto-installs dependencies, creates and activates venv):
. <(curl -fsSL https://just-buildit.github.io/just-makeit/install.sh) [-- path]pip:
pip install just-makeit && just-makeit install-deps [-- path]uv:
uv tool install just-makeit && just-makeit install-deps [-- path]Docker (no install needed):
docker run --rm -it ghcr.io/just-buildit/jm-examples-linux:latestSimple standalone extension:
just-makeit new my_project --object engine --state gain:double:1.0
cd my_project && make && make testModule subpackage — multiple types in one .so:
just-makeit new my_filters --module filter
cd my_filters
just-makeit object fir --module filter \
--state "coeffs:float[16]" --state "delay:float _Complex[16]" --state "gain:float:1.0"
just-makeit object biquad --module filter \
--arg-type float --return-type float \
--state "b0:double:1.0" --state "b1:double:0.0" --state "a1:double:0.0"
make && make testfrom my_filters.filter import Fir, Biquad # one .so, one importmy_project/
├── native/
│ ├── inc/engine/engine_core.h # public C API + inline step()
│ ├── src/engine/
│ │ ├── engine_core.c # block processor + lifecycle
│ │ └── engine_ext.c # thin Python binding
│ └── tests/test_engine_core.c # CTest
├── src/my_project/
│ ├── engine.pyi # type stub
│ └── tests/test_engine.py # pytest / unittest
├── cmake/my-project.pc.in # pkg-config template
├── CMakeLists.txt
├── Makefile
└── just-makeit.toml
engine_state_t *engine_create(double gain);
void engine_destroy(engine_state_t *state);
void engine_reset(engine_state_t *state);
static inline float complex
engine_step(const engine_state_t *state, float complex x);
void engine_steps(engine_state_t *state,
const float complex *in, float complex *out, size_t n);
double engine_get_gain(const engine_state_t *state);
void engine_set_gain(engine_state_t *state, double gain);from my_project import Engine
import numpy as np
obj = Engine(gain=2.0)
y = obj.step(1.0 + 0.5j)
x = np.ones(1024, dtype=np.complex64)
y = obj.steps(x) # allocates output ndarray
obj.steps(x, out=y) # zero-copy
obj.set_gain(0.5)
obj.reset()
with Engine() as e:
y = e.steps(x)- Python 3.11+
- CMake ≥ 3.16
- A C99 compiler (GCC, Clang, MSVC/MinGW)
- NumPy (runtime, for generated projects)
Matthew T. Hunter, Ph.D. and Claude Code
