Repositories
Publishing
Run ngit init inside an existing git repository:
ngit init --name "My Project" --description "What it does" --defaultsThis publishes a repository announcement and adds a nostr:// remote. With no --grasp-server, it uses your preferred GRASP server if you have one configured and falls back to the built-in defaults otherwise.
Choosing where it lives
A GRASP server is a relay and a git server in one, and creates the repository for you:
ngit init --name "My Project" --grasp-server grasp.example.com --defaultsAnything beyond GRASP is explicit, and empty by default:
ngit init \
--name "My Project" \
--additional-relay wss://relay.example.com \
--additional-clone https://git.example.com/my-project.git \
--defaultsThe effective sets are additive:
relays = grasp-derived relays + additional relays
clones = grasp-derived clones + additional clonesOther flags
| Flag | Purpose |
|---|---|
--name (alias --title) | Human-readable name |
--identifier | Shortname, no spaces — not editable later |
--description | One-line description |
--web | Homepage URL |
--hashtag | Discovery hashtags, repeatable |
-u, --upstream | Mark this as a fork of another repo (informational) |
--earliest-unique-commit | Usually the root commit; a later one for forks |
--private / --public | Restrict discovery to repository relays, or lift that |
--clean | Drop unknown tags when republishing instead of preserving them |
--identifier is permanent
It becomes the NIP-34 d tag. Changing it doesn't rename the repository — it creates a different one at a different coordinate.
Cloning
git clone nostr://<npub>/<relay-hint>/<identifier> # preferred
git clone nostr://<npub>/<identifier> # slower discovery
git clone nostr://user@domain.com/<identifier> # NIP-05, if given to youThe relay hint is a bare domain (relay.ngit.dev). Including it skips the discovery step.
Inspecting
ngit repo # what this repository is
ngit repo --offline # from cache, no networkShows the name, description, nostr:// URL, maintainers, relays, git servers, GRASP servers and hashtags. Run git fetch origin first if the cache may be stale.
Editing metadata
ngit repo edit preserves anything you don't mention:
ngit repo edit --description "New description"Collections use targeted add/remove actions rather than replacing the whole list:
| Setting | Add | Remove |
|---|---|---|
| GRASP server | --add-grasp-server URL | --remove-grasp-server URL |
| Additional relay | --add-additional-relay URL | --remove-additional-relay URL |
| Additional clone | --add-additional-clone URL | --remove-additional-clone URL |
| Hashtag | --add-hashtag TAG | --remove-hashtag TAG |
They repeat and combine:
ngit repo edit \
--remove-additional-relay wss://old.example.com \
--add-additional-relay wss://new.example.com \
--add-hashtag rustTo empty a collection, remove each value currently reported by ngit repo.
A few rules the CLI enforces:
- A GRASP-derived entry can't be removed as an additional entry. Remove the GRASP server instead — its paired relay and clone URL go together.
- An edit that would leave the repository with no relay, or no git server, fails before publishing anything.
Swapping git servers
This is the payoff of keeping refs on nostr. Add the new server, remove the old one, and contributors do nothing:
ngit repo edit \
--add-additional-clone https://new-host.example.com/my-project.git \
--remove-additional-clone https://old-host.example.com/my-project.gitEvery successful edit republishes the announcement. When the repository already has nostr state, ngit republishes that too, so newly added relays and servers get the authoritative refs immediately. If that second step fails, ngit prints an ngit sync recovery command — run it.
Keeping servers in sync
ngit sync # push nostr state out to the git servers
ngit sync --ref-name main # just one refUse it after adding a server, or when a server has fallen behind. See Troubleshooting for diverged refs.
Next
- Maintainers — invitations, roles, leads
- Pull requests