Installation
The C! compiler (cb) can be installed on macOS, Linux, and Windows. Choose the method that works best for you.
Quick Install (Recommended)
Run the install script to get the latest stable version:
# macOS / Linux curl -fsSL https://c-bang.integsec.com/install.sh | sh # Windows (PowerShell) irm https://c-bang.integsec.com/install.ps1 | iex
Build from Source
If you prefer to build from source or want to contribute to the compiler:
git clone https://github.com/integsec/C-Bang.git cd c-bang make install
Verify Installation
cb --version # C! compiler v0.1.0 (c-bang 2025)
Your First Project
Create a new C! project using the cb init command:
cb init my-project cd my-project
This creates a project with the following structure:
my-project/ cb.toml # Project configuration src/ main.cb # Entry point tests/ main_test.cb
Hello, World!
Open src/main.cb and you will see the generated starter code:
#[intent("Application entry point")] fn main() { println("Hello, C! world!") }
Build and run it:
cb run # Hello, C! world!
Variables & Types
C! uses let for immutable bindings and let mut for mutable ones. Types are inferred but can be annotated explicitly.
// Immutable binding (default) let name = "Alice" let age: u32 = 30 // Mutable binding let mut counter = 0 counter += 1 // Refined types with constraints let port: u16{range: 1024..65535} = 8080 // Sum types let result: Result<String, Error> = Ok("success")
No null, ever. C! has no null or nil value. Use Option<T> (which is Some(T) | None) when a value might be absent. The compiler enforces you handle both cases.
Functions
Functions are defined with fn. Parameters have explicit types, and the return type follows the -> arrow.
#[intent("Calculate the area of a rectangle")] #[pre(width > 0 && height > 0)] #[post(result == width * height)] fn area(width: f64, height: f64) -> f64 { width * height } // Generic functions fn first<T>(items: Vec<T>) -> Option<T> { match items.len() { 0 => None, _ => Some(items[0]), } }
Ownership & Linear Types
This is the most important concept in C!. Every value has an ownership qualifier that determines how it can be used:
| Qualifier | Meaning | Use count |
|---|---|---|
own |
Linear ownership — value is consumed on use | Exactly once |
borrow |
Affine — can be used at most once, safe to drop | At most once |
& |
Shared immutable reference | Unlimited reads |
&mut |
Exclusive mutable reference | One writer, no readers |
// 'own' means this function consumes the file handle fn close_file(f: own File) { f.flush(); f.close(); // f is consumed } fn example() { let file = open("data.txt"); close_file(file); // file can no longer be used here // file.read() <-- COMPILE ERROR }
Why this matters: Linear types eliminate entire vulnerability classes. Use-after-free? Impossible — the compiler won't let you use a consumed value. Resource leak? Impossible — the compiler won't let you forget to use a linear value. Double-spend? Impossible — you literally cannot use a token twice.
Intent Annotations
Intent annotations describe what your code should do. They serve two purposes: AI readability and formal verification.
#[intent("Sort a list of numbers in ascending order")] #[post(result.is_sorted())] #[post(result.len() == input.len())] fn sort(input: Vec<i64>) -> Vec<i64> { // AI can generate the implementation // Compiler verifies it satisfies the postconditions input.merge_sort() }
Available annotation types:
#[intent("...")]— Natural-language description of purpose#[pre(condition)]— Precondition that must hold before execution#[post(condition)]— Postcondition that must hold after execution#[invariant(condition)]— Condition that must hold throughout execution
Building & Running
The cb command-line tool handles building, running, and testing:
# Build for native target cb build # Build and run cb run # Run tests cb test # Build for WebAssembly cb build --target wasm # Build smart contract cb build --target evm # Format code cb fmt # Check without building cb check
Next Steps
Now that you have the basics, explore these resources to deepen your understanding: