Narwal now answers pushes to a reserved target:
git push https://gitwal.io/new HEAD
It picks a name, claims it with the token you pushed with, lands your commits there, and prints the URL back at you:
remote: narwal: created amber-otter-drift
remote:
remote: https://gitwal.io/amber-otter-drift
remote:
remote: that name is yours: the token you pushed with is its push acl.
remote: git remote set-url origin https://gitwal.io/amber-otter-drift.git
That is the whole feature. No account, no form, no name chosen in advance.
Why this was worth doing
Pushing here already needed no account. It did need a name — free, lowercase, six characters or more — and you had to pick one before finding out whether it was taken. That is a small thing that sits in exactly the wrong place: the first thirty seconds, before anyone has decided the host is worth using.
The host was already most of the way there. A repository has existed since the first version because someone pushed to a name that was free; the first valid receive-pack POST wins a create-only compare-and-swap on repo.json, and the token that won it becomes the push ACL. Nothing about that needed changing. /new moves one decision — who chooses the name — from the client to the server. Claim, ACL, and log publication are the same code they were.
The parts worth explaining
The name is three words. amber-otter-drift, not eight bytes of hex, because the point of a generated name is that a person can read it back over a call. There are about sixty-nine thousand combinations across three curated slots, which is plenty for collision-by-retry.
A test walks every combination and asserts each one parses as a valid repository name and is not reserved. That sounds excessive for a wordlist until you consider the failure it prevents: one bad word, and a rare push fails with an error the pusher can do nothing about.
Discovery reserves nothing. GET /new/info/refs advertises an empty ref list and writes not one byte. Picking a name there would be convenient and wrong: it would reserve a name before the pack, the framing, and the credential had been validated, and "claim only after validation" is the rule that keeps a malformed or unauthorized push from consuming anything. The draw happens on the POST, with the pack in hand.
The availability check is a hint, not a reservation. The server draws a name, checks that no repo.json exists for it, and proceeds. Two simultaneous magic pushes can draw the same words; the create-only CAS still decides, the same arbiter as always. The pre-check only keeps the common case off the contended path — it is an optimization, not a lock.
The URL comes back on the sideband. Band 2 already carries the remote: guidance lines that explain refusals. A success message on the same channel needs no new endpoint and no client change: stock git prints it.
Visibility is unchanged. An auto-named repository follows NARWAL_DEFAULT_VISIBILITY like any other claim, which on gitwal.io means private. A repository nobody deliberately named is not a reason to publish it by default; POST /{name}/settings makes it public when you decide to.
What we did not build
An endpoint that hands out a name as JSON before the push. To be useful it would have to reserve the name, which is the pre-allocation described above, and it turns a one-command story into two calls. If a script wants the name, it can read the URL off the sideband or ask the repository page afterwards.
Also: this host now hosts itself
gitwal.io serves its own source at gitwally — pushed with the same git push, claimed the same way, served by the code inside it. There is a pleasant test in that: if the fetch path breaks, the source explaining the fetch path stops being reachable.