---
title: Rust Program SDK Overview
description: "Build on-chain Thru programs in Rust with the thru-core crate, the
  #[entry] macro, and the RISC-V toolchain."
source_url:
  html: https://thru.org/docs/sdks/rust-program-sdk/overview/
  md: https://thru.org/docs/sdks/rust-program-sdk/overview.md
---

# Rust Program SDK Overview

Use the Rust program SDK when you want to write on-chain Thru programs in `no_std` Rust instead of C. It targets the same Thru VM and the same syscall surface as the [C SDK](https://thru.org/docs/sdks/c.md), with safe wrappers around account access.

For Rust services, CLIs, and backends that talk to a node over gRPC, use the host-side crates in [Rust SDKs Overview](https://thru.org/docs/sdks/rust.md) instead.

## Install

Install the CLI and development prerequisites through [Set Up Thru DevKit](https://thru.org/docs/program-development/setting-up-thru-devkit.md), then install the toolchain and the Rust SDK:

```bash
thru dev toolchain install
thru dev sdk install rust
```

The CLI installs the Rust SDK under `~/.thru/sdk/rust`. Programs compile with `cargo` for the RISC-V target `riscv64imac-unknown-none-elf`, so you also need a Rust toolchain with that target and `cargo-binutils` installed:

```bash
rustup target add riscv64imac-unknown-none-elf
cargo install cargo-binutils
rustup component add llvm-tools
```

## Verify your install

```bash
test -f ~/.thru/sdk/rust/Cargo.toml
test -d ~/.thru/sdk/rust/core
test -d ~/.thru/sdk/rust/macros
rustup target list --installed | grep riscv64imac-unknown-none-elf
```

## Crates

| Crate | What it provides |
| - | - |
| `thru-core` | Account access (`AccountManager`, `AccountRef`), transaction and block context, syscall wrappers, VM pointer helpers, program utilities, and logging/revert macros. |
| `thru-sdk-macros` | The `#[entry]` attribute macro that emits the VM boot shim and the exported `start` symbol. |

Both crates are `no_std`. `thru-core` also re-exports [`heapless`](https://docs.rs/heapless), which the `tvm_println!` macro uses for stack-allocated formatting.

## Minimal program

```rust
#![no_std]
#![no_main]

use thru_core::syscall::sys_emit_event;
use thru_sdk_macros::*;

#[entry(stack_size = 4096)]
fn main(_instr_data: &[u8]) -> Result<u64, u64> {
    let message = b"hello from a Rust Thru program\0";
    unsafe { sys_emit_event(message.as_ptr(), message.len() as u64) };

    Ok(0)
}
```

## Start here

| If you need… | Open this page |
| - | - |
| The shape of a program, entry signatures, and how it exits | [Program Structure](https://thru.org/docs/sdks/rust-program-sdk/program-structure.md) |
| How to read accounts, transaction fields, and block context safely | [Accounts and Transaction Context](https://thru.org/docs/sdks/rust-program-sdk/accounts-and-transaction-context.md) |
| The raw syscall wrappers and their safe `AccountManager` equivalents | [Syscalls](https://thru.org/docs/sdks/rust-program-sdk/syscalls.md) |
| How to invoke another program and delegate authority | [Cross-Program Invocation](https://thru.org/docs/sdks/rust-program-sdk/cross-program-invocation.md) |
| Return codes, reverts, and the error enums | [Error Handling and Return Codes](https://thru.org/docs/sdks/rust-program-sdk/error-handling-and-return-codes.md) |
| Cargo, linker, and make wiring for a downstream project | [Build Integration](https://thru.org/docs/sdks/rust-program-sdk/build-integration.md) |

## Related guides

- [Set Up Thru DevKit](https://thru.org/docs/program-development/setting-up-thru-devkit.md)
- [Cross-program invocation](https://thru.org/docs/program-development/cross-program-invocation.md)
- [VM syscalls overview](https://thru.org/docs/spec/vm/syscalls/overview.md)
- [Runtime overview](https://thru.org/docs/spec/runtime/overview.md)
