CactusCactus

Quickstart

Install Cactus and run your first on-device AI model

Installation

npm install cactus-react-native react-native-nitro-modules

Clone and set up the Cactus repository:

git clone https://github.com/cactus-compute/cactus && cd cactus && git checkout v1.7 && source ./setup

Build the Flutter bindings:

cactus build --flutter

Output files:

FilePlatform
libcactus.soAndroid (arm64-v8a)
cactus-ios.xcframeworkiOS
cactus-macos.xcframeworkmacOS

Clone and set up the Cactus repository:

git clone https://github.com/cactus-compute/cactus && cd cactus && git checkout v1.7 && source ./setup

Build the Android bindings:

cactus build --android

Build output: android/build/lib/libcactus.so

brew install cactus-compute/cactus/cactus

macOS:

git clone https://github.com/cactus-compute/cactus && cd cactus && source ./setup

Linux:

sudo apt-get install python3 python3-venv python3-pip cmake build-essential libcurl4-openssl-dev
git clone https://github.com/cactus-compute/cactus && cd cactus && source ./setup

Include the Cactus header in your project:

#include <cactus.h>

Build instructions are available in the Cactus repository.

Platform Integration

Android

Copy libcactus.so to android/app/src/main/jniLibs/arm64-v8a/

Copy cactus.dart to your lib/ folder

iOS

Copy cactus-ios.xcframework to your ios/ folder

Open ios/Runner.xcworkspace in Xcode

Drag the xcframework into the project

In Runner target > General > "Frameworks, Libraries, and Embedded Content", set to "Embed & Sign"

Copy cactus.dart to your lib/ folder

macOS

Copy cactus-macos.xcframework to your macos/ folder

Open macos/Runner.xcworkspace in Xcode

Drag the xcframework into the project

In Runner target > General > "Frameworks, Libraries, and Embedded Content", set to "Embed & Sign"

Copy cactus.dart to your lib/ folder

  1. Copy libcactus.so to app/src/main/jniLibs/arm64-v8a/
  2. Copy Cactus.kt to app/src/main/java/com/cactus/

Source files:

FileCopy to
Cactus.common.ktshared/src/commonMain/kotlin/com/cactus/
Cactus.android.ktshared/src/androidMain/kotlin/com/cactus/
Cactus.ios.ktshared/src/iosMain/kotlin/com/cactus/
cactus.defshared/src/nativeInterop/cinterop/

Binary files:

PlatformLocation
Androidlibcactus.soapp/src/main/jniLibs/arm64-v8a/
iOSlibcactus-device.a → link via cinterop

Configure build.gradle.kts:

kotlin {
    androidTarget()

    listOf(iosArm64(), iosSimulatorArm64()).forEach {
        it.compilations.getByName("main") {
            cinterops {
                create("cactus") {
                    defFile("src/nativeInterop/cinterop/cactus.def")
                    includeDirs("/path/to/cactus/ffi")
                }
            }
        }
        it.binaries.framework {
            linkerOpts("-L/path/to/apple", "-lcactus-device")
        }
    }

    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
        }
    }
}

Your First Completion

import { useCactusLM } from 'cactus-react-native';

const App = () => {
  const cactusLM = useCactusLM();

  useEffect(() => {
    if (!cactusLM.isDownloaded) {
      cactusLM.download();
    }
  }, []);

  const handleGenerate = () => {
    cactusLM.complete({
      messages: [{ role: 'user', content: 'What is the capital of France?' }],
    });
  };

  if (cactusLM.isDownloading) {
    return <Text>Downloading: {Math.round(cactusLM.downloadProgress * 100)}%</Text>;
  }

  return (
    <>
      <Button onPress={handleGenerate} title="Generate" />
      <Text>{cactusLM.completion}</Text>
    </>
  );
};
import 'cactus.dart';

final model = Cactus.create('/path/to/model.gguf');
final result = model.complete('What is the capital of France?');
print(result.text);
model.dispose();
import com.cactus.*

val model = Cactus.create("/path/to/model")
val result = model.complete("What is the capital of France?")
println(result.text)
model.close()
# Download and run LiquidAI's LFM2-350M
cactus run LiquidAI/LFM2-350M

# Or use a specific model
cactus run google/gemma-3-270m-it
#include <cactus.h>

// Initialize model
cactus_model_t model = cactus_init(
    "path/to/weight/folder",
    "path/to/rag/documents", // optional: for auto-RAG
);

// Prepare messages
const char* messages = R"([
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "What is the capital of France?"}
])";

// Generate response
char response[4096];
int result = cactus_complete(
    model,           // model handle
    messages,        // chat messages (JSON array)
    response,        // output buffer
    sizeof(response),// buffer size
    nullptr,         // generation options
    nullptr,         // tools for function calling
    nullptr,         // streaming callback
    nullptr          // user data for callback
);

Supported Models

v1.7 includes support for:

  • LLMs: Gemma-3, LiquidAI LFM2/LFM2.5, Qwen3 (with completion, tools, embeddings)
  • Vision: LFM2-VL, LFM2.5-VL (with Apple NPU support)
  • Transcription: Whisper (Small/Medium with Apple NPU), Moonshine-Base
  • VAD: Silero VAD for voice activity detection
  • Embeddings: Nomic-Embed, Qwen3-Embedding

See the Models dashboard for the complete list.

Next Steps