"Sovereign Edge" is a working codename tied to this repo's directory name — not a decided consumer-facing product name.
A privacy-first, fully offline AI companion for phones. You download a small language model (Gemma, Qwen, Phi, or similar) straight to your own device and talk to it with zero network requests from the chat itself — not as a promise, but because the chat and inference path contains no network code.
On top of that offline core sits an optional, explicitly-permissioned connector layer: a small set of agents that can reach outside the device — to search the web, or create a task in your own self-hosted software — but only once you have granted that specific connector that specific permission.
Fully standalone. No runtime dependency on sovereign,
and it works with zero knowledge that sovereign exists.
This repo is a pnpm workspace: apps/mobile is the shipping product below;
apps/desktop is a Tauri v2 app (see
research 0010) with epics 12
(Core Port) and 13 (App Shell) done — real on-device inference, connectors,
and a full navigation/settings UI, one release (v0.1.5) already published;
packages/* are internal, unpublished code shared between them.
See CONCEPT.md for the full concept paper.
Early development — not a release. No store build exists yet — not because the build tooling is missing (task 0.3 is done: both platforms have declarative signing and a local/CI release pipeline), but because App Store Connect and Play Console listings (task 8.2) need a paid Apple Developer Program membership and a Google Play Console account, neither of which exists yet. That task is deliberately parked rather than blocking everything else — see its epic for what's actually missing.
The offline core and the Search connector (Tier 1 — reaches the network, with explicit per-connector permission) both work on real hardware. Phase 2's first Tier 3 connectors — Calendar and a small Device Utilities connector, both purely on-device, no network at all — are done, on mobile and desktop. Phase 3's connector SDK, plugin template, public registry, and in-app Connector Store are also done. The Sovereign Tasks connector is next. See ROADMAP.md for the exact sequence.
| Area | State |
|---|---|
| Offline chat (epic 1) | ✅ Complete — streaming replies, model manager, writing-assist modes |
| Zero-network enforcement (1.5) | ✅ Enforced in CI, not just intended — see network audit |
| Design system, app shell (7, 8.1) | ✅ Theme tokens, core components, navigation, settings |
| Native build tooling (0.3) | ✅ Declarative signing (both platforms), local + CI release scripts |
| Connector framework + Search connector (2, 3) | ✅ Complete — manifest, permissions, routing, runtime, in-chat provenance, Tier 1 shipped |
| Tier 3 connectors — Calendar, Device (2.6, 10, 11) | ✅ Complete — Calendar and Device (brightness, torch), mobile + desktop |
| Connector Store, SDK, registry (5) | ✅ Complete — SDK, plugin template, public registry, in-app store |
| Entitlement model (6.1) | ✅ Complete |
| Desktop app — Core Port, App Shell (12, 13) | ✅ Complete — real inference, connectors, navigation, settings; v0.1.5 published |
| Sovereign Tasks connector (4) | 📋 Planned — Phase 2, next up |
| Tier 2 sandboxed script runtime (5.6) | 📋 Planned — Phase 3 |
| Store release (8.2) | 📋 Parked — needs a paid Apple Developer Program + Google Play Console account |
Measured on an iPhone 15 Pro (Release build, Metal active): Qwen2.5 0.5B generates at 86–91 tok/s with a 233 ms cold time-to-first-token, and takes 8.7 s to load — the GPU upload that buys the generation speed.
ROADMAP.md is the canonical task status. Anything else claiming progress is a summary and may lag.
Two trust tiers, both visible to the user:
- Chat — fully local, fully offline, always.
llama.cpp/GGUF viallama.rn. Nothing in this layer makes a network call. - Connectors — an explicit, permissioned layer. Each connector requests its own permission, separately revocable, and the UI shows which connector (if any) acted for a given reply — whether it reached the network (Tier 1) or an on-device OS capability like the calendar (Tier 3).
Connectors are tiered by how much trust they require — declarative manifests (no code, open to any developer), sandboxed transform scripts, and first-party native modules. CONCEPT.md explains why that split exists and what mobile app stores actually allow.
Everything below is about apps/mobile — the original shipping product. See
apps/mobile/AGENTS.md for the full command list and
environment quirks; see apps/desktop/AGENTS.md for
the desktop equivalent — epics 12 (Core Port) and 13 (App Shell) are done.
-
Node 24.x (see .node-version) and
pnpm11 -
iOS: macOS with Xcode 26+ and CocoaPods. Xcode 26 is a hard floor — Expo SDK 57 pulls a Swift package requiring Swift tools 6.2, and older Xcode fails at package resolution with an error naming neither.
-
Android: JDK 17 and the Android SDK (API 34+)
-
A UTF-8 locale. CocoaPods calls
String#unicode_normalizeon the install path, which throwsEncoding::CompatibilityErrorwhenLANGis unset and Ruby falls back to ASCII-8BIT. The traceback points atverify_podfile_exists!, so it reads as a missing Podfile rather than a locale problem. IflocaleshowsLC_CTYPE="C", add to your shell profile:export LANG=en_US.UTF-8 # or C.UTF-8
CI runners set this already, so it only bites locally.
git clone https://github.com/sovereignfs/sovereign-edge.git
cd sovereign-edge
pnpm install # installs the whole workspacepnpm ios # build and run on an iOS simulator
pnpm android # build and run on an Android emulatorBoth commands run expo prebuild first if needed, then compile natively.
The first run takes a while; later runs are incremental.
Expo Go does not work here, by design.
llama.rnis a native module, so a development build is the only supported workflow.pnpm startassumes a dev client is already installed.
Prefer pnpm ios over driving xcodebuild by hand. A bare
xcodebuild -sdk iphonesimulator with no -destination leaves
ONLY_ACTIVE_ARCH unable to resolve an active architecture, so it builds
every standard arch including x86_64 — which fails on Apple Silicon, because
Expo's prebuilt XCFrameworks ship no x86_64 simulator slice. If you do invoke
it directly, pass a concrete destination:
cd apps/mobile
xcodebuild -workspace ios/SovereignEdge.xcworkspace -scheme SovereignEdge \
-configuration Debug -destination 'platform=iOS Simulator,name=iPhone 17' \
-derivedDataPath ios/build CODE_SIGNING_ALLOWED=NO buildIf an iOS build fails complaining about a missing workspace, check whether
apps/mobile/ios/Pods exists. expo prebuild can exit 0 with its internal
pod install having failed, and the .xcworkspace is created by
pod install — so the first visible symptom appears one step later than the
actual failure.
| Command | Does |
|---|---|
pnpm start |
Metro bundler for an installed dev build |
pnpm ios |
Build and launch on an iOS simulator |
pnpm android |
Build and launch on an Android emulator |
pnpm prebuild |
Regenerate ios/ and android/ from scratch |
pnpm test |
Jest |
pnpm typecheck |
tsc --noEmit |
pnpm lint |
ESLint |
pnpm check:offline |
Walks imports from src/chat/ for a socket path |
pnpm format |
Prettier (code only — Markdown is left alone) |
apps/mobile/ios/ and apps/mobile/android/ are gitignored.
apps/mobile/app.json plus Expo config plugins are
the source of truth, and expo prebuild regenerates the native projects from
them — so hand-edits inside ios/ or android/ are lost on the next
prebuild. Native configuration belongs in app.json or a config plugin.
Rationale, along with why this project excludes expo-updates and EAS Build,
is in research 0002.
sovereign-edge/
├── apps/
│ ├── mobile/ # the shipping product — see apps/mobile/AGENTS.md
│ │ ├── src/ # chat, models, connectors, design-system, settings
│ │ └── ...
│ └── desktop/ # Tauri v2, epics 12 + 13 + 15 done, v0.1.5 published
│ # — see apps/desktop/AGENTS.md
├── packages/ # internal, unpublished, shared between the apps
│ ├── core/ # empty scaffold — connector manifest/permissions/
│ │ ... # routing, eventually extracted from apps/mobile
│ ├── design-tokens/
│ ├── mobile-ui/ # empty scaffold, same as core/
│ ├── desktop-ui/
│ └── connector-sdk/ # the one package meant to be published (task 5.1)
├── docs/
│ ├── epics/ # task breakdown per work stream, tagged by Scope
│ └── research/ # decision records
└── ...
See apps/mobile/AGENTS.md for the full src/
breakdown — chat/, models/, connectors/, design-system/, settings/,
shared/, one directory per epic.
models/ is a sibling of chat/ rather than a child, and that is deliberate:
acquiring a model is a visible, user-initiated download, while using one
never touches the network. Keeping them separate is what lets the rule below
be enforced mechanically.
Chat code must not import anything that opens a socket. That is checked,
not just documented — in apps/mobile, pnpm lint restricts imports and
network globals inside src/chat/, and pnpm check:offline walks the import
graph to catch a transitive route lint cannot see. See
docs/network-audit.md for what each mechanism covers
and, more importantly, what it does not.
Two workflows, split so the slow native jobs don't gate every PR:
- CI — lint, format, typecheck, and test on every PR. Nothing here
downloads model weights;
jest.setup.jsmakesfetchthrow, so an accidental network call fails the run. - Native build — on
mainand manual dispatch. Builds Release for both platforms, installs, launches, and asserts the process is still alive ten seconds later. Release rather than Debug because a Debug build loads its JS from a Metro server and so proves nothing about launching standalone.
- CONCEPT.md — concept paper: vision, architecture, phasing
- ROADMAP.md — chronological task index and canonical task status
- docs/network-audit.md — how the offline claim is enforced, what each mechanism misses, and the commands to check it yourself
- CONTRIBUTING.md — setup, branching, commits, PRs, CI
- docs/development-workflow.md — task lifecycle and how these documents fit together
- docs/epics/ — task detail per work stream, split into
mobile//desktop//shared/by each epic's ownscopefrontmatter - docs/research/ — decision records and the reasoning behind them
- AGENTS.md — shared agent-facing conventions and hard
architectural rules (
CLAUDE.mdpoints here) - apps/mobile/AGENTS.md / apps/desktop/AGENTS.md — per-app commands, native build mechanics, environment quirks
AGPL-3.0-or-later, matching the wider sovereignfs ecosystem.