{
  "name": "version-history",
  "title": "Version History & Rollback",
  "description": "File version history and rollback: view versions, restore individual files, roll back to any point in time",
  "guid": "sk_plat_ckpt",
  "category": "Agent Tools",
  "requiredTools": [],
  "content": "# Version History & Rollback\n\nEvery file write is automatically tracked with an immutable version history. You can view, restore, and roll back files at any time - no manual snapshots needed.\n\n## Commands\n\n### gipity file versions\nList the version history of any file. Shows version numbers, timestamps, sizes, and sources.\n\n```\ngipity file versions src/index.html\n```\n\n### gipity file restore\nSwitch a file to any version - older or newer. No data is lost; all versions are preserved.\n\n```\ngipity file restore src/index.html 2\n```\n\n### gipity file rollback\nRestore files and folders under a path to their state at a given point in time. Supports scoping to a specific directory and recursive/non-recursive modes.\n\n```\ngipity file rollback 2026-04-08T14:30:00Z                                   # entire project\ngipity file rollback 2026-04-08T14:30:00Z --path src/components             # one folder, recursive\ngipity file rollback 2026-04-08T14:30:00Z --path src --no-recursive         # direct children only\ngipity file rollback latest                                                  # undo previous rollback\n```\n\nAfter a restore or rollback, `gipity sync` pulls the result into your local tree, and `gipity deploy dev` ships it.\n\n## How It Works\n- Every file write creates an immutable version with a timestamp\n- `gipity file restore` switches which version is active - all versions are preserved\n- `gipity file rollback` derives the project state at any point in time from the version history\n- Rollback handles both files (version-based) and folders (timestamp-based)\n- Files created after the target time are removed; files that existed are restored\n- All operations are wrapped in a transaction - atomic and safe\n\n## When to Use\n- User says \"undo that\" → `gipity file versions` + `gipity file restore` for one file\n- User says \"go back to before I changed everything\" → `gipity file rollback` with a datetime\n- Something broke after a series of changes → `gipity file rollback` to before the changes\n- Compare what changed → `gipity file versions` shows the full timeline per file\n\n## Retention policy (how long history is kept - and billed)\n\nVersion history is not kept forever. Each account has a **retention policy** with two bounds, and a version is pruned when it hits **either** one first:\n- **Age** - versions older than *N days* are dropped.\n- **Copies** - only the newest *M versions* of each file are kept.\n\nThe **current version of every file is always kept**, no matter how old - retention only trims old *history*, never live content, so a file you haven't touched in months is never lost.\n\nRetention is enforced once a day by a cleanup pass that runs **right before** the storage meter, so the account is billed on its post-cleanup footprint. Storage is billed on physical bytes (retained versions included), so **keeping less history costs less**.\n\n### Defaults and limits (per plan)\n- **Free:** 3 days / 10 copies.\n- **Pro:** 90 days / 100 copies.\n\nThe plan sets the **maximum** a user may keep (and the default when they subscribe). A user can dial their own retention **down** from that cap to store less and pay less - never above the plan cap.\n\n### Telling the user their current policy\n`gipity storage retention` reports the effective retention (days and copies kept, whichever comes first, and the plan maximum). That's how to answer \"what's my version retention?\" or \"how long are my old versions kept?\".\n\n### Seeing what's using the space\nWhen an account is at or over its storage quota, find out where the space went before suggesting anything:\n- **CLI:** `gipity storage usage` - billed bytes against the quota, the live-vs-version-history split, how much deduplication saved, and the biggest projects. Add `--json` for a machine-readable form.\n- **API:** `GET /users/me/storage`.\n\nTwo figures matter and they are not the same. **Billed** is *physical* bytes: retained versions included, deduplicated blobs counted once - that's what the quota is enforced against. **Live** is just the current version of each file. A big gap between them means version history (or a large retention setting), not live content, is what's filling the account - so trimming retention is the fix, not deleting files.\n\nPer-project numbers are live bytes only: dedup and history can't be attributed to a single project, so they won't sum to the billed total.\n\n### When the account is over quota\nAn over-quota write fails with a storage-quota error. Freeing space always works: delete files that are no longer needed, or keep less history (below). Upgrading only helps if the user's plan isn't already the one with the largest storage grant - **credit packs do not raise the storage cap**, so telling a top-plan user to buy credits is a dead end. The error text itself only suggests an upgrade when a bigger plan actually exists; follow its lead rather than reflexively recommending a purchase.\n\n### Changing it\nRetention is a user-owned account setting - don't change it silently on their behalf. Explain the trade-off (less history = smaller storage bill, but shorter rollback reach) and point them at a surface that edits it:\n- **CLI:** `gipity storage retention` (view), `gipity storage retention --days <n> --count <n>` (set), `gipity storage retention --reset` (back to the plan default).\n- **Monitor dashboard:** Data > Files shows the policy with editable day/copy fields; Data > Browse shows a file's versions and restores one.\n- **API:** `GET /users/me/retention` (view) and `PATCH /users/me/retention` `{ days, count }` (adjust; a value above the plan cap is rejected, `null` resets a field to the plan default)."
}
