# Quickstart

## AI Coding Skill

Install the Jolt [agent skill](https://vercel.com/docs/agent-resources/skills) to let AI coding agents (Claude Code, Cursor, Codex, etc.) wrap Rust functions in Jolt proofs for you:

```bash
npx skills add a16z/jolt
```

Fallback (Claude Code / Codex):
```bash
curl -sfL jolt.rs/skill | bash
```

## Installing
Start by installing the `jolt` command line tool.
```
cargo install --git https://github.com/a16z/jolt --force --bins jolt
```

## Creating a Project
<!--- Note to maintainers: if these instructions change, please modify
    the `test-sdk` CI job to match.  --->

To create a project, use the `jolt new` command.
```
jolt new <PROJECT_NAME>
```

This will create a template Jolt project in the specified location. Make sure to cd into the project before running the next step.
```
cd <PROJECT_NAME>
```

## Project Tour
The main folder contains the host, which is the code that can generate and verify proofs. Within this main folder, there is another package called `guest` which contains the Rust functions that we can prove from the host. For more information about these concepts refer to the [guests and hosts](./guests_hosts.md) section.

We'll start by taking a look at our guest. We can view the guest code in `guest/src/lib.rs`.

```rust
#![cfg_attr(feature = "guest", no_std)]

#[jolt::provable(heap_size = 32768, max_trace_length = 65536)]
fn fib(n: u32) -> u128 {
    let mut a: u128 = 0;
    let mut b: u128 = 1;
    let mut sum: u128;
    for _ in 1..n {
        sum = a + b;
        a = b;
        b = sum;
    }

    b
}
```

As we can see, this implements a simple Fibonacci function called `fib`. All we need to do to make our function provable is add the `jolt::provable` macro above it. The generated `guest/src/main.rs` contains the `#![no_main]` binary stub that lets Jolt build a RISC-V ELF, while `guest/src/lib.rs` contains the provable functions you edit.

Next let's take a look at the host code in `src/main.rs`.

```rust
use tracing::info;

pub fn main() {
    tracing_subscriber::fmt::init();

    let target_dir = "/tmp/jolt-guest-targets";
    let mut program = guest::compile_fib(target_dir);

    let shared_preprocessing = guest::preprocess_shared_fib(&mut program).unwrap();

    let prover_preprocessing = guest::preprocess_prover_fib(shared_preprocessing.clone());
    let verifier_setup = prover_preprocessing.generators.to_verifier_setup();
    let verifier_preprocessing =
        guest::preprocess_verifier_fib(shared_preprocessing, verifier_setup, None);

    let prove_fib = guest::build_prover_fib(program, prover_preprocessing);
    let verify_fib = guest::build_verifier_fib(verifier_preprocessing);

    let (output, proof, io_device) = prove_fib(50);
    let is_valid = verify_fib(50, output, io_device.panic, proof);

    info!("output: {output}");
    info!("valid: {is_valid}");
}
```

The host uses functions generated by the `jolt::provable` macro. The pipeline has four stages:

1. **Compile** — `compile_fib` compiles the guest to RISC-V.
2. **Preprocess** — `preprocess_shared_fib` produces shared preprocessing, which is then split into prover and verifier preprocessing. This only depends on the program (not inputs) and can be reused across proofs. The last argument to `preprocess_verifier_fib` is `None` for ordinary proofs; ZK proofs pass `Some(blindfold_setup)` instead.
3. **Prove** — `build_prover_fib` returns a closure with the same inputs as the original function. It returns the output, a proof, and an `io_device` (which includes a `panic` flag).
4. **Verify** — `build_verifier_fib` returns a closure that takes the public inputs, claimed output, panic flag, and proof, returning a boolean.

## Running
<!--- Note to maintainers: if these instructions change, please modify
    the `test-sdk` CI job to match.  --->

Let's now run the host with `cargo`.
```
cargo run --release
```

This will compile the guest, perform preprocessing, and execute the host code which proves and verifies the 50th Fibonacci number. Preprocessing only needs to be performed once for a given program, and can be reused to prove multiple invocations.

Note that many logs in the example are logged at the `info` level. To see these logs, you can set the `RUST_LOG` environment variable before running the host:
```
RUST_LOG=info cargo run --release
```

If everything is working correctly, you should see output similar to the following:
```
...
2025-11-05T22:17:43.849979Z  INFO jolt_prover_legacy::zkvm: Proved in 2.6s (0.4 kHz / padded 0.8 kHz)
2025-11-05T22:17:43.923164Z  INFO example: output: 12586269025
2025-11-05T22:17:43.923300Z  INFO example: valid: true
```

## Development

### Rust

To build Jolt from source, you will need Rust:

- `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
- Rustup should automatically install the Rust toolchain and necessary targets on
the first `cargo` invocation.
You may also need to add the RISC-V target for building guest programs manually: `rustup target add riscv64imac-unknown-none-elf`.

### mdBook

To build this book from source:

`cargo install mdbook mdbook-katex`

For watching the changes in your local browser:

`mdbook watch book --open`
