{"id":51251771,"url":"https://github.com/f321x/ntrack","last_synced_at":"2026-06-29T07:30:34.809Z","repository":{"id":364776311,"uuid":"1267389051","full_name":"f321x/ntrack","owner":"f321x","description":"FOSS implementation of the Nostr-based Gart location sharing protocol","archived":false,"fork":false,"pushed_at":"2026-06-14T13:08:59.000Z","size":281,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-14T13:21:10.459Z","etag":null,"topics":["android","foss","gart","gps","location","location-sharing","nostr","rust","slint","slint-ui","tracking"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/f321x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T13:49:54.000Z","updated_at":"2026-06-14T13:08:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/f321x/ntrack","commit_stats":null,"previous_names":["f321x/ntrack"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/f321x/ntrack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f321x%2Fntrack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f321x%2Fntrack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f321x%2Fntrack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f321x%2Fntrack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/f321x","download_url":"https://codeload.github.com/f321x/ntrack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f321x%2Fntrack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34918101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","foss","gart","gps","location","location-sharing","nostr","rust","slint","slint-ui","tracking"],"created_at":"2026-06-29T07:30:31.989Z","updated_at":"2026-06-29T07:30:34.802Z","avatar_url":"https://github.com/f321x.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ntrack\n\n**Live location sharing over Nostr — end-to-end encrypted, pseudonymous, serverless.**\n\nAn Android app (Rust + [Slint](https://slint.dev) UI) that shares your live location with a\nchosen group of people. Locations are NIP-44 encrypted, so relays only ever see ciphertext from a\nthrowaway sender key — no accounts, no central server, any Nostr relay works. The wire protocol is\na small Nostr convention built on `kind:3434` events — see [docs/PROTOCOL.md](docs/PROTOCOL.md).\n\n## How it works\n\nA **group** is a shared keypair. Hand its secret key (`nsec…`) to the people who should see you —\nholding it lets them decrypt, the public key (`npub…`) is enough to send. Distribute keys over a\nsecure channel: the key *is* the membership, so rotate it whenever membership changes.\n\n**Inviting someone** — a group's *Share key* dialog shows a QR code and a tappable\n`ntrack://join?n=\u003cname\u003e\u0026k=\u003ckey\u003e` link that bundles the group **name** with its key, so the\nrecipient never retypes anything. They can **scan** it (Groups → *Scan QR code*), **tap** the link\n(ntrack opens with the import form pre-filled), or copy/paste the string. A bare `nsec…`/`npub…`\nstill works too. For a member invite the link carries the secret, so share it over a secure\nchannel — exactly as you would the bare `nsec`.\n\n- **Share** — publishes your encrypted location from a sender key that's never linked to a personal\n  Nostr identity. Updates are velocity-based — frequent while you're moving, sparse while you're\n  still — using a built-in preset (Battery saver / Normal / High) or a custom scheme you define.\n- **Track** — subscribes to your groups, verifies + dedups + decrypts incoming events, and shows\n  each sender live with an \"open in maps\" shortcut.\n- **Alert** — for dangerous situations: one tap raises a duress alert (starting a share if you\n  weren't already) that speeds up your updates and fires a loud, pinned notification on every group\n  member's phone. Arm a **check-in** timer and ntrack escalates to that alert automatically if you\n  don't confirm you're safe in time — even across a reboot.\n\nFull protocol ↔ implementation ↔ test mapping: [docs/PROTOCOL.md](docs/PROTOCOL.md).\n\n## Build the APK\n\nOnly Docker is required — the Android SDK/NDK, Gradle, and Rust toolchain all live in the builder\nimage.\n\n```sh\n./build.sh                          # → dist/ntrack-debug.apk\nadb install -r dist/ntrack-debug.apk\n```\n\n- Default ABI is `arm64-v8a`; for an emulator use `ABIS=\"arm64-v8a x86_64\" ./build.sh`.\n- The first build is slow (downloads the toolchain and compiles everything); caches make the rest\n  fast.\n- Podman is auto-detected if Docker is absent. Behind a TLS-inspecting proxy, drop its CA `.crt`\n  into `docker/certs/` (see `docker/certs/README.md`).\n\n### Releases\n\nTagged releases (`v*`) publish a signed APK two ways: to the repository's **Releases**\npage on GitHub (download `ntrack-\u003cversion\u003e.apk` and `adb install` it) and to the\n[Zapstore](https://zapstore.dev) app store (install and auto-update over Nostr).\nMaintainers: see [docs/RELEASING.md](docs/RELEASING.md) for the one-time signing-key\nsetup and how to cut a release.\n\n## Develop\n\n```sh\ncargo test --workspace                      # protocol, engine, config, relay-pool tests\ncargo clippy --workspace --all-targets\ncargo run -p ntrack-app --features desktop  # run the app on desktop (simulated GPS walk)\n```\n\nThe desktop build is the fastest way to iterate — it talks to real relays and is fully\ninteroperable with the Android build.\n\n```\ncore/      ntrack-core — protocol, keys, relay pool, engine (no UI)\napp/       ntrack-app  — Slint UI, controller, Android JNI glue, desktop sim\nandroid/   Gradle project — NativeActivity shell + foreground location service (plain Java)\ndocker/    builder image (SDK 34, NDK r27, Gradle 8.11)\ndocs/      PROTOCOL.md — protocol ↔ implementation ↔ tests\n```\n\n## Security \u0026 privacy\n\n- Locations are end-to-end encrypted (NIP-44 v2); relays see only `kind:3434` ciphertext and\n  pubkeys.\n- Anyone with a group's `nsec` can decrypt its past *and* future locations — **rotate the key when\n  membership changes** (Groups → Rotate). The sender key is rotatable too (Settings).\n- Secrets live in private app storage and are never logged. Processed event ids are persisted, so a\n  malicious relay can't replay old locations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff321x%2Fntrack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ff321x%2Fntrack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff321x%2Fntrack/lists"}