> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/harness-ai/use-harness-cli/harness-cli/harness-cli-commands/gitops-commands.md).

# GitOps

Use the Harness CLI to manage the GitOps module, including agents, applications, destination clusters, source repositories, ApplicationSets, and Argo CD AppProject mappings.

Harness GitOps is backed by Argo CD. A GitOps agent runs as the control plane inside your cluster, and applications, destination clusters, source repositories, and ApplicationSets are registered against that agent. The CLI lets you register and inspect all of these resources, trigger syncs, and refresh application state without opening the Harness UI or the Argo CD console. It also lets you map and import existing Argo CD AppProjects.

This page covers all GitOps resources and actions available in the CLI.

***

## What you will learn in this topic <a href="#what-you-will-learn-in-this-topic" id="what-you-will-learn-in-this-topic"></a>

By the end of this page, you will know how to:

* List, create, and delete GitOps agents, and fetch the manifests that install them.
* Create, update, and delete GitOps applications.
* Sync and refresh an application.
* Register destination clusters and source repositories against an agent.
* Manage ApplicationSets.
* Discover Argo CD AppProjects, map them to a Harness org and project, and import the mapped projects.
* Watch the auto-create log for services, environments, and cluster links that an import creates.

***

## Before you begin <a href="#before-you-begin" id="before-you-begin"></a>

* **Harness CLI installed and authenticated:** For setup steps, see [Install and upgrade](/harness-ai/use-harness-cli/harness-cli/install-and-upgrade.md) and [Authenticate](/harness-ai/use-harness-cli/harness-cli/authenticate.md).
* **Project scope configured:** GitOps resources require `--org` and `--project`. Set them in your profile or pass them on each command.
* **Cluster access:** To install an agent you need `helm` or `kubectl` access to the target cluster. The CLI produces the install manifest but does not apply it for you.

***

### Resource identifiers <a href="#resource-identifiers" id="resource-identifiers"></a>

Agents are top-level resources. Everything else is registered against an agent, so it uses a compound identifier:

* **`<agent>/<name>`:** An application, cluster, or repository on an agent.
* **`<agent>/<uuid>`:** An ApplicationSet on an agent.
* **`<agent>/<argo_project>`:** An AppProject mapping on an agent.

Leave the slash in a compound identifier unencoded. For the `--set`, `-f`, `--format`, paging, and scope conventions that apply to every command on this page, see [Global flags and output](/harness-ai/use-harness-cli/harness-cli/global-flags-and-output.md).

***

### Agents <a href="#agents" id="agents"></a>

A GitOps agent is the control plane that runs in your cluster and reconciles desired state from Git against live state in the cluster. Create the agent record in Harness first, then install the agent workload into the cluster.

#### List agents <a href="#list-agents" id="list-agents"></a>

Filter agents by type, scope, health, or connection state.

```sh
harness list gitops_agent
harness list gitops_agent --type <type>
harness list gitops_agent --scope <scope>
harness list gitops_agent --health-status <health_status>
harness list gitops_agent --connected-status <connected_status>
harness list gitops_agent --search "<search_term>"
```

#### Get agent details <a href="#get-agent-details" id="get-agent-details"></a>

```sh
harness get gitops_agent <agent_id>
harness get gitops_agent <agent_id> --format json
```

#### Create an agent <a href="#create-an-agent" id="create-an-agent"></a>

Create the agent record in Harness. This registers the agent but does not install anything into a cluster.

```sh
harness create gitops_agent <agent_id> \
  --set name="<agent_name>" \
  --set namespace=<namespace>

harness create gitops_agent <agent_id> -f <agent_file>.yaml
```

#### Get the agent install manifest <a href="#get-the-agent-install-manifest" id="get-the-agent-install-manifest"></a>

Fetch the Helm override values or the kubectl manifest that installs the agent into a cluster. `--output_file` is required. Pass `-f` to supply install options from a file.

```sh
harness execute gitops_agent:install <agent_id> \
  --method helm \
  --output_file <values_file>.yaml

harness execute gitops_agent:install <agent_id> \
  --method yaml \
  --output_file <manifest_file>.yaml

harness execute gitops_agent:install <agent_id> \
  --method helm \
  --output_file <values_file>.yaml \
  -f <install_options>.yaml
```

{% hint style="info" %}
This command writes the install artifact to disk. It does not run `helm` or `kubectl` for you. Apply the generated file against your cluster as a separate step.
{% endhint %}

#### Delete an agent <a href="#delete-an-agent" id="delete-an-agent"></a>

```sh
harness delete gitops_agent <agent_id>
```

***

### Applications <a href="#applications" id="applications"></a>

A GitOps application maps a source Git revision to a destination cluster and namespace. Harness reconciles the application continuously and reports drift between the desired state in Git and the live state in the cluster.

#### List applications <a href="#list-applications" id="list-applications"></a>

```sh
harness list gitops_application
harness list gitops_application --search "<search_term>"
harness list gitops_application --all --format json
```

#### Get application details <a href="#get-application-details" id="get-application-details"></a>

Use `--yaml` to return the Argo CD application spec.

```sh
harness get gitops_application <agent_id>/<application_name>
harness get gitops_application <agent_id>/<application_name> --yaml
```

#### Create an application <a href="#create-an-application" id="create-an-application"></a>

`-f` and `--cluster` are both required. Pass `--repo` to bind the application to a registered source repository, or `--skip-repo-validation` to create the application without validating the repository.

```sh
harness create gitops_application <agent_id> \
  -f <application_file>.yaml \
  --cluster <cluster_id> \
  --repo <repository_id>

harness create gitops_application <agent_id> \
  -f <application_file>.yaml \
  --cluster <cluster_id> \
  --skip-repo-validation
```

#### Update an application <a href="#update-an-application" id="update-an-application"></a>

```sh
harness update gitops_application <agent_id>/<application_name> -f <application_file>.yaml
harness update gitops_application <agent_id>/<application_name> \
  -f <application_file>.yaml \
  --cluster <cluster_id> \
  --repo <repository_id>
```

#### Sync an application <a href="#sync-an-application" id="sync-an-application"></a>

Trigger a sync to reconcile the cluster with the desired state in Git. Use `--revision` to sync a specific Git revision, `--prune` to remove resources that no longer exist in Git, and `--dry-run` to preview the sync without applying it.

```sh
harness execute gitops_application:sync <agent_id>/<application_name>
harness execute gitops_application:sync <agent_id>/<application_name> --revision <revision>
harness execute gitops_application:sync <agent_id>/<application_name> --prune
harness execute gitops_application:sync <agent_id>/<application_name> --dry-run
```

#### Refresh an application <a href="#refresh-an-application" id="refresh-an-application"></a>

Refresh the application state from its source. Add `--hard` to invalidate the manifest caches before the refresh.

```sh
harness execute gitops_application:refresh <agent_id>/<application_name>
harness execute gitops_application:refresh <agent_id>/<application_name> --hard
```

#### Delete an application <a href="#delete-an-application" id="delete-an-application"></a>

Control how the deletion cascades to the resources the application manages.

```sh
harness delete gitops_application <agent_id>/<application_name>
harness delete gitops_application <agent_id>/<application_name> --propagation-policy <policy>
harness delete gitops_application <agent_id>/<application_name> --no-cascade
harness delete gitops_application <agent_id>/<application_name> --remove-finalizers
harness delete gitops_application <agent_id>/<application_name> --app-namespace <namespace>
```

***

### Clusters <a href="#clusters" id="clusters"></a>

A GitOps cluster is a deployment destination that an agent can reach. Register a cluster on an agent before you point an application at it.

#### List and get clusters <a href="#list-and-get-clusters" id="list-and-get-clusters"></a>

```sh
harness list gitops_cluster
harness list gitops_cluster --agent <agent_id>
harness list gitops_cluster --search "<search_term>"
harness get gitops_cluster <agent_id>/<cluster_id>
```

#### Register a cluster <a href="#register-a-cluster" id="register-a-cluster"></a>

Add `--upsert` to update the cluster if it is already registered instead of failing.

```sh
harness create gitops_cluster <agent_id>/<cluster_id> -f <cluster_file>.yaml
harness create gitops_cluster <agent_id>/<cluster_id> -f <cluster_file>.yaml --upsert
```

#### Update a cluster <a href="#update-a-cluster" id="update-a-cluster"></a>

```sh
harness update gitops_cluster <agent_id>/<cluster_id> -f <cluster_file>.yaml
harness update gitops_cluster <agent_id>/<cluster_id> -f <cluster_file>.yaml --force-update
```

#### Delete a cluster <a href="#delete-a-cluster" id="delete-a-cluster"></a>

```sh
harness delete gitops_cluster <agent_id>/<cluster_id>
harness delete gitops_cluster <agent_id>/<cluster_id> --force-delete
harness delete gitops_cluster <agent_id>/<cluster_id> --query-name <name>
```

***

### Repositories <a href="#repositories" id="repositories"></a>

A GitOps repository is a source of desired state. Register the Git repository on an agent so that applications can read manifests from it.

#### List and get repositories <a href="#list-and-get-repositories" id="list-and-get-repositories"></a>

```sh
harness list gitops_repository
harness list gitops_repository --agent <agent_id>
harness list gitops_repository --search "<search_term>"
harness get gitops_repository <agent_id>/<repository_id>
```

#### Register a repository <a href="#register-a-repository" id="register-a-repository"></a>

Add `--upsert` to update an existing registration. Pass `--repo-creds-id` to reuse stored repository credentials.

```sh
harness create gitops_repository <agent_id>/<repository_id> -f <repository_file>.yaml
harness create gitops_repository <agent_id>/<repository_id> \
  -f <repository_file>.yaml \
  --upsert \
  --repo-creds-id <credentials_id>
```

#### Update a repository <a href="#update-a-repository" id="update-a-repository"></a>

```sh
harness update gitops_repository <agent_id>/<repository_id> -f <repository_file>.yaml
```

#### Delete a repository <a href="#delete-a-repository" id="delete-a-repository"></a>

```sh
harness delete gitops_repository <agent_id>/<repository_id>
harness delete gitops_repository <agent_id>/<repository_id> --force-delete
harness delete gitops_repository <agent_id>/<repository_id> --query-repo <repository_url>
```

***

### ApplicationSets <a href="#applicationsets" id="applicationsets"></a>

An ApplicationSet generates GitOps applications from a template and a generator, so one definition can fan out across many clusters, namespaces, or Git directories. ApplicationSets are identified by agent and UUID.

#### List and get ApplicationSets <a href="#list-and-get-applicationsets" id="list-and-get-applicationsets"></a>

```sh
harness list gitops_application_set
harness list gitops_application_set --agent <agent_id>
harness list gitops_application_set --search "<search_term>"
harness get gitops_application_set <agent_id>/<uuid>
```

#### Create an ApplicationSet <a href="#create-an-applicationset" id="create-an-applicationset"></a>

Add `--upsert` to update an existing ApplicationSet, or `--dry-run` to validate the definition without creating anything.

```sh
harness create gitops_application_set <agent_id> -f <application_set_file>.yaml
harness create gitops_application_set <agent_id> -f <application_set_file>.yaml --dry-run
harness create gitops_application_set <agent_id> -f <application_set_file>.yaml --upsert
```

#### Update an ApplicationSet <a href="#update-an-applicationset" id="update-an-applicationset"></a>

```sh
harness update gitops_application_set <agent_id>/<uuid> -f <application_set_file>.yaml
harness update gitops_application_set <agent_id>/<uuid> -f <application_set_file>.yaml --dry-run
harness update gitops_application_set <agent_id>/<uuid> -f <application_set_file>.yaml --upsert
```

#### Delete an ApplicationSet <a href="#delete-an-applicationset" id="delete-an-applicationset"></a>

```sh
harness delete gitops_application_set <agent_id>/<uuid>
```

***

### Argo CD AppProject mappings <a href="#argo-cd-appproject-mappings" id="argo-cd-appproject-mappings"></a>

If you run Argo CD AppProjects that Harness does not yet know about, use these commands to discover them on an agent, map each one to a Harness org and project, and import the mapped projects. Mapping and import are scriptable, so you can migrate many AppProjects without using the mapping UI on the GitOps Agent page. For the equivalent UI flow, go to [GitOps Agent](https://developer.harness.io/continuous-delivery/use-gitops/gitops-entities/agents/install-a-harness-git-ops-agent).

Use an account- or org-level agent for this workflow. A project-level agent can only map AppProjects to the single project it already belongs to.

#### List Argo CD projects <a href="#list-argo-cd-projects" id="list-argo-cd-projects"></a>

List the Argo CD AppProjects visible to an agent, including ones that are not yet mapped to a Harness project.

```sh
harness list gitops_argo_project <agent_id>
harness list gitops_argo_project <agent_id> --level account
```

Pass `--level account|org|project` to match the agent's own scope, or skip `--level` and prefix the agent ID with its scope instead. For an account-scoped agent, pass `account.<agent_id>` instead of the bare agent ID with `--level account`; for an org- or project-scoped agent, pass the ID with the matching `--level` or its scope-prefixed form. A `--level` that does not match the agent's actual scope returns a 404. Each row of output shows the Argo CD project's `name`, `description`, and `created` timestamp.

#### List AppProject mappings <a href="#list-appproject-mappings" id="list-appproject-mappings"></a>

```sh
harness list gitops_app_project_mapping <agent_id>
harness list gitops_app_project_mapping <agent_id> --level account
```

Each row shows the Argo CD project, the Harness org and project it maps to, and whether auto-create is on. An agent with no mappings returns an empty table.

#### Create an AppProject mapping <a href="#create-an-appproject-mapping" id="create-an-appproject-mapping"></a>

Map an Argo CD AppProject to a Harness org and project. Set `autoCreateServiceEnv` to `true` so that import also creates the services, environments, and cluster links that the AppProject's applications need. It defaults to `false` when omitted.

```sh
harness create gitops_app_project_mapping <agent_id> --level account \
  --set argoproject=<argo_project> org=<org> project=<project> autoCreateServiceEnv=true
```

To create multiple mappings in a single command, pass a file instead of `--set`.

```sh
harness create gitops_app_project_mapping <agent_id> --level account -f <mappings_file>.yaml
```

<details>

<summary>Mappings file example</summary>

```yaml
mappings:
  - argoproject: my-argo-project
    org: default
    project: myProject
    autoCreateServiceEnv: true
```

</details>

A row in the `-f` file that is missing `argoproject`, `org`, or `project`, or `--set` without all three, is rejected before Harness makes an API call. You cannot combine `-f` with `--set`, pass an empty `mappings` list, repeat the same `argoproject` more than once in the same file, or leave a row in the file incomplete. Mapping an AppProject that is already mapped returns an error instead of creating a duplicate mapping. The Harness org and project in each row must already exist, and all rows in the file succeed or fail together: if one row is invalid, Harness creates none of the mappings in that call.

#### Update an AppProject mapping <a href="#update-an-appproject-mapping" id="update-an-appproject-mapping"></a>

The org and project are lookup keys in the mapping, so updates only change `autoCreateServiceEnv`. All three of `org`, `project`, and `autoCreateServiceEnv` are required on every update call, `autoCreateServiceEnv` must be `true` or `false`, and a mapping that does not exist for the given org and project returns a 404. To move a mapping to a different org or project, delete it and create it again.

```sh
harness update gitops_app_project_mapping <agent_id>/<argo_project> --level account \
  --set org=<org> project=<project> autoCreateServiceEnv=true
```

#### Delete an AppProject mapping <a href="#delete-an-appproject-mapping" id="delete-an-appproject-mapping"></a>

Deleting a mapping also removes the applications, ApplicationSets, repositories, and clusters that Harness associated with that Argo CD project.

```sh
harness delete gitops_app_project_mapping <agent_id>/<argo_project> --level account \
  --set org=<org> project=<project>
```

Delete takes `org` and `project` through `--set` only, not `-f`. Omitting either value is rejected before Harness makes an API call, and a mapping that does not exist for the given org and project returns a 404.

#### Import AppProject mappings <a href="#import-appproject-mappings" id="import-appproject-mappings"></a>

Import brings the applications, clusters, and repositories for one or more mapped Argo CD AppProjects into Harness. When a mapping has `autoCreateServiceEnv: true`, import also starts the background creation of the corresponding services, environments, and cluster links, and returns an `importRequestId` you can use to track the work.

```sh
harness execute gitops_agent:import <agent_id> --level account \
  --argo-project-names <argo_project>[,<argo_project>...]
```

To import from a file instead of `--argo-project-names`:

```sh
harness execute gitops_agent:import <agent_id> --level account -f <import_file>.yaml
```

<details>

<summary>Import file example</summary>

```yaml
argoProjectNames:
  - my-argo-project
```

</details>

You cannot pass both `--argo-project-names` and `-f`, and you must pass one of them. The project list cannot be empty, and importing an Argo CD project without a mapping returns an error.

The default text summary shows the import counts per project, the `importRequestId`, and how many services, environments, and cluster links Harness plans to auto-create. The Harness CLI only asks about watching when auto-create is on for the mapping and the planned auto-create count is greater than zero. When it asks, the prompt is `Watch auto-create logs now? [y/N]` and the default answer is No. If auto-create is off, or the planned count is zero, or the import response has no `importRequestId`, the Harness CLI skips the prompt and does not watch, regardless of `--watch`.

```sh
harness execute gitops_agent:import <agent_id> --level account -f <import_file>.yaml --watch
```

{% hint style="info" %}
**A WATCH STARTED FROM IMPORT STOPS ON ITS OWN**

The watch stops as soon as the auto-create log total reaches the planned count, or after the default two-minute window elapses, and exits `0` either way. Press `Ctrl-C` to cancel the watch instead; a canceled watch exits with a non-zero code.
{% endhint %}

If you skip the watch, or the planned count is zero, the summary still prints the equivalent `list gitops_autocreate_log` command so that you can check the outcome later.

#### Watch auto-create logs <a href="#watch-auto-create-logs" id="watch-auto-create-logs"></a>

Fetch or follow the auto-create log for a specific import. Each row records whether a service, environment, or cluster link succeeded (`SUCCESS`), succeeded with a warning (`WARNING`), or failed (`FAILED`), with the failure reason as the last column. All three outcomes count toward the planned total when a watch was started from `import`. Harness writes these rows asynchronously after import returns, and retains them for seven days.

```sh
harness list gitops_autocreate_log <agent_id> --import-request-id <import_request_id>
```

Use the shared pagination flags to control how much of the log you fetch. For more information, see [Pagination flags](/harness-ai/use-harness-cli/harness-cli/global-flags-and-output.md#pagination-flags).

```sh
harness list gitops_autocreate_log <agent_id> --import-request-id <import_request_id> --all
harness list gitops_autocreate_log <agent_id> --import-request-id <import_request_id> --count
harness list gitops_autocreate_log <agent_id> --import-request-id <import_request_id> --watch
harness list gitops_autocreate_log <agent_id> --import-request-id <import_request_id> --watch --timeout 300
```

`--import-request-id` is required. `--watch` always fetches the full log, so you cannot combine it with `--offset`, `--limit`, or `--count`; `--all` cannot be combined with `--offset` or `--limit`; and `--count` cannot be combined with `--all`, `--offset`, or `--limit`. While `--watch` polls, it prints the current status plus any rows that are new or changed since the last poll, rather than reprinting the full table each time.

A standalone `--watch` call, one that you did not start from `import`, polls until it times out or you press `Ctrl-C`. It does not stop early at a planned count, because Harness only knows that planned count when the import itself is running.

#### Example: migrate several Argo CD AppProjects in one script <a href="#example-migrate-several-argo-cd-appprojects-in-one-script" id="example-migrate-several-argo-cd-appprojects-in-one-script"></a>

The following script chains the commands on this page to discover, map, import, and verify a batch of Argo CD AppProjects without touching the Harness UI.

```sh
# 1. Discover AppProjects on the agent that are not yet mapped to Harness
harness list gitops_argo_project my-agent --level account --format json

# 2. Create the Harness orgs and projects that mappings.yaml will reference
#    (there is no bulk create API, so create orgs and projects one at a time)
harness create org my-org
harness create project my-project --org my-org

# 3. Map the AppProjects to those Harness orgs and projects from a file
harness create gitops_app_project_mapping my-agent --level account -f mappings.yaml

# 4. Import the mapped projects and auto-create their services, environments, and cluster links
harness execute gitops_agent:import my-agent --level account -f import.yaml --watch

# 5. Re-check the auto-create outcome for a specific import later, by its importRequestId
harness list gitops_autocreate_log my-agent --import-request-id <import_request_id> --all --format csv > autocreate-log.csv
```

Step 4 waits inline because of `--watch`, so by the time the script continues, the import has either finished or hit its two-minute timeout. Drop `--watch` and run step 5 on a schedule instead if you would rather poll for completion from outside the script.

***

### Related articles <a href="#related-articles" id="related-articles"></a>

* [Continuous Delivery](/harness-ai/use-harness-cli/harness-cli/harness-cli-commands/cd-and-pipeline-commands.md): Manage pipelines and deployment resources.
* [Code Repository](/harness-ai/use-harness-cli/harness-cli/harness-cli-commands/code-repository-commands.md): Manage the repositories that hold your manifests.
* [Platform](/harness-ai/use-harness-cli/harness-cli/harness-cli-commands/platform-commands.md): Manage connectors and secrets.

{% @harness-feedback/feedback module="harness-ai" pagePath="harness-ai/use-harness-cli/harness-cli/harness-cli-commands/gitops-commands" %}
