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

# Define upload rules

Upload rules are an optional part of a release. They define which files on your devices get uploaded to your bucket. This page covers defining upload rules and including them when creating a release.

While a release must contain at least one config schema, it may contain any number of upload rules, including none. For the full release-creation workflow — config schemas, Git metadata, and the CLI command — see the [Create a release](/cfg-mgmt/create-a-release) guide.

## Prerequisites

Upload rules write files to a bucket, so a connected bucket is required. Connect one before creating a release with upload rules:

* [Connect an AWS bucket](/data-uploads/connect-a-bucket/aws)
* [Connect a GCS bucket](/data-uploads/connect-a-bucket/gcs)

The generic prerequisites are covered in the [Create a release](/cfg-mgmt/create-a-release) guide.

## Define the upload rules

Upload rules are defined as YAML files in your Git repository. Below is an example rule that uploads all log files from the `/var/log/robot` directory to the `my-uploads-bucket` bucket.

```yaml robot-logs.yaml theme={null}
collection_slug: robot-logs

source:
  glob: /var/log/robot/*.log
  stability_window_secs: 60

destination:
  bucket: my-uploads-bucket
  path: logs/{device_id}/{upload_id}/{file_name}
  delete_policy: never
```

Like schemas, upload rules are identified by hashing their content, so rules with equivalent content are deduplicated even if their comments or formatting differ.

### Source

A rule's `source` declares what to collect on the device: which files to match, and
when a matching file is considered finished and eligible for upload.

<ParamField path="glob" type="string" required>
  An absolute glob pattern that selects the files to upload.

  Must satisfy the following criteria:

  * Absolute — it starts with `/`
  * At most 1024 bytes, with no control characters
  * No `..` segments, and no empty segments (`//` or a trailing `/`)

  <Warning>
    You must grant the Miru Agent read access to the files you want to upload. Visit the [file system access](/developers/agent/filesys-access#data-uploads) section for more details.
  </Warning>

  Example: `/var/log/robot/*.log`
</ParamField>

<ParamField path="stability_window_secs" type="integer" default="60">
  How long, in seconds, a matching file's size and modification time must stay
  unchanged (quiescent) before it is considered stable and eligible for upload.
  See [completion detection](/data-uploads/primitives/uploads).
</ParamField>

### Destination

A rule's `destination` declares where which registered [bucket](/data-uploads/primitives/buckets) to write to, and the object path within it.

<ParamField path="bucket" type="string">
  Name of the registered bucket this rule uploads to.

  Example: `my-uploads-bucket`
</ParamField>

<ParamField path="path" type="string" default="{device_id}/{year}-{month}-{day}/{upload_id}/{file_name}">
  The template which defines the object path to which the uploaded file is written.

  The following variables are supported, which are filled in when each upload's
  object key is rendered:

  | Variable        | Example     | Description                               |
  | --------------- | ----------- | ----------------------------------------- |
  | `{upload_id}`   | `upl_123`   | The upload's ID.                          |
  | `{device_id}`   | `dvc_123`   | The uploading device's ID.                |
  | `{device_name}` | `my-robot`  | The device's name.                        |
  | `{file_name}`   | `robot.log` | The source file's basename.               |
  | `{year}`        | `2026`      | The upload's creation year (e.g. `2026`). |
  | `{month}`       | `01`        | The upload's creation month.              |
  | `{day}`         | `01`        | The upload's creation day.                |
  | `{hour}`        | `00`        | The upload's creation hour.               |
  | `{minute}`      | `00`        | The upload's creation minute.             |

  <Warning>
    Templates must contain the `{upload_id}` variable.
  </Warning>
</ParamField>

<ParamField path="delete_policy" type="enum" default="never">
  When the device deletes the local source file after collecting it.

  * `never` *(default)* — keep the local file in place; you manage local retention
    yourself.
  * `after_upload` — delete the local file once the upload is durably confirmed.
</ParamField>

## Add upload rules to a release

Upload rules ride along with `miru release create` — the same command that creates the release and its schemas. Include them with either flag (both may be repeated):

* `--upload-rule <file>` — a single upload rule YAML file
* `--upload-rules <dir>` — a directory of upload rule YAML files

```bash theme={null}
$ miru release create \
  --version v1.0.0 \
  --schemas ./schemas/ \
  --upload-rule ./upload-rules/robot-logs.yaml
```

See the [CLI reference](/references/cli/release-create) for the full flag list.
