Skip to content
Zain Mahmood
Selected work

Rescripto

Paste a rough message, pick a tone, and get back something you would actually send. Rewriting runs on the phone through llama.cpp by default, and every request the app makes passes through one guard that checks policy before anything leaves the device.

Type
Android app
State
Active · v1.3.1
Role
Solo, end to end
  • Flutter
  • Dart
  • llama.cpp
  • whisper.cpp
  • Kotlin + C++ JNI
  • SQLite
Rescripto rewrite screen with tone, intensity and length options
Where a rewrite runs, from the README
ModeRuns onText leaves the phone
LocalThe phoneNever for a rewrite
CloudYour providerEvery rewrite, to the model you chose
HybridPhone firstLong text, or a failed local rewrite you approve

At a glance

  • llama.cpp and whisper.cpp running on the phone
  • Own Flutter plugin in Kotlin and C++ over JNI
  • Signed APK and AAB built from a git tag

What I owned

Solo project. The Flutter app, the llama.cpp Flutter plugin (Kotlin and C++ over JNI), whisper.cpp dictation, local, cloud and hybrid routing, the network policy layer, encrypted backups and WebDAV sync, and the signed release pipeline.

Decisions, and what they cost

  1. One choke point for the network

    Every request from the app's Dart code goes through NetworkGuard, which checks the current policy and then logs the host and path. Headers, bodies, query strings and credentials are never logged. A lockdown button turns on the kill switch, cancels running requests, disables providers and deletes saved API keys in one step.

    What I gave upNo analytics, crash reporting or update checks. Bugs on real devices reach me only when someone reports them, which is a slower feedback loop I accepted on purpose.

  2. Four CPU builds of llama.cpp in one APK

    Android phones span a wide range of ARM instruction sets. The APK carries four builds of the llama.cpp CPU backend and loads the one that matches the phone, from plain ARMv8.0 up to ARMv8.6 with int8 matrix multiplication. Older phones get the baseline build instead of crashing on instructions they do not have.

    What I gave upA heavier APK, and no GPU path at all. The Vulkan backend needs system libraries that Android 7 does not ship, and supporting Android 7 won.

  3. The app bar always says where the next rewrite runs

    Local mode never sends a rewrite anywhere. Cloud mode uses the provider and key you set up. Hybrid starts on the phone and only goes to the cloud for long text (about 1,500 characters) or when a local rewrite fails and you agree. A chip in the app bar shows the destination before you press the button.

    What I gave upHybrid asks before sending text off the phone, which interrupts a rewrite with a prompt. Falling back from a failed cloud request to the phone happens silently, because keeping text local is never a privacy cost.

Known limitations

  • arm64-v8a only, Android 7.0 or newer. No iOS build.
  • On-device inference is CPU-only. Rewrite models are 769 MB to 1.9 GB each.
  • Android auto-backup is off by design, so moving phones means an encrypted export or WebDAV sync.
  • An F-Droid build is being prepared but is not published.

Where it stands

v1.3.1 released September 2026. 14 tones plus custom ones, workflows that chain rewrite steps, dictation with whisper.cpp or a cloud provider, resumable model downloads from Hugging Face, and a text-selection action that works from any app. The release APK now matches the F-Droid build byte for byte.