Build
History and rewind
Read any folder or file as it was at a moment, even after a rename or delete, and put a whole folder back with one call that can itself be undone.
Every save is a version and every change is written to the journal, so a space remembers how it looked at any moment. You can read a folder as it was before an agent ran, get back a file that has since been renamed or deleted, and put a whole folder back.
Moments
Anywhere that takes as_of, a moment can be:
| Form | Example | Means |
|---|---|---|
| A time | 2026-11-15T09:30:00Z | The last change at or before that time |
| A duration ago | -2h, -90m | The same, counted back from now |
| A journal seq | 1042 | Exactly after that change |
Answers carry Sidespace-As-Of-Seq, the journal seq the moment resolved to. Ask again with that seq and you get exactly the same result, even if more changes happened at the same second.
Read the past
sidespace ls "Film A" /Ep01 --as-of -2h # what the folder held two hours ago
sidespace get "Film A" /Ep01/script.md ./old.md --as-of -2hcurl -H "Authorization: Bearer $SIDESPACE_TOKEN" \
"$SIDESPACE_URL/v1/spaces/$SPACE/paths/Ep01/script.md?as_of=-2h"
curl -H "Authorization: Bearer $SIDESPACE_TOKEN" \
"$SIDESPACE_URL/v1/spaces/$SPACE/nodes/$FOLDER/children?as_of=2026-11-15T09:30:00Z"const then = await side.list("Film A", "/Ep01", { asOf: "-2h" });
const old = await side.download("Film A", "/Ep01/script.md", { asOf: "-2h" });then = side.list("Film A", "/Ep01", as_of="-2h")
with side.open("Film A", "/Ep01/script.md", as_of="-2h") as r:
old = r.read()?as_of=(or theSidespace-As-Ofheader) works onGET …/paths/{path},GET …/nodes/{nid}andGET …/nodes/{nid}/children. A path is looked up as it was then, so an old name still finds the file.- A node shows the version that was current then; download it as usual with that
head_version_id. - A file deleted for good has no past. Everything else, including files in the trash, can be read.
Rewind a folder
Rewind puts a folder back the way it was at a moment. Always look first with a dry run:
sidespace rewind "Film A" /Ep01 --to -2h --dry-run # what would change
sidespace rewind "Film A" /Ep01 --to -2hcurl -X POST -H "Authorization: Bearer $SIDESPACE_TOKEN" -H "Content-Type: application/json" \
"$SIDESPACE_URL/v1/spaces/$SPACE/nodes/$FOLDER/rewind" -d '{"as_of": "-2h", "dry_run": true}'const plan = await side.rewind("Film A", "/Ep01", "-2h", { dryRun: true });
for (const c of plan.changes) console.log(c.action, c.path, c.from_path ?? "");plan = side.rewind("Film A", "/Ep01", "-2h", dry_run=True)The answer lists each change:
action | What happens |
|---|---|
restore | The file's old content is saved as a new version. Files with the same bytes are left alone. |
undelete | A file or folder that was deleted comes back from the trash |
move | Something moved or renamed since goes back where it was. If the old name is taken, it gets a unique one and note says so. |
trash | Something that wasn't there then goes to the trash |
missing | A file that was there but has been deleted for good; it can't come back |
- A rewind runs in one transaction, and every step is an ordinary journaled change. So nothing is lost, and a rewind can itself be rewound.
- A dry run does the same work and rolls back, so it reports exactly what a real run would do.
- It needs the editor role on the folder and on everything it changes, and the
files:writescope. - Sidecars travel with their versions. Comments are not part of the folder and are not rewound.
Over MCP and S3
- The MCP tools
list_folderandread_texttakeas_of, andrewind_folderrewinds. Its description tells the agent to dry run first and show you. See Use it in Claude. - Over the S3 gateway, every bucket is versioned, and the
x-sidespace-as-ofheader (or query parameter, for presigned URLs) lists and reads a bucket as it was.