Nostr git hosting on gittr: mirror code from any forge, run issues and pull requests with signed events, publish Pages, discover apps, and use Lightning bounties. Import from GitHub, GitLab, or Codeberg when you want a backup — not because gittr is a copy of another site. What is Nostr git?
NIPs & event kinds: Nostr schemata on gittr (nostrability) — e.g. NIP-34 for git repos, issues, and PRs.
index.html then Push Manifest). README pagelink and custom site name are optional. Browse the directory at /pages. Owner tools live in the Code sidebar under Nostr Pages . How-to: Publish Pages, Apps & Releases.git.gittr.space like any other git host. SSH Keys.For better security, download a NIP-07 browser extension like:
On mobile browsers: Mobile browsers don't support browser extensions. Install Nowser to sign via NIP-46/NIP-07, or use a remote signer (NIP-46) with a hardware device.
Once installed, the extension will automatically detect when you visit the login page and allow you to sign in securely.
You can create a new repository or import from GitHub/GitLab/Codeberg. There are three ways to get started:
Import an existing repository from GitHub, GitLab, or Codeberg:
owner/repo (e.g. arbadacarbaYK/gittr)https://github.com/owner/repoLoad a GitHub user/org list, then choose what to import. Opening the bulk page does not import anything until you fetch, select, and confirm. GitHub only — GitLab / Codeberg / Gitea need Option 1 with a full URL (one repo at a time).
Web UI: Open the repo → Upload (or land there after Create empty). Drag & drop files or whole folders; nested paths like src/app/page.tsx are kept. Then Push to Nostr when ready.
Upload first syncs your browser to the published tip (when you have no unpushed edits), then merges your new files on top — so an older local cache cannot overwrite a newer Nostr/bridge state. If you already have unpushed local edits, upload merges into those instead (use Refresh from gittr only if you want to discard them).
If the Code tab already shows files from the network but Upload / Push complains about nothing local, use Refresh from gittr once (sidebar) so your browser stores a copy. Upload then merges your new files on top; Push publishes the combined tree.
Git CLI: after creating an empty repo, you can also push via Git:
git clone [email protected]:<pubkey>/<repo>.gitgit add . && git commit -m "Initial commit"git push origin mainImported repos already include files in the UI. The bridge only shows committed/pushed trees for empty creates.
Go to Settings → Account to configure LNbits (send/receive keys), Lightning address (lud16 / lnurl receive), or NWC. Repository-specific overrides live under each repo's Settings → Payment configuration.
gittr is installable as a Progressive Web App (PWA) on modern browsers. This gives you an app icon, standalone window, and offline fallback page.
Other Nostr app stores look for a GitHub Release with an .apk. Tagging v* on arbadacarbaYK/gittr builds a thin app (space.gittr.app) that opens gittr.space — same site as this PWA, not an offline self-hosted copy. Sign in with Amber / a remote signer; browser extensions are not inside the APK. After the Release exists, announce that tag from this repo’s Releases tab or Code sidebar Nostr Apps (NIP-82). Use app id space.gittr.app (the Android package — not space.gittr.gittr). zapstore.yaml in the git repo is what Zapstore uses to whitelist the publisher (icon + images: screenshots under ui/public/zapstore/, 1080×1920, gallery order: repo Code, Apps, Pages, Repos list, Appearance). Other apps put the same images: field in their source-repo zapstore.yaml (repo paths or https links); gittr copies those onto the Nostr listing when you Publish on Nostr.
Already on this APK? Open the user menu (your avatar, or the phone hamburger if you are signed out) and tap Update app. gittr checks GitHub for a newer installer and opens the download in your system browser. The Apps page card for space.gittr.app uses that same GitHub latest so it does not lag Zapstore. Pages inside the app already match the live website; you only need a new APK when the wrapper itself was rebuilt.
Note: In-app browsers (Telegram/Twitter, etc.) often block PWA install. Open in the system browser. Offline mode only shows a fallback screen and does not replace full online functionality.
You can create repositories in three ways:
createRepo (HTTPS + nsec, no SSH). Operators can use gn repo create. Same git host as the website.All repos are stored locally in your browser and can be pushed to Nostr for public access. Tip: After Create empty, use Upload (files or folders, drag & drop) or push via Git — then Push to Nostr for public access.
📖 Complete Workflow for Empty Repositories
After creating an empty repository (website, MCP createRepo, or gn):
gn ssh-key add). The website is not in the SSH path after that.git clone [email protected]:<your-npub>/<repo-name>.git or HTTPS https://git.gittr.space/<hex>/<repo>.gitgit add . && git commit -m "Initial commit"git push origin mainFiles will appear in the web UI after pushing. See Git Operations section for detailed instructions.
a tag set each time).Repo Settings → Repository Links adds documentation, Discord, Slack, YouTube, Twitter, GitHub, or other URLs. They show on the repository page below contributors — a YouTube video or a social post is a valid docs link, not only a README.
Owners use Delete Repository on the repo Settings page. You must sign. gittr publishes a Nostr deletion marker so other clients see it gone, hides it locally, and best-effort removes related Pages and app announces. This cannot be undone.
View, edit, and delete files or folders directly in the browser (owners: trash icon on each Code tree row, or Delete while a file is open). Deleting a folder marks it and everything inside for removal — the next Push to Nostr deletes it on the git host (GRASP / bridge), not just in this browser. Use the fuzzy file finder (Cmd/Ctrl+P) to quickly navigate large repositories.
Files live on git hosts (GRASP / gitnostr bridge), not inside Nostr events. NIP-34 announcements carry metadata and clone[] URLs. The Code sidebar shows where the tree is loading from: bridge / GRASP, GitHub, GitLab, and so on. Legacy “embedded in the event” trees are rare.
Bring an existing remote into gittr, then Push to Nostr so others can discover and clone it from GRASP / the bridge (not only from the original host). Details: When your git host goes dark.
git clone. Bulk import is GitHub-only. Forgejo/Gitea (including Codeberg and self-hosted) uses the same paste-URL import; Issues, PRs, and Releases then refresh from /api/v1. Nostr Pages and app announce work the same as for GitHub once a Release exists on that forge.npub…/repo, a gittr.space repo page, or a git.gittr.space clone URL on Option 1. The Fork button on a repo page uses the same import (parent files, not an empty About stub).gittr does not treat every git website the same under the hood. After you import, it refreshes metadata (fork parent, stars, issues, pull requests, releases) using one of three API families:
GitHub API → github.com
Bulk import, OAuth linking, and GitHub-specific metadata. Uses GitHub's REST API (/repos/…).
GitLab API → gitlab.com (and similar)
Paste a GitLab clone URL on Create repository. gittr uses GitLab's v4 API for fork parent lookup, files, and Releases. Issues and merge requests are not live-synced yet (that is still the GitLab half of GitHub issue #27). Self-hosted GitLab instances with the same API shape work the same way for files.
Gitea / Forgejo API (/api/v1) → Codeberg, gitea.com, self-hosted Forgejo / Gitea
Forgejo is open-source forge software (a community fork of Gitea). Codeberg ( codeberg.org) is a popular public site that runs Forgejo — not a separate product. They share the same URL layout (host/owner/repo) and the same REST API, so gittr handles Codeberg, gitea.com, and your own Forgejo/Gitea server with one code path. Import is always paste-URL + git clone; Issues, PRs, Releases, and fork badges then refresh from /api/v1.
In short: GitHub, GitLab, and Gitea/Forgejo are three different "languages" gittr speaks for files. Issue and PR lists live-sync from GitHub and from Codeberg/Gitea. GitLab issues/MRs are not in that loop yet.
GitHub import (/api/import) returns file paths and metadata, not file bodies. If that JSON is still larger than ~4 MB (very large trees), you get Repository is too large / repo_too_large. Import a smaller repo, or use a URL clone + Push to Nostr so the bridge holds the objects.
Paste-URL imports (/api/import-git) do not use that same 4 MB metadata cap. Huge binaries still belong in git LFS / releases on a real git host, not in the browser editor.
Privacy on gittr is tied to your Nostr pubkey, not your GitHub username. Settings → Private publishes ["public-read","false"] on kind 30617 (gittr extension; not core NIP-34). After Push, listings and the bridge honor that.
maintainers can open private repos (web, SSH, HTTPS).permission denied for read operation— ask the owner to add your npub.gittr.space repositories support multiple clone URL formats:
Option A: SSH (Standard Git - Recommended)
git clone [email protected]:npub1.../repo-name.gitFor laptop Git, like GitHub. Publish your public key once (Settings → SSH Keys, or gn ssh-key add). After that, clone/push never go through the website.
Option B: HTTPS (GRASP git servers)
git clone https://git.gittr.space/<owner-pubkey>/repo-name.gitSame bare repo as SSH. Public clones work over HTTPS. gittr-mcp pushes over HTTPS + a local nsec (no SSH, no Amber). Authenticated HTTPS is not read-only.
Option C: nostr:// Protocol (Ecosystem Standard)
git clone nostr://[email protected]/repo-nameRequires git-remote-nostr. This helper translates nostr:// URLs into standard Git fetches and is used by other NIP-34 clients.
Install git-remote-nostr
pip install git-remote-nostr (Python 3.10+)which git-remote-nostr)How it works:
Once installed, git clone nostr://… works with or without SSH keys - git-remote-nostr automatically chooses the best option.
SSH, HTTPS, and nostr:// clone URLs all ship inside every NIP-34 repository event. Pick whichever matches your workflow.
NIP-34 events carry metadata (name, description,clone[] URLs) — not the full file tree. gittr loads the tree from git servers and our bridge mirror.
source or GitHub clone URL existsclone[] (in parallel): read our on-disk mirror, or shallow-clone that URL directly, or mirror it onto gittr then readIf one mirror is down (502) but another works (e.g. relay.ngit.dev), you still get files from the working URL. The status chip on the repo shows ✓/✗ per source.
SSH / CLI vs Code tab: git clone [email protected]:… reads the same bridge bare repo the Code tab uses. The website additionally walks published clone[] /source URLs (forge first, then GRASP mirrors). File timestamps on the Code list come from the selected tip/branch on that mirror. Nostr Backups should list every pushable GRASP host from the event (not only git.gittr.space). After a clean Push with a forge source, the tip should match the forge — not a new empty “Push from gittr” commit. Details: FILE_FETCHING_INSIGHTS.md.
Newest metadata: we use the latest kind 30617 from relays. Newest commit across all mirrors: we currently show the first mirror that responds with a tree, not a full compare of every server's HEAD — see FILE_FETCHING_INSIGHTS.md.
Day-to-day
git pull / git fetchgit checkout <branch>git statusgit add / git commitPublishing
Use Push to Nostr on the Code tab. Approve with whatever you logged in with: NIP-07 extension, NIP-46 remote signer (Amber / bunker), or nsec. That publishes the NIP‑34 announcement to your relays and, on gittr, tries to mirror the Git repo to git.gittr.space so clones here work. Imported repos still keep their original forge (GitHub, etc.) as the source — the bridge is a mirror, not the only copy.
CLI fan? You can still run git push origin main to a bridge remote; that updates the same gittr mirror.
Branches & Tags
git branch -a / git switch -cgit tag v1.2.3Git tags are part of the repo history after you push them. Downloadable release files live on the forge Releases page — see Releases & where they live.
Troubleshooting
git remote -vgit config --listgit log --onelineAfter making local changes, click Push to Nostr on the Code tab (sidebar). Result and cache-flush messages open in a gittr dialog that grows to fit the full text (not the browser's tiny alert box). Sign with NIP-07, Amber / NIP-46 remote signer, or nsec — same login as Settings. Or use gittr-mcp publishRepoAnnouncement / createRepo (same events, local nsec, no SSH).
Amber must stay open/unlocked on your phone. Push first opens sockets to Amber's bunker relays; if that fails, nothing is published. Hard-refresh once if a previous page load left those relays stuck, then try Push again.
That does two different things — and it does not create a forge Release, upload installers, or list the app on /apps. Those are separate, on-purpose steps (Releases, Pages & Apps):
git.gittr.space so people can clone from here. That usually works after Push, but it is not guaranteed if the mirror step fails.Imported repos: Push does not move your project off GitHub/GitLab/Codeberg. The forge stays the original (source). gittr lists its bridge/GRASP URLs for Nostr clients and tries to mirror objects onto the bridge. Other GRASP hosts (e.g. relay.ngit.dev) may also appear in clone links if configured — those are extra mirrors/links, not “everything lives only on gittr.”
If you see "Please repush on local edits", use Push to Nostr so relays (and the mirror attempt) get those edits. Import alone stays local until you Push. For repos that already live on the gittr bridge but not in this browser, Refresh from gittr (or just Upload — it will prepare a local copy) before Push.
📦 Where files come from during Push
If you already edited files in the browser, those local files are uploaded to the bridge. For a clean import with no local edits, the bridge often clones from the forge source URL instead.
If the tree looks empty after Push: Re-import or open the repo so files load, then Push again — or git push to a bridge remote.
⚡ Push Paywall (if enabled by repo owner)
pending invoice (BOLT11) directly. Pay it, then run git push again.Push payment required — pay the invoice, then retry.push payment authorization expired — create/pay a fresh invoice in the web UI, then git push again.Rough week for some self-hosted Git setups — here's the practical bit, no panic.
A normal git clone or gittr import only copies repo objects (commits, trees, blobs). It does not bring over Gitea's app.ini, internal token, or planted service hooks. Those stay on the compromised or shut-down host. So code you already imported into gittr is not carrying that server compromise with it.
What keeps the repo visible and cloneable online is an independent mirror: import (or clone) into gittr, then Push to Nostr. That publishes the announcement on relays and puts objects on GRASP / the bridge (git.gittr.space and other clone[] hosts). Others can keep discovering and cloning without the original forge.
Quick check: can someone still git clone from a URL in your announcement clone[] without the original host? If yes, that snapshot is fine. If every clone URL still points only at the dead host, finish a Push (or push to a GRASP remote) so the tree has somewhere else to live.
| Path | What is stored | If that host dies or gets taken down |
|---|---|---|
| gittr import, never Push to Nostr | Mostly browser localStorage plus a pointer (source) at the original forge. Objects are not the Gitea server compromise. | Not enough for others yet. Only your browser has the files; Push so relays and GRASP can serve them. |
| gittr import + successful Push to Nostr | Kind 30617 / 30618 on relays, and objects mirrored onto the GRASP / bridge hosts listed in clone[] (for example git.gittr.space) | Safe for that snapshot and still discoverable. Others clone from GRASP, not the original forge. If the old host was compromised, rotate secrets that lived only there (and any tokens you once committed inside the repo). |
| Forge Release assets (APK, AppImage, MSI, …) | Binary files on GitHub / Codeberg / GitLab (or another host). gittr's Releases tab mostly lists those links; it does not store the installers. | Download buttons that point at the dead forge break. Code you already Push'd to GRASP can still be cloned — that is source, not the release installers. See Releases & where they live. |
| Nostr Apps announce (NIP-82 / Zapstore) | Signed events on relays (app / release / asset). Asset url usually still points at the forge download. Owners can optionally pin a copy onto public Blossom hosts (not gittr’s Pages Blossom). Listing appears on /apps and your profile Apps section. | The announce stays discoverable; the forge download may 404 if GitHub/Codeberg/GitLab is gone. Optional pin onto public Blossom hosts keeps a copy off gittr. Pages (kind 35128) still upload to gittr’s Pages Blossom — not Apps. |
nak / git-remote-nostr announce with clone / source = original forge only | Metadata on Nostr pointing at the original forge | Not enough. The announcement stays; the tree is gone when the forge is. Push objects to a GRASP remote (or import + Push on gittr). |
| nak / git-remote-nostr that actually pushed to a GRASP remote | Objects on that GRASP host plus the announcement | Same idea as a good gittr push: independent mirror, still findable. |
What to do now
Looking for a Nostr mirror of a known forge repo (GitHub, GitLab, Codeberg, Gitea, … — exact URL / owner/repo, not fuzzy name)? Use MCP findReposBySource or GET /api/nostr/repos-by-github?source=https://…— returns npub + gittr URL so you can reach them on Nostr (profile / DM) when the forge is unreachable. Needs a Push to Nostr announce that kept the source tag. Import / clone only copies repo objects (commits, trees, blobs) — not the old forge's server config. After Push, confirm a clone[] URL works without the original host. If you still run self-hosted Gitea older than 1.27.1, patch that machine separately: GHSA-6v53-hr58-556r, GHSA-rcr6-4jqh-j84m, Gitea 1.27.1.
SSH keys are only for laptop [email protected]. They are Nostr kind 52 events the bridge copies into authorized_keys. The website is not in the SSH path after the key is registered.
ssh-keygenlocally.gn ssh-key add ~/.ssh/id_ed25519.pubPush to Nostr, issues, and PRs in the browser use your Nostr key, not SSH.
For complete documentation on SSH and Git operations:
📖 SSH & Git Access Guide (gittr) →📖 gitnostr bridge SSH guide →📖 gitnostr infrastructure (no git hook — SSH + relays) →Select code in any file viewer to share it as a standalone snippet on Nostr. The action bar appears near your selection with options to copy a permalink or share as a snippet.
Markdown anchors: In Markdown preview, headings show a link icon on hover. Click it to copy a direct heading link and update the URL hash for easy sharing. GitHub-style emoji shortcodes such as :no_entry: render as the real emoji (same as on GitHub).
Mobile-friendly: Line numbers are hidden on mobile devices to avoid alignment issues, but all functionality is preserved. Code lines remain fully clickable for selection.
Share code snippets from your repositories as standalone, discoverable events on Nostr.
How to Share:
What Gets Shared:
Reference code snippets in issue and PR comments. Snippets will appear inline with syntax highlighting.
💡 How it works:
nostr:note1... or hex format)Learn more about NIP-C0:
📖 NIP-C0 on gittr schemata →Zap a repository to tip the owner (and optionally split among contributors). Repo Settings → Zap Split Policy sets weights. The zap button’s Split (N) mode shares among those people. Owner only resolves where the invoice is paid to using the priority below. When the LNURL-pay endpoint supports NIP-57, gittr requests a real zap invoice. Split mode mints the invoice from your LNbits wallet (repo payment config first, then Settings → Account) plus the SplitPayments extension — it does not rely on Nostr zap receipts for routing.
| Flow | Payer (sender) | Recipient / repo | How gittr confirms |
|---|---|---|---|
| Repo zap — Owner only | NIP-07 extension to sign a zap request when NIP-57 is available; any Lightning wallet to pay the invoice. Your LNbits / NWC send in Settings → Account is only for polling when gittr issued the invoice through the fallback server path. | Receive address priority: (1) owner Nostr kind 0 lud16 / lnurl / NWC receive, (2) if you are that owner, your Settings → Account receive fields, (3) else Repo → Payment configuration receive fields. LNURL must advertise allowsNostr for the NIP-57 path. | NIP-57: the page does not auto-detect your wallet; a kind 9735 receipt may appear in Your Zaps after relays gossip it. Fallback invoice (no NIP-57): same modal notice; LNbits keys in your account may allow polling when gittr created the invoice server-side. |
| Repo zap — Split | Send wallet priority: (1) Repo → Payment configuration LNbits URL + admin key if set, (2) otherwise Settings → Account. SplitPayments targets in that LNbits wallet must match contributor Lightning addresses. | Each included contributor needs a discoverable Lightning address (Nostr profile or linked identity). | LNbits invoice / wallet state — designed for reliable server-side settlement, not Nostr gossip latency. |
| Bounties | Bounty creator: LNbits URL + admin key in Settings → Account (creates withdraw links from that wallet). | PR author: Lightning address on their Nostr profile for claim payout. | LNbits withdraw link lifecycle (reserve, release, claim) — must stay fast and auditable on the server. |
| Pay-to-merge / push paywall | Payer uses the shown invoice; optional NWC / WebLN from Settings → Account. | Repo owner: keys under Repo → Payment configuration (and/or global account keys per push flow) so gittr / the bridge can verify settlement — see setup docs for the exact key types. | Server checks invoice / push policy — not NIP-57 receipts. |
Rows above describe what each flow needs, not every optional shortcut. Bounty creation always uses the bounty creator's keys from Settings → Account (not the repo's LNbits send configuration).
💬 Payment Messages:
All zaps and bounties automatically include a payment message with your username, "via gittr.space", and bolt emojis (⚡⚡). This helps recipients identify where the payment came from. The message format is: {username} via gittr.space ⚡⚡ (max 160 characters).
Anyone can fund issues with bounties to incentivize contributions. Put sats on a new feature, or leave a bounty sitting on an issue for someone who discloses a security problem — there is no separate “CVE queue”; it is a normal issue with a bounty. Bounties use LNURL-withdraw links created from the bounty creator's LNbits wallet. The funds are reserved in the creator's wallet and will be deducted when the PR author claims the withdraw link.
lud16 / lnurl) in Kind 0Visit the Bounty Hunt page to discover funded issues across all repositories.
Go to Settings → Notifications to set up:
/start, paste the User ID into Settings → Notifications. No public channel post required. You can enable Nostr and Telegram together.Save now does two things: publishes your toggles as a kind 30078 event (d=gittr/notifications) so prefs sync across browsers, and registers delivery on the server (Telegram User ID stays off public relays). DMs always use the recipient's saved prefs — not whoever clicked in their own browser.
Bounty announcements are also posted to the public @gittrspace channel (announcements only — not used for auth).
You can enable/disable notifications for:
Defaults: collaboration (new issues, issue comments, PRs, reviews, merges, mentions, bounties) is on; stars / watches / zaps are off; security (CVE) alerts stay off until you opt in.
Dependency notices are listed under Dependency notices (CVE).
Important: Changes to notification preferences are not active until you click "SAVE NOW". Make sure to save your preferences after making changes.
Supply-chain attacks on git forges are a hot topic. gittr scans the dependencies of every repo against the public OSV.dev vulnerability database and shows the result on the repo's Dependencies tab.
Exact matches only: an advisory is only reported as confirmed when the exact dependency version from your committed lockfile (package-lock.json, yarn.lock, Cargo.lock, go.mod, pinned requirements.txt, …) falls inside the version range the advisory declares as affected. Versions guessed from ranges in package.json are listed separately as unconfirmed and never trigger alarms.
How the message looks: Telegram / Nostr DMs lead with the repo name, list at most a few findings, and link to that repo's Dependencies tab — not a public Issues entry. Advisory names stay in the private message. Wording is deliberately calm: this is a dependency advisory notice, not a claim that the project is compromised.
How often does the check run? The audit runs fresh every time the Dependencies tab of a repo is opened — there is no fixed schedule. It reads the lockfiles from the pushed repo tip on gittr (the bridge clone), not from files only on your laptop or only on GitHub until those are synced here. Advisory details are cached on the server for about 6 hours, so a newly published CVE shows up within hours, at the latest on the next visit after the cache expires.
How alerts reach you (Dependabot-style): when a published CRITICAL or HIGH advisory matches a direct pinned dependency on a repo that has code on gittr (created / imported / pushed here — not merely announced from another client), the platform can send a private notice on the same channels you enabled (Nostr and/or Telegram). GitHub Dependabot keeps vulnerability alerts off the public Issues tab; gittr does the same. Nostr issues are public on relays — there is no owner-only issue kind — so we never post CVE names there. A lockfile match still needs your check: whether your code actually uses the affected APIs. All notification toggles (including Security) live in one kind 30078 event (d=gittr/notifications) so they sync across browsers. Save also registers delivery on this server (Telegram User ID stays off public relays).
Your repos only — not watched / starred: Security scans the repos you own on gittr (your kind 30617 announcements), not projects you only watch, star, or follow. Watching someone else's stack is intentionally out of scope — noisy, permission-awkward, and easy to get wrong. If you want CVE / early-warning coverage of another project, fork or import it under your account so you own the tip on gittr, then keep Push in sync as usual.
Fresh tip only — keep announcement in line with source: the scanner reads lockfiles from the gittr bridge clone, but only when Nostr repo state (kind 30618) exactly matches that clone. No tip, or tip ≠ bridge → skip (no DM about the wrong tree). That match is what a successful Push from the gittr UI is supposed to publish. If you changed the repo on GitHub (or another forge) and want CVE coverage of that tip: bring it onto gittr (sync / refetch from source on the repo), then Push so the announcement lines up with the mirror. A browser-only file refresh without Push does not update the announcement. Same idea if you only update in another Nostr git client — Push/sync on gittr again when you want alerts here.
How notices are sent: when you are opted in, the platform bot DMs you (Nostr and/or Telegram per your prefs) for each new CRITICAL/HIGH lockfile match. It does not open a public issue. The same advisory is not re-sent on later scans.
Early (pre-CVE) warnings — same opt-in: with Security enabled you also get private DMs when the public Vulnerability Spoiler Alert RSS flags a HIGH/CRITICAL finding that looks related to a direct dependency in that repo (often before a CVE exists). There is no extra checkbox. These tips are not shown on the Dependencies tab (that tab stays OSV/confirmed only), and we do not open a gittr Issues entry for them. If the Spoiler feed is unreachable, Dependencies + normal dependency notices keep working unchanged.
One alert per problem — not per scan: each advisory triggers at most one issue per package per repo. Repeated scans that find the same known vulnerability stay silent.
Get the most protection:
package==1.2.3 in requirements.txt).30618 matches the tip on gittr — otherwise CVE alerts stay skipped.When you are logged in, gittr shows a small hop badge next to other people's names on profiles, repo owners, /apps, and /pages. It is relative to you — how many follow-hops away they are — not a global score. Labels: In your network, N hops from you, Outside your network when the oracle finds no path, or Distance unknown when the lookup is down or the WoT extension has no distance (a mute or an incomplete graph). Logged out, the hop badge is hidden. Your own profile does not show hops to yourself.
Direct follows come from your kind-3 contact list. Multi-hop distance can use a browser WoT extension or the public oracle. Linked external identities are a separate signal: they help you decide whether the npub is the same person as a GitHub or X account.
Under Settings → Profile, claim GitHub, X, Telegram, Mastodon, and other accounts so others can see you are the same person on Nostr. Claims publish as NIP-39 kind 10011. Optional proof (GitHub Gist, tweet). The chips also help when someone is judging Web of Trust, and imports can match GitHub contributors to Nostr profiles. NIP-05 (name@domain) is a separate checkmark on kind 0 — name, bio, and avatar stay on that event.
Tip: if you connected GitHub on Settings → SSH Keys, it can appear under Verified Identities automatically — then save Profile to publish the claim.
Open Lab in the header for a snapshot map of ecosystem dependencies around gittr (gittr is the seed repo), and which repos that use those dependencies look affected. Display-only — not a live hunt. Run local-agent yourself if you want to hunt on your own machine.
Per-repo lockfile CVEs stay on each repo's Dependencies tab, with optional private DMs — that is a different surface from Lab. See Dependency notices (CVE).
Bounty notifications are sent to:
Bounty announcements are also automatically posted to the public @gittrspace Telegram channel, regardless of your notification preferences.
Think of three separate layers. Mixing them up is what causes confusion — not the UI itself.
| Layer | What it is | Where it lives |
|---|---|---|
| Forge Release | A tagged Release on GitHub / Codeberg / GitLab with real download files (APK, AppImage, MSI, checksums, …). Create those assets on the forge (or with their CLI / CI). | On that forge. gittr's Releases tab syncs and lists them when the repo has a matching source URL. The same tab also lists NIP-82 / Blossom releases from Nostr for GRASP-only repos (no forge required to read). |
| gittr "New release" | Optional notes / tag in this browser. Does not attach files, does not publish to Nostr or /apps. | Local to your browser (per-repo storage). Useful as a memo; not a substitute for forge assets. |
| Nostr Apps announce | Owner-only. Same NIP-82 events from Code sidebar → Nostr Apps (always the latest forge Release tag) or Releases → Announce on Nostr on a chosen tag. Needs a hashed installer on that tag (APK, AppImage, DMG, tar.gz, …). An .apk is preferred for Zapstore Android. Other verified platform files on the same tag can be linked as extra NIP-82 assets. Never a tagless app listing. It never runs on ordinary Push to Nostr. | Signed events on Nostr relays (kinds 32267 app, 30063 release, 3063 asset). Shown on /apps, your profile Apps section, and optionally Zapstore. Download url still points at the forge unless you host elsewhere. |
If the forge later goes offline, mirrored source code (after Push) can still be cloned from GRASP — but release installers that only lived on the forge will not. Full table: When your git host goes dark.
Owners publish a static site from the repo Code sidebar → Nostr Pages. Required: a root index.html, then Push Manifest (uploads to Blossom and publishes kind 35128). That is what puts the page online — it is not a git push and not an issue. Optional: a custom site name (1–13 characters in the live URL; longer names like conference-loop become conference-lo) and a README pagelink for repo visitors. If you changed files or the README, Push to Nostr first, then Push Manifest. Browse live sites at /pages.
gittr's gateway is adapted from hzrd146's nsite work — credit where it's due:
Owners list an app from the Code sidebar → Nostr Apps (latest forge Release tag) or from the Releases tab on a chosen tag. Both use the same form (screenshots, pin, publish). A Nostr version like 1.0.0 matches GitHub v1.0.0. Link a GitHub / Codeberg / GitLab source URL. The chosen Release must include an announceable binary (an .apk is preferred for Zapstore Android). Verify the file, then Publish on Nostr (NIP-82). Zapstore needs the APK; other binaries on the same Release tag (DMG, AppImage, MSI/EXE, …) can be linked as extra NIP-82 assets on that version. Files stay on the forge by default; gittr only announces. An optional checkbox pins a copy onto public Blossom hosts (Primal, Ditto, Haven) — never blossom.gittr.space except gittr’s own Android APK (space.gittr.app), which also publishes the dark-plate bird as the app icon, phone screenshots, and the product about. Other apps copy their public repo logo when one exists, and copy images: from their source-repo zapstore.yaml as listing screenshots (optional extra https URLs in the announce panel). gittr’s own listing has no extra-URL box — those shots always come from ui/public/zapstore/. The repo Releases tab lists all forge download assets (not only APKs). The Code-tab About → Links sidebar shows the app name (same as /apps) for everyone — from the last Push, or hydrated from the app catalog if this browser never announced. Duplicate App rows for the same package id are collapsed. Listed on /apps is unique publisher + package id (not every new card you notice) — a republish of the same id updates the listing without adding 1. After Zapstore paging, Listed can sit around three thousand because Zapstore’s indexer lists a large mobile catalog underone publisher (still unique publisher + id). That is the same Nostr app list gittr already counts — Zapstore’s relay is just where most kind 32267 events live, not a second counter added on top. Owner Remove listing is NIP-09 and hides that author’s card; it does not shrink Zapstore’s catalog. Zapstore only answers 50 app events per request, so Listed keeps climbing for a short while as gittr walks older pages. The hub keeps a running snapshot so those apps are not dropped on the next refresh. Announcing does not put the APK into the git file tree. How Releases, forge files, and announces fit together: Releases & where they live. Discover apps at /apps. Each card's Repo button is the source tree so you can verify the code (gittr Code when the announce has a NIP-34 pointer, otherwise Zapstore's repository URL — that tag is meant to be git clone-able). Releases is the forge download page. Signed-in owners: user menu Your Apps to remove a leftover listing (one app id) without deleting the git repo or the APK file. The Code-tab app name link stays so the next Push still publishes it — leftover GITTR is not kept next to space.gittr.app.
Optional Zapstore catalog: add zapstore.yaml at the source repo root (pubkey, repository, plus images: screenshot paths or https links), then publish again. Details:
Create PRs to propose changes. Reviewers can approve, request changes, or merge PRs. Repo owners editing their own Nostr / bridge repos on the Code tab can Save changes locally and use Push to Nostr — they do not need a PR.
Merge vs Close (what hits Nostr)
#12, URL /pulls/12). Comment here if you want; gittr will not merge or close the origin. Close / Merge still show; they pop a message instead of hiding the row (a local hide would come back on refetch). Do that on the forge so the two sides stay in sync. A Nostr PR on the same repo (long id in the URL) can still be merged here.📋 How PRs Are Organized
Each repo has a ToDo tab (Projects) with Kanban and Roadmap views. If the git source is GitHub/GitLab/Codeberg, gittr shows that forge’s board read-only — it does not write cards back, and it does not keep a second this-browser board in that view (that is why notes seemed to vanish after a restart). Nostr-only repos keep the board in this browser until a kanban NIP exists; drag cards to update status. Milestones live in repo Settings and on issues/PRs. Open /projects for the aggregated board.
Forge-backed repos show GitHub Discussions only, read-only — gittr never posts back. Nostr-only repos publish NIP-23 threads to relays and keep a cache in this browser. After a restart the cache is still there; if the live relay copy differs, use Nostr vs This browser to pick which version to read.
Track bugs, feature requests, and discussions. Add bounties to incentivize solutions — a new feature, or an issue sitting open for someone who discloses a security problem.
How Issues Are Organized
#12 and URL /issues/12). Nostr issues use a long event id in the address bar and a short hex label in the list — not a local #9 that can look like GitHub #9.Link your GitHub profile in Settings to show your profile picture as a contributor icon.
All your data (repos, keys, settings) is stored locally in your browser. It never leaves your device unless you explicitly push to Nostr.
⚠️ Browser & Domain Isolation
Your data is stored separately for each browser and domain:
If you're missing repos, PRs, or edits: They might be in a different browser or on a different domain. Use the Repos page to see all repositories from Nostr (consistent across browsers). Someone's profile lists their public Nostr announcements the same way whether you are signed in or not — opening one of their repos does not become their whole catalog.
Settings → Security shows how you actually sign in. Amber / NIP-46 and NIP-07 keep your identity key off this site — you do not need encryption for login. Encryption is for an nsec stored in this browser, and for Lightning / NWC secrets on Settings → Account if you saved any.
Repositories default to public when pushed to Nostr. You can set them to private in repository settings.
If you have questions or hit issues, see the gittr source repo, plus gitnostr and gittr-helper-tools, gittr-blossom, and the Nostr schemata reference for NIPs and kinds.