• PSA: How to type ADB commands on your phone instead of on your PC.

    From Maria Sophia@mariasophia@comprehension.com to comp.sys.mac.advocacy,comp.sys.mac.system,comp.sys.mac.apps on Fri Aug 21 11:38:49 2026
    From Newsgroup: comp.sys.mac.system

    PSA: How to type ADB commands on our phones instead of on our PCs.

    This tutorial shows desktop folks how to remove the laptop/desktop
    (whether macOS, Linux, or Windows) from the Android adb equation.

    Note that Termux/Remote-interactive-shell (rish), localadb (ladb)
    and ShizuShell are all effectively the same thing, where each
    can run the same ADB commands locally on Android without the PC.

    I've already written a tutorial for building ladb from source, and
    I've written a tutorial for installing ShizuShell instead of Termux.

    Therefore, this is a tutorial for installing and using Termux/rish
    (remote interactive shell) to run the same adb commands, which we
    normally would run connected to the desktop over Wi-Fi or USB, but,
    with this tutorial, we can now omit the desktop & still use adb.

    The problem turning Termux into an adb-capable terminal emulator...
    a. Shizuku runs a background service daemon with shell privileges.
    b. But Termux is blocked from running system commands, by default.
    c. So this remote interactive shell installation fixes that problem.

    If we know *exactly* how to do it, it's probably worth doing
    because it allows us to run all our adb commands, without the PC.

    However there is an unholy labyrinth of traps such as copy/paste issues, permissions issues, buffer limitations, obnoxious Termux side drawers, etc.

    An example is Termux has an obnoxious side drawer that attacks us when
    we're just trying to copy. Worse, Termux won't accept a long paste from
    scrcpy keyboards unless we know enough to change scrcpy invocation from
    scrcpy --keyboard=sdk
    to
    C:\> scrcpy --legacy-paste

    It's an OMG experience if we're doing it sans good instructions.
    But it's trivial to set up, if we already know how to do it.

    Here is a straightforward, mostly sane way to survive the gauntlet.
    [Some things are so ungodly crazy that we need a tutorial to do them.]

    Bear in mind that Termux is just an unprivileged app sandboxed by Android, where Shizuku opens the backend door via its binder daemon, and rish acts
    as the bridge so that we can pass text commands through it sans a PC.

    Note: We can choose either a manual Shizuku export from the phone,
    or we can choose an automated installer script off the Internet
    to install the necessary files inside of the Termux private storage.

    Option 1: The Manual Export Method (using Shizuku's built-in export)
    Instead of letting an automated script pull the files, we can
    manually have Shizuku generate and export the base rish files.
    A. Open the Shizuku app on the phone.
    B. Tap "Use Shizuku in terminal apps".
    C. Tap "Export files" & choose an accessible folder on the device.
    This exports two files:
    a. A helper script, see below.
    Name: rish
    Size: 882 bytes
    SHA256: 3B01B0CC72CFAD779BFF56EFC29E6AD30AAA9B3969AA349CDF2AA5F876BF2066
    b. A Java background handler
    Name: rish_shizuku.dex
    Size: 6828 bytes (6 KiB)
    SHA256: 3AA6AD7B64796C54DAA1FB6D5A046495513466166E87E5739967D5A4C565560E
    I had exported to an existing directory on my internal storage named...
    /storage/emulated/0/0000/apk/rish
    /storage/emulated/0/0000/apk/rish/rish_shizuku.dex

    Step 2: Grant storage access (because Termux cannot use shared storage).
    A. Open Termux on the phone
    B. Run this command and accept the system prompt:
    $ termux-setup-storage
    C. Follow prompts

    Option 2: The Automated Installer Script Method (using curl)
    We can let a community-written tested script fetch and configure
    everything automatically using the methodology below.
    A. Run this in Termux while connected to the Internet:
    $ curl -fsSL tinyurl.com/rish3266 | sh
    B. Follow the prompts inside of Termux
    C. When it asks to select source, choose "1"
    (Offline / Extract app) if we want it to pull directly from
    our installed Shizuku app package automatically.

    That "curl" downloads "tinyurl.com/rish3266" hosted by merbah3266
    on GitHub and those fsSL flags tell curl to be quiet and to follow
    web redirects if the link changes & to fail silently if the network
    errors. The pipe to sh feeds it into the shell interpreter so that
    it executes immediately, saving us time and effort (especially
    given Termux copy/paste/typing is essentially atrocious).

    Note the rish remote interactive shell is the official companion tool
    built by the Shizuku developer team (RikkaApps) specifically designed
    to let terminal apps like Termux tap into Shizuku's ADB/shell bridge.

    That script will automatically pull the assets, drop them into
    Termux's binary folder ($PREFIX/bin) and it will configure rish.

    Here is what the script is doing step-by-step under the hood:
    1. Safety Check:
    It makes sure we aren't accidentally running it as the system
    root user (which would break things).
    2. Menu Prompt:
    It asks us how we want to get the Shizuku files
    (e.g., pulling them directly from the Shizuku app already
    installed on the phone, or downloading them from GitHub).
    3. Dependency Check:
    It checks if tools like unzip and sed are available, and if not,
    it automatically downloads a lightweight utility called BusyBox
    so it can still do its job.
    4. Extraction:
    It unpacks the Shizuku APK to pull out the two necessary files
    (rish and rish_shizuku.dex).
    5. Installation:
    It automatically copies those files into Termux's system binary
    folder ($PREFIX/bin), sets the correct executable permissions
    (chmod), and creates handy shortcuts so we can just type
    rish from anywhere.

    Step 4: Once the installation finishes, we are ready to test it.
    A. Type the new shortcut command:
    $ rish
    B. A popup will ask "Allow Termux to access Shizuku".
    C. Tap "Allow all the time".

    Note: This error is apparently bogus:
    Request timeout. The connection between the current app
    and Shizuku app may be blocked...

    That is apparently a false alarm caused by Shizuku's 5-second
    handshake timer getting bogged down the first time it wakes up.

    Just repeat the typing of "rish" a second time if that happens.

    Step 5. The prompt will change from "~ $" to something like "a32x:/ $".
    A. Check elevated status
    a32x:/ $ whoami
    We should see "shell"
    B. Read a restricted system property
    a32x:/ $ getprop ro.serialno
    We should see our phone hardware serial number.

    C. Check system process ownership
    a32x:/ $ ps -AZ | grep shell
    We should see active system processes
    filtered for the shell context, e.g.,
    u:r:shell:s0 shell 28060 1 shizuku_server
    Voila!
    This means Termux & Shizuku are now bridged which means we
    bypassed Android sandboxing, without needing a full device
    root on my Android 13, non-rooted Samsung Galaxy A32-5G.

    The rish bridge is talking to the shizuku_server, running under
    the true shell security context, bypassing the normal app sandbox.

    REFERENCE FILES:
    ----- < below is rish > -----
    #!/system/bin/sh
    BASEDIR=$(dirname "$0")
    DEX="$BASEDIR"/rish_shizuku.dex

    if [ ! -f "$DEX" ]; then
    echo "Cannot find $DEX, please check the tutorial in Shizuku app"
    exit 1
    fi

    if [ $(getprop ro.build.version.sdk) -ge 34 ]; then
    if [ -w $DEX ]; then
    echo "On Android 14+, app_process cannot load writable dex."
    echo "Attempting to remove the write permission..."
    chmod 400 $DEX
    fi
    if [ -w $DEX ]; then
    echo "Cannot remove the write permission of $DEX."
    echo "You can copy to file to terminal app's private directory (/data/data/<package>, so that remove write permission is possible"
    exit 1
    fi
    fi

    # Replace "PKG" with the application id of your terminal app
    [ -z "$RISH_APPLICATION_ID" ] && export RISH_APPLICATION_ID="PKG"
    /system/bin/app_process -Djava.class.path="$DEX" /system/bin --nice-name=rish rikka.shizuku.shell.ShizukuShellLoader "$@"
    ----- < above is rish > -----

    ----- < below is the Shizuku rish installer > ------
    exec 2>/dev/null
    BIN="$(dirname "$(command -v bash)")"
    RISH="$BIN/rish"; DEX="$BIN/rish_shizuku.dex"
    ACTION="install"; SILENT_MODE=0; SOURCE_MODE="default"; SOURCE_PATH=""; SOURCE_PROVIDED=0

    if [ "$(id -u)" -eq 0 ]; then
    printf "\033[1;31m[x]\033[0m Please do not run this as root!\n" >&2
    exit 1
    fi

    while [ $# -gt 0 ]; do
    case "$1" in
    --uninstall) ACTION="uninstall" ;;
    --reinstall) ACTION="reinstall" ;;
    --silent) SILENT_MODE=1 ;;
    --source=*) SOURCE_MODE="${1#*=}"; SOURCE_PROVIDED=1 ;;
    --source) shift; SOURCE_MODE="$1"; SOURCE_PROVIDED=1 ;;
    --path=*) SOURCE_PATH="${1#*=}" ;;
    --path) shift; SOURCE_PATH="$1" ;;
    esac
    shift
    done

    if [ -t 1 ]; then
    C0='\033[0m'
    CR='\033[1;31m'
    CG='\033[1;32m'
    CY='\033[1;33m'
    CB='\033[1;34m'
    CC='\033[1;36m'
    else
    C0=''
    CR=''
    CG=''
    CY=''
    CB=''
    CC=''
    fi

    cancel(){ echo -e "${CY}[!]${C0} $1"; exit 0; }
    msg(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CB}[i]${C0} $1"; }
    ok(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CG}[+]${C0} $1"; }
    warn(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CY}[!]${C0} $1"; }
    err(){ echo -e "${CR}[x]${C0} $1"; exit 1; }
    step(){ [ "$SILENT_MODE" -eq 0 ] && echo -e "${CC}==>${C0} $1"; }

    cleanup() {
    [ -n "$TMP_SUBDIR" ] && rm -rf "$TMP_SUBDIR"
    }

    on_cancel() {
    echo -e "\n${CY}[!]${C0} Operation cancelled by user."
    exit 1
    }

    trap on_cancel INT
    trap cleanup EXIT

    if [ "$ACTION" = "uninstall" ]; then
    rm -f "$RISH" "$DEX" "$HOME/rish" "$HOME/rish_shizuku.dex"
    find "$HOME" -maxdepth 1 -type l -name "rish*" -delete || true
    echo -e "${CG}[+]${C0} rish has been removed."
    exit 0
    fi

    detect_pkg(){
    p="${PREFIX:-$(pwd)}"
    case "$p" in
    /data/data/*)
    echo "${p#/data/data/}" | cut -d/ -f1
    return
    ;;
    /data/user/*)
    echo "$p" | cut -d/ -f5
    return
    ;;
    esac

    if [ -n "$HOME" ]; then
    case "$HOME" in
    /data/data/*)
    echo "${HOME#/data/data/}" | cut -d/ -f1
    return
    ;;
    /data/user/*)
    echo "$HOME" | cut -d/ -f5
    return
    ;;
    esac
    fi

    echo "unknown"
    }

    PKG="$(detect_pkg)"
    [ "$PKG" = "unknown" ] && err "Package detect failed"

    if [ -f "$RISH" ] && [ "$ACTION" != "reinstall" ] && [ "$SILENT_MODE" -eq 0 ]; then
    echo -ne "${CY}[?]${C0} rish installed. Reinstall? [y/N]: "
    read -r c < /dev/tty
    case "$c" in
    y|Y) ACTION="reinstall" ;;
    *) cancel "Cancelled."; exit 0 ;;
    esac
    fi

    if [ "$SILENT_MODE" -eq 0 ] && [ "$SOURCE_PROVIDED" -eq 0 ]; then
    echo -e "\n${CB}Select source:${C0}\n 1) Offline (Extract app)\n 2) RikkaApps/Shizuku\n 3) thedjchi/Shizuku\n 4) Custom Repo\n 5) Direct URL\n 6) Local APK"
    printf "Choice [1-6]: "
    read src_choice < /dev/tty

    case "$src_choice" in
    1) SOURCE_MODE="local_app" ;;
    2) SOURCE_MODE="default" ;;
    3) SOURCE_MODE="thedjchi" ;;
    4)
    SOURCE_MODE="custom_repo"
    printf "Repo (user/repo): "
    read SOURCE_PATH < /dev/tty
    ;;
    5)
    SOURCE_MODE="custom_url"
    printf "URL: "
    read SOURCE_PATH < /dev/tty
    ;;
    6)
    SOURCE_MODE="local_file"
    printf "Path: "
    read SOURCE_PATH < /dev/tty
    ;;
    *)
    cancel "Invalid choice. Cancelled."
    ;;
    esac
    fi

    [ "$SILENT_MODE" -eq 1 ] && echo -e "${CG}[+]${C0} Starting silent rish installation..."

    RAND_ID="$RANDOM"
    TMP_SUBDIR="${TMPDIR:-/tmp}/rish.$RAND_ID"
    mkdir -p "$TMP_SUBDIR"

    PLAN_A=1
    for t in unzip sed grep install; do
    command -v "$t" >/dev/null 2>&1 || PLAN_A=0
    done

    if [ "$PLAN_A" -eq 1 ]; then
    UNZIP=unzip
    SED=sed
    GREP=grep
    INSTALL=install
    else
    warn "Using busybox"

    ARCH="$(uname -m)"
    case "$ARCH" in
    aarch64|arm64|armv8*) ARCH=arm64 ;;
    armv*|armhf|arm) ARCH=arm ;;
    x86_64|amd64) ARCH=x86_64 ;;
    i386|i686|x86) ARCH=x86 ;;
    *) err "Unsupported arch" ;;
    esac

    BB="$TMP_SUBDIR/busybox"
    step "Downloading BusyBox..."

    curl -fsSL "https://raw.githubusercontent.com/merbah3266/rish_installer/main/busybox/$ARCH/busybox" -o "$BB" || err "BB download failed"

    chmod +x "$BB"

    UNZIP="$BB unzip"
    SED="$BB sed"
    GREP="$BB grep"
    INSTALL="$BB install"

    ok "BusyBox ready."
    fi

    APK_PATH="$TMP_SUBDIR/app.apk"
    OFFLINE_OK=0

    if [ "$SOURCE_MODE" = "local_app" ] || [ "$SOURCE_MODE" = "default" ]; then
    step "Offline attempt..."

    EXTRACTED="$(cmd package path moe.shizuku.privileged.api --user 0 2>/dev/null | cut -d: -f2)"

    if [ -n "$EXTRACTED" ] && cp "$EXTRACTED" "$APK_PATH" 2>/dev/null; then
    ok "Local APK extracted"
    OFFLINE_OK=1
    elif [ "$SOURCE_MODE" = "local_app" ]; then
    cancel "Shizuku not found locally. Cancelled."
    else
    warn "Offline failed, falling back online..."
    fi
    fi

    if [ "$OFFLINE_OK" -eq 0 ]; then
    case "$SOURCE_MODE" in
    local_file)
    step "Using local file"
    [ -z "$SOURCE_PATH" ] && cancel "No path provided. Cancelled."
    [ ! -f "$SOURCE_PATH" ] && cancel "File not found. Cancelled."
    cp "$SOURCE_PATH" "$APK_PATH" || cancel "Copy failed. Cancelled."
    ok "Copied"
    ;;

    custom_url)
    step "Downloading from URL"
    [ -z "$SOURCE_PATH" ] && cancel "No URL provided. Cancelled."
    curl -fsSL -o "$APK_PATH" "$SOURCE_PATH" || cancel "Download failed. Cancelled."
    ok "Downloaded"
    ;;

    default|thedjchi|custom_repo)
    if [ "$SOURCE_MODE" = "default" ]; then
    REPO="RikkaApps/Shizuku"
    elif [ "$SOURCE_MODE" = "thedjchi" ]; then
    REPO="thedjchi/Shizuku"
    else
    REPO="$SOURCE_PATH"
    fi

    [ -z "$REPO" ] && cancel "No repo provided. Cancelled."

    step "Fetching from $REPO..."

    URL="$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\.apk\)".*/\1/p')"

    [ -z "$URL" ] && cancel "URL fetch failed. Cancelled."

    step "Downloading APK..."
    curl -fsSL -o "$APK_PATH" "$URL" || cancel "Download failed. Cancelled."
    ok "Downloaded"
    ;;

    *)
    cancel "Invalid source. Cancelled."
    ;;
    esac
    fi

    step "Extracting..."
    $UNZIP -qq "$APK_PATH" -d "$TMP_SUBDIR" || err "Unzip failed"

    [ ! -f "$TMP_SUBDIR/assets/rish" ] && err "rish not found"
    [ ! -f "$TMP_SUBDIR/assets/rish_shizuku.dex" ] && err "dex not found"

    SH_PATH="$(command -v sh)"
    [ -z "$SH_PATH" ] && err "sh not found"

    TMP_RISH="$TMP_SUBDIR/rish.$RAND_ID"

    echo "#!$SH_PATH" > "$TMP_RISH"
    $GREP -v '^#' "$TMP_SUBDIR/assets/rish" >> "$TMP_RISH"
    $SED -i "s/PKG/$PKG/g" "$TMP_RISH"

    step "Installing..."
    INSTALL_SUCCESS=0

    if $INSTALL -m755 "$TMP_RISH" "$RISH" 2>/dev/null &&
    $INSTALL -m400 "$TMP_SUBDIR/assets/rish_shizuku.dex" "$DEX" 2>/dev/null; then
    ok "Installed to bin ($BIN)"
    ln -sf "$RISH" "$HOME/rish" 2>/dev/null
    ln -sf "$DEX" "$HOME/rish_shizuku.dex" 2>/dev/null
    INSTALL_SUCCESS=1
    else
    warn "Bin failed, trying Home..."

    if $INSTALL -m755 "$TMP_RISH" "$HOME/rish" 2>/dev/null &&
    $INSTALL -m400 "$TMP_SUBDIR/assets/rish_shizuku.dex" "$HOME/rish_shizuku.dex" 2>/dev/null; then
    ok "Installed to Home"
    INSTALL_SUCCESS=1
    fi
    fi

    if [ "$INSTALL_SUCCESS" -eq 1 ]; then
    [ "$SILENT_MODE" -eq 1 ] &&
    echo -e "${CG}[+]${C0} Success: rish installed." ||
    ok "Setup complete. Run 'rish' or '~/rish'"
    else
    err "Installation failed"
    fi
    ----- < above is the Shizuku rish installer > ------

    SOFTWARE:

    *Termux* by Fredrik Fornwall
    <https://packages.termux.dev/>
    <https://github.com/termux/termux-app>
    <https://f-droid.org/en/packages/com.termux/>
    <https://f-droid.org/repo/com.termux_118.apk>
    Warning: Google Play versions of Termux are deprecated:
    <https://play.google.com/store/apps/details?id=com.termux>

    *Rish* (remote interactive shell) installer
    <https://github.com/merbah3266/rish_installer>

    *Shizuku* by Xingchen & Rikka
    <https://github.com/RikkaApps/Shizuku>
    <https://play.google.com/store/apps/details?id=moe.shizuku.privileged.api>

    *ShizuShell* by Nindle Studio
    <https://play.google.com/store/apps/details?id=com.noxinfinity.shell>

    *Local adb*
    <https://github.com/tytydraco/LADB>
    <https://play.google.com/store/apps/details?id=com.draco.ladb>

    *Android Debug Bridge* (adb)
    Windows:
    <https://dl.google.com/android/repository/platform-tools-latest-windows.zip>
    macOS:
    <https://dl.google.com/android/repository/platform-tools-latest-darwin.zip>
    Linux:
    <https://dl.google.com/android/repository/platform-tools-latest-linux.zip>
    --
    Some things are so unintuitive that we need a tutorial to do them.
    --- Synchronet 3.22a-Linux NewsLink 1.2