Update ngit skill to v1.18

This commit is contained in:
greenart7c3
2026-09-14 08:03:40 -03:00
parent f4865b406f
commit ad0a50c03b
18 changed files with 454 additions and 454 deletions
+57 -54
View File
@@ -1,32 +1,39 @@
---
name: ngit
description: Commands and workflows for NIP-34 git collaboration over Nostr with the ngit CLI and git-remote-nostr. Use in any repository with a nostr:// remote for generic collaboration requests (open an Issue, create or review a Pull Request (PR), comment, merge, clone) and whenever a task involves nostr:// URLs, ngit commands, Grasp servers, gitworkshop.dev, Nostr CI status and workflows, software releases and Zapstore publication, OCI container images, or nsite static sites published through Blossom.
description:
Commands and workflows for NIP-34 git collaboration over Nostr with the ngit
CLI and git-remote-nostr. Use in any repository with a nostr:// remote for
generic collaboration requests (open an Issue, create or review a Pull Request
(PR), comment, merge, clone) and whenever a task involves nostr:// URLs, ngit
commands, Grasp servers, gitworkshop.dev, Nostr CI status and workflows,
software releases and Zapstore publication, OCI container images, or nsite
static sites published through Blossom.
license: CC-BY-SA-4.0
metadata:
version: "1.17"
version: "1.18"
---
# ngit — Nostr Plugin for Git
ngit makes `git clone`, `fetch`, and `push` work with `nostr://` URLs and adds
a CLI for pull requests, issues, membership, CI results, releases, OCI
containers, and nsites. Repository state (which commit each ref points to) is
published as signed Nostr events and is the source of truth; git objects live
on ordinary git servers, so servers are interchangeable. A grasp server bundles
a relay and a git server and creates the repository automatically when an
announcement lists it. Explanation: https://ngit.dev/how-it-works
ngit makes `git clone`, `fetch`, and `push` work with `nostr://` URLs and adds a
CLI for pull requests, issues, membership, CI results, releases, OCI containers,
and nsites. Repository state (which commit each ref points to) is published as
signed Nostr events and is the source of truth; git objects live on ordinary git
servers, so servers are interchangeable. A grasp server bundles a relay and a
git server and creates the repository automatically when an announcement lists
it. Explanation: https://ngit.dev/how-it-works
## Where to look
- **This skill documents ngit v3.** Run `ngit --version` first; the commands
here need 3.0.0 or later. If ngit is missing or older, report that and
offer an install or update: `curl -fsSL https://ngit.dev/install.sh | bash`
installs or replaces `ngit` and `git-remote-nostr`, and `ngit update` works
on v3 or later. Other methods: https://ngit.dev/install
- **`ngit <command> --help`** is the authority for the installed version's
flags and defaults.
- **https://ngit.dev** holds the guides. Any page is available as raw
Markdown at `https://ngit.dev/markdown/<route>.md`; the index is
here need 3.0.0 or later. If ngit is missing or older, report that and offer
an install or update: `curl -fsSL https://ngit.dev/install.sh | bash` installs
or replaces `ngit` and `git-remote-nostr`, and `ngit update` works on v3 or
later. Other methods: https://ngit.dev/install
- **`ngit <command> --help`** is the authority for the installed version's flags
and defaults.
- **https://ngit.dev** holds the guides. Any page is available as raw Markdown
at `https://ngit.dev/markdown/<route>.md`; the index is
https://ngit.dev/llms.txt. Web UI: https://gitworkshop.dev
## Rules
@@ -35,44 +42,40 @@ announcement lists it. Explanation: https://ngit.dev/how-it-works
policy. Carry through the selected signer, target, hosting, CI, and
replication settings; do not add gates, waits, workflow edits, or
configuration changes that the task or repository did not choose.
- **PR branches MUST start with `pr/`** (e.g. `pr/my-feature`). Any other
branch name is a plain push and never creates a PR.
- **PR branches MUST start with `pr/`** (e.g. `pr/my-feature`). Any other branch
name is a plain push and never creates a PR.
- **Read ngit output with `--json`.** It is a global option and works at any
position. Stdout is exactly one JSON document; progress and diagnostics go
to stderr. `git` commands have no `--json`. Top-level `command_status` is
`ok` for exit 0 and `error` otherwise; it never describes a nested domain
result (`ngit ci status --json` reports `ok` with
`ci.conclusion: "failure"` unless a gate was requested).
position. Stdout is exactly one JSON document; progress and diagnostics go to
stderr. `git` commands have no `--json`. Top-level `command_status` is `ok`
for exit 0 and `error` otherwise; it never describes a nested domain result
(`ngit ci status --json` reports `ok` with `ci.conclusion: "failure"` unless a
gate was requested).
- **Add `--offline` after the first network read** in a session, on commands
that support it. `git fetch origin` also refreshes the cache.
- **Identifiers.** `<ID|nevent>` accepts `nevent1…`, a 64-char hex ID, or a
unique hex prefix with an optional `#` (quote it: `'#deadbeef'`). JSON `id`
and `reply_to` fields are already `nevent1…`; container publication instead
returns a raw-hex `event_id` plus the repository `naddr`. Reference events
inside `--body` text as `nostr:nevent1…` or `nostr:naddr1…`, never as raw
hex. Never construct a NIP-05 address (`user@domain`); use `npub1…` unless
a NIP-05 address was given to you.
- **Multiline text.** `ngit` options such as `--body` and `--description`
accept real newlines: `--body "$(cat note.md)"`. Git push options cannot
carry newlines: write literal `\n` in a short inline `-o description=…`, and
never convert a file into a push option (open the PR with `ngit send`
instead).
inside `--body` text as `nostr:nevent1…` or `nostr:naddr1…`, never as raw hex.
Never construct a NIP-05 address (`user@domain`); use `npub1…` unless a NIP-05
address was given to you.
- **Multiline text.** `ngit` options such as `--body` and `--description` accept
real newlines: `--body "$(cat note.md)"`. Git push options cannot carry
newlines: write literal `\n` in a short inline `-o description=…`, and never
convert a file into a push option (open the PR with `ngit send` instead).
- **Signers.** `--signer <alias|npub|profile-name>` selects a stored identity
for one `ngit` command; `git -c nostr.signer=<alias|npub|profile-name>
push …` does the same for one git command. Neither changes the configured
login. Never export or pass an nsec merely to switch between configured
accounts.
- **CI.** A successful push says nothing about CI. Nostr CI runs workflows
from `.ngit/act/workflows/`; another provider's directory is not evidence.
When CI matters, query the exact commit or PR with
`ngit ci status <target> --json` and read `ci.state` and `ci.conclusion`,
not `command_status`.
for one `ngit` command; `git -c nostr.signer=<alias|npub|profile-name> push …`
does the same for one git command. Neither changes the configured login. Never
export or pass an nsec merely to switch between configured accounts.
- **CI.** A successful push says nothing about CI. Nostr CI runs workflows from
`.ngit/act/workflows/`; another provider's directory is not evidence. When CI
matters, query the exact commit or PR with `ngit ci status <target> --json`
and read `ci.state` and `ci.conclusion`, not `command_status`.
- **Target repository.** With several `nostr://` remotes, pass global
`--repo <REMOTE|NADDR|NOSTR-URL>`; a configured remote name, an naddr, and
a nostr:// URL are all accepted. Without it ngit
infers the target from config and branch tracking and fails rather than
guesses. Before a signing command, check the
`target repository: <naddr> (source: …)` line on stderr.
`--repo <REMOTE|NADDR|NOSTR-URL>`; a configured remote name, an naddr, and a
nostr:// URL are all accepted. Without it ngit infers the target from config
and branch tracking and fails rather than guesses. Before a signing command,
check the `target repository: <naddr> (source: …)` line on stderr.
## Detecting a nostr repo
@@ -81,11 +84,11 @@ git remote -v | grep -q 'nostr://' # primary check, no cache needed
ngit repo --json --offline # full metadata when needed
```
`ngit repo` always exits 0, and `is_nostr_repo: false` can be a cold-cache
false negative: if a remote shows `nostr://`, run `git fetch origin` and
retry. The output includes the roster (`members`, `lead_source`, `lead_path`,
`pending_actions`, `health`); read `reference/repositories.md` before
changing membership or hosting.
`ngit repo` always exits 0, and `is_nostr_repo: false` can be a cold-cache false
negative: if a remote shows `nostr://`, run `git fetch origin` and retry. The
output includes the roster (`members`, `lead_source`, `lead_path`,
`pending_actions`, `health`); read `reference/repositories.md` before changing
membership or hosting.
## nostr:// URLs
@@ -100,11 +103,11 @@ Standard git commands accept these URLs directly.
## Task index
Read the bundled reference before performing that slice of work; the guide
adds tutorials and background.
Read the bundled reference before performing that slice of work; the guide adds
tutorials and background.
| Task | Bundled reference | ngit.dev guide |
| ---- | ----------------- | -------------- |
| ---------------------------------------------------------- | --------------------------- | ------------------------------------ |
| Publish, clone, host repositories; maintainers, moderators | `reference/repositories.md` | `/repositories`, `/maintainers` |
| Open, update, stack, review, merge PRs | `reference/prs.md` | `/pull-requests` |
| Issues | `reference/issues.md` | `/issues` |
+8 -8
View File
@@ -1,8 +1,8 @@
# Accounts — identity, login, secrets
Read when managing accounts, logins, or credential storage.
Guide: https://ngit.dev/accounts (storage modes, pairing a remote signer for
CI, rotation).
Read when managing accounts, logins, or credential storage. Guide:
https://ngit.dev/accounts (storage modes, pairing a remote signer for CI,
rotation).
```bash
ngit account whoami --json --offline # every usable signer with npub, aliases, scope, active state; `account list` is an alias
@@ -40,8 +40,8 @@ unaliased connection. Log in with `--alias` to keep an extra connection and
select it by alias. Older ngit versions ignore the exact-session binding and
select the identity's default connection.
**nbunksec** is a portable established connection: remote-signer pubkey,
client secret, relays, and optional pairing secret. It holds no npub, so
one-shot use resolves the identity from the signer. The `--nbunksec-file` and
`--nsec-file` forms keep secrets out of process arguments. A fresh pairing
needs interactive approval, so unattended runs use a stored connection.
**nbunksec** is a portable established connection: remote-signer pubkey, client
secret, relays, and optional pairing secret. It holds no npub, so one-shot use
resolves the identity from the signer. The `--nbunksec-file` and `--nsec-file`
forms keep secrets out of process arguments. A fresh pairing needs interactive
approval, so unattended runs use a stored connection.
+22 -22
View File
@@ -1,18 +1,18 @@
# Nostr CI
Read when checking whether CI ran, interpreting a result, or writing a
workflow that uses ngit. Guides: https://ngit.dev/ci (coordinators, results,
trust, secrets) and https://ngit.dev/ci/workflows/ (what the coordinator
accepts, refuses, and adds compared with GitHub Actions).
Read when checking whether CI ran, interpreting a result, or writing a workflow
that uses ngit. Guides: https://ngit.dev/ci (coordinators, results, trust,
secrets) and https://ngit.dev/ci/workflows/ (what the coordinator accepts,
refuses, and adds compared with GitHub Actions).
## Workflows
Nostr CI (ngit-ci) runs workflows from `.ngit/act/workflows/` with
GitHub Actions syntax in Linux containers. `.github/workflows/` is run only by
GitHub Actions on a mirror; the directories are independent, so a check that
must run in both systems needs a file in each. ngit-ci refuses macOS and
Windows `runs-on` labels and job-level `uses:` (reusable workflows); composite
actions in steps work in both systems.
Nostr CI (ngit-ci) runs workflows from `.ngit/act/workflows/` with GitHub
Actions syntax in Linux containers. `.github/workflows/` is run only by GitHub
Actions on a mirror; the directories are independent, so a check that must run
in both systems needs a file in each. ngit-ci refuses macOS and Windows
`runs-on` labels and job-level `uses:` (reusable workflows); composite actions
in steps work in both systems.
Read the workflow at the commit under investigation and confirm that its
triggers and steps cover the check in question:
@@ -43,25 +43,25 @@ ngit ci status <target> --json --offline # later cache
ngit ci status <target> --require-ci-trust maintainer-directed --json # exit non-zero unless green at this floor
```
Query the exact commit that introduced the change. A PR target reports only
its latest revision. Read:
Query the exact commit that introduced the change. A PR target reports only its
latest revision. Read:
- `ci.state`: pending, running, or concluded. `ci.conclusion` counts only
once the state is concluded.
- `ci.state`: pending, running, or concluded. `ci.conclusion` counts only once
the state is concluded.
- `ci.conclusion`: success, failure, cancellation, or another outcome.
`command_status: "ok"` means only that the query worked.
- `ci.runs[].workflow` and `ci.runs[].jobs`: which workflow and job passed or
failed.
- `ci.runs[].integrity`: the commit is present locally and the workflow hash
matches.
- `coverage` and each run's classification and evidence: how completely and
why the result is trusted. Partial coverage is not success.
- `coverage` and each run's classification and evidence: how completely and why
the result is trusted. Partial coverage is not success.
If no run appears, report that no matching Nostr CI event was found. Then
check that the workflow existed at that commit, its trigger matched, a
coordinator serves the repository, and the query refreshed the relays before
concluding that CI did not run.
If no run appears, report that no matching Nostr CI event was found. Then check
that the workflow existed at that commit, its trigger matched, a coordinator
serves the repository, and the query refreshed the relays before concluding that
CI did not run.
Trust floors are `maintainer-directed` and `operationally-associated`.
`ngit pr merge --require-ci-trust <LEVEL>` applies the same gate to a merge
when the caller wants one.
`ngit pr merge --require-ci-trust <LEVEL>` applies the same gate to a merge when
the caller wants one.
+39 -40
View File
@@ -1,16 +1,16 @@
# Containers — publish OCI images
Read before publishing an OCI image, updating a container tag, choosing
Blossom storage, or constructing a gateway pull reference. Protocol
background: https://ngit.dev/protocol/software-publishing
Read before publishing an OCI image, updating a container tag, choosing Blossom
storage, or constructing a gateway pull reference. Protocol background:
https://ngit.dev/protocol/software-publishing
## Model
`ngit container publish` (alias `ngit oci publish`) uploads the OCI blobs
reachable from the tagged entries of an OCI image layout to Blossom, then
signs a kind-30624 addressable event mapping tags to manifest digests. The
event is bound to the current kind-30617 git repository, so run it inside that
repository with a signer who is a confirmed maintainer. Gateways are read-only:
reachable from the tagged entries of an OCI image layout to Blossom, then signs
a kind-30624 addressable event mapping tags to manifest digests. The event is
bound to the current kind-30617 git repository, so run it inside that repository
with a signer who is a confirmed maintainer. Gateways are read-only:
```bash
docker pull ncontainer.io/<npub>/<repository>:<tag>
@@ -31,8 +31,8 @@ ngit container publish myimage \
--json
```
A checked-in `.ngit/containers.yaml` lets `ngit container publish myimage
--json` select an entry:
A checked-in `.ngit/containers.yaml` lets
`ngit container publish myimage --json` select an entry:
```yaml
schema: 1
@@ -47,10 +47,10 @@ containers:
Relative paths resolve from the repository root. `--manifest PATH` selects
another file; `--no-manifest` ignores the default and requires `--layout`. A
loaded manifest must define `NAME`. CLI layout and metadata override the
entry, a non-empty CLI Blossom list replaces the configured list, and CLI
relays extend configured relays. Signer selection, `--replace`, and output
mode stay on the command line.
loaded manifest must define `NAME`. CLI layout and metadata override the entry,
a non-empty CLI Blossom list replaces the configured list, and CLI relays extend
configured relays. Signer selection, `--replace`, and output mode stay on the
command line.
Behaviour to know:
@@ -59,44 +59,43 @@ Behaviour to know:
`index.json`; filenames and git tags are irrelevant. `index.json` itself is
never uploaded; ngit merges the layout's tags into the tag map fetched from
the latest kind-30624 event.
- Without `--blossom-server`, ngit uses the publisher's latest kind-10063
server list. A single server means no redundancy. Every blob is checked on
every server, missing copies are uploaded with bounded retries and
verified, and the event is signed once each blob has at least one confirmed
copy; incomplete replication is reported per server.
- `--relay` extends the repository's relays; account and default relays are
not added. ngit reads the repository relays before and after uploading and
needs at least one success each time. A total preflight failure or a
- Without `--blossom-server`, ngit uses the publisher's latest kind-10063 server
list. A single server means no redundancy. Every blob is checked on every
server, missing copies are uploaded with bounded retries and verified, and the
event is signed once each blob has at least one confirmed copy; incomplete
replication is reported per server.
- `--relay` extends the repository's relays; account and default relays are not
added. ngit reads the repository relays before and after uploading and needs
at least one success each time. A total preflight failure or a
concurrent-update refusal is safe to retry: uploaded blobs are
content-addressed. Keep a known state-bearing repository relay reachable
when changing relay sets, because a healthy empty relay cannot reveal an
event stranded elsewhere and a publish could then omit old tags.
content-addressed. Keep a known state-bearing repository relay reachable when
changing relay sets, because a healthy empty relay cannot reveal an event
stranded elsewhere and a publish could then omit old tags.
## Merge versus replace
Ordinary publication updates the tags found in the new layout and retains
older tags, previous server hints, omitted metadata, and unknown event tags.
Ordinary publication updates the tags found in the new layout and retains older
tags, previous server hints, omitted metadata, and unknown event tags.
`--replace` publishes only the new layout's tags and selected servers, drops
omitted description, source, and unknown tags, and sets the title to
`--title` or `NAME`. Use it only when the user explicitly wants complete
replacement.
omitted description, source, and unknown tags, and sets the title to `--title`
or `NAME`. Use it only when the user explicitly wants complete replacement.
## JSON
A successful result has `command: "container.publish"`, a `warnings` array,
and `result` fields: `repository`, `git_repository`, `npub`, `name`, `naddr`,
`manifest_path` (or `null`), raw-hex `event_id` (unlike collaboration
commands' `nevent` ids), `tags` and `updated_tags`, per-blob SHA-256, size,
and per-server placement, final `blossom_servers`, and per-relay `accepted`.
Success means at least one relay accepted the event; inspect every
`result.relays[].accepted` when full fanout matters. Failures use
`command_status: "error"` with `error.details` holding per-blob and
per-server outcomes and possible orphan blobs.
A successful result has `command: "container.publish"`, a `warnings` array, and
`result` fields: `repository`, `git_repository`, `npub`, `name`, `naddr`,
`manifest_path` (or `null`), raw-hex `event_id` (unlike collaboration commands'
`nevent` ids), `tags` and `updated_tags`, per-blob SHA-256, size, and per-server
placement, final `blossom_servers`, and per-relay `accepted`. Success means at
least one relay accepted the event; inspect every `result.relays[].accepted`
when full fanout matters. Failures use `command_status: "error"` with
`error.details` holding per-blob and per-server outcomes and possible orphan
blobs.
## Limits
ngit accepts OCI and Docker v2 manifests and indexes using SHA-256, uploads
only blobs reachable from tagged roots, and rejects missing, oversized, deeply
ngit accepts OCI and Docker v2 manifests and indexes using SHA-256, uploads only
blobs reachable from tagged roots, and rejects missing, oversized, deeply
nested, or mismatched graphs. It snapshots one blob at a time, so allow
temporary disk roughly equal to the largest layer. It does not build images,
push to registries, run a gateway, chunk layers, pull, list, or delete remote
+4 -4
View File
@@ -17,13 +17,13 @@ ngit issue set-subject <ID|nevent> --subject "New title" --json
ngit issue set-cover-note <ID|nevent> --body "$(cat cover-note.md)" --json
```
`resolved` records that the problem was fixed; `close` records that it will
not be. Reference other events in `--body` as `nostr:nevent1…`.
`resolved` records that the problem was fixed; `close` records that it will not
be. Reference other events in `--body` as `nostr:nevent1…`.
## Auto-resolve from commits
A commit pushed to the declared default branch resolves an issue when its
message contains a form of `close`, `fix`, `resolve`, or `implement` followed
by a unique hex ID or prefix or a `nostr:nevent1…` reference, for example
message contains a form of `close`, `fix`, `resolve`, or `implement` followed by
a unique hex ID or prefix or a `nostr:nevent1…` reference, for example
`Fixes #deadbeef`. The status is published only when the pusher is the issue
author or a confirmed repository member.
+27 -28
View File
@@ -1,14 +1,14 @@
# Nsites — publish static sites
Read before publishing an already-built website with `ngit nsite` or
diagnosing its Blossom uploads and NIP-5A manifest.
Guide: https://ngit.dev/releases/nsites (nsyte comparison, PR previews).
Read before publishing an already-built website with `ngit nsite` or diagnosing
its Blossom uploads and NIP-5A manifest. Guide: https://ngit.dev/releases/nsites
(nsyte comparison, PR previews).
## Publish
Pass the build output directory, not the source tree. ngit uploads every
regular file, runs no build, applies no ignore files, and rejects symlinks,
unsafe paths, and filenames without extensions.
Pass the build output directory, not the source tree. ngit uploads every regular
file, runs no build, applies no ignore files, and rejects symlinks, unsafe
paths, and filenames without extensions.
```bash
ngit nsite publish dist --json # reads nsyte's .nsite/config.json when present
@@ -26,33 +26,32 @@ ngit --nbunksec-file /run/secrets/publisher-nbunksec nsite publish dist --json
- Config: `.nsite/config.json` (JSON, not YAML) fields `id`, `title`,
`description`, `source`, `fallback`, `servers`, and `relays` are read;
`--config PATH` selects another file and `--no-config` ignores it. Explicit
CLI values win, and any repeated `--blossom-server` or `--relay` replaces
that whole config array. Unsupported nsyte publication options
(`publishProfile`, `publishRelayList`, `publishServerList`,
`publishAppHandler`) produce a warning; nsyte signer fields are ignored.
- Metadata: `--title`, `--description` or `--description-file`, and
`--source` (`https://` or `nostr://`; omitted, ngit infers the selected
public repository and never a private one). NIP-5A has no logo tag; ship a
`favicon.ico` or `favicon.svg` in the build output.
CLI values win, and any repeated `--blossom-server` or `--relay` replaces that
whole config array. Unsupported nsyte publication options (`publishProfile`,
`publishRelayList`, `publishServerList`, `publishAppHandler`) produce a
warning; nsyte signer fields are ignored.
- Metadata: `--title`, `--description` or `--description-file`, and `--source`
(`https://` or `nostr://`; omitted, ngit infers the selected public repository
and never a private one). NIP-5A has no logo tag; ship a `favicon.ico` or
`favicon.svg` in the build output.
- `--fallback SITE_PATH` (or config `fallback`) maps an existing HTML file in
the output to `/404.html` without another upload.
- Servers: omit `--blossom-server` to use the account's latest kind-10063
list; repeat it for replication. `--concurrency` (default 4, range 1–64) is
a global limit across presence checks and uploads.
- Servers: omit `--blossom-server` to use the account's latest kind-10063 list;
repeat it for replication. `--concurrency` (default 4, range 1–64) is a global
limit across presence checks and uploads.
## Guarantees
ngit snapshots the directory before network work, deduplicates content, checks
every blob on every selected server, and uploads missing copies with BUD-11
authorization. It signs the manifest only after every blob has at least one
confirmed copy, so a failed deployment cannot point the live manifest at
missing content. A server that fails three consecutive initial checks is
skipped for the rest of that pass while the others continue.
confirmed copy, so a failed deployment cannot point the live manifest at missing
content. A server that fails three consecutive initial checks is skipped for the
rest of that pass while the others continue.
Rerun the same command after a failure: blobs already on a server are
confirmed with `HEAD` and skipped, so continuation is per blob and server. An
unchanged deployment reuses the current manifest without a new signature or
relay write.
Rerun the same command after a failure: blobs already on a server are confirmed
with `HEAD` and skipped, so continuation is per blob and server. An unchanged
deployment reuses the current manifest without a new signature or relay write.
## JSON
@@ -61,10 +60,10 @@ Check `command_status`, then:
- `result.changed`: publication versus an unchanged no-op;
- `result.config_path`, `result.fallback`, `result.relays`: resolved settings;
- `result.blossom.blobs[].servers[]`: each blob and server outcome;
- `result.publication.relays[]`: manifest acknowledgements (at least one
relay must accept);
- `warnings[]`: unknown MIME types, unsupported config publications, and
failed uploads or post-upload verification per server.
- `result.publication.relays[]`: manifest acknowledgements (at least one relay
must accept);
- `warnings[]`: unknown MIME types, unsupported config publications, and failed
uploads or post-upload verification per server.
On a Blossom failure inspect `error.details.blobs` and
`error.details.possible_orphan_blobs`, fix the server or signer problem, and
+20 -21
View File
@@ -1,12 +1,12 @@
# Pull requests — open, update, stack, review, merge
Read before opening, updating, reviewing, or merging PRs.
Guide: https://ngit.dev/pull-requests
Read before opening, updating, reviewing, or merging PRs. Guide:
https://ngit.dev/pull-requests
## Open or update a PR
The branch name MUST start with `pr/`. No push option turns another branch
into a PR.
The branch name MUST start with `pr/`. No push option turns another branch into
a PR.
```bash
git checkout -b pr/my-feature
@@ -21,18 +21,18 @@ git push --force origin pr/my-feature # update the PR after amend
- `-d`/`--defaults` accepts the single-commit title and description without a
prompt.
- Do not use `$'…\n…'` for push options, and do not pre-escape a Markdown
file into `-o description=`; open the PR with `ngit send` instead.
- Do not use `$'…\n…'` for push options, and do not pre-escape a Markdown file
into `-o description=`; open the PR with `ngit send` instead.
- Stacks are inferred: a branch that contains the unique latest tip of one of
your other open or draft PRs becomes that PR's child and follows the parent
as it advances. Rebase the child onto the parent's latest tip before updating
it; ngit refuses stale children and ambiguous candidates rather than
guessing. Use `base=` for a cross-author, historical, or ambiguous parent,
and repeat it on each update if the child should stay pinned.
your other open or draft PRs becomes that PR's child and follows the parent as
it advances. Rebase the child onto the parent's latest tip before updating it;
ngit refuses stale children and ambiguous candidates rather than guessing. Use
`base=` for a cross-author, historical, or ambiguous parent, and repeat it on
each update if the child should stay pinned.
- To push as another stored identity, use
`git -c nostr.signer=<alias|npub|profile-name> push …`; `--signer` applies
to `ngit` commands only. `ngit account login --local <alias>` makes an
identity the repository default instead.
`git -c nostr.signer=<alias|npub|profile-name> push …`; `--signer` applies to
`ngit` commands only. `ngit account login --local <alias>` makes an identity
the repository default instead.
## ngit send
@@ -70,13 +70,12 @@ ngit pr merge <ID|nevent> --exclude-description --json # summary line and
git push origin <target-branch> # publishes the merge and the applied status
```
`ngit merge` is a compatibility alias with the same options. The merge lands
on the PR's declared target, or the default branch, resolved against the
latest Nostr repository state rather than a local tracking ref, with the
message `Merge #<8-hex>: <PR title>`. Closed and applied PRs are refused
before any git change. On conflicts, resolve them and run `git commit`; the
message is already prepared, and JSON reports `action: "conflicted"` instead
of `"merged"`.
`ngit merge` is a compatibility alias with the same options. The merge lands on
the PR's declared target, or the default branch, resolved against the latest
Nostr repository state rather than a local tracking ref, with the message
`Merge #<8-hex>: <PR title>`. Closed and applied PRs are refused before any git
change. On conflicts, resolve them and run `git commit`; the message is already
prepared, and JSON reports `action: "conflicted"` instead of `"merged"`.
Before merging or adding maintainer fixes, run
`git log --merges --oneline origin/<target>..HEAD`. A prior `Merge #…` means a
+20 -20
View File
@@ -1,9 +1,9 @@
# Repositories — publish, clone, hosting, membership
Read when publishing or cloning a repository, resolving `nostr://` URL forms,
or changing an announcement's hosting, metadata, or roster. Guides:
https://ngit.dev/repositories (hosting choices, migrating from a forge,
mirrors, private repositories), https://ngit.dev/maintainers, and
Read when publishing or cloning a repository, resolving `nostr://` URL forms, or
changing an announcement's hosting, metadata, or roster. Guides:
https://ngit.dev/repositories (hosting choices, migrating from a forge, mirrors,
private repositories), https://ngit.dev/maintainers, and
https://ngit.dev/maintainers/going-deeper (leadless repositories, delegated
trust, removal, roster repair).
@@ -36,9 +36,9 @@ ngit repo --json --offline # run git fetch origin first when the cache may
The output reports `nostr_url`, effective `git_servers`, `relays`, `hashtags`,
and `grasp_servers` detected from paired clone and relay entries, plus the
roster: `members`, `lead_source`, `lead_path`, `pending_actions`, and
`health`. Follow the actionable error or `pending_actions` rather than
replacing an announcement wholesale.
roster: `members`, `lead_source`, `lead_path`, `pending_actions`, and `health`.
Follow the actionable error or `pending_actions` rather than replacing an
announcement wholesale.
## Publish and host
@@ -66,8 +66,8 @@ Every announcement needs at least one relay and one git server; `init` and
announcement that already lacks one half. Repair it in the same command, e.g.
`ngit repo edit --name "New name" --add-grasp-server grasp.example.com`.
`--identifier` is set at initial publication only: changing the `d` tag
creates a different repository coordinate.
`--identifier` is set at initial publication only: changing the `d` tag creates
a different repository coordinate.
## Edit
@@ -75,21 +75,21 @@ creates a different repository coordinate.
repeatable actions that can be combined in one command:
| 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` |
Scalars use replacement flags: `--name`, `--description`, `--web`, `--u`,
`--earliest-unique-commit`. A grasp-derived relay or clone cannot be removed
as an additional entry; remove the grasp server and its pair goes with it. To
empty a collection, remove every value currently reported.
`--earliest-unique-commit`. A grasp-derived relay or clone cannot be removed as
an additional entry; remove the grasp server and its pair goes with it. To empty
a collection, remove every value currently reported.
Each successful edit publishes a fresh announcement and, when the repository
has Nostr state, republishes that state once so new relays and servers hold
the authoritative refs. If that fails, follow the reported `ngit sync`
recovery guidance.
Each successful edit publishes a fresh announcement and, when the repository has
Nostr state, republishes that state once so new relays and servers hold the
authoritative refs. If that fails, follow the reported `ngit sync` recovery
guidance.
## Roles and membership
@@ -101,9 +101,9 @@ recovery guidance.
- **Moderator**: publishes issue, PR, and patch status events (including
recording an existing merge) but cannot publish git state or merge.
Membership is reciprocal: a listing is an invitation until the invitee
publishes an announcement acknowledging the role, and an invited member's
events are not authoritative until then.
Membership is reciprocal: a listing is an invitation until the invitee publishes
an announcement acknowledging the role, and an invited member's events are not
authoritative until then.
```bash
ngit repo edit --add-maintainer <npub> --json # a sole maintainer's first add makes them lead
+7 -7
View File
@@ -1,7 +1,7 @@
# Sync, flags, and configuration
Read when syncing refs, choosing flags, or tuning git config.
Guides: https://ngit.dev/configuration and https://ngit.dev/troubleshooting
Read when syncing refs, choosing flags, or tuning git config. Guides:
https://ngit.dev/configuration and https://ngit.dev/troubleshooting
## Sync
@@ -16,7 +16,7 @@ These accept any command position. `--offline` is per command; check
`ngit <command> --help`.
| Flag | Description |
| ---- | ----------- |
| --------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `--json` | One JSON document on stdout (ngit commands only) |
| `-d`, `--defaults` | Non-interactive; accept defaults |
| `-q`, `--quiet` | Hide non-essential stderr progress (not combinable with `-v`) |
@@ -39,11 +39,11 @@ git config nostr.http-io-timeout-ms 600000 # allow large grasp pushes
NGIT_CACHE_DIR=/writable/path ngit repo --json # override the global event-cache directory
```
`nostr.auto-pr-branches` follows normal git config precedence. With the
default `false`, PRs appear as branches only after `ngit pr checkout`; run
`nostr.auto-pr-branches` follows normal git config precedence. With the default
`false`, PRs appear as branches only after `ngit pr checkout`; run
`git fetch --prune` once to drop branches fetched by an older version, or use
`git clone --config nostr.auto-pr-branches=true <nostr-url>` to opt in from
the start.
`git clone --config nostr.auto-pr-branches=true <nostr-url>` to opt in from the
start.
If the global cache directory is unavailable ngit falls back to an in-memory
cache; the repository's git common directory must still be writable.
+57 -54
View File
@@ -1,32 +1,39 @@
---
name: ngit
description: Commands and workflows for NIP-34 git collaboration over Nostr with the ngit CLI and git-remote-nostr. Use in any repository with a nostr:// remote for generic collaboration requests (open an Issue, create or review a Pull Request (PR), comment, merge, clone) and whenever a task involves nostr:// URLs, ngit commands, Grasp servers, gitworkshop.dev, Nostr CI status and workflows, software releases and Zapstore publication, OCI container images, or nsite static sites published through Blossom.
description:
Commands and workflows for NIP-34 git collaboration over Nostr with the ngit
CLI and git-remote-nostr. Use in any repository with a nostr:// remote for
generic collaboration requests (open an Issue, create or review a Pull Request
(PR), comment, merge, clone) and whenever a task involves nostr:// URLs, ngit
commands, Grasp servers, gitworkshop.dev, Nostr CI status and workflows,
software releases and Zapstore publication, OCI container images, or nsite
static sites published through Blossom.
license: CC-BY-SA-4.0
metadata:
version: "1.17"
version: "1.18"
---
# ngit — Nostr Plugin for Git
ngit makes `git clone`, `fetch`, and `push` work with `nostr://` URLs and adds
a CLI for pull requests, issues, membership, CI results, releases, OCI
containers, and nsites. Repository state (which commit each ref points to) is
published as signed Nostr events and is the source of truth; git objects live
on ordinary git servers, so servers are interchangeable. A grasp server bundles
a relay and a git server and creates the repository automatically when an
announcement lists it. Explanation: https://ngit.dev/how-it-works
ngit makes `git clone`, `fetch`, and `push` work with `nostr://` URLs and adds a
CLI for pull requests, issues, membership, CI results, releases, OCI containers,
and nsites. Repository state (which commit each ref points to) is published as
signed Nostr events and is the source of truth; git objects live on ordinary git
servers, so servers are interchangeable. A grasp server bundles a relay and a
git server and creates the repository automatically when an announcement lists
it. Explanation: https://ngit.dev/how-it-works
## Where to look
- **This skill documents ngit v3.** Run `ngit --version` first; the commands
here need 3.0.0 or later. If ngit is missing or older, report that and
offer an install or update: `curl -fsSL https://ngit.dev/install.sh | bash`
installs or replaces `ngit` and `git-remote-nostr`, and `ngit update` works
on v3 or later. Other methods: https://ngit.dev/install
- **`ngit <command> --help`** is the authority for the installed version's
flags and defaults.
- **https://ngit.dev** holds the guides. Any page is available as raw
Markdown at `https://ngit.dev/markdown/<route>.md`; the index is
here need 3.0.0 or later. If ngit is missing or older, report that and offer
an install or update: `curl -fsSL https://ngit.dev/install.sh | bash` installs
or replaces `ngit` and `git-remote-nostr`, and `ngit update` works on v3 or
later. Other methods: https://ngit.dev/install
- **`ngit <command> --help`** is the authority for the installed version's flags
and defaults.
- **https://ngit.dev** holds the guides. Any page is available as raw Markdown
at `https://ngit.dev/markdown/<route>.md`; the index is
https://ngit.dev/llms.txt. Web UI: https://gitworkshop.dev
## Rules
@@ -35,44 +42,40 @@ announcement lists it. Explanation: https://ngit.dev/how-it-works
policy. Carry through the selected signer, target, hosting, CI, and
replication settings; do not add gates, waits, workflow edits, or
configuration changes that the task or repository did not choose.
- **PR branches MUST start with `pr/`** (e.g. `pr/my-feature`). Any other
branch name is a plain push and never creates a PR.
- **PR branches MUST start with `pr/`** (e.g. `pr/my-feature`). Any other branch
name is a plain push and never creates a PR.
- **Read ngit output with `--json`.** It is a global option and works at any
position. Stdout is exactly one JSON document; progress and diagnostics go
to stderr. `git` commands have no `--json`. Top-level `command_status` is
`ok` for exit 0 and `error` otherwise; it never describes a nested domain
result (`ngit ci status --json` reports `ok` with
`ci.conclusion: "failure"` unless a gate was requested).
position. Stdout is exactly one JSON document; progress and diagnostics go to
stderr. `git` commands have no `--json`. Top-level `command_status` is `ok`
for exit 0 and `error` otherwise; it never describes a nested domain result
(`ngit ci status --json` reports `ok` with `ci.conclusion: "failure"` unless a
gate was requested).
- **Add `--offline` after the first network read** in a session, on commands
that support it. `git fetch origin` also refreshes the cache.
- **Identifiers.** `<ID|nevent>` accepts `nevent1…`, a 64-char hex ID, or a
unique hex prefix with an optional `#` (quote it: `'#deadbeef'`). JSON `id`
and `reply_to` fields are already `nevent1…`; container publication instead
returns a raw-hex `event_id` plus the repository `naddr`. Reference events
inside `--body` text as `nostr:nevent1…` or `nostr:naddr1…`, never as raw
hex. Never construct a NIP-05 address (`user@domain`); use `npub1…` unless
a NIP-05 address was given to you.
- **Multiline text.** `ngit` options such as `--body` and `--description`
accept real newlines: `--body "$(cat note.md)"`. Git push options cannot
carry newlines: write literal `\n` in a short inline `-o description=…`, and
never convert a file into a push option (open the PR with `ngit send`
instead).
inside `--body` text as `nostr:nevent1…` or `nostr:naddr1…`, never as raw hex.
Never construct a NIP-05 address (`user@domain`); use `npub1…` unless a NIP-05
address was given to you.
- **Multiline text.** `ngit` options such as `--body` and `--description` accept
real newlines: `--body "$(cat note.md)"`. Git push options cannot carry
newlines: write literal `\n` in a short inline `-o description=…`, and never
convert a file into a push option (open the PR with `ngit send` instead).
- **Signers.** `--signer <alias|npub|profile-name>` selects a stored identity
for one `ngit` command; `git -c nostr.signer=<alias|npub|profile-name>
push …` does the same for one git command. Neither changes the configured
login. Never export or pass an nsec merely to switch between configured
accounts.
- **CI.** A successful push says nothing about CI. Nostr CI runs workflows
from `.ngit/act/workflows/`; another provider's directory is not evidence.
When CI matters, query the exact commit or PR with
`ngit ci status <target> --json` and read `ci.state` and `ci.conclusion`,
not `command_status`.
for one `ngit` command; `git -c nostr.signer=<alias|npub|profile-name> push …`
does the same for one git command. Neither changes the configured login. Never
export or pass an nsec merely to switch between configured accounts.
- **CI.** A successful push says nothing about CI. Nostr CI runs workflows from
`.ngit/act/workflows/`; another provider's directory is not evidence. When CI
matters, query the exact commit or PR with `ngit ci status <target> --json`
and read `ci.state` and `ci.conclusion`, not `command_status`.
- **Target repository.** With several `nostr://` remotes, pass global
`--repo <REMOTE|NADDR|NOSTR-URL>`; a configured remote name, an naddr, and
a nostr:// URL are all accepted. Without it ngit
infers the target from config and branch tracking and fails rather than
guesses. Before a signing command, check the
`target repository: <naddr> (source: …)` line on stderr.
`--repo <REMOTE|NADDR|NOSTR-URL>`; a configured remote name, an naddr, and a
nostr:// URL are all accepted. Without it ngit infers the target from config
and branch tracking and fails rather than guesses. Before a signing command,
check the `target repository: <naddr> (source: …)` line on stderr.
## Detecting a nostr repo
@@ -81,11 +84,11 @@ git remote -v | grep -q 'nostr://' # primary check, no cache needed
ngit repo --json --offline # full metadata when needed
```
`ngit repo` always exits 0, and `is_nostr_repo: false` can be a cold-cache
false negative: if a remote shows `nostr://`, run `git fetch origin` and
retry. The output includes the roster (`members`, `lead_source`, `lead_path`,
`pending_actions`, `health`); read `reference/repositories.md` before
changing membership or hosting.
`ngit repo` always exits 0, and `is_nostr_repo: false` can be a cold-cache false
negative: if a remote shows `nostr://`, run `git fetch origin` and retry. The
output includes the roster (`members`, `lead_source`, `lead_path`,
`pending_actions`, `health`); read `reference/repositories.md` before changing
membership or hosting.
## nostr:// URLs
@@ -100,11 +103,11 @@ Standard git commands accept these URLs directly.
## Task index
Read the bundled reference before performing that slice of work; the guide
adds tutorials and background.
Read the bundled reference before performing that slice of work; the guide adds
tutorials and background.
| Task | Bundled reference | ngit.dev guide |
| ---- | ----------------- | -------------- |
| ---------------------------------------------------------- | --------------------------- | ------------------------------------ |
| Publish, clone, host repositories; maintainers, moderators | `reference/repositories.md` | `/repositories`, `/maintainers` |
| Open, update, stack, review, merge PRs | `reference/prs.md` | `/pull-requests` |
| Issues | `reference/issues.md` | `/issues` |
+8 -8
View File
@@ -1,8 +1,8 @@
# Accounts — identity, login, secrets
Read when managing accounts, logins, or credential storage.
Guide: https://ngit.dev/accounts (storage modes, pairing a remote signer for
CI, rotation).
Read when managing accounts, logins, or credential storage. Guide:
https://ngit.dev/accounts (storage modes, pairing a remote signer for CI,
rotation).
```bash
ngit account whoami --json --offline # every usable signer with npub, aliases, scope, active state; `account list` is an alias
@@ -40,8 +40,8 @@ unaliased connection. Log in with `--alias` to keep an extra connection and
select it by alias. Older ngit versions ignore the exact-session binding and
select the identity's default connection.
**nbunksec** is a portable established connection: remote-signer pubkey,
client secret, relays, and optional pairing secret. It holds no npub, so
one-shot use resolves the identity from the signer. The `--nbunksec-file` and
`--nsec-file` forms keep secrets out of process arguments. A fresh pairing
needs interactive approval, so unattended runs use a stored connection.
**nbunksec** is a portable established connection: remote-signer pubkey, client
secret, relays, and optional pairing secret. It holds no npub, so one-shot use
resolves the identity from the signer. The `--nbunksec-file` and `--nsec-file`
forms keep secrets out of process arguments. A fresh pairing needs interactive
approval, so unattended runs use a stored connection.
+22 -22
View File
@@ -1,18 +1,18 @@
# Nostr CI
Read when checking whether CI ran, interpreting a result, or writing a
workflow that uses ngit. Guides: https://ngit.dev/ci (coordinators, results,
trust, secrets) and https://ngit.dev/ci/workflows/ (what the coordinator
accepts, refuses, and adds compared with GitHub Actions).
Read when checking whether CI ran, interpreting a result, or writing a workflow
that uses ngit. Guides: https://ngit.dev/ci (coordinators, results, trust,
secrets) and https://ngit.dev/ci/workflows/ (what the coordinator accepts,
refuses, and adds compared with GitHub Actions).
## Workflows
Nostr CI (ngit-ci) runs workflows from `.ngit/act/workflows/` with
GitHub Actions syntax in Linux containers. `.github/workflows/` is run only by
GitHub Actions on a mirror; the directories are independent, so a check that
must run in both systems needs a file in each. ngit-ci refuses macOS and
Windows `runs-on` labels and job-level `uses:` (reusable workflows); composite
actions in steps work in both systems.
Nostr CI (ngit-ci) runs workflows from `.ngit/act/workflows/` with GitHub
Actions syntax in Linux containers. `.github/workflows/` is run only by GitHub
Actions on a mirror; the directories are independent, so a check that must run
in both systems needs a file in each. ngit-ci refuses macOS and Windows
`runs-on` labels and job-level `uses:` (reusable workflows); composite actions
in steps work in both systems.
Read the workflow at the commit under investigation and confirm that its
triggers and steps cover the check in question:
@@ -43,25 +43,25 @@ ngit ci status <target> --json --offline # later cache
ngit ci status <target> --require-ci-trust maintainer-directed --json # exit non-zero unless green at this floor
```
Query the exact commit that introduced the change. A PR target reports only
its latest revision. Read:
Query the exact commit that introduced the change. A PR target reports only its
latest revision. Read:
- `ci.state`: pending, running, or concluded. `ci.conclusion` counts only
once the state is concluded.
- `ci.state`: pending, running, or concluded. `ci.conclusion` counts only once
the state is concluded.
- `ci.conclusion`: success, failure, cancellation, or another outcome.
`command_status: "ok"` means only that the query worked.
- `ci.runs[].workflow` and `ci.runs[].jobs`: which workflow and job passed or
failed.
- `ci.runs[].integrity`: the commit is present locally and the workflow hash
matches.
- `coverage` and each run's classification and evidence: how completely and
why the result is trusted. Partial coverage is not success.
- `coverage` and each run's classification and evidence: how completely and why
the result is trusted. Partial coverage is not success.
If no run appears, report that no matching Nostr CI event was found. Then
check that the workflow existed at that commit, its trigger matched, a
coordinator serves the repository, and the query refreshed the relays before
concluding that CI did not run.
If no run appears, report that no matching Nostr CI event was found. Then check
that the workflow existed at that commit, its trigger matched, a coordinator
serves the repository, and the query refreshed the relays before concluding that
CI did not run.
Trust floors are `maintainer-directed` and `operationally-associated`.
`ngit pr merge --require-ci-trust <LEVEL>` applies the same gate to a merge
when the caller wants one.
`ngit pr merge --require-ci-trust <LEVEL>` applies the same gate to a merge when
the caller wants one.
+39 -40
View File
@@ -1,16 +1,16 @@
# Containers — publish OCI images
Read before publishing an OCI image, updating a container tag, choosing
Blossom storage, or constructing a gateway pull reference. Protocol
background: https://ngit.dev/protocol/software-publishing
Read before publishing an OCI image, updating a container tag, choosing Blossom
storage, or constructing a gateway pull reference. Protocol background:
https://ngit.dev/protocol/software-publishing
## Model
`ngit container publish` (alias `ngit oci publish`) uploads the OCI blobs
reachable from the tagged entries of an OCI image layout to Blossom, then
signs a kind-30624 addressable event mapping tags to manifest digests. The
event is bound to the current kind-30617 git repository, so run it inside that
repository with a signer who is a confirmed maintainer. Gateways are read-only:
reachable from the tagged entries of an OCI image layout to Blossom, then signs
a kind-30624 addressable event mapping tags to manifest digests. The event is
bound to the current kind-30617 git repository, so run it inside that repository
with a signer who is a confirmed maintainer. Gateways are read-only:
```bash
docker pull ncontainer.io/<npub>/<repository>:<tag>
@@ -31,8 +31,8 @@ ngit container publish myimage \
--json
```
A checked-in `.ngit/containers.yaml` lets `ngit container publish myimage
--json` select an entry:
A checked-in `.ngit/containers.yaml` lets
`ngit container publish myimage --json` select an entry:
```yaml
schema: 1
@@ -47,10 +47,10 @@ containers:
Relative paths resolve from the repository root. `--manifest PATH` selects
another file; `--no-manifest` ignores the default and requires `--layout`. A
loaded manifest must define `NAME`. CLI layout and metadata override the
entry, a non-empty CLI Blossom list replaces the configured list, and CLI
relays extend configured relays. Signer selection, `--replace`, and output
mode stay on the command line.
loaded manifest must define `NAME`. CLI layout and metadata override the entry,
a non-empty CLI Blossom list replaces the configured list, and CLI relays extend
configured relays. Signer selection, `--replace`, and output mode stay on the
command line.
Behaviour to know:
@@ -59,44 +59,43 @@ Behaviour to know:
`index.json`; filenames and git tags are irrelevant. `index.json` itself is
never uploaded; ngit merges the layout's tags into the tag map fetched from
the latest kind-30624 event.
- Without `--blossom-server`, ngit uses the publisher's latest kind-10063
server list. A single server means no redundancy. Every blob is checked on
every server, missing copies are uploaded with bounded retries and
verified, and the event is signed once each blob has at least one confirmed
copy; incomplete replication is reported per server.
- `--relay` extends the repository's relays; account and default relays are
not added. ngit reads the repository relays before and after uploading and
needs at least one success each time. A total preflight failure or a
- Without `--blossom-server`, ngit uses the publisher's latest kind-10063 server
list. A single server means no redundancy. Every blob is checked on every
server, missing copies are uploaded with bounded retries and verified, and the
event is signed once each blob has at least one confirmed copy; incomplete
replication is reported per server.
- `--relay` extends the repository's relays; account and default relays are not
added. ngit reads the repository relays before and after uploading and needs
at least one success each time. A total preflight failure or a
concurrent-update refusal is safe to retry: uploaded blobs are
content-addressed. Keep a known state-bearing repository relay reachable
when changing relay sets, because a healthy empty relay cannot reveal an
event stranded elsewhere and a publish could then omit old tags.
content-addressed. Keep a known state-bearing repository relay reachable when
changing relay sets, because a healthy empty relay cannot reveal an event
stranded elsewhere and a publish could then omit old tags.
## Merge versus replace
Ordinary publication updates the tags found in the new layout and retains
older tags, previous server hints, omitted metadata, and unknown event tags.
Ordinary publication updates the tags found in the new layout and retains older
tags, previous server hints, omitted metadata, and unknown event tags.
`--replace` publishes only the new layout's tags and selected servers, drops
omitted description, source, and unknown tags, and sets the title to
`--title` or `NAME`. Use it only when the user explicitly wants complete
replacement.
omitted description, source, and unknown tags, and sets the title to `--title`
or `NAME`. Use it only when the user explicitly wants complete replacement.
## JSON
A successful result has `command: "container.publish"`, a `warnings` array,
and `result` fields: `repository`, `git_repository`, `npub`, `name`, `naddr`,
`manifest_path` (or `null`), raw-hex `event_id` (unlike collaboration
commands' `nevent` ids), `tags` and `updated_tags`, per-blob SHA-256, size,
and per-server placement, final `blossom_servers`, and per-relay `accepted`.
Success means at least one relay accepted the event; inspect every
`result.relays[].accepted` when full fanout matters. Failures use
`command_status: "error"` with `error.details` holding per-blob and
per-server outcomes and possible orphan blobs.
A successful result has `command: "container.publish"`, a `warnings` array, and
`result` fields: `repository`, `git_repository`, `npub`, `name`, `naddr`,
`manifest_path` (or `null`), raw-hex `event_id` (unlike collaboration commands'
`nevent` ids), `tags` and `updated_tags`, per-blob SHA-256, size, and per-server
placement, final `blossom_servers`, and per-relay `accepted`. Success means at
least one relay accepted the event; inspect every `result.relays[].accepted`
when full fanout matters. Failures use `command_status: "error"` with
`error.details` holding per-blob and per-server outcomes and possible orphan
blobs.
## Limits
ngit accepts OCI and Docker v2 manifests and indexes using SHA-256, uploads
only blobs reachable from tagged roots, and rejects missing, oversized, deeply
ngit accepts OCI and Docker v2 manifests and indexes using SHA-256, uploads only
blobs reachable from tagged roots, and rejects missing, oversized, deeply
nested, or mismatched graphs. It snapshots one blob at a time, so allow
temporary disk roughly equal to the largest layer. It does not build images,
push to registries, run a gateway, chunk layers, pull, list, or delete remote
+4 -4
View File
@@ -17,13 +17,13 @@ ngit issue set-subject <ID|nevent> --subject "New title" --json
ngit issue set-cover-note <ID|nevent> --body "$(cat cover-note.md)" --json
```
`resolved` records that the problem was fixed; `close` records that it will
not be. Reference other events in `--body` as `nostr:nevent1…`.
`resolved` records that the problem was fixed; `close` records that it will not
be. Reference other events in `--body` as `nostr:nevent1…`.
## Auto-resolve from commits
A commit pushed to the declared default branch resolves an issue when its
message contains a form of `close`, `fix`, `resolve`, or `implement` followed
by a unique hex ID or prefix or a `nostr:nevent1…` reference, for example
message contains a form of `close`, `fix`, `resolve`, or `implement` followed by
a unique hex ID or prefix or a `nostr:nevent1…` reference, for example
`Fixes #deadbeef`. The status is published only when the pusher is the issue
author or a confirmed repository member.
+27 -28
View File
@@ -1,14 +1,14 @@
# Nsites — publish static sites
Read before publishing an already-built website with `ngit nsite` or
diagnosing its Blossom uploads and NIP-5A manifest.
Guide: https://ngit.dev/releases/nsites (nsyte comparison, PR previews).
Read before publishing an already-built website with `ngit nsite` or diagnosing
its Blossom uploads and NIP-5A manifest. Guide: https://ngit.dev/releases/nsites
(nsyte comparison, PR previews).
## Publish
Pass the build output directory, not the source tree. ngit uploads every
regular file, runs no build, applies no ignore files, and rejects symlinks,
unsafe paths, and filenames without extensions.
Pass the build output directory, not the source tree. ngit uploads every regular
file, runs no build, applies no ignore files, and rejects symlinks, unsafe
paths, and filenames without extensions.
```bash
ngit nsite publish dist --json # reads nsyte's .nsite/config.json when present
@@ -26,33 +26,32 @@ ngit --nbunksec-file /run/secrets/publisher-nbunksec nsite publish dist --json
- Config: `.nsite/config.json` (JSON, not YAML) fields `id`, `title`,
`description`, `source`, `fallback`, `servers`, and `relays` are read;
`--config PATH` selects another file and `--no-config` ignores it. Explicit
CLI values win, and any repeated `--blossom-server` or `--relay` replaces
that whole config array. Unsupported nsyte publication options
(`publishProfile`, `publishRelayList`, `publishServerList`,
`publishAppHandler`) produce a warning; nsyte signer fields are ignored.
- Metadata: `--title`, `--description` or `--description-file`, and
`--source` (`https://` or `nostr://`; omitted, ngit infers the selected
public repository and never a private one). NIP-5A has no logo tag; ship a
`favicon.ico` or `favicon.svg` in the build output.
CLI values win, and any repeated `--blossom-server` or `--relay` replaces that
whole config array. Unsupported nsyte publication options (`publishProfile`,
`publishRelayList`, `publishServerList`, `publishAppHandler`) produce a
warning; nsyte signer fields are ignored.
- Metadata: `--title`, `--description` or `--description-file`, and `--source`
(`https://` or `nostr://`; omitted, ngit infers the selected public repository
and never a private one). NIP-5A has no logo tag; ship a `favicon.ico` or
`favicon.svg` in the build output.
- `--fallback SITE_PATH` (or config `fallback`) maps an existing HTML file in
the output to `/404.html` without another upload.
- Servers: omit `--blossom-server` to use the account's latest kind-10063
list; repeat it for replication. `--concurrency` (default 4, range 1–64) is
a global limit across presence checks and uploads.
- Servers: omit `--blossom-server` to use the account's latest kind-10063 list;
repeat it for replication. `--concurrency` (default 4, range 1–64) is a global
limit across presence checks and uploads.
## Guarantees
ngit snapshots the directory before network work, deduplicates content, checks
every blob on every selected server, and uploads missing copies with BUD-11
authorization. It signs the manifest only after every blob has at least one
confirmed copy, so a failed deployment cannot point the live manifest at
missing content. A server that fails three consecutive initial checks is
skipped for the rest of that pass while the others continue.
confirmed copy, so a failed deployment cannot point the live manifest at missing
content. A server that fails three consecutive initial checks is skipped for the
rest of that pass while the others continue.
Rerun the same command after a failure: blobs already on a server are
confirmed with `HEAD` and skipped, so continuation is per blob and server. An
unchanged deployment reuses the current manifest without a new signature or
relay write.
Rerun the same command after a failure: blobs already on a server are confirmed
with `HEAD` and skipped, so continuation is per blob and server. An unchanged
deployment reuses the current manifest without a new signature or relay write.
## JSON
@@ -61,10 +60,10 @@ Check `command_status`, then:
- `result.changed`: publication versus an unchanged no-op;
- `result.config_path`, `result.fallback`, `result.relays`: resolved settings;
- `result.blossom.blobs[].servers[]`: each blob and server outcome;
- `result.publication.relays[]`: manifest acknowledgements (at least one
relay must accept);
- `warnings[]`: unknown MIME types, unsupported config publications, and
failed uploads or post-upload verification per server.
- `result.publication.relays[]`: manifest acknowledgements (at least one relay
must accept);
- `warnings[]`: unknown MIME types, unsupported config publications, and failed
uploads or post-upload verification per server.
On a Blossom failure inspect `error.details.blobs` and
`error.details.possible_orphan_blobs`, fix the server or signer problem, and
+20 -21
View File
@@ -1,12 +1,12 @@
# Pull requests — open, update, stack, review, merge
Read before opening, updating, reviewing, or merging PRs.
Guide: https://ngit.dev/pull-requests
Read before opening, updating, reviewing, or merging PRs. Guide:
https://ngit.dev/pull-requests
## Open or update a PR
The branch name MUST start with `pr/`. No push option turns another branch
into a PR.
The branch name MUST start with `pr/`. No push option turns another branch into
a PR.
```bash
git checkout -b pr/my-feature
@@ -21,18 +21,18 @@ git push --force origin pr/my-feature # update the PR after amend
- `-d`/`--defaults` accepts the single-commit title and description without a
prompt.
- Do not use `$'…\n…'` for push options, and do not pre-escape a Markdown
file into `-o description=`; open the PR with `ngit send` instead.
- Do not use `$'…\n…'` for push options, and do not pre-escape a Markdown file
into `-o description=`; open the PR with `ngit send` instead.
- Stacks are inferred: a branch that contains the unique latest tip of one of
your other open or draft PRs becomes that PR's child and follows the parent
as it advances. Rebase the child onto the parent's latest tip before updating
it; ngit refuses stale children and ambiguous candidates rather than
guessing. Use `base=` for a cross-author, historical, or ambiguous parent,
and repeat it on each update if the child should stay pinned.
your other open or draft PRs becomes that PR's child and follows the parent as
it advances. Rebase the child onto the parent's latest tip before updating it;
ngit refuses stale children and ambiguous candidates rather than guessing. Use
`base=` for a cross-author, historical, or ambiguous parent, and repeat it on
each update if the child should stay pinned.
- To push as another stored identity, use
`git -c nostr.signer=<alias|npub|profile-name> push …`; `--signer` applies
to `ngit` commands only. `ngit account login --local <alias>` makes an
identity the repository default instead.
`git -c nostr.signer=<alias|npub|profile-name> push …`; `--signer` applies to
`ngit` commands only. `ngit account login --local <alias>` makes an identity
the repository default instead.
## ngit send
@@ -70,13 +70,12 @@ ngit pr merge <ID|nevent> --exclude-description --json # summary line and
git push origin <target-branch> # publishes the merge and the applied status
```
`ngit merge` is a compatibility alias with the same options. The merge lands
on the PR's declared target, or the default branch, resolved against the
latest Nostr repository state rather than a local tracking ref, with the
message `Merge #<8-hex>: <PR title>`. Closed and applied PRs are refused
before any git change. On conflicts, resolve them and run `git commit`; the
message is already prepared, and JSON reports `action: "conflicted"` instead
of `"merged"`.
`ngit merge` is a compatibility alias with the same options. The merge lands on
the PR's declared target, or the default branch, resolved against the latest
Nostr repository state rather than a local tracking ref, with the message
`Merge #<8-hex>: <PR title>`. Closed and applied PRs are refused before any git
change. On conflicts, resolve them and run `git commit`; the message is already
prepared, and JSON reports `action: "conflicted"` instead of `"merged"`.
Before merging or adding maintainer fixes, run
`git log --merges --oneline origin/<target>..HEAD`. A prior `Merge #…` means a
+20 -20
View File
@@ -1,9 +1,9 @@
# Repositories — publish, clone, hosting, membership
Read when publishing or cloning a repository, resolving `nostr://` URL forms,
or changing an announcement's hosting, metadata, or roster. Guides:
https://ngit.dev/repositories (hosting choices, migrating from a forge,
mirrors, private repositories), https://ngit.dev/maintainers, and
Read when publishing or cloning a repository, resolving `nostr://` URL forms, or
changing an announcement's hosting, metadata, or roster. Guides:
https://ngit.dev/repositories (hosting choices, migrating from a forge, mirrors,
private repositories), https://ngit.dev/maintainers, and
https://ngit.dev/maintainers/going-deeper (leadless repositories, delegated
trust, removal, roster repair).
@@ -36,9 +36,9 @@ ngit repo --json --offline # run git fetch origin first when the cache may
The output reports `nostr_url`, effective `git_servers`, `relays`, `hashtags`,
and `grasp_servers` detected from paired clone and relay entries, plus the
roster: `members`, `lead_source`, `lead_path`, `pending_actions`, and
`health`. Follow the actionable error or `pending_actions` rather than
replacing an announcement wholesale.
roster: `members`, `lead_source`, `lead_path`, `pending_actions`, and `health`.
Follow the actionable error or `pending_actions` rather than replacing an
announcement wholesale.
## Publish and host
@@ -66,8 +66,8 @@ Every announcement needs at least one relay and one git server; `init` and
announcement that already lacks one half. Repair it in the same command, e.g.
`ngit repo edit --name "New name" --add-grasp-server grasp.example.com`.
`--identifier` is set at initial publication only: changing the `d` tag
creates a different repository coordinate.
`--identifier` is set at initial publication only: changing the `d` tag creates
a different repository coordinate.
## Edit
@@ -75,21 +75,21 @@ creates a different repository coordinate.
repeatable actions that can be combined in one command:
| 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` |
Scalars use replacement flags: `--name`, `--description`, `--web`, `--u`,
`--earliest-unique-commit`. A grasp-derived relay or clone cannot be removed
as an additional entry; remove the grasp server and its pair goes with it. To
empty a collection, remove every value currently reported.
`--earliest-unique-commit`. A grasp-derived relay or clone cannot be removed as
an additional entry; remove the grasp server and its pair goes with it. To empty
a collection, remove every value currently reported.
Each successful edit publishes a fresh announcement and, when the repository
has Nostr state, republishes that state once so new relays and servers hold
the authoritative refs. If that fails, follow the reported `ngit sync`
recovery guidance.
Each successful edit publishes a fresh announcement and, when the repository has
Nostr state, republishes that state once so new relays and servers hold the
authoritative refs. If that fails, follow the reported `ngit sync` recovery
guidance.
## Roles and membership
@@ -101,9 +101,9 @@ recovery guidance.
- **Moderator**: publishes issue, PR, and patch status events (including
recording an existing merge) but cannot publish git state or merge.
Membership is reciprocal: a listing is an invitation until the invitee
publishes an announcement acknowledging the role, and an invited member's
events are not authoritative until then.
Membership is reciprocal: a listing is an invitation until the invitee publishes
an announcement acknowledging the role, and an invited member's events are not
authoritative until then.
```bash
ngit repo edit --add-maintainer <npub> --json # a sole maintainer's first add makes them lead
+7 -7
View File
@@ -1,7 +1,7 @@
# Sync, flags, and configuration
Read when syncing refs, choosing flags, or tuning git config.
Guides: https://ngit.dev/configuration and https://ngit.dev/troubleshooting
Read when syncing refs, choosing flags, or tuning git config. Guides:
https://ngit.dev/configuration and https://ngit.dev/troubleshooting
## Sync
@@ -16,7 +16,7 @@ These accept any command position. `--offline` is per command; check
`ngit <command> --help`.
| Flag | Description |
| ---- | ----------- |
| --------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `--json` | One JSON document on stdout (ngit commands only) |
| `-d`, `--defaults` | Non-interactive; accept defaults |
| `-q`, `--quiet` | Hide non-essential stderr progress (not combinable with `-v`) |
@@ -39,11 +39,11 @@ git config nostr.http-io-timeout-ms 600000 # allow large grasp pushes
NGIT_CACHE_DIR=/writable/path ngit repo --json # override the global event-cache directory
```
`nostr.auto-pr-branches` follows normal git config precedence. With the
default `false`, PRs appear as branches only after `ngit pr checkout`; run
`nostr.auto-pr-branches` follows normal git config precedence. With the default
`false`, PRs appear as branches only after `ngit pr checkout`; run
`git fetch --prune` once to drop branches fetched by an older version, or use
`git clone --config nostr.auto-pr-branches=true <nostr-url>` to opt in from
the start.
`git clone --config nostr.auto-pr-branches=true <nostr-url>` to opt in from the
start.
If the global cache directory is unavailable ngit falls back to an in-memory
cache; the repository's git common directory must still be writable.