CJIT runs C the way a shell script runs Python, with TinyCC doing the compiling
Tiny and portable C compiler
At a glance
- What is it?
- CJIT is a TinyCC-powered C runner and compiler frontend that can execute a C file straight from memory, compile it to an object, or link an executable without running it. It is deliberately not a tracing JIT, and the README says so before you build one.
- Who is it for?
- Adopt CJIT if you want to treat C as a scripting language during development, or if you need a tiny C toolchain for a deployment where a full compiler does not belong. Do not adopt it expecting a JIT that gets faster as it runs, because the README is explicit that it does not interpret first and optimise hot paths later, and do not expect the system-libtcc build to support the in-memory and embedded-asset routes, which the README says it cannot execute.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 40 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 October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A C runner built on TinyCC, not a virtual machine
CJIT is described as a TinyCC-powered C runner and lightweight compiler frontend, and the homepage is dyne.org/cjit.
The TinyCC part is the whole mechanism. TinyCC is a small C compiler that compiles quickly, and CJIT uses it to compile C often in memory and execute the result immediately. So when you run a C file through CJIT, a real compiler runs, produces machine code and the code executes. Nothing is interpreted.
The README has a section titled What CJIT Is Not, and it is the first thing worth reading. CJIT is not a tracing or adaptive JIT in the VM sense, it does not interpret first and optimize hot paths later.
That is a rare thing to find stated plainly, because the name invites the opposite assumption. A reader looking for a tracing JIT will not find one here, and the project says so in the first lines rather than leaving you to infer it from the behaviour.
The stated design goal is fast iteration, scripting-style execution, and small deployment footprints. The first two are about the developer experience, and the third is about shipping: a tool that compiles C with TinyCC and can run it from memory is a candidate for a device where a full compiler and its runtime would be unwelcome.
The primary language of the repository is C, and it is maintained by the Dyne.org foundation with Jaromil credited as designer, writer and maintainer. The last push was on 2026-09-13, and the recent releases v1.1.3, v1.1.4 and v1.2.0 all landed on 2026-09-12 and 2026-09-13, so the project is moving quickly at a small version number.
Five modes, and the difference between running and building
The capability list is short enough to enumerate, and each entry maps onto a distinct invocation.
It can compile and execute one or more C inputs directly from memory. It can compile one source file to an object. It can build an executable without running it. It can inspect runtime configuration and extract bundled runtime assets. And it can extract tar.gz archives, or use cjit-ar or cjit -ar for archive operations.
The basic usage section gives each one a command. Running a single source file is the plainest form.
./cjit hello.cCompiling one source file to an object is the same tool with a flag.
./cjit -c hello.cAnd building an executable without running it names the output.
./cjit -o hello hello.cThe third is the interesting one for deployment, because it separates the compile step from the run step without asking you to install a compiler on the target. The object mode sits between them, which is what you want when you are linking against something else.
The quick start also shows that you can mix C sources and dynamic libraries in one invocation, which is the case where the in-memory compilation earns its keep.
./cjit.exe mysource.c mylib.dllThat example is from the README and it is Windows flavoured, so the .dll is the giveaway, but the shape of the command is the same everywhere.
Arguments after the separator, and the runtime inspection flags
Two behaviours are worth pinning down before you write a script around CJIT.
The first is how arguments reach the compiled program. The README gives the form with a double dash separator.
./cjit app.c -- --name cjit --verboseEverything after the separator belongs to the program CJIT just compiled, and everything before it belongs to CJIT. Without that separator there would be no way to pass a flag that CJIT also understands, and the ambiguity would be resolved by whoever happened to claim the flag first. It is a small design decision and it is the kind that saves an afternoon when your program takes a -v of its own.
The second is the runtime side. The version and configuration flag is a single letter.
./cjit -vAnd then there are the two extraction flags, one for the runtime assets CJIT carries and one for tar.gz archives.
./cjit --xass /tmp/cjit-assets
./cjit --xtgz bundle.tar.gzThe --xass form takes a destination directory and writes CJIT's own bundled assets there, which is what you want when you are packaging something that needs the runtime on the other end. The --xtgz form extracts a tar.gz archive, and the README notes the same archive work is available through a separate cjit-ar tool or through cjit with the -ar option, so the archive path is a first class part of the tool rather than an afterthought.
Taken together, the asset extraction mode and the in-memory compilation mode are the two features that make CJIT interesting for a deployment, and they are also the two that the system-libtcc build cannot do, which is where the build constraints come in.
Getting it, and the one-liner that installs the demo
The quick start says to download the latest CJIT release for your system from the GitHub releases page, then launch it from a terminal. There is no package manager entry in the README and no build required for the ordinary case.
There is also a demo package with running examples, and the README gives a one-liner per platform family. On Windows it is a PowerShell download string.
iex ((New-Object System.Net.WebClient).DownloadString('https://dyne.org/cjit/demo'))On Apple and GNU/Linux it is a curl into bash.
curl -sL https://dyne.org/cjit/demo.sh | bashBoth forms fetch and execute a script from the network in one line, which is convenient and is the kind of command that is worth reading before you run it rather than after. If you prefer to see what it does, the script is fetched at that URL and can be inspected first.
Documentation sits alongside the code. There is a CJIT tutorial at dyne.org/docs/cjit, a Frequently Asked Questions page, and a manpage. The manpage is installed on UNIX systems, so once CJIT is on your path you can read man cjit, and it is also published online.
The README's own advice is to take a tour with the tutorial, and given that the README covers the common invocations rather than the full option set, the manpage is where the details are.
Building it: the bundled Linux build and the system-libtcc one
The build section is where the constraints appear, and it separates two builds that are not equivalent.
The bundled Linux build used by maintainers is two commands.
make linux CC=clang
make checkThe second one, make check, is broader than it sounds. The README says make check-ci omits the Linux dmon smoke test while make check includes it for a Linux target, and that make check-unit runs deterministic C units while the Bats suites exercise public CLI and platform behavior. So there are two test layers, a C-level unit layer and a Bats layer that drives the command line as a user would.
The other build route is the one with real limits. A system-libtcc build uses make meson and requires the distribution tcc, libtcc-dev, Meson and Ninja packages. Then the README states the consequence: it cannot execute the in-memory and embedded-asset routes that the bundled build supports.
That is the single most important fact for an evaluator, because the in-memory compilation and the asset extraction are the features that make CJIT interesting. If you build against your distribution's TinyCC, you lose them.
Two more build targets exist for the maintainer workflow. make coverage CC=clang writes the maintained Linux coverage summary to coverage/maintained.txt, and make debug-asan CC=clang builds the sanitizer variant. The presence of a maintained coverage summary file rather than a generic one suggests the coverage tooling is expected to be run on a specific subset rather than the whole tree.
The repository layout backs this up: a GNUmakefile at the top level, LICENSES/ and REUSE.toml for the licence metadata, build/, src/, lib/, examples/, test/ and docs/ directories, and an AGENTS.md at the root.
Where CJIT is the wrong tool
Three cases, and the first is the one the README warns about in its own section heading.
If you want a program that gets faster the longer it runs, CJIT is not that. It is not a tracing or adaptive JIT in the VM sense and it does not interpret first and optimise hot paths later. Every run compiles from source through TinyCC and executes the resulting machine code. For a long-running numeric program where a real JIT would amortise its compilation cost, CJIT pays the compile cost every time, and the trade the project optimises for is development iteration rather than steady-state throughput. The examples in the repository, dmon, donut, flappy, life, a frei0r generator, nuklear and raylib maze, are small programs where the compile cost is not the point.
The second is a production toolchain requirement. If you need a system package manager to install CJIT, or a compiler that produces optimised code for a specific architecture, or reproducible builds with a supported toolchain, TinyCC is not the answer and CJIT is a layer on top of a compiler you already have.
The third is the system-libtcc build again, from the other direction. If your distribution policy forbids bundling a compiler and requires you to use the packaged TinyCC, then the features that distinguish CJIT from a plain TinyCC invocation, in-memory compilation and bundled asset extraction, are exactly the ones you lose. In that case you are left with a frontend that compiles to an object and runs the result, which is useful but not what the project is for.
One more practical note. The README lists the example files at the top of the repository, and several of them depend on external libraries, raylib, SDL2, miniaudio, frei0r, nuklear and termbox2. Building those examples needs those libraries present, so the first build of the examples directory is more work than the two-line build of CJIT itself.
Licensing, where the two components differ
The licensing is split across the components and the README is explicit about it, which matters if you intend to ship something built with CJIT.
CJIT is copyright (C) 2024-2026 by the Dyne.org foundation, designed, written and maintained by Jaromil. The README states the project is free and open source under the GNU General Public License v3.
The TinyCC core component is copyright (C) 2001-2004 by Fabrice Bellard, and TinyCC is also free and open source, under the GNU Lesser General Public License.
So the frontend is GPLv3 and the compiler underneath it is LGPL. That combination is the usual arrangement for a tool that links to a permissively licensed library, but GPLv3 is copyleft and its obligations attach to distribution of the combined work, so anyone planning to embed CJIT in a product should read the licensing section of the manpage, which the README links as more information on CJIT licensing. That is a matter for your own counsel rather than advice from this article.
The repository has a LICENSES/ directory and a REUSE.toml file at the top level, which is the REUSE specification for licence metadata across a tree with mixed licences, and it is a good sign for a project that bundles code from more than one copyright holder.
On maintenance, the release cadence has been fast recently, with three tagged versions on 2026-09-12 and 2026-09-13 and a last push on 2026-09-13. The project is at version 1.2.0, the release process is driven by a .releaserc file, and the CI lives in a .github/ directory.
Editorial conclusion
Adopt CJIT if you want to treat C as a scripting language during development, or if you need a tiny C toolchain for a deployment where a full compiler does not belong. Do not adopt it expecting a JIT that gets faster as it runs, because the README is explicit that it does not interpret first and optimise hot paths later, and do not expect the system-libtcc build to support the in-memory and embedded-asset routes, which the README says it cannot execute. Verify first that your target has the bundled build available, and read the manpage for the option list because the README only covers the common cases.
Frequently asked questions
What is CJIT?
CJIT is a TinyCC-powered C runner and lightweight compiler frontend from the Dyne.org foundation. It compiles C with TinyCC, often in memory, and executes the result immediately.
Is CJIT a tracing or adaptive JIT?
No. The README has a section titled What CJIT Is Not and states that CJIT is not a tracing or adaptive JIT in the VM sense and does not interpret first and optimize hot paths later.
How do I pass arguments to a program compiled with CJIT?
Use a double dash separator, so ./cjit app.c -- --name cjit --verbose. Everything before the separator is a CJIT option and everything after it goes to the compiled program.
How do I build CJIT from source on Linux?
Run make linux CC=clang followed by make check. A system-libtcc build instead uses make meson and requires tcc, libtcc-dev, Meson and Ninja, but that build cannot execute the in-memory and embedded-asset routes the bundled build supports.
What licence does CJIT use?
CJIT is free and open source under the GNU General Public License v3, copyright 2024-2026 by the Dyne.org foundation. The TinyCC core component it uses is under the GNU Lesser General Public License, and the manpage links to more detail on licensing.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dyne-cjit)Was this useful?