# Declarative Management

Catalyst resources — [apps](https://docs.diagrid.io/operate/project-operations/ids), [components](https://docs.diagrid.io/operate/project-operations/components), subscriptions, resiliency policies, HTTP endpoints, and configurations — can be managed declaratively from YAML files. This lets you keep the full configuration of a project in Git, review changes in pull requests, and promote resources between projects without clicking through the console.

Two commands do most of the work:

- diagrid apply — Apply a YAML file or directory of Catalyst resources to a project. Create, update, and synchronize resources declaratively.
- diagrid export — Export existing Catalyst resources from a project to YAML so you can version them in Git or promote them to another project.

Full CLI details for `diagrid apply` live in its [command reference](https://docs.diagrid.io/references/catalyst/cli-reference/apply); run `diagrid export --help` for the export flags.

## Apply resources from YAML

`diagrid apply` takes a file or directory and applies every Catalyst resource it contains to the target project. Missing resources are created and existing resources are updated to match the spec. Resources not present in the file are left alone — `diagrid apply` is additive, not synchronizing.

```bash
# Apply a single resource file
diagrid apply -f appid.yaml --project my-project

# Apply an entire directory tree — every .yaml file is processed
diagrid apply -f ./resources/ --project my-project

# Preview what would change without applying
diagrid apply -f ./resources/ --project my-project --dry-run
```

:::tip Use `--project` or the active project

If `--project` is omitted, `diagrid apply` uses the currently selected project (set with [`diagrid project use`](https://docs.diagrid.io/references/catalyst/cli-reference/project/use)). Prefer the explicit `--project` flag in CI so the target isn't ambiguous.

:::

### Supported resource kinds

Each kind has a fixed `apiVersion`. The shape mirrors Dapr's Kubernetes CRDs for the Dapr-defined resources, and Catalyst's own API group for workloads:

| Kind | `apiVersion` | Concept | CLI reference |
|------|--------------|---------|---------------|
| `AppIdentity` | `cra.diagrid.io/v1beta1` | [Apps](https://docs.diagrid.io/operate/project-operations/ids) | [`diagrid app`](https://docs.diagrid.io/references/catalyst/cli-reference/app) |
| `Component` | `dapr.io/v1alpha1` | [Components](https://docs.diagrid.io/operate/project-operations/components) | [`diagrid component`](https://docs.diagrid.io/references/catalyst/cli-reference/component) |
| `Subscription` | `dapr.io/v2alpha1` | [Subscriptions](https://docs.diagrid.io/operate/project-operations/components#subscriptions) | [`diagrid subscription`](https://docs.diagrid.io/references/catalyst/cli-reference/subscription) |
| `Resiliency` | `dapr.io/v1alpha1` | [Resiliency policies](https://docs.diagrid.io/operate/project-operations/components#resiliency-policies) | `diagrid resiliency` |
| `Configuration` | `dapr.io/v1alpha1` | [Configuration](https://docs.diagrid.io/operate/project-operations/components#configuration) | [`diagrid configuration`](https://docs.diagrid.io/references/catalyst/cli-reference/configuration) |
| `HTTPEndpoint` | `dapr.io/v1alpha1` | [HTTP endpoints](https://docs.diagrid.io/operate/project-operations/components#http-endpoints) | `diagrid httpendpoint` |
| `MCPServer` | `dapr.io/v1alpha1` | [MCP servers](https://docs.diagrid.io/operate/project-operations/mcp-servers) | [`diagrid mcpserver`](https://docs.diagrid.io/operate/project-operations/mcp-servers) |
| `TokenBudget` | `cra.diagrid.io/v1beta1` | [Token budgets](https://docs.diagrid.io/concepts/token-budgets) | `diagrid tokenbudget` |

Every resource also requires a `metadata.name` and a `spec` block matching its kind.

### A complete example

Typical project layout in Git:

```
resources/
├── appids/
│   ├── publisher.yaml
│   └── subscriber.yaml
├── components/
│   ├── pubsub-redis.yaml
│   └── state-postgres.yaml
├── subscriptions/
│   └── orders.yaml
└── resiliency/
    └── default.yaml
```

A component spec:

```yaml
# resources/components/state-postgres.yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: my-state
spec:
  type: state.postgresql
  version: v1
  metadata:
    - name: connectionString
      value: "postgres://user:password@host:5432/db"
    - name: tableName
      value: state
scopes:
  - publisher
  - subscriber
```

A subscription spec:

```yaml
# resources/subscriptions/orders.yaml
apiVersion: dapr.io/v2alpha1
kind: Subscription
metadata:
  name: orders-subscription
spec:
  pubsubname: my-pubsub
  topic: orders
  routes:
    default: /orders
scopes:
  - subscriber
```

Apply the whole tree:

```bash
diagrid apply -f ./resources/ --project my-project
```

:::info Secrets in plaintext metadata

When you `diagrid apply` a resource with sensitive metadata in plaintext (passwords, tokens, access keys), Catalyst automatically extracts the values into a managed secret store and rewrites the stored spec to reference them via `secretKeyRef`. Plaintext values never land in the control plane database. See [Managing Secrets](https://docs.diagrid.io/operate/project-operations/secrets) for full details and bring-your-own-secret-store patterns.

:::

## Export resources to YAML

`diagrid export` writes the current spec of every resource in a project (or a single resource) as YAML — the output is compatible with `diagrid apply`.

```bash
# Write the project to a directory, one file per resource (round-trippable with diagrid apply)
diagrid export --project my-project --out-dir ./resources

# Export a single resource
diagrid export --project my-project --id publisher
diagrid export --project my-project --component my-state
diagrid export --project my-project --subscription orders-subscription
diagrid export --project my-project --resiliency default
diagrid export --project my-project --configuration tracing-enabled
```

Use cases for `diagrid export`:

- **Bootstrap Git from an existing project** — run `diagrid export --out-dir ./resources` after building a project in the console, then commit the output.
- **Promote resources between projects** — export from `staging`, tweak environment-specific values, then apply to `prod`.
- **Inspect the server-side spec** — `diagrid export` prints the resource exactly as Catalyst sees it, after defaults and secret extraction.

## GitOps workflow

A common setup pairs `diagrid apply` with your CI system:

1. Developers edit resource YAML in a Git repository and open a pull request.
2. CI runs `diagrid apply` against each resource subdirectory in `--dry-run` mode to preview changes (see [the layout example above](#a-complete-example)).
3. On merge to `main`, CI re-runs `diagrid apply` without `--dry-run`, authenticated with a scoped API key (see [API keys](https://docs.diagrid.io/operate/platform-operations/identity-and-access#api-keys)).
4. Drift detection can be scheduled with `diagrid export --out-dir` + a repo diff, alerting when the live spec no longer matches Git.

:::tip Scope the API key to the target project

For CI/CD, create a project-scoped editor API key rather than a global admin key:

```bash
diagrid apikey create \
  --name ci-apply-key \
  --role cra.diagrid:editor:projects:my-project \
  --duration 2592000
```

Then pass it via `--api-key` (or the `DIAGRID_API_KEY` environment variable) in your pipeline. See [`diagrid apikey create`](https://docs.diagrid.io/references/catalyst/cli-reference/apikey/create) for the full role syntax.

:::

## Common patterns

### Promote a project between environments

```bash
# Export the staging project
diagrid export --project staging --out-dir ./staging-snapshot

# Review, edit, and apply to prod
diagrid apply -f ./staging-snapshot --project prod --dry-run
diagrid apply -f ./staging-snapshot --project prod
```

### Scaffold a local dev environment from an existing project

`diagrid dev scaffold` generates a [multi-app run file](https://docs.diagrid.io/develop/local-development/catalyst-cli#run-multiple-applications-with-a-multi-app-file) from an existing project, combining app metadata with resource specs. Use this when a team member wants to run the same topology locally:

```bash
diagrid dev scaffold
diagrid dev run -f dev-my-project.yaml
```

See [`diagrid dev scaffold`](https://docs.diagrid.io/references/catalyst/cli-reference/dev/scaffold) for the full command.

### Keep secrets out of Git

Pair [bring-your-own secret stores](https://docs.diagrid.io/operate/project-operations/secrets#bring-your-own-secret-store) with `secretKeyRef` references in your YAML. This keeps sensitive values in your Vault / AWS Secrets Manager / Azure Key Vault while component configuration lives in Git.

```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: my-redis
spec:
  type: state.redis
  version: v1
  metadata:
    - name: redisHost
      value: "redis.example.com:6379"
    - name: redisPassword
      secretKeyRef:
        name: redis-creds
        key: password
auth:
  secretStore: my-vault
scopes:
  - my-app
```

## What's next

- [`diagrid apply`](https://docs.diagrid.io/references/catalyst/cli-reference/apply) — command reference.
- `diagrid export` — run `diagrid export --help` for the full flag set.
- [Components](https://docs.diagrid.io/operate/project-operations/components) — supported resource kinds and their specs.
- [Managing secrets](https://docs.diagrid.io/operate/project-operations/secrets) — transparent extraction and bring-your-own stores.
- [Manage Access](https://docs.diagrid.io/operate/platform-operations/identity-and-access#api-keys) — scoped API keys for CI/CD.
