Official documentation

Mobile support

Technical reference for Mobile support — Joss language and Joss Red ecosystem.

Mobile Support: Android and iOS

Joss supports execution and development on mobile platforms through two approaches: 1. Standalone CLI and binaries on Android (Termux / ADB): Run and compile Joss scripts directly on Android devices. 2. Embeddable libjoss SDK (pkg/mobile) for Android and iOS: Integrate the Joss engine into native and hybrid applications written in Kotlin (Android) and Swift (iOS). This is suitable for educational apps such as Aprende más, interactive playgrounds, or client-side business-rule execution.


1. Approach A: Standalone CLI on Android

Android is based on the Linux kernel and can run static ELF binaries.

Supported architectures

The Joss native cross-compiler supports the four standard Android architectures: - android/arm64 (most modern phones) - android/arm (older 32-bit devices) - android/amd64 (x86_64 Android Studio emulators) - android/386 (older 32-bit emulators)

Cross-compiling from the development machine

To compile the Joss CLI or a self-contained Joss project for Android:

# Compilar un script o proyecto para Android arm64
joss build native android arm64

# O compilar el CLI completo directamente con Go
CGO_ENABLED=0 GOOS=android GOARCH=arm64 go build ./cmd/joss

Transfer the resulting binary to the device and install it in Termux:

# En el terminal de Termux en Android:
chmod +x joss
mv joss $PREFIX/bin/
joss version

[!NOTE] iOS does not provide a standalone command console because of Apple’s security and sandboxing policies. Joss therefore supports iOS through the embeddable SDK described in Approach B.


2. Approach B: Embeddable libjoss SDK (pkg/mobile)

The github.com/jossecurity/joss/pkg/mobile package exposes a high-level API for mobile applications built with Java, Kotlin, Swift, Flutter, or React Native.

API methods

Function Description Return value
Run(source string, timeoutMs int) Runs Joss source code, captures stdout and stderr, and applies a time limit to protect against infinite loops.

| JSON ExecutionResult | | Analyze(source string) | Performs static and syntactic analysis without running the code; reports line-and-column diagnostics for mobile editors.

| JSON AnalysisResult | | Version() | Returns the current Joss engine version.

| string |

JSON response structure (ExecutionResult)

{
  "success": true,
  "stdout": "Hola desde Joss en Android!\n",
  "stderr": "",
  "error": "",
  "timed_out": false,
  "duration_ms": 15,
  "diagnostics": []
}

If the code contains a syntax or type error, success is false and diagnostics contains the details needed to highlight the error in the app interface:

{
  "success": false,
  "error": "JOSS-TYPE-001: tipo incompatible",
  "duration_ms": 2,
  "diagnostics": [
    {
      "code": "JOSS-TYPE-001",
      "severity": "error",
      "message": "no se puede asignar string a int",
      "line": 3,
      "column": 5,
      "suggestion": "declara el tipo compatible o usa mixed"
    }
  ]
}

3. Android Integration (Kotlin / Jetpack Compose)

In applications such as Aprende más, call the SDK from a ViewModel or execution service.

Kotlin example

// Invocación del motor Joss desde Kotlin
fun ejecutarCodigoJoss(codigoFuente: String): JossResult {
    // timeout de 3000 ms para evitar que bucles infinitos cuelguen la app
    val resultadoJson: String = Mobile.run(codigoFuente, 3000)
    return Gson().fromJson(resultadoJson, JossResult::class.java)
}

data class JossResult(
    val success: Boolean,
    val stdout: String,
    val stderr: String,
    val error: String?,
    val timed_out: Boolean?,
    val duration_ms: Long,
    val diagnostics: List<JossDiagnostic>?
)

data class JossDiagnostic(
    val code: String,
    val severity: String,
    val message: String,
    val line: Int,
    val column: Int,
    val suggestion: String?
)

4. iOS Integration (Swift / SwiftUI)

On iOS, include the SDK in the Xcode project as an .xcframework.

Swift example

import SwiftUI
import JossMobile

class JossRunnerViewModel: ObservableObject {
    @Published var salida: String = ""
    @Published var estaEjecutando: Bool = false

    func ejecutar(codigo: String) {
        estaEjecutando = true
        DispatchQueue.global(qos: .userInitiated).async {
            // timeout de 3 segundos
            let jsonString = MobileRun(codigo, 3000)
            
            if let data = jsonString.data(using: .utf8),
               let result = try? JSONDecoder().decode(JossResult.self, from: data) {
                DispatchQueue.main.async {
                    self.salida = result.success ? result.stdout : (result.error ?? "Error desconocido")
                    self.estaEjecutando = false
                }
            }
        }
    }
}

5. Building the SDK for Production

Generate an Android AAR with gomobile

go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
gomobile bind -target=android -o libjoss.aar ./pkg/mobile

Place the generated libjoss.aar file in the Android Studio app/libs/ directory.

Generate an iOS XCFramework with gomobile

gomobile bind -target=ios -o JossMobile.xcframework ./pkg/mobile

Drag the JossMobile.xcframework directory into the Xcode project’s Frameworks, Libraries, and Embedded Content section on macOS.