Skip to content


Folders and files

Last commit message
Last commit date

Latest commit



59 Commits

Repository files navigation


Run C/C++ scripts, just like you would do with Python, Ruby etc.

Build Status


  1. My C script, test.c:

    #!/usr/bin/env crun
    /* -Wall -O3 */
    #include <stdio.h>
    int main(int argc, char *argv[]) {
        printf("Hello, world %s!", argv[1]);
        return 0;

    Note: We added a shebang on the 1st line! (#!/usr/bin/env crun)
    Note: We added flags to be used in compilation in 2nd line! (-Wall -O3)

  2. Make it executable

    $ chmod +x test.c
  3. Run it

    $ ./test.c Koninchwa

    Note: We can pass arguments to the script! (Koninchwa)


I just love C! (and why not?!) Okay! This allows me to write more C code for day-to-day tasks, not just when you want to speed up some component of an application. It makes C more practical for use. Also, it is really handy when you are learning C/C++; everything important is contained in the single file.

The first time you invoke a crun script, it is compiled using cc (for C files with extension .c) or g++ (for CPP files with extensions other than .c) in the directory holding the script, stored away in /tmp/crun and run immediately. Subsequent invocations will run the compiled executable, rather than re-compile, unless the source file has been modified (in which case we compile!).

If you may want to change the directory where the executables are stored, you can use the ${CRUN_CACHE_DIR} variable. This is useful if you wish to cache executables across restarts. If no directory exists at ${CRUN_CACHE_DIR} yet, it will be created using mkdir -p. Make sure crun has permissions to write to the directory.

If you have compilation flags that you need to be passed to cc/g++, you place them in the 2nd line separately, inside a comment using /* and */. For example,

/* -Wall -O3 */

Note: While you can start your code in the 2nd line, it is advisable you avoid doing so since crun, in the case the 2nd line contains /* and */, will assume it's being fed compilation flags. This may lead to some weird compilation errors!


By default, bash expressions in the string holding the flags are not are evaluated. This is a neat feature but I do understand it adds a new edge in the attack graph. You will need to explicitly enable this feature, using the environment variable ${CRUN_DO_EVAL} or the command-line argument --do-eval. If enabled, a string such as /* $(pkg-config --libs libuv) */ for the compilation flags will be evaluated. So,

$ export CRUN_DO_EVAL=1  # you could place this in your ~/.bashrc (or equivalent)

# OR

$ crun --do-eval filename.c

Note: Do not run scripts you do not trust, even if eval is disabled! Always remember, no system/application can ever be 100% secure!

To allow maximum efficiency, you can create a quick template of a script using:

$ crun --create my_script

This will create an executable crun script that you can edit to add the meat.

In some cases, you want the script re-compiled, maybe you've modified some library files. To bypass the cache:

$ crun --force-compile my_script

Sometimes, you may want to debug your script with gdb, or you just want to skip running the compiled executable:

$ crun --just-compile my_script

Since --just-compile will make crun not run your executable, any arguments passed will be considered to be more compilation flags to use. It also echo's back the path to the compiled executable. So you could do something like:

$ gdb `crun --just-compile script.c -Wall -g`
$ valgrind --leak-check=yes `crun --just-compile script.c -Wall -g` arg1 arg2


It's simple!

  1. Download
  2. Rename it to crun
  3. Place it in a directory in your $PATH.

For example,

$ cd ~/bin/
$ wget
$ mv crun


# Run tests.
make test

# Clean up after tests.
make clean



The MIT License (MIT)

Copyright (c) 2015-2016 GochoMugo