Skip to content

Getting Started

By the end of this guide you will have a SLIM node running locally and an application connected to it, ready to start exchanging messages.

Time to complete: ~5 minutes

Prerequisites

  • macOS, Linux, or Windows
  • One of: Python 3.9+, Go 1.21+, Java 17+, Kotlin, Node.js 18+, .NET 6+

Step 1: Install slimctl

slimctl is the quickest way to start a local SLIM node. Install it for your platform:

brew tap agntcy/slim https://github.com/agntcy/slim.git
brew install slimctl
curl -LO https://github.com/agntcy/slim/releases/download/slimctl-v2.0.0/slimctl-darwin-arm64.tar.gz
tar -xzf slimctl-darwin-arm64.tar.gz
sudo mv slimctl /usr/local/bin/

Gatekeeper

If macOS blocks the binary, run:

sudo xattr -rd com.apple.quarantine /usr/local/bin/slimctl

curl -LO https://github.com/agntcy/slim/releases/download/slimctl-v2.0.0/slimctl-darwin-amd64.tar.gz
tar -xzf slimctl-darwin-amd64.tar.gz
sudo mv slimctl /usr/local/bin/

Gatekeeper

If macOS blocks the binary, run:

sudo xattr -rd com.apple.quarantine /usr/local/bin/slimctl

curl -LO https://github.com/agntcy/slim/releases/download/slimctl-v2.0.0/slimctl-linux-amd64-gnu.tar.gz
tar -xzf slimctl-linux-amd64-gnu.tar.gz
sudo mv slimctl /usr/local/bin/
curl -LO https://github.com/agntcy/slim/releases/download/slimctl-v2.0.0/slimctl-linux-arm64-gnu.tar.gz
tar -xzf slimctl-linux-arm64-gnu.tar.gz
sudo mv slimctl /usr/local/bin/

Download the binary from the GitHub releases page and add it to your PATH. See CLI Installation for full Windows instructions.

Verify the install:

slimctl help

See CLI Installation for build-from-source instructions.

Step 2: Start a SLIM node

slimctl slim start

This starts a SLIM node on 127.0.0.1:46357 with insecure (no TLS) defaults. The node runs in the foreground — press Ctrl-C to stop it.

Step 3: Install the SDK

Install the SLIM bindings for your language:

pip install slim-bindings
go get github.com/agntcy/slim-bindings-go@v2.0.0
# Run the setup tool to download the native library
go run github.com/agntcy/slim-bindings-go/cmd/slim-bindings-setup
// build.gradle.kts
dependencies {
    implementation("io.agntcy.slim:slim-bindings-java:2.0.0")
}
// build.gradle.kts
dependencies {
    implementation("io.agntcy.slim:slim-bindings-kotlin:2.0.0")
}
npm install @agntcy/slim-bindings
dotnet add package Agntcy.Slim
npm install @agntcy/slim-bindings-react-native

See SDK Installation for full per-language setup details.

Step 4: Connect your first app

With the node running, initialise the SLIM service, connect, and register an application identity:

use slim_service::Service;
use slim_service::config::ClientConfig;
use slim_auth::shared_secret::SharedSecret;
use slim_datapath::api::ProtoName;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let service = Service::builder().build("slim/0")?;
    service.run().await?;
    let conn_id = service.connect(ClientConfig::with_endpoint("http://127.0.0.1:46357")).await?;

    let name = ProtoName::from_strings(["myorg", "default", "my-service"]);
    let provider = SharedSecret::new("myorg/default/my-service", "change-me-before-going-to-production")?;
    let verifier = SharedSecret::new("myorg/default/my-service", "change-me-before-going-to-production")?;

    let (app, _rx) = service.create_app(&name, provider, verifier)?;
    app.subscribe(&name, Some(conn_id)).await?;

    println!("App ready: myorg/default/my-service");
    // app and conn_id are passed to create_session in the next tutorial

    Ok(())
}
import asyncio
import slim_bindings

async def main():
    slim_bindings.uniffi_set_event_loop(asyncio.get_running_loop())
    slim_bindings.initialize_with_defaults()

    service = slim_bindings.get_global_service()

    client_config = slim_bindings.new_insecure_client_config("http://127.0.0.1:46357")
    conn_id = await service.connect_async(client_config)

    local_name = slim_bindings.Name("myorg", "default", "my-service")
    local_app = service.create_app_with_secret(local_name, "change-me-before-going-to-production")
    await local_app.subscribe_async(local_name, conn_id)

    print(f"App ready: {local_name}, id={local_app.id()}")
    # local_app and conn_id are passed to create_session in the next tutorial

asyncio.run(main())
package main

import (
    "fmt"
    "log"

    slim "github.com/agntcy/slim-bindings-go/v2"
)

func main() {
    slim.InitializeWithDefaults()

    config := slim.NewInsecureClientConfig("http://127.0.0.1:46357")
    connID, err := slim.GetGlobalService().ConnectAsync(config)
    if err != nil {
        log.Fatal(err)
    }

    appName, err := slim.NameFromString("myorg/default/my-service")
    if err != nil {
        log.Fatal(err)
    }

    app, err := slim.GetGlobalService().CreateAppWithSecret(appName, "change-me-before-going-to-production")
    if err != nil {
        log.Fatal(err)
    }
    defer app.Destroy()

    if err := app.SubscribeAsync(app.Name(), &connID); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("App ready: %s, id=%s\n", appName, app.Id())
    // app and connID are passed to create_session in the next tutorial
}
import io.agntcy.slim.bindings.*;

public class Main {
    public static void main(String[] args) {
        SlimBindings.initializeWithDefaults();
        Service service = SlimBindings.getGlobalService();

        ClientConfig config = SlimBindings.newInsecureClientConfig("http://127.0.0.1:46357");
        Long connId = service.connect(config);

        Name localName = Name.fromString("myorg/default/my-service");
        App app = service.createAppWithSecret(localName, "change-me-before-going-to-production");
        app.subscribe(app.name(), connId);

        System.out.println("App ready: " + localName + ", id=" + app.id());
        // app and connId are passed to create_session in the next tutorial
    }
}
import io.agntcy.slim.bindings.*

fun main() {
    initializeWithDefaults()
    val service = getGlobalService()

    val clientConfig = newInsecureClientConfig("http://127.0.0.1:46357")
    val connId: ULong = service.connectAsync(clientConfig)

    val localName = Name.fromString("myorg/default/my-service")
    val localApp = service.createAppWithSecret(localName, "change-me-before-going-to-production")
    localApp.subscribeAsync(localName, connId)

    println("App ready: $localName, id=${localApp.id()}")
    // localApp and connId are passed to create_session in the next tutorial
}
import slimBindings from '@agntcy/slim-bindings';

async function main() {
    slimBindings.initializeWithDefaults();
    const service = slimBindings.getGlobalService();

    const config = slimBindings.newInsecureClientConfig("http://127.0.0.1:46357");
    const connId = await service.connectAsync(config);

    const localName = new slimBindings.Name("myorg", "default", "my-service");
    const app = service.createAppWithSecret(localName, "change-me-before-going-to-production");
    await app.subscribeAsync(localName, BigInt(connId));

    console.log(`App ready: ${localName}, id=${app.id()}`);
    // app and connId are passed to create_session in the next tutorial
}

main();
using Agntcy.Slim;

Slim.Initialize();

var connId = Slim.Connect("http://127.0.0.1:46357");

using var localName = SlimName.Parse("myorg/default/my-service");
using var service = Slim.GetGlobalService();
var app = service.CreateApp(localName, "change-me-before-going-to-production");
app.Subscribe(app.Name, connId);

Console.WriteLine($"App ready: {app.Name}, id={app.Id}");
// app and connId are passed to CreateSession in the next tutorial
import slimBindings from '@agntcy/slim-bindings-react-native';

await slimBindings.waitForJSIBindings(5000);
slimBindings.initializeWithDefaults();
const service = slimBindings.getGlobalService();

const config = slimBindings.newInsecureClientConfig("http://192.168.1.x:46357");
const connId = service.connect(config);

const localName = new slimBindings.Name("myorg", "default", "my-service");
const app = service.createAppWithSecret(localName, "change-me-before-going-to-production");
await app.subscribeAsync(localName, connId);

console.log(`App ready: ${localName}, id=${app.id()}`);
// app and connId are passed to createSession in the next tutorial

Insecure mode

new_insecure_client_config skips TLS and is for local development only. See Authentication for production TLS, mTLS, and SPIRE options.

Next Steps

You have a running SLIM node and a connected application. Continue with the SDK tutorials to start exchanging messages:

Or explore further: