lnbits-extensions/CLAUDE.md
2026-09-14 15:34:56 +02:00

105 lines
4.3 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this repo is
A single-file catalog: `extensions.json` is the manifest LNbits hosts read
via `LNBITS_EXTENSIONS_MANIFESTS`. No server code, no build, no tests, no
tags. Every commit on `main` is live for every host that pulls the raw URL
(`…/aiolabs/lnbits-extensions/raw/branch/main/extensions.json`), including
bohm's native lnbits and the regtest compose stack. Hosts pick up changes
on lnbits restart, then upgrade via the admin UI. Audit trail is `git log`;
rollback is `git revert`.
This is an **infra repo: commit straight to `main`**, no PR. The release
procedure that leads up to a catalog commit (merge PRs in the extension
repo, `chore(release)` bump, test on dev lnbits, tag, hash) lives in
`~/dev/CLAUDE.md` under "Extension release procedure". This file only
covers the catalog side.
## Manifest shape
```
{ "featured": [<id>, …], "extensions": [<entry>, …] }
```
Required entry fields: `id`, `repo`, `name`, `version`, `short_description`,
`archive`, `hash` (sha256 of the archive zip). Optional: `icon`,
`min_lnbits_version`, `max_lnbits_version`, `details_link`. Many entries
omit `min_lnbits_version` entirely; copy the previous entry for the same
`id` and change only `version`, `archive`, `hash`.
Entries are grouped by `id` in the file. Insert a new version directly after
the last existing entry for that `id`, not at the end of the array.
## Rules that bite
- **Add, never overwrite.** A new version is a new object alongside the old
ones; installs on the previous version must still resolve it. The one
historical exception (`lnurlp: replace v1.3.0-aio.1 with v1.3.0-aio.2`)
was a same-day fix of a broken tag.
- **Keep 4-space indent and `ensure_ascii=False`.** A 2-space re-serialise
once turned a one-entry bump into a whole-file diff and needed a follow-up
`chore: restore 4-space JSON formatting` commit. Hand-edit the block, or
round-trip with the snippet below (verified byte-identical).
- **Aio forks point at `git.atitlan.io/aiolabs/<ext>`, never GitHub.** The
three `github.com/lnbits/lnurlp` entries (1.1.3, 1.2.0, 1.3.0) predate the
fork and stay only for installs that still run them. Don't add new
upstream entries for any extension that has an aio fork; production only
sees this manifest, so an upstream URL here bypasses our vetting.
- **Aio semver must outrank the upstream tag** (`v1.3.0-aio.2` > `v1.3.0`).
Dev instances also see LNbits's built-in catalog; if upstream wins the
semver comparison, clicking Upgrade overwrites the git checkout under
`~/dev/shared/extensions/`.
- **`hash` is the integrity gate.** LNbits refuses to install when the
downloaded archive's sha256 differs. Always recompute from the tag's
archive URL; never copy a hash from a previous entry.
## Commands
Compute the hash for a tagged release (Forgejo archive URL form):
```sh
curl -sL https://git.atitlan.io/aiolabs/<ext>/archive/v<version>.zip | sha256sum
```
Validate the manifest before committing (parse, required fields, duplicate
`id`+`version`, and that the `archive` URL's tag matches `version`):
```sh
python3 - <<'EOF'
import json, sys
d = json.load(open("extensions.json"))
req = {"id","repo","name","version","short_description","archive","hash"}
seen = set(); bad = 0
for e in d["extensions"]:
key = (e.get("id"), e.get("version"))
for m in (req - e.keys(), ["dup"] if key in seen else [], ["archive!=version"] if f"v{e.get('version')}.zip" not in e.get("archive","") else []):
if m: print(key, m); bad += 1
seen.add(key)
sys.exit(bad)
EOF
```
Re-serialise without formatting drift (only if editing programmatically):
```sh
python3 -c "
import json
d = json.load(open('extensions.json'))
open('extensions.json','w').write(json.dumps(d, indent=4, ensure_ascii=False) + '\n')"
```
Verify a committed entry matches the live archive:
```sh
git diff -U0 HEAD~1 | grep -oE '"(archive|hash)": "[^"]+"'
```
## Commit message convention
One entry per commit, subject `<ext>: add v<version> (<one-line what changed>)`,
e.g. `events: add v1.6.1-aio.15 (promo codes enforced)`. The parenthetical
is the only human-readable changelog the catalog has, so name the user-visible
change, not "bump". Formatting-only fixes use `chore:`.