First commit over REST
Weft Repos gives every user, session, or agent its own real git repository — created in under 100 ms, written and read entirely over HTTP.
0. Before you start
Three things, once, and each takes about a minute:
- Create an account. Free, no card; your personal namespace holds public repositories.
- Create an organization from the dashboard if the repositories will be private or shared with a team. Creating one saves a card and charges nothing, and stays free while everything in it is public; see organizations and billing.
- Mint a token for
your scripts. It is the
$WEFT_TOKENin every example below.
1. Create a repo
curl -X POST https://api.weft.sh/v1/orgs/acme/repos \
-H "Authorization: Bearer $WEFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "session-8412" }'
Response: 201 with the repo and its clone_url. Need a fleet? Batch up to
1,000 per call at /v1/orgs/acme/repos/batch/create.
2. Commit
curl -X POST https://api.weft.sh/v1/orgs/acme/repos/session-8412/commits \
-H "Authorization: Bearer $WEFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"branch": "main",
"message": "agent step 1",
"context": { "agent_run": "r-42", "prompt": "p-991" },
"operations": [
{ "op": "put", "path": "src/app.js", "content": "console.log(1)\n" },
{ "op": "put", "path": "README.md", "content": "# session\n" }
]
}'
The response carries the new commit id. The context blob lands in the
immutable audit trail alongside the acting token —
that’s how you answer “what did the agent change and when” months later.
Concurrency: pass expected_parent with the commit you built against.
If the branch moved, you get 409 with the current tip — rebase and retry.
Commits are durable at acknowledgment.
3. Read anything at any version
# newest version (ETag = content hash; If-None-Match gives you 304s)
curl -H "Authorization: Bearer $WEFT_TOKEN" \
https://api.weft.sh/v1/orgs/acme/repos/session-8412/files/src/app.js
# the same file two commits ago
curl -H "Authorization: Bearer $WEFT_TOKEN" \
"https://api.weft.sh/v1/orgs/acme/repos/session-8412/files/src/app.js?at=$OLD_COMMIT"
Also available: /tree listings (each entry carries a size, null for
directories), /diff?from=…&to=…, paginated /log, /refs for
everything at once, and /branches and /tags when you want one kind,
sorted, with the default marked.
One file’s history
/log takes a path, and then returns only the commits that changed it:
curl -H "Authorization: Bearer $WEFT_TOKEN" \
"https://api.weft.sh/v1/orgs/acme/repos/session-8412/log?path=src/app.js"
{ "entries": [
{ "commit": "9f2c…", "message": "fix the parser", "change": "modified",
"author": "Ada <ada@acme.dev> 1766000000 +0000", "parents": ["7b1a…"] } ],
"next_after": null }
change is added, modified or deleted — what that commit did to
that path. It appears only on a filtered request, because an unfiltered
walk says nothing about any particular file.
Do this rather than asking for the whole log and dropping rows yourself.
Both give the same answer on a small repository; on a real one, a file
touched once near the start means downloading an entire history to find
a single commit. A filtered request examines at most 500 commits and
then hands back next_after, so a long search is several bounded
requests instead of one unbounded scan.
A /files response says what it is rather than leaving you to guess:
X-Weft-Binary is true or false, X-Weft-Commit is where the
content came from, and ETag is the blob oid — send it back as
If-None-Match and an unchanged file costs a 304 and no bytes.
Content-Type is sniffed, and deliberately narrow. Anything textual is
text/plain; charset=utf-8 whatever it is called: this endpoint returns
whatever somebody committed, and answering text/html for a file named
index.html would let a repository serve script from this origin.
Images and PDFs get their real type, because a browser can display those
and cannot be tricked by them; everything else is
application/octet-stream.
All of this is in the dashboard too. Open a repository and press Browse files — directory listings, a file view with line numbers, the commit log and a branch switcher, all on real URLs, so a link to a line of code is a link you can send somebody. A file page carries its own history: who last touched it, what each commit did to it, and a click to read any earlier version — which puts that revision in the URL, so an old version is as sendable as the current one.
4. Undo
# put the branch back where it was before the agent went sideways
curl -X POST https://api.weft.sh/v1/orgs/acme/repos/session-8412/reset \
-H "Authorization: Bearer $WEFT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "branch": "main", "to": "'$GOOD_COMMIT'", "expected_head": "'$BAD_COMMIT'" }'
The undone commits stay reachable by SHA until garbage collection — undo never erases the record. See audit & undo.
5. It’s still git
git clone https://x:$WEFT_TOKEN@api.weft.sh/acme/session-8412.git
Clone it, push to it, or export it as a standard bundle any time. Adopting Weft is not a lock-in decision.