Git collaboration on Nostr: 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.
NIPs & event kinds: Nostr schemata on gittr (nostrability) — e.g. NIP-34 for git repos, issues, and PRs.
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:
📦 Option 1: Import Single Repository
Import an existing repository from GitHub, GitLab, or Codeberg:
owner/repo (e.g., arbadacarbaYK/gittr)https://github.com/owner/repo➕ Option 2: Create Empty Repository
Create a new empty repository from scratch:
📚 Option 3: Bulk Import from GitHub
Load a GitHub user/org list, then choose what to import. Opening the bulk page does not import anything or touch your local Git until you fetch the list, select repos, and confirm import.
⚠️ Important: Getting Files Into Your Repository
For empty repositories created via web UI: After creating an empty repository, you need to push files to it before they appear in the web UI. The workflow is:
git clone [email protected]:<your-pubkey>/<repo-name>.gitgit add . && git commit -m "Initial commit"git push origin mainWhy this is necessary: The git-nostr-bridge stores repositories as bare Git repositories. Files only appear in the web UI after they've been committed and pushed via Git.
For imported repositories: Files are automatically fetched during import, so they appear immediately in the web UI.
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.
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:
All repos are stored locally in your browser and can be pushed to Nostr for public access. Important: Empty repositories created via web UI will not show files until you push them via Git.
📖 Complete Workflow for Empty Repositories
After creating an empty repository via web UI:
git clone [email protected]:<your-pubkey>/<repo-name>.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).View, edit, and delete files directly in the browser. Use the fuzzy file finder (Cmd/Ctrl+P) to quickly navigate large repositories.
gittr.space follows the NIP-34 architecture for file storage. Files are stored on git servers (via gitnostr bridge), not in Nostr events. The repository's "About" sidebar shows where files come from:
This architecture ensures files are stored efficiently and can be fetched from multiple sources for redundancy.
You can import repositories from:
Imported repos maintain a link to their source (sourceUrl) and fetch files from the original git server.
🔒 Private Repository Support
GitHub Private Repos: When you import a private GitHub repository, the privacy status is preserved locally. The repository will be marked as "Private" in gittr.space. Privacy is enforced via the maintainers tag (NIP-34 spec) and bridge access control.
public-read or public-write tags. Privacy is determined by the maintainers tag (which IS in the spec) and bridge-level access control.maintainers tag can identify private repos and enforce access control accordingly.maintainers tag (or the repository owner) can access private repos. This is enforced at the bridge level for Git operations (SSH/HTTPS) and at the API level for file fetching.🔗 Identity Mapping & Access Control
How Access Works: Access to private repositories is determined by your Nostr pubkey (npub), not your GitHub username. This means:
Why This Matters: When importing from GitHub, contributors are mapped to Nostr identities using:
["i", "github:username"] tags, your identity is claimed on Nostr⚠️ Common Issue: "Access Denied" for Maintainers
If you're a maintainer on GitHub but can't access a private repo on gittr.space:
💻 CLI & API Access
When accessing private repositories via Git CLI or API:
fatal: permission denied for read operation with hints on how to get access.Note: The same access control applies - you need your npub added as a maintainer by the owner, regardless of whether you access via web UI, CLI, or API.
⚠️ 4 MB Import Limit
Next.js API routes hard-cap responses at ~4 MB. When importing we fetch every file (including releases/binaries), so very large repos will fail with “Repository is too large”. Remove heavy artifacts (release archives, media, build outputs) or import a slimmer subset before retrying.
gittr.space repositories support multiple clone URL formats:
Option A: SSH (Standard Git - Recommended)
git clone [email protected]:npub1.../repo-name.gitRequires SSH keys (Settings → SSH Keys). Works out of the box with any Git client.
Option B: HTTPS (GRASP git servers)
git clone https://git.gittr.space/<owner-pubkey>/repo-name.gitRead-only clones from our public mirrors (git.gittr.space, gitnostr.com, relay.ngit.dev, ngit-relay.nostrver.se, ...). Great for CI/CD or quick testing.
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.
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 the Push to Nostr button in the repo UI. We publish the NIP‑34 event and automatically sync your repo to our git bridge so other clients can clone it immediately.
CLI fan? You can still run git push origin main; it hits the same bridge endpoint.
Branches & Tags
git branch -a / git switch -cgit tag v1.2.3Releases and tags show up instantly in the UI.
Troubleshooting
git remote -vgit config --listgit log --onelineAfter making local changes, click "Push to Nostr" in your repository settings to publish updates.
We sign the NIP‑34 event, publish it to your relays, and sync the Git repo to git.gittr.space automatically. Only small metadata files live inside the Nostr event; the real Git objects stay on the bridge.
If you see "Local changes are not visible in other clients yet", push to Nostr to publish those edits to relays.
📦 File Content During Push
Files are sourced from your browser's localStorage (from create/import workflow) or from the bridge API if missing. The push process does NOT fetch files from external sources (GitHub, GitLab, etc.).
If files are missing: Re-import the repository to load all files into localStorage before pushing.
⚡ Push Paywall (if enabled by repo owner)
pending invoice (BOLT11) directly. Pay it, then run git push again.🛠️ Common Push Errors
Push payment required in browser/API: pay the shown invoice first, then retry.push payment authorization expired in SSH: create/pay a fresh invoice in the web UI, then run git push again.Manage your SSH keys in Settings → SSH Keys. You'll need these for Git operations over 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.
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). 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. 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.
⚠️ Important Requirements:
lud16 or lnurl) in their Nostr profile (Kind 0 metadata)Bounty Flow:
🔒 Bounty Protection & Trust Model:
Bounty Flow Diagram:
Bounty statuses:
Key Points:
lud16 or lnurl fields.Visit the Bounty Hunt page to discover funded issues across all repositories.
Go to Settings → Notifications to set up:
Bounty announcements are also posted to the public @gittrspace channel.
You can enable/disable notifications for:
Default Settings: Most notifications are disabled by default to reduce noise. The recommended settings (enabled by default) are: New issues, Issue comments, New PRs, PR reviews, PR merges, Mentions, My Bounties, and Bounty releases.
Important: Changes to notification preferences are not active until you click "SAVE NOW". Make sure to save your preferences after making changes.
Bounty notifications are sent to:
Bounty announcements are also automatically posted to the public @gittrspace Telegram channel, regardless of your notification preferences.
Create PRs to propose changes. Reviewers can approve, request changes, or merge PRs.
📋 How PRs Are Organized
Track bugs, feature requests, and discussions. Add bounties to incentivize solutions.
📋 How Issues Are Organized
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).
Your Nostr private key and payment credentials are encrypted with a password you set. Enable encryption in Settings → Security.
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, and the Nostr schemata reference for NIPs and kinds.