---
title: "Push Files"
description: "Documentation for Push Files Command in ZeyOS SDK CLI"
canonical_url: "https://www.zeyos.com/sdk/synchronization/zeysdk-push"
markdown_url: "https://www.zeyos.com/ai/guide/sdk/synchronization/zeysdk-push.md"
section: "sdk"
authority: "guide"
language: "en"
source_repository: "zeyos/sdk-v2"
source_path: "docs/Synchronization/zeysdk-push.md"
source_revision: "a99897af74253b4dc5af6fecb9301cea0ae18e27"
---

# Push Files

The `push` command uploads local files to the ZeyOS server.

```bash
zeysdk push [ASSET_PATH...] [options]
```

**Parameters**

| Parameter | Description | Required | Example |
|-----------|-------------|----------|---------|
| `ASSET_PATH` | Specific asset paths to push | No | `services/backup.ixml` |

Instance-specific settings must match the active instance. For example, when linked to `dev`, `push settings/settings.production.json` is rejected before requesting server data or changing project files. Select `settings/settings.dev.json` or switch the active instance first.

**Options**

| Option | Description |
|--------|-------------|
| `-f, --force` | Skip the confirmation before applying the push. Does not change what the token is authorized to do |
| `--verbose` | Show detailed output |
| `--debug` | Show detailed debug information |
| `--debug-log` | Write debug output to `.zeysdk/debug.log` |
| `--break-lock` | Replace the current sync lock after you verify its operation is no longer running |
| `--dry-run` | Read and report planned server changes without applying them |
| `--keep-remote` | Preserve server-only assets that have no sync baseline in this checkout, instead of deleting them |
| `--concurrency <number>` | Maximum concurrent file operations (default: `10`) |
| `-q, --quiet` | Suppress progress indicators |

**Process**

1. **State Loading**
   - Reads `.zeysdk/sync.json`
   - Scans local files and manifest metadata
   - Fetches server state for comparison

2. **Change Detection**
   - Identifies files that changed locally
   - Detects local creates, deletes, and metadata updates
   - Marks services, weblets, resources, and assets that exist only on the server for deletion
   - Builds the server update payload

3. **Push Execution**
   - Uploads selected or detected local changes
   - Applies remote asset and metadata updates
   - Deletes server-only assets unless `--keep-remote` is supplied
   - Updates local sync state for the entries the server confirmed

4. **Safety Controls**
   - Acquires the project sync lock and releases its owner token on success, failure, or cancellation
   - Creates a rotating `sync.json` backup for a non-dry-run push
   - Uses `--dry-run` to preview server changes and `--force` to skip the apply confirmation

**Authoritative Push**

A whole-project push makes the server match the working copy. Any service, weblet, resource, or asset that exists on the server but not locally is deleted, whether or not this checkout has ever synchronized it. The preview lists each one as `delete` before the confirmation prompt, and the prompt states how many files will be removed.

Three things are never deleted this way:

- Settings slots (`settingscode`, `usersettingscode`, `defaultsettings`, `settings.&lt;instance&gt;.json`, `readme`) when the local project has no copy and no sync baseline for them. These are fixed server-side slots, so a missing local file means the project was never scaffolded with it rather than that the file was removed.
- Paths outside a targeted push (`zeysdk push services/backup.ixml`), which only touches the paths you name. A selected tracked file that has been removed locally can still be deleted on the server.
- Server-only assets with no sync baseline in this checkout, when `--keep-remote` is supplied.

`--keep-remote` does not protect every asset that is missing locally. If this checkout has a sync baseline for an asset and you remove it locally, a whole-project push still deletes it from the server, with or without `--keep-remote`.

Use `--dry-run` or `zeysdk compare` first when pushing to a shared instance, and `--keep-remote` when another developer's work may live on the same instance.

**Timeouts**

Requests time out after 30 seconds by default; set `ZEYSDK_REQUEST_TIMEOUT_MS` to change this. The request layer does not resend a push update automatically. `zeysdk watch` is the exception: it keeps a failed batch and pushes it again with backoff. After a timeout the outcome is unknown, because the server may have applied the change. Stop any running watcher and run `zeysdk compare` before pushing again. See [Verification Checkpoints](https://www.zeyos.com/ixml/ixml-guide/development-environment/verification-checkpoints).

**Locking**

Push uses `.zeysdk/.sync.lock`, shared with pull, sync, rollout, and recover. If another operation owns the lock, push exits without applying changes. A stale lock is reclaimed automatically. Use `--break-lock` only after confirming that the recorded process is no longer performing synchronization work.

The lock is released from a `finally` path, including when the user declines the confirmation prompt. Rollout holds this same project lock and passes its ownership into each nested push.

**Dry Run**

`--dry-run` still scans local files and reads the active instance. It reports uploads and server deletions without patching the server, cleaning missing entries out of `zeyos.app.json`, updating `sync.json`, or creating a sync-state backup. When `--debug-log` is also supplied, the requested `.zeysdk/debug.log` is still written.

During a normal push, manifest cleanup removes missing resource, service, and weblet entries before the change set is built. This cleanup is intentionally skipped for a dry run.

**Sync-State Backup Scope**

A non-dry-run push rotates `.zeysdk/sync.json.backup*` before applying its server change set. If push reports an error, it restores the pre-push manifest snapshot and attempts to restore the newest sync backup. It cannot reverse a server patch that succeeded before a later local update failed. Use `zeysdk recover --list` to inspect retained sync backups.

**File Hashing and Synchronization**

The push process determines which files need to be synchronized by comparing stored hashes with hashes calculated from the local files. There is no timestamp or file-size pre-check before hashing.

The `lastmodified` value returned by the server after a push is stored in `sync.json` for the synced item. It is not used to decide whether a file needs to be pushed.

Use `--verbose` to see detailed comparison and processing output.

**Examples**

```bash
zeysdk push --verbose
zeysdk push services/backup.ixml weblets/dashboard.ixml
zeysdk push -f
zeysdk push --dry-run
zeysdk push --keep-remote
```

**Error Handling**

| Error | Description | Resolution |
|-------|-------------|------------|
| Missing sync.json | No sync configuration | Run `zeysdk link` first |
| Invalid sync.json | Missing id/url | Re-link instance |
| Network error | Server unreachable | Check connection |
| Auth error | Invalid/expired token | Re-link application |
| Lock error | Sync lock already exists | Wait for current sync or use `--break-lock` |
| File error | Cannot read local file | Check permissions |

**Notes**

- Push uses the currently active instance
- Push favors local content and can overwrite server-side changes; use `sync` when conflicts need explicit resolution
- A whole-project push deletes server-only assets; pass `--keep-remote` to preserve those with no sync baseline in this checkout
- A baseline is advanced only for entries the server echoed back in its PATCH response
- Successful server deletions are also removed from the corresponding local sync baseline
- `--dry-run` reports planned changes without modifying the server, manifest, or sync state
- Automatic recovery restores only `sync.json`; it is not a server rollback
- Debug output can be written to `.zeysdk/debug.log`

**Best Practices**

- Run `zeysdk compare` before pushing to shared or production instances
- Push specific files when only part of the app should change
- Use `--force` only when you have already reviewed the change set
- Confirm the active instance with `zeysdk whoami` before production pushes
