> ## 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.

# lua sync

> Detect drift between local code and the server, then resolve it in either direction

`lua sync` compares your project with the agent on the server and resolves the differences, either interactively or with one flag per direction. Pulling writes local files; pushing updates the agent's name, model, governance, and persona on the server. Primitive versions are reported but never pushed by this command.

*Verified against lua-cli 3.33.0.*

## Synopsis

```bash theme={null}
lua sync
lua sync --check
lua sync --pull [--force]
lua sync --push
```

## Description

Every run starts by compiling the project with server reconciliation: the server's ids and active versions are written back into `lua.skill.yaml`, and any compiled primitive the agent does not have yet is registered on the server as an entity record with no version. This happens with `--check` too, so `lua sync` is not read-only on the server; a plain [`lua compile`](/reference/cli/compile) never contacts it. Registered but unversioned primitives show as `not deployed` in [`lua status`](/reference/cli/status).

The comparison covers the agent's name, persona, model, and governance as written in `src/index.ts` and `src/governance.ts`, and the version of each skill, webhook, job, preprocessor, postprocessor, and active MCP server recorded in `lua.skill.yaml` against the active version on the server. A primitive drifts when the versions differ, when it exists only locally, or when it exists only on the server. Triggers, devices, voices, and workflows are not compared here; `lua status` covers them.

`--check` prints a summary and exits 1 with `✖ error: Operation failed` when anything drifted. `--pull` takes the server's side: for drifted source primitives it restores files from the latest source backup (recorded by `lua push`, including `lua push backup`), syncs MCP servers live into `lua.skill.yaml`, and then writes the server's name, persona, and model into `src/index.ts` and its governance into `src/governance.ts`. Before writing, a conflict guard hashes every file the backup would overwrite; if any changed since your last backup it refuses, lists the files, and exits 1, unless you pass `--force`. Primitives that drifted but are absent from the backup are listed and make the command exit 1. `--push` takes your side for agent configuration only: it creates a persona version, which the agent serves from its next message, and updates the name, model, and governance, then lists drifted primitives with a hint to run `lua push all --force`. An absent local governance file is never pushed over a server policy; clear one with [`lua governance remove`](/reference/cli/governance). `--accept` is an alias of `--pull`.

If a run aborts, `lua.skill.yaml` is restored to its pre-compile bytes so the next run detects the same drift.

## Arguments

None.

## Options

| Option     | Description                                                                                     | Default |
| ---------- | ----------------------------------------------------------------------------------------------- | ------- |
| `--check`  | Report drift only; exit 1 when any is found.                                                    | off     |
| `--pull`   | Take the server's state without prompting. Guarded by the local-changes check.                  | off     |
| `--accept` | Alias of `--pull`, kept for compatibility.                                                      | off     |
| `--push`   | Push name, persona, model, and governance without prompting. Primitives are listed, not pushed. | off     |
| `--force`  | With `--pull`: skip the local-changes check and overwrite changed files. Destructive.           | off     |

## Examples

Fail a CI job when the code and the server disagree; here the persona in `src/index.ts` was edited after the last push:

```bash theme={null}
lua sync --check --ci
```

```text Output theme={null}
…
✅ Compiled 8 primitives (1 agent, 1 skill, 3 tools, 1 webhook, 1 preprocessor, 1 postprocessor) in 523ms

============================================================
🔍 Drift Check Summary
============================================================

⚠️  Persona drift detected:
   Local:  "You are Acme Helpdesk Triage (drift check). Create..."
   Server: "You are Acme Helpdesk Triage. Create, look up and ..."

============================================================
Total: 1 component(s) with drift

💡 Use 'lua sync --push' to push local changes to server
   Use 'lua sync --accept' to pull server state to local
   Use 'lua sync' for interactive resolution

✖ error: Operation failed
```

Every mode prompts for nothing except bare `lua sync`, whose per-item menu exits 1 under `--ci`; pass `--check`, `--pull`, or `--push`.

Take the server's state, refusing if local files changed since the last backup:

```bash theme={null}
lua sync --pull
```

Overwrite local changes with the server's state:

```bash theme={null}
lua sync --pull --force
```

Push agent configuration after editing the persona in `src/index.ts`, then push the primitives it reported:

```bash theme={null}
lua sync --push
lua push all --force
```

Resolve each difference by hand, choosing push, pull, or skip per item:

```bash theme={null}
lua sync
```

When nothing drifted, every mode prints `✅ No drift detected. Local code is in sync with server.` and exits 0.

## Exit codes

| Code | Meaning                                                                                                                        |
| ---- | ------------------------------------------------------------------------------------------------------------------------------ |
| `0`  | No drift, or every drifted item was resolved.                                                                                  |
| `1`  | `--check` found drift, `--pull` refused because local files changed, or some primitives could not be restored from the backup. |
| `2`  | Not inside a project, or no agent configured in `lua.skill.yaml`.                                                              |
| `9`  | No credential, or the server rejected it.                                                                                      |
| `11` | The server or network is unavailable; nothing is written locally.                                                              |

## See also

* [Release an agent](/ship/releasing) — where drift checks fit in a release
* [Back up and restore source](/ship/backups-and-restore)
* [`lua status`](/reference/cli/status) — per-primitive sync state without side effects
* [`lua pull`](/reference/cli/pull) — restore files from a specific backup or version
* [`lua push`](/reference/cli/push) — push primitive versions
