# End-to-End Walkthrough: RudderTyper v2 with Rudder CLI


This tutorial shows you how to use [RudderTyper v2]({{< ref "dev-tools/rudder-cli/ruddertyper-v2.md" >}}) via the [Rudder CLI tool]({{< ref "dev-tools/rudder-cli/" >}}) to:

- Generate type-safe TypeScript, Kotlin, or Swift bindings from your Tracking Plans
- Install the generated bindings in your web (JavaScript), Android, JVM, or iOS application
- Customize the generated code with platform-specific options
- Instrument your application using the generated bindings

## Prerequisites

- [Rudder CLI tool]({{< ref "dev-tools/rudder-cli/installation.md" >}}) (`rudder-cli`) installed locally
- A [workspace-level Service Access Token]({{< ref "access-management/service-access-tokens.md#workspace-sat" >}}) or [Personal Access Token]({{< ref "access-management/personal-access-tokens.md" >}}) with read access to the Tracking Plan you want to use
- An existing Tracking Plan in your RudderStack workspace

## 1. Authenticate Rudder CLI

Run the following command and enter your access token when prompted:

```bash
rudder-cli auth login
```

## 2. Identify your Tracking Plan ID

To generate type-safe bindings, first identify the Tracking Plan you want to generate bindings against. Run the following command:

```bash
rudder-cli workspace tracking-plans list
```

The above command displays an interactive table with all available Tracking Plans in your workspace. The output shows a list of Tracking Plans on the left, and selecting a Tracking Plan displays its details on the right, including the plan's name, description, and current version.

Use this information to identify the Tracking Plan you want to use and copy its ID, as highlighted below:

{{< image src="images/dev-tools/ruddertyper-v2/quickstart-1.webp" alt="List of Tracking Plans in your workspace" >}}

{{< tip >}}
Navigate using the arrow keys if you have more Tracking Plans than what can be displayed, and exit the view by pressing the **Escape** key.
{{< /tip >}}

## 3. Generate bindings

Using the Tracking Plan ID, run the following command for your target platform:

{{< tabs tabTotal="3" >}}
{{% tab tabName="TypeScript" %}}
```bash
rudder-cli typer generate --platform=typescript --tracking-plan-id=<TRACKING_PLAN_ID> -o <OUTPUT_DIRECTORY>
```
{{% /tab %}}
{{% tab tabName="Kotlin" %}}
```bash
rudder-cli typer generate --platform=kotlin --tracking-plan-id=<TRACKING_PLAN_ID> -o <OUTPUT_DIRECTORY>
```
{{% /tab %}}
{{% tab tabName="Swift" %}}
```bash
rudder-cli typer generate --platform=swift --tracking-plan-id=<TRACKING_PLAN_ID> -o <OUTPUT_DIRECTORY>
```
{{% /tab %}}
{{< /tabs >}}

The above command generates bindings for the platform indicated by the `--platform` flag (`typescript`, `kotlin`, or `swift`), for the Tracking Plan indicated by the `--tracking-plan-id` flag, and stores the generated files in the directory indicated by the `-o` flag.

Note that:

- `--platform` and `--tracking-plan-id` are **required** flags
- `-o` is optional and defaults to the current working directory if omitted
- You can view all available options by running `rudder-cli typer generate -h`

See the [RudderTyper v2 Command Reference]({{< ref "dev-tools/rudder-cli/ruddertyper-v2-command-reference.md" >}}) for more information on the above command and the supported flags.

## 4. Install bindings in your application

{{< tabs tabTotal="3" >}}
{{% tab tabName="TypeScript" %}}
RudderTyper generates a single `RudderTyper.ts` file. Add this file to your application's source directory and import the generated `RudderTyper` class where you instrument events.

The generated code depends on the [RudderStack JavaScript SDK](https://github.com/rudderlabs/rudder-sdk-js) (`@rudderstack/analytics-js`), which your application should already be configured to use. If you haven't set up the SDK yet, follow the steps in the [JavaScript SDK documentation]({{< ref "sources/event-streams/sdks/rudderstack-javascript-sdk/" >}}).
{{% /tab %}}
{{% tab tabName="Kotlin" %}}
Copy the generated files to a location of your choice inside your application's source directory. Typically, this should be in a structure that mimics the generated code's package name.

By default, the package name is `com.rudderstack.ruddertyper`, which means the code should be copied to a directory that looks like below:

```text
src/main/kotlin/com/rudderstack/ruddertyper
```

{{< tip >}}
Place the generated code based on your application's structure.

Generally, developers put the generated code under `build/generated/source` directories, which IDEs treat specifically as generated code that cannot be modified.
{{< /tip >}}

The generated code only has a dependency on the SDK library, which your application should already be configured to use, following the steps in the [Android (Kotlin) SDK documentation]({{< ref "sources/event-streams/sdks/kotlin-sdk/" >}}).
{{% /tab %}}
{{% tab tabName="Swift" %}}
RudderTyper generates a single `RudderTyper.swift` file. Add this file to your Xcode project or Swift Package by dragging it into your project navigator or including it in your target's **Compile Sources** build phase.

The generated code depends on the [RudderStack Swift SDK](https://github.com/rudderlabs/rudder-sdk-swift) (`RudderStackAnalytics`), which your application should already be configured to use. If you haven't set up the SDK yet, follow the steps in the [iOS (Swift) SDK documentation]({{< ref "sources/event-streams/sdks/swift-sdk/" >}}).
{{% /tab %}}
{{< /tabs >}}

## 5. Optional: Customize the generated code

Depending on the platform, RudderTyper supports platform-specific options that customize the generated code.

You can provide these options to the `rudder-cli typer generate` command using one or more `--option` flags that accept a key-value pair separated by `=`.

To view available options for your platform, run:

{{< tabs tabTotal="3" >}}
{{% tab tabName="TypeScript" %}}
```bash
rudder-cli typer options --platform=typescript
```

The TypeScript platform supports the following options:

| Option | Default | Description |
| :----| :------| :------|
| `outputFileName` | `RudderTyper.ts` | Name of the generated TypeScript file, for example, `Events.ts` |

For example, to generate bindings with a custom output file name:

```bash
rudder-cli typer generate --platform=typescript --tracking-plan-id=<TRACKING_PLAN_ID> --option outputFileName=Events.ts
```
{{% /tab %}}
{{% tab tabName="Kotlin" %}}
```bash
rudder-cli typer options --platform=kotlin
```

The above command gives an output like below:

{{< image src="images/dev-tools/ruddertyper-v2/quickstart-2.webp" alt="Rudder CLI Kotlin platform options" >}}

The Kotlin platform supports the following options:

| Option | Default | Description |
| :----| :------| :------|
| `packageName` | `com.rudderstack.ruddertyper` | Package name for the generated Kotlin code. |
| `outputFileName` | `Main.kt` | Name of the generated Kotlin file, for example, `MyEvents.kt` |
| `composeImmutable` | `false` | Annotates every generated `data class` with `@androidx.compose.runtime.Immutable`. Enable this if you use the generated types directly in Jetpack Compose UI trees. |

For example, to generate bindings with a custom package name:

```bash
rudder-cli typer generate --platform=kotlin --tracking-plan-id=<TRACKING_PLAN_ID> --option packageName=com.example.package
```

To enable Compose `@Immutable` annotations:

```bash
rudder-cli typer generate --platform=kotlin --tracking-plan-id=<TRACKING_PLAN_ID> --option composeImmutable=true
```

{{< warning >}}
Enabling `composeImmutable` requires `androidx.compose.runtime` on your module's classpath. Any module that already uses Jetpack Compose has this dependency. If you enable this flag in a non-Compose module, the build fails with an unresolved reference.
{{< /warning >}}

{{% /tab %}}
{{% tab tabName="Swift" %}}
```bash
rudder-cli typer options --platform=swift
```

The Swift platform does not currently expose any platform-specific options. The generated code is output as a single `RudderTyper.swift` file.
{{% /tab %}}
{{< /tabs >}}

## 6. Instrument your application

After installing the generated files in your application's source folders, you can use them as a wrapper over the RudderStack SDK.

Assuming your SDK instance is initialized and available through a variable called `analytics`, instantiate and use the RudderTyper wrapper by passing the `analytics` object as an argument:

{{< tabs tabTotal="3" >}}
{{% tab tabName="TypeScript" %}}
```typescript
import { RudderAnalytics } from "@rudderstack/analytics-js";
import { RudderTyper } from "./RudderTyper";

// Example setup of the SDK
const analytics = new RudderAnalytics();
analytics.load("<WRITE_KEY>", "<DATA_PLANE_URL>");

// Setup of RudderTyper bindings
const typer = new RudderTyper(analytics);
```
{{% /tab %}}
{{% tab tabName="Kotlin" %}}
```kotlin
import com.rudderstack.ruddertyper.RudderAnalytics
import com.rudderstack.sdk.kotlin.android.Analytics
import com.rudderstack.sdk.kotlin.android.Configuration

// Example setup of the SDK
val configuration = Configuration(
    writeKey = BuildConfig.WRITE_KEY,
    application = this,
    dataPlaneUrl = BuildConfig.DATA_PLANE_URL,
    flushPolicies = listOf(
        CountFlushPolicy(1)
    )
)

analytics = Analytics(configuration)

// Setup of RudderTyper bindings
val typer = com.rudderstack.ruddertyper.RudderAnalytics(analytics)
```
{{% /tab %}}
{{% tab tabName="Swift" %}}
```swift
import RudderStackAnalytics

// Example setup of the SDK
let config = Configuration(
    writeKey: "<WRITE_KEY>",
    dataPlaneUrl: "<DATA_PLANE_URL>"
)

let analytics = Analytics(configuration: config)

// Setup of RudderTyper bindings
let rudderTyper = RudderTyperAnalytics(analytics: analytics)
```
{{% /tab %}}
{{< /tabs >}}

### Use the generated bindings

The wrapper object exposes methods that correspond to the events in your Tracking Plan.

For `identify`, `screen`, and `group` event types added as rules to the Tracking Plan, the wrapper exposes methods with signatures identical to those exposed by the SDK, except with strongly typed properties or trait arguments. For TypeScript, which targets the web-based JavaScript SDK, the wrapper exposes a `page` method instead of `screen`.

For example, an `identify` event with a single `name` property added to its traits through the Tracking Plan:

{{< tabs tabTotal="3" >}}
{{% tab tabName="TypeScript" %}}
```typescript
typer.identify("1hKOmRA4GRlm", {
  name: "Alex Keener"
})
```
{{% /tab %}}
{{% tab tabName="Kotlin" %}}
```kotlin
import com.rudderstack.ruddertyper.IdentifyTraits

typer.identify(
  userId = "1hKOmRA4GRlm",
  traits = IdentifyTraits(
    name = "Alex Keener"
  )
)
```
{{% /tab %}}
{{% tab tabName="Swift" %}}
```swift
rudderTyper.identify(
    userId: "1hKOmRA4GRlm",
    traits: IdentifyTraits(name: "Alex Keener")
)
```
{{% /tab %}}
{{< /tabs >}}

Similarly, `track` events added as rules in a Tracking Plan correspond to methods named with a `track` prefix followed by a CamelCase version of the event's name. For example, you can send an event named `User Login` using:

{{< tabs tabTotal="3" >}}
{{% tab tabName="TypeScript" %}}
```typescript
typer.trackUserLogin({
  // ... properties defined in your Tracking Plan
})
```
{{% /tab %}}
{{% tab tabName="Kotlin" %}}
```kotlin
typer.trackUserLogin(
  properties = TrackUserLoginProperties(
    // ... properties defined in your Tracking Plan
  )
)
```
{{% /tab %}}
{{% tab tabName="Swift" %}}
```swift
rudderTyper.trackUserLogin(
    properties: TrackUserLoginProperties(
        // ... properties defined in your Tracking Plan
    )
)
```
{{% /tab %}}
{{< /tabs >}}

## Next steps

- See the [RudderTyper v2 Command Reference]({{< ref "dev-tools/rudder-cli/ruddertyper-v2-command-reference.md" >}}) for detailed information about all available CLI commands and parameters
- See the [Limitations]({{< ref "dev-tools/rudder-cli/ruddertyper-v2.md#limitations" >}}) section for more information on the limitations of the 
generated bindings
