> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Back up and restore agent source

> Push source backups, restore a project on another machine, and roll source back to an earlier version

After this guide, you can rebuild a project from the server on any machine and return to any earlier state of its source. Every `lua push` uploads a source backup: an append-only, content-addressed copy of the project files, numbered `v1`, `v2`, and so on. An [agent version](/concepts/releases-and-versions) records which source backup it was created from, so `lua pull --version <n>` returns the code behind a release. Backups are not a substitute for git; see [Keep a git history](#keep-a-git-history).

*Verified against lua-cli 3.33.0.*

**Before you begin**

* A project signed in with `lua auth configure` and an agent ID in `lua.skill.yaml`.
* For a restore on a new machine: the agent ID (from `lua agents` or the admin dashboard) and an empty directory.

<Steps>
  <Step title="Push a backup explicitly">
    `lua push all` and every single-primitive push run the backup automatically. Run it on its own after edits you have not pushed, such as a README change.

    ```bash theme={null}
    lua push backup --force --fresh
    ```

    `--fresh` walks the disk instead of trusting the last compile, so it captures files a compile never saw; `--force` skips the freshness guard that refuses to overwrite a newer backup pushed from another machine. A backup includes every project file except `node_modules`, `dist`, `dist-v2`, `.git`, `.lua`, `.temp`, `coverage`, `.next`, and `.turbo` directories, dotfiles (so `.env` is never backed up), lockfiles, test files (`*.test.*`, `*.spec.*`, `__tests__`), `.d.ts` and `.map` files, and any file over 256 KB. `src/` is stored in full on Lua's servers, a webhook's `secret` literal included; nothing deletes a backup (a pull or rollback appends a new version), and any credential with `agents:read` on the agent can download one. The result is recorded in `lua.skill.yaml`:

    ```yaml lua.skill.yaml theme={null}
    backup:
      activeVersion: 3
      lastHash: 8198f4f371f01a496147ec72b4cfcbc208aa0242803167d56c20323117d1af47
      lastPushedAt: '2026-09-12T12:49:51.474Z'
    ```
  </Step>

  <Step title="List backup versions">
    Each version records who created it, what triggered it, and a hash of the project contents; `*` marks the version your checkout last pushed or restored.

    ```bash theme={null}
    lua source list --limit 3
    ```

    ```text Output theme={null}
    VERSION   CREATED            BY        TRIGGERED BY                   HASH
    v88 *	2026-09-09 17:49	9029d3f6-3d88-487f-a5ef-4d866059d9f6	push workflow cx2-sig         	0fcdc50c...
    v87	2026-09-09 17:44	9029d3f6-3d88-487f-a5ef-4d866059d9f6	push trigger                  	af10a445...
    v86	2026-09-09 17:43	9029d3f6-3d88-487f-a5ef-4d866059d9f6	push workflow big-arr         	da9e5a3f...
    ```

    The list shows the most recent 50; `--all` fetches the full history ([`lua source` reference](/reference/cli/source)).
  </Step>

  <Step title="Restore a project on a new machine">
    `lua init` for an existing agent in an empty directory downloads the latest backup, writes `lua.skill.yaml`, and installs dependencies. `--restore-sources` answers the overwrite prompt so the command runs unattended.

    ```bash theme={null}
    lua init --ci --agent-id <agent-id> --restore-sources
    lua compile --ci
    ```

    If the agent has no backup yet, `lua init` says so (`No backup on file for this agent.`) and scaffolds a fresh project instead; push from the original machine first ([`lua init` reference](/reference/cli/init)).
  </Step>

  <Step title="Pull a backup into an existing checkout">
    `lua pull` overwrites local files with the latest backup; `--version <n>` takes an agent version number and restores the source that version was created from.

    ```bash theme={null}
    lua pull --force
    lua pull --version 8 --force
    ```

    <Warning>
      Both forms overwrite local files without merging and then append the restored state as a new backup version. Commit or push your own changes first.
    </Warning>
  </Step>

  <Step title="Roll source back to an earlier backup">
    `lua source rollback` restores backup `v<n>` locally and records it as `v<latest+1>`; history is never rewritten. It changes files on disk only: what runs in production is still the promoted agent version, which you change with `lua version promote`.

    ```bash theme={null}
    lua source rollback --version 86 --force
    ```

    For an agent under versioning the command prints a deprecation notice and points to `lua version promote`; use `lua pull --version <n>` when you want the source of a specific release.
  </Step>

  <Step title="Verify">
    Confirm the new version is the active one and that the checkout matches it.

    ```bash theme={null}
    lua source list --limit 2
    lua status --json --ci | jq '.backup'
    ```

    `backup.status` is `synced` when the files on disk match the last pushed backup, `out-of-sync` when they differ, and `never-compiled` before the first compile.
  </Step>
</Steps>

## Options you may need

### Find the backup behind an agent version

`lua version create` requires a backup and fails with ``No backup exists for this agent. Run `lua push` first, or pass `--auto-push` to push and snapshot in one step.`` when there is none. `lua version list --json` and `lua version show <n> --json` include `sourceManifestVersion`, the backup number behind each agent version, and `lua pull --version <n>` refuses a version with none linked (`Version v<n> has no source backup linked.`).

### Keep a git history

`lua git connect` turns on auto-commits: after each `lua push`, `lua version create|promote|delete`, and `lua pull`, the CLI commits the working tree and tags version snapshots as `lua/v<n>`. It requires a git repository with `user.name` and `user.email` set and never runs `git init` for you. `--auto-push` additionally pushes to a GitHub HTTPS `origin` once you link an account with `lua git auth github`. `lua git disconnect` turns it off and leaves existing commits alone ([`lua git` reference](/reference/cli/git)).

## If it isn't working

<Accordion title="❌ Refusing to push backup — server has a different backup than this machine's last push:">
  Another machine pushed after your last push. Run `lua sync --pull` to take the server's files first, or `lua push backup --force` to replace the server backup with yours (the other machine's changes remain in history as an earlier version).
</Accordion>

<Accordion title="❌ Refusing to pull — <n> local file(s) have uncommitted changes since your last push">
  `lua sync --pull` found files changed since your last backup. Save them with `lua push backup`, or pass `--force` to overwrite them.
</Accordion>

<Accordion title="✖ error: No backup versions available to pull.">
  The agent has never been pushed from the CLI. Run `lua push backup --force --fresh` on the machine that has the source, then pull again.
</Accordion>

## Next steps

<Columns cols={2}>
  <Card title="Release an agent to production" href="/ship/releasing">How agent versions are created and promoted.</Card>
  <Card title="lua sync reference" href="/reference/cli/sync">Drift detection and the `--pull` conflict guard.</Card>
  <Card title="lua pull reference" href="/reference/cli/pull">Restore the latest backup or a version's source.</Card>
  <Card title="About security and data" href="/concepts/security-and-data">What a backup stores and what it never includes.</Card>
</Columns>
