skills/bun-runtime-c-compiler/SKILL.md
Compile and run C from JavaScript with low overhead
npx skillsauth add jarle/bun-skills Bun C CompilerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Compile and run C from JavaScript with low overhead
bun:ffi has experimental support for compiling and running C from JavaScript with low overhead.
bun:ffi)See the introduction blog post for more information.
JavaScript:
import { cc } from "bun:ffi";
import source from "./hello.c" with { type: "file" };
const {
symbols: { hello },
} = cc({
source,
symbols: {
hello: {
args: [],
returns: "int",
},
},
});
console.log("What is the answer to the universe?", hello());
C source:
int hello() {
return 42;
}
When you run hello.js, it will print:
bun hello.js
What is the answer to the universe? 42
Under the hood, cc uses TinyCC to compile the C code and then link it with the JavaScript runtime, efficiently converting types in-place.
The same FFIType values in dlopen are supported in cc.
| FFIType | C Type | Aliases |
| ----------- | -------------- | --------------------------- |
| cstring | char* | |
| function | (void*)(*)() | fn, callback |
| ptr | void* | pointer, void*, char* |
| i8 | int8_t | int8_t |
| i16 | int16_t | int16_t |
| i32 | int32_t | int32_t, int |
| i64 | int64_t | int64_t |
| i64_fast | int64_t | |
| u8 | uint8_t | uint8_t |
| u16 | uint16_t | uint16_t |
| u32 | uint32_t | uint32_t |
| u64 | uint64_t | uint64_t |
| u64_fast | uint64_t | |
| f32 | float | float |
| f64 | double | double |
| bool | bool | |
| char | char | |
| napi_env | napi_env | |
| napi_value | napi_value | |
To make it easier to work with strings, objects, and other non-primitive types that don't map 1:1 to C types, cc supports N-API.
To pass or receive a JavaScript values without any type conversions from a C function, you can use napi_value.
You can also pass a napi_env to receive the N-API environment used to call the JavaScript function.
For example, if you have a string in C, you can return it to JavaScript like this:
import { cc } from "bun:ffi";
import source from "./hello.c" with { type: "file" };
const {
symbols: { hello },
} = cc({
source,
symbols: {
hello: {
args: ["napi_env"],
returns: "napi_value",
},
},
});
const result = hello();
And in C:
#include <node/node_api.h>
napi_value hello(napi_env env) {
napi_value result;
napi_create_string_utf8(env, "Hello, Napi!", NAPI_AUTO_LENGTH, &result);
return result;
}
You can also use this to return other types like objects and arrays:
#include <node/node_api.h>
napi_value hello(napi_env env) {
napi_value result;
napi_create_object(env, &result);
return result;
}
cc Referencelibrary: string[]The library array is used to specify the libraries that should be linked with the C code.
type Library = string[];
cc({
source: "hello.c",
library: ["sqlite3"],
});
symbolsThe symbols object is used to specify the functions and variables that should be exposed to JavaScript.
type Symbols = {
[key: string]: {
args: FFIType[];
returns: FFIType;
};
};
sourceThe source is a file path to the C code that should be compiled and linked with the JavaScript runtime.
type Source = string | URL | BunFile;
cc({
source: "hello.c",
symbols: {
hello: {
args: [],
returns: "int",
},
},
});
flags: string | string[]The flags is an optional array of strings that should be passed to the TinyCC compiler.
type Flags = string | string[];
These are flags like -I for include directories and -D for preprocessor definitions.
define: Record<string, string>The define is an optional object that should be passed to the TinyCC compiler.
type Defines = Record<string, string>;
cc({
source: "hello.c",
define: {
NDEBUG: "1",
},
});
These are preprocessor definitions passed to the TinyCC compiler.
development
Using TypeScript with Bun, including type definitions and compiler options
development
Learn how to write tests using Bun's Jest-compatible API with support for async tests, timeouts, and various test modifiers
testing
Learn how to use snapshot testing in Bun to save and compare output between test runs
testing
Learn about Bun test's runtime integration, environment variables, timeouts, and error handling