Skip to content

Version history

Prompts are code, and code needs history. Saving an agent, skill, workflow, dashboard, widget, or atlas definition records a version under <latchHome>/history/<kind>/<name>/, so “it worked yesterday” is a question with an answer.

Version history for a document

Versions for one document, newest first, with the selected one previewed in full.

Three things are worth knowing before you go looking for a version. Only the live file is ever read — prompts and the executor never see the history directory. A burst of saves is one version, so an editing session collapses to “the state before the burst” rather than one copy per save. And history survives deletion, which is what makes restore-after-delete possible.

Kinds agent, skill, workflow, dashboard, widget, atlas
Path <latchHome>/history/<kind>/<name>/<epoch-ms>.<ext>.md for everything but workflows, which are .json
What is recorded The outgoing content: the live file as it was before the save that triggered it
Coalescing window 5 minutes — a save whose newest version is younger than that records nothing
Retention 50 versions per document; the oldest are pruned on write
Skipped when The content is byte-identical to the newest version
Recorded on Every write, including re-filing a workflow into a sidebar folder. Never on delete — a delete simply leaves the history behind.

Because versions are named by millisecond timestamp, the directory sorts chronologically and ls is a perfectly good history browser:

Terminal window
ls ~/LatchAI/history/agent/code-reviewer/
# 1753380114882.md 1753466520431.md 1753552903117.md

They are ordinary files. Diff two of them with diff, or diff one against the live document, and nothing in LatchAI minds:

Terminal window
diff ~/LatchAI/history/agent/code-reviewer/1753466520431.md ~/LatchAI/agents/code-reviewer.md

That last command is also how you get a diff at all: the in-app browser previews a version, it does not compare two.

Restore writes the old content back to the live file, so it helps to know where that is — and one of them is not where you’d guess:

Kind Live file
agent <latchHome>/agents/<name>.md
workflow <latchHome>/workflows/<id>.json
dashboard <latchHome>/dashboards/<id>.md
widget <latchHome>/widgets/<name>.md
atlas <latchHome>/atlas/<id>.md
skill <latchHome>/workspace/.claude/skills/<name>/SKILL.md

Skills live in the workspace, not beside the other definitions, because that is where an agent’s skills are discovered from.

  • Workflows — the ⏱ History button in the workflow toolbar.
  • Dashboards — the ⏱ History button in the dashboard editor’s toolbar.
  • Agents, skills, and widget types — the history button in their Settings editors.

Atlas definitions are recorded on every save too, but have no browser — their versions are on disk under history/atlas/ and are restorable through the API below.

LatchAI has three histories and they do not overlap. It’s worth knowing which one you want:

Layer Covers Where
Version history Documents you author — agents, skills, workflows, dashboards, widgets, atlases <latchHome>/history/
Checkpoints Workspace files changed by a run or a chat turn <latchHome>/runs/checkpoints.git
Your own git The repositories you mounted Your repos

A bad prompt edit is version history. A run that wrote the wrong file is a checkpoint. A commit you regret is git.

Vault notes are a fourth thing and deliberately not here: a vault is its own git repository, and the daemon commits it when you accept, reject or refile a note. Its history is git log, not history/.

The history browser lists versions newest first with their size and age, previews the one you select, and restores it. Restoring writes the old content back to the live file — which, being a save, records a version of its own.

That last part is the point: restore is itself undoable. The snapshot taken on restore ignores the coalescing window, precisely so a restore can never be the save that got collapsed away. A workflow is validated against the schema before its live file is touched, so restoring a version that predates a schema change fails cleanly instead of writing a file the executor can’t load.

The whole flow is also an API, which is what a “roll every agent back to Tuesday” script would use — and it is the only way to restore a document you have already deleted, since a deleted document has no editor to open the browser from:

Terminal window
curl -s localhost:7777/api/history/agent/code-reviewer
# {"versions":[{"id":"1753552903117","ts":1753552903117,"bytes":4210}, …]}
curl -s localhost:7777/api/history/agent/code-reviewer/1753552903117 # {"content":"---\nname: …"}
curl -XPOST localhost:7777/api/history/agent/code-reviewer/1753552903117/restore

Versions are always newest-first, ids are always millisecond timestamps, and an unrecognised kind is an error rather than an empty list.

A brand-new document shows “No versions yet.” That is correct, not a bug. A version is the state a save replaced, so creating a document records nothing — there was no previous live file. The first version appears on your second save. The same logic explains a suspiciously thin history after a fast editing session: only the first save in a burst records anything — the state before the burst — and everything within five minutes of it is deliberately collapsed away.

A version you expected is missing. Two rules drop one silently, both on purpose: a save whose content is byte-identical to the newest version records nothing, and the 51st version prunes the oldest. A document you have been editing for months holds its last 50 states, not all of them.

History under a name you don’t recognise. History is keyed by <kind>/<name>, and the name is the filename. Saving a document under a different name starts a fresh timeline and leaves the old one intact under the old name — nothing is lost, but it is somewhere else.