# superintelligence-android
Fork of [superintelligence (JG2HQZWB/superintelligence)](https://notdouble.com/p/JG2HQZWB/superintelligence) — the same
hands-on LLM agent, ported from a Rust terminal CLI to an **Android app**: Kotlin +
Jetpack Compose, a streaming OpenAI-compatible client, and dialogs instead of
`[Y/n]` prompts.
## What it does
Point the app at any OpenAI-compatible server (llama-server, LiteLLM, vLLM —
anything exposing `/v1/chat/completions` and streaming SSE) and it behaves like
the CLI original:
- **Streams replies** (SSE) with tool-call deltas assembled as they arrive.
- **Tools** the model can call, scoped to the app's private working directory
(`Android/data/net.kentonc.si/files`):
- `read_file(path)`
- `list_dir(path?)`
- `search(pattern, path?, include?)` — regex walk, skips binaries/`.git`/`target`/…
- `write_file(path, content)` — **approval dialog**
- `run_shell(command)` — runs `sh -c` in the working root, 60s timeout — **approval dialog**
- **Image attachments** via the system photo picker (png/jpeg/gif/webp, 20 MB cap).
- **Markdown replies** rendered with a small built-in renderer (headings, lists,
code fences, blockquotes, inline formatting).
- Approvals: `write_file` / `run_shell` pop a dialog; the tool stays parked
(a `CompletableDeferred`) until you tap **Run it** / **Decline**. Declines are
reported back to the model exactly as the CLI does. Settings has an
auto-approve switch, equivalent to the CLI's `--yes`.
The same guardrails from the Rust port carried over: paths can't escape the
working root, tool output is truncated (16 KB), shell commands time out at 60s,
a tool-budget of 50 rounds per turn, and on any error the turn's messages are
rolled back out of the history.
## Config
Everything else you'd find in `src/config.rs` in the CLI owner is editable in
the app's **Settings** screen (persisted in SharedPreferences): base URL, API
key, model, temperature, max tokens, auto-approve.
Settings default mirrors the CLI (`http://127.0.0.1:8085`, model
`Qwen3.8-27B-GSQ-RCO-IQ3_XXS-mtp.gguf`) — point it at a server on your LAN
instead (Ollama is `http://<ip>:11434`, llama-server is `http://<ip>:8085`).
Cleartext http is allowed on purpose for exactly that. Opening Settings
auto-lists the models the selected server serves — from Ollama's `/api/tags`
(with on-disk sizes) or any OpenAI-compatible `/v1/models` — as a dropdown, so
you never have to type a model name; typing a custom one still works.
## Build
Requires Android SDK (platform 35, build-tools 35) and a JDK 17+:
```sh
cd android && ./gradlew :app:assembleDebug
# -> android/app/build/outputs/apk/debug/app-debug.apk
```
Gradle 8.10.2 + AGP 8.7.3 + Kotlin 2.0.21 + Compose BOM 2024.12.01. A wrapper
is included, so no local Gradle install is needed.
Install on a device:
```sh
adb install android/app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n net.kentonc.si/.MainActivity
```
## Install the APK
A ready-to-install debug APK ships **inside this project's bundle** (releases
tab → "artifacts in the bundle"), extracted under `bin/`. The name embeds the
release version, e.g.:
```sh
tar -xf superintelligence-android.tar.gz bin/superintelligence-android-0.2.3.apk
adb install bin/superintelligence-android-0.2.3.apk
adb shell am start -n net.kentonc.si/.MainActivity
```
It's the standard debug signature (installable directly); versionName matches
the project version on the hub.
## In-app self-update
From **0.2.3 on**, the app checks the hub on launch and shows a deep-update
icon in the top bar whenever `notdouble.com` has a newer release than the
installed build. Tap it: it downloads the new APK into app cache (with an in-bar
progress ring) and launches the system installer. The first update needs the
"allow installs from this app" toggle (Android requires it for anything
sideloaded); the app walks you to it, remember to come back and tap the button
again. After that first grant, updates are one tap with no re-download of
anything.
## Build the Rust original is still here
This fork deliberately kept the original CLI sources untouched — `src/`,
`Cargo.toml`, and `make build` still produce the `si` terminal binary on any
machine. The Android port is a sibling of the CLI, not a replacement of it; both
share the same mental model of tools and approvals.
## Layout
```
android/ the new thing: the Android app
app/src/main/java/net/kentonc/si/
agent/ Agent.kt LlmClient.kt Tools.kt Models.kt Settings.kt (the port of src/llm.rs + src/tools.rs + src/config.rs)
ui/ ChatScreen.kt SettingsScreen.kt MarkdownText.kt Theme.kt
AgentViewModel.kt MainActivity.kt
src/ the original Rust CLI (unchanged)
```
## Publish to the hub
```sh
make upload # nd validate && nd upload
```
This directory ships to the hub as `JG2HQZWB/superintelligence-android`
(fork lineage points at `JG2HQZWB/superintelligence`). Build artifacts
(`target/`, Gradle `build/` dirs, APKs) are excluded via `.ndignore`.