Skip to content

Build & tooling commands


just-makeit build [dir]

Build the C extensions and package a wheel.

just-makeit build           # wheel → dist/
just-makeit build wheels/   # wheel → wheels/

Configures CMake (if not already done), builds the C extensions, then runs pip wheel via just-buildit. Must be run from a project directory containing pyproject.toml.


just-makeit test

Build (if needed), then run all tests.

just-makeit test
  • CTest runs the C tests in each object's tests/ directory.
  • pytest (or unittest, depending on how the project was scaffolded) runs the Python tests in src/.

just-makeit dry-run

Show what would be compiled and packaged without running any build steps.

just-makeit dry-run

Output includes the list of C source files and the full cmake configure command that just-makeit build would invoke.



make coverage

Generate C and Python coverage HTML reports. Run from the project root after scaffolding with just-makeit.

make coverage

Requires lcov/genhtml for the C side and pytest-cov for Python:

sudo apt-get install lcov          # Debian/Ubuntu
brew install lcov                  # macOS
sudo pacman -S lcov                # Arch/CachyOS
uv add --dev pytest-cov

What it does:

  1. Compiles a separate build/cov/ tree with -DCMAKE_C_FLAGS="--coverage -O0" — the Release build in build/ is untouched.
  2. Runs CTest against the coverage binary.
  3. Collects .gcda files with lcov --capture, strips system and test paths, and renders docs/coverage/c/index.html via genhtml.
  4. Runs pytest --cov=<package> --cov-report=html:docs/coverage/python.

Both reports land under docs/ (already in .gitignore).


make docs

Build both C and Python API documentation. Run from the project root.

make docs

Requires doxygen for the C side and zensical + mkdocstrings-python for Python:

sudo apt-get install doxygen       # Debian/Ubuntu
brew install doxygen               # macOS
uv add --dev zensical mkdocstrings-python

C API — Doxygen

Reads Doxyfile (generated by just-makeit, edit freely) and produces docs/doxygen/html/index.html. Covers every *.h and *.c under native/inc/ and native/src/. JavaDoc-style /** @brief ... */ comments in your C source appear automatically.

Python API — Zensical + mkdocstrings

Reads zensical.toml (generated by just-makeit) and produces site/index.html. The generated docs/api.md page uses a single mkdocstrings directive:

::: my_package
    options:
      show_source: true
      members: true

mkdocstrings introspects the compiled extension and renders docstrings from PyDoc_STR(...) in the C binding.

Serve live with hot-reload:

zensical serve

just-makeit perf

Upgrade an existing project to use performance annotations without overwriting any user code. Must be run from the project root.

just-makeit perf

Writes native/inc/jm_perf.h, adds #include "jm_perf.h" to each object header, and replaces static inline with JM_FORCEINLINE JM_HOT on step(). Records perf = true in just-makeit.toml so future object and add commands inherit it. Safe to run on a project with a filled-in step(). Idempotent.

See Performance annotations for the full macro reference and JM_DEFINE_STEPS documentation.


just-makeit apply

Reconcile the generated files with just-makeit.toml. Use this after hand-editing the manifest, after git pull, or to materialize any files missing from a checkout. Must be run from the project root.

just-makeit apply

apply follows the sacred / glue contract:

File On every apply
<comp>_ext.c Glue — fully regenerated from the manifest.
src/<pkg>/<comp>.pyi Glue — fully regenerated.
CMakeLists.txt Glue — fully regenerated.
<comp>_core.h Mixed — a missing method/property declaration is injected; the inline step() body and the state struct are sacred and never re-rendered.
<comp>_core.c Sacred — never spliced or re-rendered once it exists. steps()/lifecycle bodies are yours.

So editing the manifest always propagates to the glue, and apply injects any missing method/property declaration into _core.h. The struct and inline step() stay sacred. Changing a signature in TOML — or adding a state field — is structural: rebuild the body from the manifest with jm regenerate (or jm add, which is regenerate specialized for state). A new method or computed property is additive instead — jm method / jm property inject a declaration and append a fresh stub.


just-makeit regenerate <component>

The deliberate-refresh half of the sacred/glue contract. Deletes every file the component owns, then re-runs jm apply to rebuild them all from the manifest. The manifest itself is left untouched (unlike jm remove). Works for standalone and module objects. Must be run from the project root.

git stash                          # regenerate discards hand-written bodies
just-makeit regenerate engine
just-makeit regenerate engine --force   # skip the confirmation

Because the rebuilt _core.c comes straight from the manifest, any hand-written body in <comp>_core.c is discardedgit stash or commit first. A single confirmation guards the deletion; --force skips it.

Flag Description
--force Skip the deletion confirmation.

just-makeit ci [--provider NAME]

Generate a continuous-integration workflow that builds the project and runs its tests (make && make test), so a scaffolded project is CI-green as fast as it builds and tests locally. Must be run from the project root.

just-makeit ci                         # GitHub Actions: .github/workflows/ci.yml
just-makeit ci --provider woodpecker  # Woodpecker: .woodpecker.yml
just-makeit ci --force                 # overwrite an existing workflow file

The generated workflow installs the build dependencies and runs the same build-and-test the test target drives locally. If the project enabled pytest, the dependency step also installs the Python test requirements; otherwise it stays C-only.

Flag Description
--provider NAME github (default → .github/workflows/ci.yml) or woodpecker (→ .woodpecker.yml).
--force Overwrite the workflow file if it already exists.

just-makeit config [key value]

Show or edit the project configuration stored in just-makeit.toml. Must be run from the project root.

just-makeit config                 # print current config
just-makeit config version 0.2.0  # update version

Example output

project:  my_project
version:  0.1.0

engine:
  rate:  double = 1.0
  order: int    = 4

parser:
  depth:  int = 8
  strict: int = 1

Supported keys

Key Description
version Project version string stored in just-makeit.toml.

just-makeit bind <component>

Synthesise <comp>_ext.c and <comp>.pyi by reading <comp>_core.h directly, without consulting just-makeit.toml. This is the "point at your C and get Python" path. Must be run from the project root.

just-makeit bind engine          # synthesise engine_ext.c from engine_core.h
just-makeit bind engine --check  # exit 1 if the generated binding differs from the file on disk

jm bind parses the header for the standard just-makeit naming conventions (<comp>_state_t, <comp>_create, <comp>_step, scalar field defaults from the reset body) and renders the binding from the same context builders the manifest-driven flow uses — so a bound _ext.c is byte-identical to a scaffolded one.

Current scope: the simple processor shape — a state struct with scalar fields, a <comp>_create() taking those fields in order, and a scalar-in / scalar-out inline step(). If the header doesn't match that shape the parser raises an error before touching any files.

--check as a CI gate: run jm bind <comp> --check in CI to ensure the committed _ext.c never silently drifts from the header it was generated from. Green means byte-identical; non-zero exit means regenerate and commit.

Shapes not yet supported (see roadmap): methods, init_params, opaque state, variable-output, result-structs.

Flag Description
--check Diff the synthesised binding against the file on disk; exit 1 if they differ.

just-makeit status

Show which files in the project tree have drifted from what jm apply would generate — a read-only drift report. Must be run from the project root.

just-makeit status

Prints a table of files with one of three states:

Status Meaning
OK File matches what the manifest would generate.
MISSING File is declared in the manifest but does not exist on disk.
STALE File exists but differs from the manifest-generated content.

status never writes anything; it is always safe to run. Use it to confirm that jm apply is a no-op before a release, or to see what changed after a manual edit to just-makeit.toml.


just-makeit script

Print a shell script to stdout that fully reconstructs the current project from scratch via CLI commands. Must be run from the project root.

just-makeit script              # print to stdout
just-makeit script > rebuild.sh # save to file

Reads just-makeit.toml and emits one command per scaffold step in the correct order: newmoduleobjectmethodpropertyfunction. The output is a valid shell script that, when run from the parent directory, produces an identical just-makeit.toml.

Note: --impl / --replace are not stored in just-makeit.toml (the lifted body is patched directly into the generated files), so they are not reproduced. Implemented function and step bodies are preserved in your C source files and are unaffected.

Example

Given a project with two objects, just-makeit.toml looks like:

[project]
name = "dsp_toolkit"
version = "0.1.0"
build = "cmake"

[gain]
arg_type = "float"
return_type = "float"

[[gain.state]]
name = "gain"
type = "float"
default = "1.0"

[ema]
arg_type = "float"
return_type = "float"

[[ema.state]]
name = "alpha"
type = "double"
default = "0.1"

[[ema.state]]
name = "prev"
type = "float"
default = "0.0"

just-makeit script produces:

#!/usr/bin/env sh
# Reconstructed from just-makeit.toml

just-makeit new dsp_toolkit
cd dsp_toolkit

just-makeit object gain \
    --state gain:float:1.0 \
    --arg-type float
just-makeit object ema \
    --state alpha:double:0.1 \
    --state prev:float:0.0 \
    --arg-type float

Running that script from the parent directory recreates the project structure and an identical just-makeit.toml.