diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml
new file mode 100644
index 00000000..6b567ad4
--- /dev/null
+++ b/.github/workflows/e2e-tests.yml
@@ -0,0 +1,78 @@
+# E2E Tests for analytics-java
+# Copy this file to: analytics-java/.github/workflows/e2e-tests.yml
+#
+# This workflow:
+# 1. Checks out the SDK and sdk-e2e-tests repos
+# 2. Builds the SDK and e2e-cli
+# 3. Runs the e2e test suite
+
+name: E2E Tests
+
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+ workflow_dispatch: # Allow manual trigger
+
+jobs:
+ e2e-tests:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout SDK
+ uses: actions/checkout@v4
+ with:
+ path: sdk
+
+ - name: Checkout sdk-e2e-tests
+ uses: actions/checkout@v4
+ with:
+ repository: segmentio/sdk-e2e-tests
+ path: sdk-e2e-tests
+
+ - name: Setup Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: '11'
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+
+ - name: Build Java SDK and e2e-cli
+ working-directory: sdk
+ run: mvn package -pl e2e-cli -am -DskipTests
+
+ - name: Find e2e-cli jar
+ id: find-jar
+ working-directory: sdk
+ run: |
+ JAR_PATH=$(find e2e-cli/target -name "e2e-cli-*-jar-with-dependencies.jar" | head -1)
+ echo "jar_path=$JAR_PATH" >> $GITHUB_OUTPUT
+
+ - name: Install sdk-e2e-tests dependencies
+ working-directory: sdk-e2e-tests
+ run: npm ci
+
+ - name: Build sdk-e2e-tests
+ working-directory: sdk-e2e-tests
+ run: npm run build
+
+ - name: Run E2E tests
+ working-directory: sdk-e2e-tests
+ env:
+ CLI_COMMAND: java -jar ${{ github.workspace }}/sdk/${{ steps.find-jar.outputs.jar_path }}
+ E2E_TEST_SUITES: basic,retry
+ # E2E_TEST_SKIP: exponential-backoff # skip specific test files if needed
+ run: npm test
+
+ - name: Upload test results
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: e2e-test-results
+ path: sdk-e2e-tests/test-results/
+ if-no-files-found: ignore
diff --git a/e2e-cli/README.md b/e2e-cli/README.md
new file mode 100644
index 00000000..b319749e
--- /dev/null
+++ b/e2e-cli/README.md
@@ -0,0 +1,54 @@
+# analytics-java e2e-cli
+
+E2E test CLI for the [analytics-java](https://github.com/segmentio/analytics-java) SDK. Accepts a JSON input describing events and SDK configuration, sends them through the real SDK, and outputs results as JSON.
+
+Built with Kotlin (JVM) and packaged as a fat jar via Maven.
+
+## Setup
+
+```bash
+mvn package -pl e2e-cli -am
+```
+
+## Usage
+
+```bash
+java -jar e2e-cli/target/e2e-cli-*-jar-with-dependencies.jar --input '{"writeKey":"...", ...}'
+```
+
+## Input Format
+
+```jsonc
+{
+ "writeKey": "your-write-key", // required
+ "apiHost": "https://...", // optional — SDK default if omitted
+ "sequences": [ // required — event sequences to send
+ {
+ "delayMs": 0,
+ "events": [
+ { "type": "track", "event": "Test", "userId": "user-1" }
+ ]
+ }
+ ],
+ "config": { // optional
+ "flushAt": 250,
+ "flushInterval": 10000,
+ "maxRetries": 3,
+ "timeout": 15
+ }
+}
+```
+
+Note: Java is a server-side SDK — there is no CDN settings fetch, so `cdnHost` does not apply.
+
+## Output Format
+
+```json
+{ "success": true, "sentBatches": 1 }
+```
+
+On failure:
+
+```json
+{ "success": false, "error": "description", "sentBatches": 0 }
+```
diff --git a/e2e-cli/pom.xml b/e2e-cli/pom.xml
new file mode 100644
index 00000000..b5782b8f
--- /dev/null
+++ b/e2e-cli/pom.xml
@@ -0,0 +1,91 @@
+
+
+
+ 4.0.0
+
+
+ analytics-parent
+ com.segment.analytics.java
+ 3.5.5-SNAPSHOT
+
+
+ com.segment.analytics.java
+ e2e-cli
+ 3.5.5-SNAPSHOT
+ Analytics Java E2E CLI
+
+ E2E testing CLI for Segment Analytics for Java.
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ ${kotlin.version}
+
+
+ com.segment.analytics.java
+ analytics
+ ${project.version}
+
+
+ org.jetbrains.kotlinx
+ kotlinx-serialization-json
+ 1.4.1
+
+
+
+
+ src/main/kotlin
+
+
+
+ kotlin-maven-plugin
+ org.jetbrains.kotlin
+ ${kotlin.version}
+
+
+ kotlinx-serialization
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-serialization
+ ${kotlin.version}
+
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ jar-with-dependencies
+
+
+
+ cli.MainKt
+
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
diff --git a/e2e-cli/src/main/kotlin/cli/Main.kt b/e2e-cli/src/main/kotlin/cli/Main.kt
new file mode 100644
index 00000000..6db10cbd
--- /dev/null
+++ b/e2e-cli/src/main/kotlin/cli/Main.kt
@@ -0,0 +1,159 @@
+package cli
+
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.segment.analytics.Analytics
+import com.segment.analytics.Callback
+import com.segment.analytics.messages.*
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicBoolean
+
+data class CLIOutput(
+ val success: Boolean,
+ val error: String? = null,
+ val sentBatches: Int = 0
+)
+
+data class CLIConfig(
+ val flushAt: Int? = null,
+ val flushInterval: Long? = null,
+ val maxRetries: Int? = null,
+ val timeout: Int? = null
+)
+
+data class EventSequence(
+ val delayMs: Long = 0,
+ val events: List