Skip to content

libtermux/libtermux-android

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

23 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“¦ libtermux-android

World's first Standalone Termux SDK for Android.
Embed a full Linux environment inside any Android app β€” no Termux installation required.


πŸš€ What is this?

libtermux-android is a high-performance Android library that bootstraps a complete, isolated Linux environment (Termux runtime) inside your app's private storage. Your users get all the power of a Linux terminal without ever knowing it exists.

Your App β†’ LibTermux SDK β†’ Isolated Linux Env β†’ bash, python, node, ruby, pkg install...

✨ Features

Feature Description
Standalone Mode No Termux app required β€” bootstrap is auto-installed
Kotlin DSL API Clean, idiomatic Kotlin interface
Java Compatible Full Java Builder pattern support
Multi-language Python Β· Node.js Β· Bash Β· Ruby Β· Perl + any pkg
Package Manager pkg install, pip install, npm install -g
Streaming Output Real-time Flow<OutputLine> from running processes
Background Service Keep scripts running when app is minimized
TerminalView Drop-in terminal UI widget
JNI PTY Layer Full pseudo-terminal support for interactive programs
Multi-arch arm64-v8a Β· x86_64 Β· armeabi-v7a Β· x86

πŸ“¦ Installation

Gradle (JitPack)

// settings.gradle.kts
repositories {
    maven { url = uri("https://jitpack.io") }
}

// app/build.gradle.kts
dependencies {
    implementation("com.github.libtermux:libtermux-android:1.0.0")

    // Optional: terminal UI widget
    implementation("com.github.libtermux:terminal-view:1.0.0")
}

Maven

<repository>
    <id>jitpack.io</id>
    <url>https://jitpack.io</url>
</repository>

<dependency>
    <groupId>com.github.libtermux</groupId>
    <artifactId>libtermux-android</artifactId>
    <version>1.0.0</version>
</dependency>

⚑ Quick Start

Kotlin

class MyActivity : AppCompatActivity() {

    private val termux by lazy {
        LibTermux.create(this) {
            autoInstall  = true
            logLevel     = LogLevel.DEBUG
            env("MY_APP", "libtermux")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleScope.launch {
            // 1. Initialize (downloads bootstrap on first run ~30MB)
            termux.initialize().collect { state ->
                when (state) {
                    is InstallState.Downloading -> showProgress(state.progress)
                    is InstallState.Completed   -> onReady()
                    is InstallState.Failed      -> showError(state.error)
                    else -> {}
                }
            }
        }
    }

    private suspend fun onReady() {
        val bridge = termux.bridge

        // Run any shell command
        val result = bridge.run("uname -a")
        println(result.stdout)

        // Run Python
        val py = bridge.python("""
            import json, sys
            print(json.dumps({"python": sys.version, "status": "works!"}))
        """)
        println(py.stdout)

        // Install packages
        bridge.install("git", "curl", "wget")

        // Stream real-time output
        bridge.runStreaming("ping -c 5 8.8.8.8").collect { line ->
            when (line) {
                is OutputLine.Stdout -> updateUI(line.text)
                is OutputLine.Stderr -> showError(line.text)
                is OutputLine.Exit   -> println("done: ${line.code}")
            }
        }
    }
}

Java

LibTermux termux = LibTermux.builder(this)
    .autoInstall(true)
    .logLevel(LogLevel.DEBUG)
    .build();

// Blocking init (run on background thread!)
new Thread(() -> {
    try {
        termux.initializeBlocking();
        String output = termux.getBridge().runOrThrow("echo Hello Linux!");
        Log.d("TAG", output); // Hello Linux!
    } catch (Exception e) {
        Log.e("TAG", "Failed", e);
    }
}).start();

πŸ”§ Advanced Usage

Background Execution

// Start background service
TermuxBackgroundService.start(context, config)

// Run a long-running server in background
TermuxBackgroundService.runCommand(context, "node-server", "node server.js")

Terminal UI Widget

<!-- activity_main.xml -->
<com.libtermux.view.TerminalView
    android:id="@+id/terminal"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
val session = termux.sessions.createSession("main")
binding.terminal.attachSession(session)
session.run("bash") // Start interactive shell

Multiple Sessions

val session1 = termux.sessions.createSession("python-repl")
val session2 = termux.sessions.createSession("node-server")

session1.run("python3 myapp.py")
session2.run("node server.js")

termux.sessions.closeSession(session1.session.id)

Package Management

// Install packages
termux.packages.install("python", "nodejs", "git", "curl")
termux.packages.pipInstall("requests", "numpy", "flask")
termux.packages.npmInstall("express", "axios")

// Search
val results = termux.packages.search("machine learning")

// List installed
val installed = termux.packages.listInstalled()

File Operations

// Write a Python script to HOME
termux.bridge.writeFile("app.py", """
    import flask
    app = flask.Flask(__name__)

    @app.route('/')
    def hello(): return "Hello from LibTermux!"

    app.run(host='127.0.0.1', port=8080)
""")

// Run it
termux.bridge.run("python3 ~/app.py")

// Read output
val content = termux.bridge.readFile("output.txt")

πŸ” Shizuku Integration (Elevated Privileges)

libtermux-android optionally integrates with Shizuku to run commands with elevated (root/system) privileges. This allows your app to perform system-level operations like accessing protected files, modifying system settings, or executing privileged commandsβ€”all without requiring the user to manually install Shizuku or root their device (Shizuku can run via ADB or root).

The library provides a simple API that falls back to normal execution when Shizuku is unavailable, so your app remains functional in all environments.

Installation

Add the Shizuku module dependency:

dependencies {
    implementation("com.github.libtermux:libtermux-android:1.0.0")
    implementation("com.github.libtermux:shizuku:1.0.0") // optional: elevated commands
}

Usage

class MyActivity : AppCompatActivity() {
    private lateinit var shizukuTermux: ShizukuTermux

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        shizukuTermux = ShizukuTermux.getInstance(this) {
            autoInstall = true
        }

        lifecycleScope.launch {
            shizukuTermux.initialize().collect { state ->
                if (state is InstallState.Completed) {
                    // Request Shizuku permission if needed
                    if (!shizukuTermux.isShizukuPermissionGranted) {
                        shizukuTermux.requestShizukuPermission()
                    }

                    // Run normal command
                    val normal = shizukuTermux.bridge.run("echo Hello")
                    println(normal.stdout)

                    // Run elevated command (e.g., read system files)
                    val elevated = shizukuTermux.runElevated("cat /system/build.prop")
                    println("Exit code: ${elevated.exitCode}")
                }
            }
        }
    }
}

Permission

Add the following permission to your AndroidManifest.xml:

<uses-permission android:name="dev.rikka.shizuku.permission.API_V23" />

Optionally, include the Shizuku provider for automatic service binding:

<provider
    android:name="rikka.shizuku.ShizukuProvider"
    android:authorities="${applicationId}.shizuku"
    android:enabled="true"
    android:exported="false" />

API Reference

Method Description

ShizukuTermux.getInstance(context, config) Get singleton instance (also supports DSL). isShizukuAvailable Check if Shizuku service is installed and running. isShizukuPermissionGranted Check if permission has been granted. suspend fun requestShizukuPermission() Request permission (suspends until granted/denied). suspend fun runElevated(command, env, workDir) Execute command with elevated privileges. Returns ElevatedResult.

Fallback Behavior

If Shizuku is not installed, not running, or permission is denied, runElevated() automatically falls back to normal execution within the Termux environment. You can check the elevated flag in the result to know how it was executed.


πŸ—οΈ Project Structure

libtermux-android/
β”œβ”€β”€ core/                          # Main SDK library
β”‚   └── src/main/
β”‚       β”œβ”€β”€ kotlin/com/libtermux/
β”‚       β”‚   β”œβ”€β”€ LibTermux.kt       # ← Main entry point
β”‚       β”‚   β”œβ”€β”€ TermuxConfig.kt    # ← Configuration DSL
β”‚       β”‚   β”œβ”€β”€ bootstrap/         # Bootstrap installer
β”‚       β”‚   β”œβ”€β”€ executor/          # Command execution engine
β”‚       β”‚   β”œβ”€β”€ fs/                # Virtual file system
β”‚       β”‚   β”œβ”€β”€ pkg/               # Package manager
β”‚       β”‚   β”œβ”€β”€ bridge/            # Developer API bridge
β”‚       β”‚   β”œβ”€β”€ service/           # Background service
β”‚       β”‚   └── utils/             # Utilities + JNI bindings
β”‚       └── jni/                   # C++ native layer (PTY, process, symlinks)
β”‚
β”œβ”€β”€ terminal-view/                 # Terminal UI widget (optional)
β”‚   └── src/main/kotlin/
β”‚       └── com/libtermux/view/
β”‚           └── TerminalView.kt
β”‚
β”œβ”€β”€ shizuku/                       # Shizuku integration for elevated commands (optional)
β”‚   └── src/main/kotlin/
β”‚       └── com/libtermux/shizuku/
β”‚           β”œβ”€β”€ ShizukuTermux.kt   # Entry point for elevated execution
β”‚           └── ElevatedResult.kt  # Result class for elevated commands
β”‚
β”œβ”€β”€ sample/                        # Demo app
β”‚   └── src/main/kotlin/
β”‚       └── com/libtermux/sample/
β”‚           β”œβ”€β”€ MainActivity.kt
β”‚           └── MainViewModel.kt
β”‚
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ setup_dev.sh               # Developer environment setup
β”‚   └── publish_local.sh           # Publish to local Maven
β”‚
└── .github/workflows/
    β”œβ”€β”€ ci.yml                     # CI: lint + test + build
    └── release.yml                # Release: publish to Maven Central

πŸ” Permissions

Add to your AndroidManifest.xml:

<!-- Required for bootstrap download -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Required for background service -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

<!-- Optional: for notifications -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

πŸ“Š Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Your Android App                     β”‚
β”‚                                                           β”‚
β”‚  LibTermux.create(context) { ... }                        β”‚
β”‚       β”‚                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚              LibTermux (Singleton)                  β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚TermuxBridge β”‚  β”‚SessionManagerβ”‚  β”‚PackageMgr β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”˜                β”‚         β”‚  β”‚
β”‚  β”‚                  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”           β”‚         β”‚  β”‚
β”‚  β”‚                  β”‚CommandExec  β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚  β”‚
β”‚  β”‚                  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                     β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚  β”‚  β”‚VirtualFileSystem   β”‚ β”‚ β”‚BootstrapInstaller    β”‚   β”‚  β”‚
β”‚  β”‚  β”‚  /usr /home /tmp   β”‚β—„β”˜ β”‚  (Download + Extract)β”‚   β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚  β”‚                                                       β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚  β”‚  β”‚     libtermux_jni.so  (C++ Native Layer)        β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  PTY Β· Process Fork Β· Symlinks Β· chmod          β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚   App Private Storage: filesDir/libtermux/            β”‚ β”‚
β”‚  β”‚   └── usr/bin/bash, python3, node ...                 β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🀝 Contributing

  1. Fork the repo
  2. Run ./scripts/setup_dev.sh
  3. Create a feature branch: git checkout -b feature/amazing-feature
  4. Run tests: ./gradlew :core:testDebugUnitTest
  5. Push and open a Pull Request

πŸ“„ License

Copyright 2026 LibTermux Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

About

The ultimate Android library to embed a full-featured Linux environment (Termux power) into any Android app. Zero-root, High-performance, and API 34+ compatible.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors