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

# Annotations

export const ImmutableBadge = ({size = "sm"}) => {
  return <Tooltip tip="Property cannot be modified">
            <Badge icon="lock" color="gray" size={size}>immutable</Badge>
        </Tooltip>;
};

Annotations are a convenient way to store metadata with your schemas. Most annotations are optional, but some are required for Miru to process the schemas correctly.

<ParamField path="config type" required>
  The config type is a required annotation that identifies the config type to which a schema belongs. Below is the syntax for annotating a schema with a [config type slug](/cfg-mgmt/concepts/config-types#param-slug).

  <CodeGroup>
    ```yaml JSON Schema theme={null}
    x-miru-config-type: "{config-type-slug}"
    ```

    ```cue CUE theme={null}
    @miru(config_type="{config-type-slug}")
    ```

    ```yaml Opaque theme={null}
    config_type: "{config-type-slug}"
    ```
  </CodeGroup>

  If the provided config type slug does not yet exist, it is automatically created. To edit a config type after creation, visit the [config types documentation](/cfg-mgmt/concepts/config-types#edit-a-config-type).

  Examples: `mobility`, `communication`, `perception`
</ParamField>

<ParamField path="schema language">
  The schema language declares the language that a schema is written in. This annotation applies to [Opaque](/cfg-mgmt/concepts/schemas/languages/opaque) schemas only, and is required for them.

  JSON Schema and CUE schemas have no schema language annotation. Their language is inferred from the schema file itself, so a `.cue` file is read as CUE, and a `.json` or `.yaml` file is read as JSON Schema unless it declares itself opaque.

  ```yaml Opaque theme={null}
  language: "opaque"
  ```

  Because an opaque schema is written as JSON or YAML — the same formats as a JSON Schema — this annotation is what distinguishes the two.
</ParamField>

<ParamField path="instance file path">
  The instance file path is the absolute file system path where config instances for this schema are written on the device.

  <Warning>
    The Miru Agent ships with out-of-the-box access to `/srv/miru`. To deploy configs to a custom directory, please visit the [File system access](/developers/agent/filesys-access#configs) page.
  </Warning>

  This annotation is optional and defaults to `/srv/miru/configs/{config-type-slug}.{instance-format}`. To share the same schema amongst multiple config instances, declare [instance slots](#param-instance-slots) instead.

  <CodeGroup>
    ```yaml JSON Schema theme={null}
    x-miru-instance-filepath: "/srv/miru/configs/{config-type-slug}.json"
    ```

    ```cue CUE theme={null}
    @miru(instance_filepath="/srv/miru/configs/{config-type-slug}.json")
    ```

    ```yaml Opaque theme={null}
    instance_filepath: "/srv/miru/configs/{config-type-slug}.json"
    ```
  </CodeGroup>

  Examples:

  * `/srv/miru/configs/mobility.json`
  * `/home/myapp/configs/communication.yaml`
  * `/var/lib/myapp/configs/safety.yaml`
</ParamField>

<ParamField path="instance slots">
  Instance slots define one or more config instances that are valid for a given schema.
  Instead of maintaining a near-identical config type for each destination, declare
  several slots to allow multiple config instances to share a single schema.

  <Warning>
    A schema may declare an instance file path OR instance slots. Declaring both will error.
  </Warning>

  This annotation is optional. Omitting it will either use the instance file path annotation, or create a single slot with default values.

  <CodeGroup>
    ```yaml JSON Schema theme={null}
    x-miru-instance-slots:
      - key: "left-arm"
        name: "Left Arm"
        filepath: "/srv/miru/configs/v1/left-arm.json"
        required: true
        description: "Config for the left arm controller"
      - key: "right-arm"
        name: "Right Arm"
        filepath: "/srv/miru/configs/v1/right-arm.json"
        required: false
    ```

    ```cue CUE theme={null}
    @miru_instance_slot(
      key="left-arm", 
      name="Left Arm", 
      filepath="/srv/miru/configs/v1/left-arm.json", 
      required=true, 
      description="Config for the left arm controller",
    )
    @miru_instance_slot(
      key="right-arm", 
      name="Right Arm", 
      filepath="/srv/miru/configs/v1/right-arm.json", 
      required=false,
    )
    ```

    ```yaml Opaque theme={null}
    instance_slots:
      - key: "left-arm"
        name: "Left Arm"
        filepath: "/srv/miru/configs/v1/left-arm.json"
        required: true
        description: "Config for the left arm controller"
      - key: "right-arm"
        name: "Right Arm"
        filepath: "/srv/miru/configs/v1/right-arm.json"
        required: false
    ```
  </CodeGroup>

  For more information about instance slots, visit the [Instance slots](/cfg-mgmt/concepts/schemas/annotations#instance-slots) section of the schemas documentation.
</ParamField>

<ParamField path="instance format">
  The instance format declares the format that config instances for this schema are deployed as on the device.

  Visit the [File formats](/cfg-mgmt/concepts/schemas/overview#file-formats) section of the schemas documentation to learn which formats are supported for each schema language.

  This annotation is optional and is inferred from the instance file path's extension. Under the default instance file path of `/srv/miru/configs/{config-type-slug}.json`, the instance format therefore defaults to `json`.

  <CodeGroup>
    ```yaml JSON Schema theme={null}
    x-miru-instance-format: "yaml"
    ```

    ```cue CUE theme={null}
    @miru(instance_format="yaml")
    ```

    ```yaml Opaque theme={null}
    instance_format: "xml"
    ```
  </CodeGroup>

  Examples: `json`, `yaml`, `xml`, `text`
</ParamField>

## Instance slots

An instance slot defines one or more valid config instances that are valid for a given schema. Instance slots are declared with the [instance slots](#param-instance-slots) annotation.

### Multiple slots

Instance slots are primarily used to define a schema that serves multiple config instances with the same validation.

<CodeGroup>
  ```yaml JSON Schema theme={null}
  x-miru-config-type: "Motor Controller"
  x-miru-instance-slots:
    - key: "motor-controller-1"
      name: "Motor Controller 1"
      filepath: "/srv/miru/configs/motor-controller-1.json"
      required: true
    - key: "motor-controller-2"
      name: "Motor Controller 2"
      filepath: "/srv/miru/configs/motor-controller-2.json"
      required: true
    - key: "motor-controller-3"
      name: "Motor Controller 3"
      filepath: "/srv/miru/configs/motor-controller-3.json"
      required: true
  [...schema content...]
  ```

  ```cue CUE theme={null}
  @miru(config_type="Motor Controller")
  @miru_instance_slot(
    name="Motor Controller 1",
    key="motor-controller-1",
    filepath="/srv/miru/configs/motor-controller-1.json",
    required=true
  )
  @miru_instance_slot(
    name="Motor Controller 2",
    key="motor-controller-2",
    filepath="/srv/miru/configs/motor-controller-2.json",
    required=true,
  )
  @miru_instance_slot(
    name="Motor Controller 3",
    key="motor-controller-3",
    filepath="/srv/miru/configs/motor-controller-3.json",
    required=true,
  )

  [...schema content...]
  ```

  ```YAML Opaque theme={null}
  config_type: "Motor Controller"
  instance_slots:
    - key: "motor-controller-1"
      name: "Motor Controller 1"
      filepath: "/srv/miru/configs/motor-controller-1.json"
      required: true
    - key: "motor-controller-2"
      name: "Motor Controller 2"
      filepath: "/srv/miru/configs/motor-controller-2.json"
      required: true
    - key: "motor-controller-3"
      name: "Motor Controller 3"
      filepath: "/srv/miru/configs/motor-controller-3.json"
      required: true
  [...schema content...]
  ```
</CodeGroup>

A schema with multiple slots allows multiple config instances to be written to different destinations.  This structure allows a `motor-controller` schema to serve three identical motor controllers.

All instance slots share the exact same validation. So two files that need different validation belong to two config types, not to two slots of one schema.

### Slot fields

Each instance slot is defined by the following fields:

<ParamField path="key" type="string" required>
  <ImmutableBadge />

  An immutable, code-friendly identifier for the slot.

  Slot keys must be unique within a schema. Two slots cannot have the same key.

  Examples: `motor-controller-1`, `motor-controller-2`, `motor-controller-3`
</ParamField>

<ParamField path="name" type="string" required>
  <ImmutableBadge />

  A human-readable display name for the slot.

  Examples: `Motor Controller 1`, `Motor Controller 2`, `Motor Controller 3`
</ParamField>

<ParamField path="filepath" type="string" required>
  <ImmutableBadge />

  The absolute file system path where this slot's config instance is written on the device.

  Slot file paths must be unique within a schema. Two slots cannot have the same file path.

  Examples: `/srv/miru/configs/motor-controller-1.json`, `/srv/miru/configs/motor-controller-2.json`, `/srv/miru/configs/motor-controller-3.json`
</ParamField>

<ParamField path="required" type="boolean" required>
  <ImmutableBadge />

  Whether a deployment must include a config instance for this slot or not.

  If `true`, a deployment must include a config instance for this slot. If `false`, a deployment may optionally include a config instance for this slot.

  Examples: `true`, `false`
</ParamField>

<ParamField path="description" type="string">
  <ImmutableBadge />

  An optional explanation of what the slot is for.

  Examples: `The first motor controller`, `The second motor controller`, `The third motor controller`
</ParamField>
