Prompt: publish a list of git repos as anonymous public repos over IPFS
Have an agent publish git repos as anonymous, publicly clonable repos at
https://<host>/<name>.git — static files on IPFS, no git server —
with the anonymity gates, pin lifecycle and end-to-end verification that
the ird.cod-sursa.ro ecosystem itself uses.
Needs: ird access (MCP server or the ird CLI, logged in); a shell with git, jq, rsync, python3; a hostname on a zone hosted on ird DNS
Costs: hourly per MB pinned plus per MB served (credits_prices → recurring.ipfs-pin-hourly)
Group: hosting
Paste everything below the line into a fresh conversation. Fill in the
FILL IN block first.
Task
Publish the repos listed below as anonymous, publicly clonable git repos at
https://<HOST>/<name>.git, using the "static git over IPFS" pattern: no
git server — each repo becomes a bare mirror of plain static files, all
mirrors are assembled into one root folder, the folder is pinned on IPFS,
and the host's IPNS name is re-pointed at the new CID. Cloning works over
git's dumb-HTTP protocol (plain GETs of static files).
FILL IN
HOST: src.example.ro # gateway domain for the ecosystem (a subdomain on an ird-DNS zone)
IDENT: nightowl # anonymous git identity (name; email is <IDENT>@noreply.local)
ASSEMBLER: ~/src-site # assembler dir (create if missing)
REPOS: # one line per repo: <name> <local path> <one-line description>
parser ~/code/parser tolerant JSON/EDN parsing library
webring ~/code/webring tiny static webring generator
…
Non-negotiable rules
- Anonymity. Every published commit must be authored and committed by
exactly
IDENT <IDENT@noreply.local>. Set git config user.name/user.email
per repo BEFORE the first commit. Never commit with a personal identity.
- No identity bytes in public content. Real names, usernames, personal
emails, or absolute home paths must not appear in any published file,
script, commit message, or git object. Identity regexes for the leak scan
live in an untracked local file
~/.config/cod-sursa/idpat (one
extended-regex per line, # comments). If that file is missing, ask the
human to create it — do NOT write their identity strings into any file
inside a repo, including the scan scripts themselves.
- Gate before publish. Run the anonymity gate on every mirror, every
time. If any check fails, stop and report — never publish over a failure.
- Cost awareness. Pinning bills hourly per MB. Always unpin the
previous root after a successful publish. Don't pin gigabytes without
asking.
Toolkit
Ready-made scripts (mirror builder + gate, assembler, standalone auditor,
this workflow's full tutorial in README.md):
git clone https://ird.cod-sursa.ro/publish.git
Use its templates/publish-repo.sh and templates/assemble.sh instead of
rewriting them. If the clone is unreachable, reconstruct from the algorithm
below.
Algorithm
A. One-time host setup (skip if HOST already serves content):
- CLI:
ird ipfs ipns create <HOST> --serve — creates the IPNS name,
attaches the gateway domain, writes DNS (A + _dnslink TXT), issues the
TLS cert (~1 min). MCP: ipns_create(hostname=<HOST>, serve=true).
- Requires the domain's DNS zone to be hosted on ird (
dns_list_zones).
B. Per repo (for each <name> <path> in REPOS):
- Identity:
git config user.name IDENT && git config user.email IDENT@noreply.local
(in the repo). If history already has other identities, stop and ask —
history rewrite is a human decision.
.gitignore must contain deploy/.site/.
- Install
deploy/publish-repo.sh from the toolkit template; set
APP=<name>, IDENT=<IDENT>; chmod +x.
- Write
site/index.html — a small landing page: what the repo is, the
clone command git clone https://<HOST>/<name>.git, a link back to
https://<HOST>/. For libraries, show how to depend on the git URL
(e.g. Clojure :git/url + :git/sha).
- Commit (as IDENT).
What the mirror builder does (already encoded in the template): bare-clone
with --no-local into deploy/.site/<name>.git, explode packs into loose
objects (git unpack-objects), git update-server-info, delete hooks/
and config, then gate: (a) all authors+committers == IDENT, (b) no
deploy/.site committed, (c) zlib-decompress every object and grep against
the idpat file — abort on any hit.
C. Assembler (once; then register each repo):
- Directory ASSEMBLER with
assemble.sh (toolkit template: set
HOST, ROOT, fill repo_for() + default APPS) and a root
index.html with one card per repo (name, description, clone command,
link to /<name>/). Keep the assembler dir itself a git repo with the
same anonymous identity.
The assembler also generates a static in-browser source browser per repo
(/<name>/browse/, highlighted code + rendered markdown) via the toolkit's
gen-browse.py; its stylesheet is served from the ecosystem CDN host
(cdn.cod-sursa.ro). This happens automatically — no extra steps.
D. Publish:
NO_PUBLISH=1 ./assemble.sh — builds every mirror (gates run), assembles
the root; inspect it.
./assemble.sh — pins the root, renames the pin to site:<HOST>
(re-pin same CID under that name, drop the folder-named entry), runs
ird ipfs ipns publish <HOST> <CID>, unpins the previous root.
E. Verify:
- Immediately, by CID (bypasses DNS/IPNS caches):
curl -s https://ipfs.ird.ro/ipfs/<CID>/<name>.git/info/refs — must list
the repo's refs.
- The domain flips when its DNSLink cache expires (zone TTL, typically
≤1h). Then:
git clone https://<HOST>/<name>.git into a temp dir and
check git log — do this for at least one repo before declaring success.
- Report per repo: clone URL, landing URL, HEAD sha, mirror size, and the
new root CID.
Deliverable
All repos in REPOS clonable at https://<HOST>/<name>.git, each with a
landing page at https://<HOST>/<name>/, root index listing all of them,
exactly one pin named site:<HOST>, previous root unpinned, and a
verification report as in step E.