diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-03-05 10:11:05 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-03-05 10:11:05 +0000 |
| commit | 243b563a3dc847a3a036a034dd7597685742c20c (patch) | |
| tree | 263ee1043bfb931e318c31a99187bf16add1d3b4 /skills/ngit/SKILL.md | |
| parent | 93c3e5fa18bc5ffb39b4e28b7b7b38bb6ce3fd93 (diff) | |
compact ngit skill to 168 lines for iterative refinement
Rewrite for conciseness: collapse concept sections to command
references, remove prose explanations Claude already knows,
merge workflows into inline examples, drop redundant comments.
Diffstat (limited to 'skills/ngit/SKILL.md')
| -rw-r--r-- | skills/ngit/SKILL.md | 568 |
1 files changed, 74 insertions, 494 deletions
diff --git a/skills/ngit/SKILL.md b/skills/ngit/SKILL.md index 918f310..5c4fc1c 100644 --- a/skills/ngit/SKILL.md +++ b/skills/ngit/SKILL.md | |||
| @@ -8,581 +8,161 @@ metadata: | |||
| 8 | 8 | ||
| 9 | # ngit — Nostr Plugin for Git | 9 | # ngit — Nostr Plugin for Git |
| 10 | 10 | ||
| 11 | ngit makes native git commands (`clone`, `fetch`, `push`) work with `nostr://` URLs and adds a CLI for pull requests, issues, and repository management — all over the decentralised Nostr protocol. No GitHub, no centralised forge. | 11 | ngit makes `clone`, `fetch`, `push` work with `nostr://` URLs and adds a CLI for PRs, issues, and repo management over the decentralised Nostr protocol. |
| 12 | 12 | ||
| 13 | - Homepage: https://ngit.dev | 13 | - Install: `curl -Ls https://ngit.dev/install.sh | bash` (installs `ngit` and `git-remote-nostr`) |
| 14 | - Source: `nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit` | 14 | - Web UI: https://gitworkshop.dev |
| 15 | - Web UI for browsing repos/PRs/issues: https://gitworkshop.dev | ||
| 16 | 15 | ||
| 17 | ## Installation | 16 | ## Key rules |
| 18 | 17 | ||
| 19 | ```bash | 18 | - **Always use `--json`** on `ngit` commands when reading output — far easier to parse than human-readable text. `git` commands do not support `--json`. |
| 20 | curl -Ls https://ngit.dev/install.sh | bash | 19 | - **Use `--offline`** on all but the first `ngit` command in a session — reads from local cache instantly. `git fetch origin` also refreshes the cache. |
| 21 | ``` | 20 | - **Never construct NIP-05 addresses** (`user@domain`). Use the `npub1...` form unless a NIP-05 address was explicitly provided. |
| 22 | 21 | - **`<ID|nevent>`** accepts a 64-char hex event ID or a `nevent1...` bech32 string. Get IDs from `ngit pr list --json` or `ngit issue list --json`. | |
| 23 | This installs two binaries: | ||
| 24 | |||
| 25 | - `ngit` — the main CLI | ||
| 26 | - `git-remote-nostr` — a git remote helper that enables `nostr://` URLs to work transparently with git | ||
| 27 | |||
| 28 | ## Machine-readable output | ||
| 29 | |||
| 30 | **All `ngit` commands support `--json` for structured output. Always use `--json` when scripting or parsing output** — it is far easier to process reliably than human-readable text. Standard `git` commands do not support `--json`; use them as normal. | ||
| 31 | |||
| 32 | ## Detecting a Nostr Repository | ||
| 33 | 22 | ||
| 34 | Before running any `ngit` commands, check whether the current directory is a nostr repository: | 23 | ## Detecting a nostr repo |
| 35 | |||
| 36 | ```bash | ||
| 37 | ngit repo --json --offline | ||
| 38 | ``` | ||
| 39 | |||
| 40 | Always exits 0. Returns `{"is_nostr_repo": false}` when not in a nostr repo, or the full repo info when it is. | ||
| 41 | |||
| 42 | To check without loading the full repo details, grep for the key field: | ||
| 43 | 24 | ||
| 44 | ```bash | 25 | ```bash |
| 26 | # Check if current directory is a nostr repo (always exits 0) | ||
| 45 | ngit repo --json --offline | grep -q '"is_nostr_repo":true' | 27 | ngit repo --json --offline | grep -q '"is_nostr_repo":true' |
| 46 | ``` | 28 | ``` |
| 47 | 29 | ||
| 48 | Script usage: | 30 | Returns full repo info (including `nostr_url`, `maintainers`, `grasp_servers`) when true. |
| 49 | |||
| 50 | ```bash | ||
| 51 | if ngit repo --json --offline | grep -q '"is_nostr_repo":true'; then | ||
| 52 | ngit pr list --json | ||
| 53 | fi | ||
| 54 | ``` | ||
| 55 | |||
| 56 | --- | ||
| 57 | 31 | ||
| 58 | ## Caching and --offline | 32 | ## nostr:// URLs |
| 59 | |||
| 60 | Every `git fetch` and every `ngit` command that contacts relays fetches and caches the latest PRs, issues, and comments locally. This means **when running multiple ngit commands in quick succession, use `--offline`** on all but the first — it reads from the local cache and is instant. | ||
| 61 | |||
| 62 | ```bash | ||
| 63 | # First command fetches from relays and populates the cache | ||
| 64 | ngit pr list --json | ||
| 65 | |||
| 66 | # Subsequent commands in the same session can skip the network | ||
| 67 | ngit pr view <ID> --offline --comments | ||
| 68 | ngit issue list --json --offline | ||
| 69 | ngit repo --json --offline | ||
| 70 | ``` | ||
| 71 | |||
| 72 | `git fetch origin` also triggers a relay sync, so after a fetch all cached data is fresh. | ||
| 73 | |||
| 74 | --- | ||
| 75 | |||
| 76 | ## Core Concepts | ||
| 77 | |||
| 78 | ### What is a `nostr://` URL? | ||
| 79 | |||
| 80 | A `nostr://` URL identifies a repository on the Nostr network. It encodes the maintainer's public key and a short repository identifier: | ||
| 81 | 33 | ||
| 82 | ``` | 34 | ``` |
| 83 | nostr://<npub>/<identifier> | 35 | nostr://<npub>/<identifier> |
| 84 | nostr://<npub>/<relay-hint>/<identifier> | 36 | nostr://<npub>/<relay-hint>/<identifier> # relay-hint is bare domain, e.g. relay.ngit.dev |
| 85 | ``` | ||
| 86 | |||
| 87 | **`<npub>` is the only reliable form to construct yourself.** It is the bech32-encoded Nostr public key, always starting with `npub1`. Get it from `ngit repo --json` (the `maintainers` field) or `ngit account export-keys`. | ||
| 88 | |||
| 89 | The relay hint is a bare domain (no `wss://`) and speeds up discovery — use the repo's grasp server. Get it from `ngit repo --json` (`grasp_servers[0]`). | ||
| 90 | |||
| 91 | ``` | ||
| 92 | nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/relay.ngit.dev/ngit | ||
| 93 | ``` | ||
| 94 | |||
| 95 | **NIP-05 addresses** (`user@domain.com`) are also valid if the user has set one up, but they require a `/.well-known/nostr.json` file deployed to that domain — do not attempt to construct or guess them. Use the npub form unless a NIP-05 address has been explicitly provided to you. | ||
| 96 | |||
| 97 | These URLs work directly with git — no special commands needed: | ||
| 98 | |||
| 99 | ```bash | ||
| 100 | git clone nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/relay.ngit.dev/ngit | ||
| 101 | git fetch origin | ||
| 102 | git push origin main | ||
| 103 | ``` | ||
| 104 | |||
| 105 | The `git-remote-nostr` helper resolves the URL to actual git servers behind the scenes. | ||
| 106 | |||
| 107 | ### How repositories work | ||
| 108 | |||
| 109 | When a maintainer publishes a repo with `ngit init`, they broadcast a **repository announcement event** to Nostr relays. This event contains: | ||
| 110 | |||
| 111 | - Repository name, description, and identifier | ||
| 112 | - Git server URLs (where the actual git data lives) | ||
| 113 | - Nostr relay URLs (where events like PRs and issues are published) | ||
| 114 | - Maintainer public keys | ||
| 115 | |||
| 116 | Anyone can clone using the `nostr://` URL. The remote helper fetches the announcement, finds the git servers, and performs the actual git operations. | ||
| 117 | |||
| 118 | ### Authentication | ||
| 119 | |||
| 120 | ngit uses your Nostr private key (nsec) for signing events. See [CONCEPT 5: Account Management](#concept-5-account-management) for full details. | ||
| 121 | |||
| 122 | --- | ||
| 123 | |||
| 124 | ## CONCEPT 1: Publishing a Repository | ||
| 125 | |||
| 126 | _"Making a git repo discoverable and collaborative on Nostr"_ | ||
| 127 | |||
| 128 | ### First-time publish (from an existing git repo) | ||
| 129 | |||
| 130 | ```bash | ||
| 131 | # Interactive (recommended for humans) | ||
| 132 | ngit init | ||
| 133 | |||
| 134 | # Non-interactive / scripted — uses sensible defaults | ||
| 135 | ngit init --name "My Project" --description "What it does" -d | ||
| 136 | |||
| 137 | # With explicit grasp server (hosted git+nostr infrastructure) | ||
| 138 | ngit init --name "My Project" --description "What it does" \ | ||
| 139 | --grasp-server https://relay.ngit.dev -d | ||
| 140 | ``` | 37 | ``` |
| 141 | 38 | ||
| 142 | After `ngit init`: | 39 | Standard git commands work directly with these URLs — `git-remote-nostr` resolves them transparently. |
| 143 | |||
| 144 | - A repository announcement is published to Nostr relays | ||
| 145 | - The `origin` remote is updated to the `nostr://` URL | ||
| 146 | - Your code is pushed to the configured git server(s) | ||
| 147 | - You get a shareable URL like `https://gitworkshop.dev/npub.../myrepo` | ||
| 148 | 40 | ||
| 149 | ### Update repository metadata | 41 | ## Publishing a repo |
| 150 | 42 | ||
| 151 | ```bash | 43 | ```bash |
| 152 | ngit repo edit --description "Updated description" | 44 | ngit init # interactive |
| 153 | ngit repo edit --hashtag rust --hashtag cli | 45 | ngit init --name "My Project" --description "What it does" -d # non-interactive |
| 46 | ngit repo edit --description "New description" # update metadata | ||
| 47 | ngit repo --json --offline # view repo info (check nostr_url field) | ||
| 154 | ``` | 48 | ``` |
| 155 | 49 | ||
| 156 | ### View repository info | 50 | ## Cloning |
| 157 | |||
| 158 | ```bash | ||
| 159 | ngit repo | ||
| 160 | ``` | ||
| 161 | |||
| 162 | --- | ||
| 163 | |||
| 164 | ## CONCEPT 2: Cloning and Working with a Repo | ||
| 165 | |||
| 166 | _"Getting and staying in sync with a nostr repository"_ | ||
| 167 | 51 | ||
| 168 | ```bash | 52 | ```bash |
| 169 | # Clone using npub + relay hint + identifier (preferred — always works) | 53 | git clone nostr://<npub>/<relay-hint>/<identifier> # preferred |
| 170 | git clone nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/relay.ngit.dev/ngit | 54 | git clone nostr://<npub>/<identifier> # slower discovery, no relay hint |
| 171 | 55 | git clone nostr://user@domain.com/<identifier> # NIP-05, only if given to you | |
| 172 | # Clone using npub + identifier (no relay hint — slightly slower discovery) | ||
| 173 | git clone nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit | ||
| 174 | |||
| 175 | # Clone using NIP-05 address if its already been given to you in the clone url. | ||
| 176 | git clone nostr://dan@danconwaydev.com/ngit | ||
| 177 | |||
| 178 | # Standard git operations work normally after cloning | ||
| 179 | git fetch origin | ||
| 180 | git pull origin main | ||
| 181 | git push origin main | ||
| 182 | ``` | 56 | ``` |
| 183 | 57 | ||
| 184 | ### Remote branches and PRs | 58 | ## Pull Requests |
| 185 | |||
| 186 | When you fetch from a nostr remote, open and draft PRs appear as remote branches with the `pr/` prefix: | ||
| 187 | |||
| 188 | ```bash | ||
| 189 | git fetch origin | ||
| 190 | git branch -r | ||
| 191 | # origin/main | ||
| 192 | # origin/pr/fix-login-bug ← open PR | ||
| 193 | # origin/pr/add-dark-mode ← open PR | ||
| 194 | ``` | ||
| 195 | 59 | ||
| 196 | You can check out a PR branch directly: | 60 | ### Open a PR |
| 197 | |||
| 198 | ```bash | ||
| 199 | git checkout pr/fix-login-bug | ||
| 200 | # or by event ID | ||
| 201 | ngit pr checkout <ID|nevent> | ||
| 202 | ``` | ||
| 203 | |||
| 204 | --- | ||
| 205 | |||
| 206 | ## CONCEPT 3: Pull Requests | ||
| 207 | |||
| 208 | _"Proposing and reviewing changes"_ | ||
| 209 | |||
| 210 | ### Opening a PR | ||
| 211 | |||
| 212 | Create a branch with the `pr/` prefix and push it. Always include `-o title=` and `-o description=`: | ||
| 213 | 61 | ||
| 214 | ```bash | 62 | ```bash |
| 215 | git checkout -b pr/my-feature | 63 | git checkout -b pr/my-feature |
| 216 | # ... make commits ... | 64 | # ... commits ... |
| 217 | git push -u origin pr/my-feature \ | 65 | git push -u origin pr/my-feature \ |
| 218 | -o 'title=Add dark mode' \ | 66 | -o 'title=My feature title' \ |
| 219 | -o 'description=Implements a dark mode toggle in settings.\n\nAdds a toggle to the settings page and persists the preference.' | 67 | -o 'description=Summary.\n\nDetail here.' |
| 220 | ``` | 68 | ``` |
| 221 | 69 | ||
| 222 | Use `\n\n` in the description for paragraph breaks. | 70 | Push options `title=` and `description=` are required. Use `\n\n` for paragraph breaks. |
| 223 | 71 | ||
| 224 | ### Opening a PR (advanced — `ngit send`) | 72 | ### Advanced: ngit send |
| 225 | 73 | ||
| 226 | ```bash | 74 | ```bash |
| 227 | # Send commits ahead of main as a PR | 75 | ngit send HEAD~2 --title "My Feature" --description "Details" |
| 228 | ngit send HEAD~2 --title "My Feature" --description "Details here" | 76 | ngit send --defaults # non-interactive |
| 229 | 77 | ngit send HEAD~2 --in-reply-to <PR-event-id> # update existing PR | |
| 230 | # Non-interactive with defaults | ||
| 231 | ngit send --defaults | ||
| 232 | |||
| 233 | # Update an existing PR (new version/revision) | ||
| 234 | ngit send HEAD~2 --in-reply-to <PR-event-id> | ||
| 235 | ``` | 78 | ``` |
| 236 | 79 | ||
| 237 | ### Listing PRs | 80 | ### List / view / comment |
| 238 | 81 | ||
| 239 | ```bash | 82 | ```bash |
| 240 | # List open and draft PRs (default) | ||
| 241 | ngit pr list | ||
| 242 | |||
| 243 | # List all statuses | ||
| 244 | ngit pr list --status open,draft,closed,applied | ||
| 245 | |||
| 246 | # Filter by label | ||
| 247 | ngit pr list --label bug | ||
| 248 | |||
| 249 | # Output as JSON (for scripting) | ||
| 250 | ngit pr list --json | 83 | ngit pr list --json |
| 251 | ``` | 84 | ngit pr list --json --status open,draft,closed,applied |
| 252 | 85 | ngit pr list --json --label bug | |
| 253 | ### Viewing a PR | ||
| 254 | |||
| 255 | ```bash | ||
| 256 | ngit pr view <ID|nevent> | ||
| 257 | |||
| 258 | # Include full comment thread | ||
| 259 | ngit pr view <ID|nevent> --comments | ||
| 260 | |||
| 261 | # JSON output | ||
| 262 | ngit pr view <ID|nevent> --json | 86 | ngit pr view <ID|nevent> --json |
| 87 | ngit pr view <ID|nevent> --json --comments | ||
| 88 | ngit pr comment <ID|nevent> --body "Looks good" | ||
| 89 | ngit pr comment <ID|nevent> --body "Fixed!" --reply-to <comment-ID> | ||
| 263 | ``` | 90 | ``` |
| 264 | 91 | ||
| 265 | ### Reviewing a PR | 92 | ### Checkout / apply |
| 266 | 93 | ||
| 267 | ```bash | 94 | ```bash |
| 268 | # Checkout the PR branch locally | ||
| 269 | ngit pr checkout <ID|nevent> | 95 | ngit pr checkout <ID|nevent> |
| 270 | |||
| 271 | # Or apply patches to current branch | ||
| 272 | ngit pr apply <ID|nevent> | 96 | ngit pr apply <ID|nevent> |
| 273 | ``` | 97 | ``` |
| 274 | 98 | ||
| 275 | ### Commenting on a PR | 99 | ### Merge (maintainer) |
| 276 | |||
| 277 | ```bash | ||
| 278 | ngit pr comment <ID|nevent> --body "Looks good, just one nit..." | ||
| 279 | |||
| 280 | # Reply to a specific comment | ||
| 281 | ngit pr comment <ID|nevent> --body "Fixed!" --reply-to <comment-ID> | ||
| 282 | ``` | ||
| 283 | |||
| 284 | ### Merging a PR (maintainer only) | ||
| 285 | |||
| 286 | Prefer `git merge` then push — this creates the merge commit and the push updates the Nostr state automatically: | ||
| 287 | 100 | ||
| 288 | ```bash | 101 | ```bash |
| 289 | # Checkout the PR branch, test it, then merge | ||
| 290 | ngit pr checkout <ID|nevent> | 102 | ngit pr checkout <ID|nevent> |
| 291 | git checkout main | 103 | git checkout main |
| 292 | git merge pr/my-feature | 104 | git merge pr/my-feature # or: git merge --squash pr/my-feature && git commit |
| 293 | git push origin main | 105 | git push origin main # push to nostr remote records the merge event |
| 294 | # pushing to the nostr remote records the merge event on Nostr | ||
| 295 | |||
| 296 | # Squash merge | ||
| 297 | git merge --squash pr/my-feature | ||
| 298 | git commit -m "feat: add dark mode" | ||
| 299 | git push origin main | ||
| 300 | ``` | 106 | ``` |
| 301 | 107 | ||
| 302 | ### PR lifecycle management | 108 | ### Lifecycle |
| 303 | 109 | ||
| 304 | ```bash | 110 | ```bash |
| 305 | # Close a PR (author or maintainer) | ||
| 306 | ngit pr close <ID|nevent> | 111 | ngit pr close <ID|nevent> |
| 307 | |||
| 308 | # Reopen a closed PR | ||
| 309 | ngit pr reopen <ID|nevent> | 112 | ngit pr reopen <ID|nevent> |
| 310 | 113 | ngit pr ready <ID|nevent> # mark draft as ready for review | |
| 311 | # Mark a draft PR as ready for review | ||
| 312 | ngit pr ready <ID|nevent> | ||
| 313 | ``` | 114 | ``` |
| 314 | 115 | ||
| 315 | --- | 116 | ## Issues |
| 316 | |||
| 317 | ## CONCEPT 4: Issues | ||
| 318 | |||
| 319 | _"Tracking bugs, features, and tasks"_ | ||
| 320 | |||
| 321 | ### Creating an issue | ||
| 322 | 117 | ||
| 323 | ```bash | 118 | ```bash |
| 324 | # Interactive | 119 | ngit issue create --title "Bug title" --body "Details" --label bug |
| 325 | ngit issue create | 120 | ngit issue create --title "Feature" --body "..." --label enhancement --label help-wanted |
| 326 | |||
| 327 | # Non-interactive | ||
| 328 | ngit issue create --title "Bug: login fails on mobile" \ | ||
| 329 | --body "Steps to reproduce: ..." \ | ||
| 330 | --label bug | ||
| 331 | |||
| 332 | # Multiple labels | ||
| 333 | ngit issue create --title "Add dark mode" \ | ||
| 334 | --body "Feature request" \ | ||
| 335 | --label enhancement --label help-wanted | ||
| 336 | ``` | ||
| 337 | |||
| 338 | ### Listing issues | ||
| 339 | |||
| 340 | ```bash | ||
| 341 | # List open issues (default) | ||
| 342 | ngit issue list | ||
| 343 | |||
| 344 | # Filter by status | ||
| 345 | ngit issue list --status open | ||
| 346 | ngit issue list --status closed | ||
| 347 | |||
| 348 | # Filter by label | ||
| 349 | ngit issue list --label bug | ||
| 350 | |||
| 351 | # JSON output | ||
| 352 | ngit issue list --json | 121 | ngit issue list --json |
| 353 | ``` | 122 | ngit issue list --json --status closed |
| 354 | 123 | ngit issue list --json --label bug | |
| 355 | ### Viewing an issue | ||
| 356 | |||
| 357 | ```bash | ||
| 358 | ngit issue view <ID|nevent> | ||
| 359 | |||
| 360 | # Include comment thread | ||
| 361 | ngit issue view <ID|nevent> --comments | ||
| 362 | |||
| 363 | # JSON output | ||
| 364 | ngit issue view <ID|nevent> --json | 124 | ngit issue view <ID|nevent> --json |
| 365 | ``` | 125 | ngit issue view <ID|nevent> --json --comments |
| 366 | 126 | ngit issue comment <ID|nevent> --body "Reproduced on v2.1" | |
| 367 | ### Commenting on an issue | 127 | ngit issue comment <ID|nevent> --body "Thanks!" --reply-to <comment-ID> |
| 368 | |||
| 369 | ```bash | ||
| 370 | ngit issue comment <ID|nevent> --body "I can reproduce this on v1.2.3" | ||
| 371 | |||
| 372 | # Reply to a specific comment | ||
| 373 | ngit issue comment <ID|nevent> --body "Thanks for the report!" --reply-to <comment-ID> | ||
| 374 | ``` | ||
| 375 | |||
| 376 | ### Closing and reopening issues | ||
| 377 | |||
| 378 | ```bash | ||
| 379 | # Close (author or maintainer) | ||
| 380 | ngit issue close <ID|nevent> | 128 | ngit issue close <ID|nevent> |
| 381 | |||
| 382 | # Reopen | ||
| 383 | ngit issue reopen <ID|nevent> | 129 | ngit issue reopen <ID|nevent> |
| 384 | ``` | 130 | ``` |
| 385 | 131 | ||
| 386 | --- | 132 | ## Account management |
| 387 | |||
| 388 | ## CONCEPT 5: Account Management | ||
| 389 | |||
| 390 | _"Managing your Nostr identity"_ | ||
| 391 | |||
| 392 | All credentials are stored as git config keys. You can set them directly or via `ngit account login`. | ||
| 393 | 133 | ||
| 394 | ```bash | 134 | ```bash |
| 395 | # Login interactively (stores credentials in global git config) | 135 | ngit account login # interactive, stores nsec in global git config |
| 396 | ngit account login | 136 | ngit account login --bunker-url bunker://... # NIP-46 remote signer |
| 397 | 137 | ngit account login --local # this repo only | |
| 398 | # Login with a bunker:// URL (remote signer / NIP-46) | ||
| 399 | ngit account login --bunker-url bunker://... | ||
| 400 | |||
| 401 | # Login only for this repository (local git config) | ||
| 402 | ngit account login --local | ||
| 403 | |||
| 404 | # Create a new account | ||
| 405 | ngit account create --name "Alice" | 138 | ngit account create --name "Alice" |
| 406 | |||
| 407 | # Export keys (to use in other Nostr clients) | ||
| 408 | ngit account export-keys | 139 | ngit account export-keys |
| 409 | |||
| 410 | # Logout (removes stored credentials from git config) | ||
| 411 | ngit account logout | 140 | ngit account logout |
| 141 | git config --global nostr.nsec <nsec> # set directly | ||
| 142 | ngit --nsec <nsec> <command> # inline for CI, no login needed | ||
| 412 | ``` | 143 | ``` |
| 413 | 144 | ||
| 414 | Credentials are stored as standard git config entries and can be set or inspected directly: | 145 | ## Sync |
| 415 | |||
| 416 | ```bash | ||
| 417 | # Set nsec globally for all repos | ||
| 418 | git config --global nostr.nsec <nsec> | ||
| 419 | |||
| 420 | # Set nsec for this repo only | ||
| 421 | git config nostr.nsec <nsec> | ||
| 422 | |||
| 423 | # View stored npub | ||
| 424 | git config --global nostr.npub | ||
| 425 | ``` | ||
| 426 | |||
| 427 | For CI/automation, pass `--nsec` inline — no login step required: | ||
| 428 | |||
| 429 | ```bash | ||
| 430 | ngit --nsec <nsec> issue create --title "CI report" --body "..." -d | ||
| 431 | ``` | ||
| 432 | |||
| 433 | --- | ||
| 434 | |||
| 435 | ## CONCEPT 6: Sync and Maintenance | ||
| 436 | |||
| 437 | _"Keeping git servers in sync with Nostr state"_ | ||
| 438 | |||
| 439 | ```bash | ||
| 440 | # Sync all refs from nostr state to git servers | ||
| 441 | ngit sync | ||
| 442 | |||
| 443 | # Sync a specific ref | ||
| 444 | ngit sync --ref-name main | ||
| 445 | ngit sync --ref-name v1.5.2 | ||
| 446 | ``` | ||
| 447 | |||
| 448 | Use `ngit sync` if git servers have fallen out of sync with the Nostr state (e.g. after relay-side changes). | ||
| 449 | |||
| 450 | --- | ||
| 451 | |||
| 452 | ## Common Workflows | ||
| 453 | |||
| 454 | ### Workflow: Publish a new repository | ||
| 455 | |||
| 456 | ```bash | ||
| 457 | cd my-project | ||
| 458 | git init | ||
| 459 | git add . | ||
| 460 | git commit -m "initial commit" | ||
| 461 | ngit init --name "My Project" --description "A cool project" -d | ||
| 462 | # origin is now set to nostr://... and code is pushed | ||
| 463 | |||
| 464 | # Get the canonical nostr:// URL to share (npub + relay hint + identifier) | ||
| 465 | ngit repo --json --offline | ||
| 466 | # Look for the "nostr_url" field in the output | ||
| 467 | # e.g. nostr://npub1abc.../relay.ngit.dev/my-project | ||
| 468 | ``` | ||
| 469 | |||
| 470 | ### Workflow: Contribute a PR to someone else's repo | ||
| 471 | |||
| 472 | ```bash | ||
| 473 | git clone nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/relay.ngit.dev/ngit | ||
| 474 | cd ngit | ||
| 475 | git checkout -b pr/fix-typo | ||
| 476 | # ... make changes ... | ||
| 477 | git commit -m "fix: correct typo in README" | ||
| 478 | git push -u origin pr/fix-typo \ | ||
| 479 | -o 'title=Fix typo in README' \ | ||
| 480 | -o 'description=Corrects a spelling mistake in the introduction.\n\nSmall copy fix, no functional changes.' | ||
| 481 | # Verify the PR was created | ||
| 482 | ngit pr list --json --offline | ||
| 483 | ``` | ||
| 484 | |||
| 485 | ### Workflow: Review and merge a PR (maintainer) | ||
| 486 | 146 | ||
| 487 | ```bash | 147 | ```bash |
| 488 | # See what's open | 148 | ngit sync # sync all refs from nostr state to git servers |
| 489 | ngit pr list --json | 149 | ngit sync --ref-name main # sync specific ref |
| 490 | |||
| 491 | # Review the PR | ||
| 492 | ngit pr view <ID> --json --comments | ||
| 493 | |||
| 494 | # Check it out and test locally | ||
| 495 | ngit pr checkout <ID> | ||
| 496 | # ... run tests ... | ||
| 497 | |||
| 498 | # Merge via git and push — push records the merge on Nostr | ||
| 499 | git checkout main | ||
| 500 | git merge pr/my-feature | ||
| 501 | git push origin main | ||
| 502 | # Verify the PR is now closed/applied | ||
| 503 | ngit pr view <ID> --json --offline | ||
| 504 | ``` | 150 | ``` |
| 505 | 151 | ||
| 506 | ### Workflow: File and close an issue | 152 | ## Key flags |
| 507 | |||
| 508 | ```bash | ||
| 509 | # File | ||
| 510 | ngit issue create --title "Crash on startup" \ | ||
| 511 | --body "Reproducible with v2.1 on Linux.\n\nSteps: run ngit init in an empty dir." \ | ||
| 512 | --label bug | ||
| 513 | # Verify the issue was created and note its ID | ||
| 514 | ngit issue list --json --offline | ||
| 515 | |||
| 516 | # Later, close it | ||
| 517 | ngit issue close <ID> | ||
| 518 | # Verify it is closed | ||
| 519 | ngit issue view <ID> --json --offline | ||
| 520 | ``` | ||
| 521 | 153 | ||
| 522 | ### Workflow: Non-interactive / CI scripting | 154 | | Flag | Description | |
| 155 | | --- | --- | | ||
| 156 | | `-d`, `--defaults` | Non-interactive; use sensible defaults | | ||
| 157 | | `--offline` | Local cache only, skip network | | ||
| 158 | | `--json` | Structured output (ngit commands only) | | ||
| 159 | | `-n`, `--nsec <NSEC>` | Provide nsec or hex private key inline | | ||
| 160 | | `-f`, `--force` | Bypass safety guards | | ||
| 161 | | `-v`, `--verbose` | Verbose output | | ||
| 523 | 162 | ||
| 524 | Use `-d` / `--defaults` to skip all prompts and `--nsec` to provide credentials: | 163 | ## git config |
| 525 | 164 | ||
| 526 | ```bash | 165 | ```bash |
| 527 | ngit --nsec <nsec> init --name "My Repo" --description "CI-published repo" -d | 166 | ngit --customize # show all options |
| 528 | ngit --nsec <nsec> issue create --title "Automated report" --body "..." -d | 167 | git config nostr.repo-relay-only true # don't broadcast to personal relays |
| 529 | ``` | ||
| 530 | |||
| 531 | --- | ||
| 532 | |||
| 533 | ## Reference: ID formats | ||
| 534 | |||
| 535 | Many commands accept an `<ID|nevent>` argument. This can be: | ||
| 536 | |||
| 537 | - A hex event ID: `a1b2c3d4...` (64 hex chars) | ||
| 538 | - A bech32 nevent: `nevent1...` | ||
| 539 | |||
| 540 | Get IDs from `ngit pr list --json` or `ngit issue list --json`. | ||
| 541 | |||
| 542 | --- | ||
| 543 | |||
| 544 | ## Reference: Push options for PRs | ||
| 545 | |||
| 546 | When pushing a `pr/` branch, always set title and description via `-o` push options: | ||
| 547 | |||
| 548 | | Option | Description | | ||
| 549 | | -------------------- | ----------------------------------------------- | | ||
| 550 | | `title=<text>` | PR title | | ||
| 551 | | `description=<text>` | PR description; use `\n\n` for paragraph breaks | | ||
| 552 | |||
| 553 | ```bash | ||
| 554 | git push -u origin pr/my-branch \ | ||
| 555 | -o 'title=My PR Title' \ | ||
| 556 | -o 'description=Summary of changes.\n\nMore detail here.' | ||
| 557 | ``` | ||
| 558 | |||
| 559 | --- | ||
| 560 | |||
| 561 | ## Reference: Key flags | ||
| 562 | |||
| 563 | | Flag | Description | | ||
| 564 | | --------------------- | ----------------------------------------------------------- | | ||
| 565 | | `-d`, `--defaults` | Non-interactive mode; use sensible defaults for all prompts | | ||
| 566 | | `-i`, `--interactive` | Force interactive prompts (default behaviour) | | ||
| 567 | | `-f`, `--force` | Bypass safety guards | | ||
| 568 | | `-n`, `--nsec <NSEC>` | Provide nsec or hex private key inline | | ||
| 569 | | `--offline` | Use local cache only, skip network fetch | | ||
| 570 | | `--json` | Output as JSON (on commands that support it) | | ||
| 571 | | `-v`, `--verbose` | Verbose output | | ||
| 572 | |||
| 573 | --- | ||
| 574 | |||
| 575 | ## Reference: git config customisation | ||
| 576 | |||
| 577 | All ngit settings live in git config under the `nostr.*` namespace. | ||
| 578 | |||
| 579 | ```bash | ||
| 580 | # Show all customisation options | ||
| 581 | ngit --customize | ||
| 582 | |||
| 583 | # Store credentials | ||
| 584 | git config --global nostr.nsec <nsec> | ||
| 585 | |||
| 586 | # Repo-only relay publishing (don't broadcast to personal relays) | ||
| 587 | git config nostr.repo-relay-only true | ||
| 588 | ``` | 168 | ``` |