<!-- [![Acurast Banner](.banner.png)](https://acurast.com) -->

<h2 align="center">Acurast CLI</h2>

<p align="center">
  <em>
    Deploy apps on the Acurast Cloud
  </em>
</p>

<p align="center">
  <a href="https://github.com/acurast/acurast-cli/actions?query=workflow%3AProd+branch%3Amain">
    <img alt="Github Actions Build Status" src="https://img.shields.io/github/actions/workflow/status/acurast/acurast-cli/build.yml?label=Prod&style=flat-square"></a>
  <a href="https://www.npmjs.com/package/@acurast/cli">
    <img alt="npm version" src="https://img.shields.io/npm/v/@acurast/cli.svg?style=flat-square"></a>
  <a href="https://www.npmjs.com/package/@acurast/cli">
    <img alt="weekly downloads from npm" src="https://img.shields.io/npm/dw/@acurast/cli.svg?style=flat-square"></a>
  <a href="#badge">
    <img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"></a>
  <a href="https://twitter.com/Acurast">
    <img alt="Follow Acurast on Twitter" src="https://img.shields.io/badge/%40Acurast-9f9f9f?style=flat-square&logo=x&labelColor=555"></a>
</p>

## Intro

The Acurast CLI helps you to deploy apps on the Acurast Cloud.

## Installation

To install the Acurast CLI, you can use npm:

```bash
npm install -g @acurast/cli
```

## Usage

To use the Acurast CLI, type `acurast` followed by any of the available options or commands.

### Options

- `-v`, `--version` - Output the version number.
- `-h`, `--help` - Display help for command.

### Commands

- `new <project-name>` - Create a new Acurast project from a template.
- `deploy [options] [project]` - Deploy the current project to the Acurast platform.
- `deploy vps [options]` - Deploy an SSH-able VPS on an Acurast processor (see [Deploy a VPS](#deploy-a-vps)).
- `cancel <deployment-id> [options]` - Cancel (deregister) a deployment on-chain and return any unused locked funds.
- `estimate-fee [options] [project]` - Estimate the fee for the current project.
- `deployments [arg] [options]` - List, view, and manage deployments.
  - `deployments ls` or `deployments list` - List all your deployments.
  - `deployments <id>` - View details of a specific deployment.
  - `deployments <id> --update-env-vars` - Update environment variables for a deployment.
  - `deployments --cleanup` - Clean up old, finished deployments.
  - `deployments <id> --cleanup` - Clean up a specific deployment.
  - `deployments update script <deployment-id> <script-ipfs> [options]` - Update the script of a mutable deployment.
  - `deployments update editor <deployment-id> <new-editor-address> [options]` - Transfer editor permissions for a mutable deployment.
- `live [options] [project]` - Setup a "live-code-processor" and run your project on the processor in real time.
- `init` - Create an acurast.json file and .env file.
- `devtools <deployment-id>` - Request a DevTools view key and print the URL for a deployment.
- `open` - Open the Acurast resources in your browser.
- `help [command]` - Display help for command.

## Configuration

### Example Configuration

The acurast.json file is generated by running acurast init. Here is an example configuration:

```json
{
  "projects": {
    "example": {
      "projectName": "example",
      "fileUrl": "dist/bundle.js",
      "network": "mainnet",
      "onlyAttestedDevices": true,
      "enableDevtools": false,
      "assignmentStrategy": {
        "type": "Single"
      },
      "execution": {
        "type": "onetime",
        "maxExecutionTimeInMs": 10000
      },
      "maxAllowedStartDelayInMs": 10000,
      "usageLimit": {
        "maxMemory": 0,
        "maxNetworkRequests": 0,
        "maxStorage": 0
      },
      "numberOfReplicas": 64,
      "requiredModules": [],
      "minProcessorReputation": 0,
      "maxCostPerExecution": 100000000000,
      "includeEnvironmentVariables": [],
      "processorWhitelist": [],
      "mutability": "Immutable",
      "reuseKeysFrom": null
    }
  }
}
```

This is the configuration that is read when `acurast deploy` is called and the app is deployed according to those parameters.

Additionaly, a `.env` file is generated that will hold some of the secrets to deploy the app, and also any environmnet variables that you may want to add to your deployment.

```
ACURAST_MNEMONIC=abandon abandon about ...
# ACURAST_IPFS_URL=https://api.pinata.cloud
# ACURAST_IPFS_API_KEY=eyJhb...
# ACURAST_RPC=wss://...
```

### Configuration Details

#### acurast.json

- `projectName`: The name of the project.
- `fileUrl`: The path to the bundled file, including all dependencies (e.g., `dist/bundle.js`).
- `network`: The network on which the project will be deployed. One of `mainnet`, `canary`, or `devnet`. See [Networks](#networks) for endpoint defaults and how to override them via env vars.
- `onlyAttestedDevices`: A boolean to specify if only attested devices are allowed to run the app.
- `enableDevtools`: A boolean to enable [DevTools](#devtools) for the deployment. When enabled, console logs from processor executions are forwarded to the DevTools dashboard. Defaults to `false`.
- `startAt`: The start time of the deployment.
  - `msFromNow`: The deployment will start the specified number of milliseconds from now.
  - `timestamp`: The deployment will start at the specified timestamp.
- `assignmentStrategy`: Defines the assignment strategy, which can be:
  - `type`: `AssignmentStrategyVariant.Single`: Assigns one set of processors for a deployment. If instantMatch is provided, specifies processors and maximum allowed start delay:
    - `processor`: Processor address.
    - `maxAllowedStartDelayInMs`: Maximum allowed start delay in milliseconds.
    - See [Instant match](#instant-match) for a full example; the repository’s `acurast.json` also defines a `test-instant-match` project you can copy from.
  - `type`: `AssignmentStrategyVariant.Competing`: Assigns a new set of processors for each execution.
- `execution`: Specifies the execution details, which can be:
  - `type`: 'onetime'`: Run the deployment only once.
    - `maxExecutionTimeInMs`: Maximum execution time in milliseconds.
  - `type`: 'interval'`: Multiple executions for the deployment.
    - `intervalInMs`: Interval in milliseconds between each execution start.
    - `numberOfExecutions`: The number of executions.
    - `maxExecutionTimeInMs`: Maximum execution time for each execution in milliseconds. If not specified, the full duration of the interval will be used (minus a 10s buffer). It is recommended to set this to at least 10s less than `intervalInMs`.
    - `maxAllowedStartDelayInMs`: Specifies the maximum allowed start delay (relative to the starting time) of the deployment in milliseconds.
- `usageLimit`: The usage limits for the deployment:
  - `maxMemory`: Maximum memory usage in bytes.
  - `maxNetworkRequests`: Maximum number of network requests.
  - `maxStorage`: Maximum storage usage in bytes.
- `numberOfReplicas`: The number of replicas, specifying how many processors will run the deployment in parallel.
- `requiredModules`: Modules that the processor needs to support to run the deployment. Supported values: `"DataEncryption"`, `"LLM"`, `"Shell"`. Defaults to `[]`. When `runtime` is `"Shell"`, `"Shell"` is auto-injected.
- `runtime`: The runtime environment used to execute the deployment.
  - `"NodeJSWithBundle"` (default): Node.js, bundled file deployment.
  - `"NodeJS"`: Node.js, single-file deployment.
  - `"Shell"`: Native binary inside a Linux distro image, isolated via PRoot. See [Shell Runtime](#shell-runtime).
- `image`: Linux distro image used by the Shell runtime. Required when `runtime` is `"Shell"`. Ignored otherwise.
  - `url`: HTTPS URL of a `.tar.xz` distro image (see [Termux proot-distro](https://github.com/termux/proot-distro) for supported images).
  - `sha256`: SHA256 hash of the image, used by the processor to verify the download.
- `minProcessorReputation`: The minimum required reputation of the processor.
- `maxCostPerExecution`: The maximum cost per execution in the smallest denomination of ACU.
- `includeEnvironmentVariables`: An array of environment variables in the .env file that will be passed to the deployment.
- `processorWhitelist`: A whitelist of processors that can be used for the deployment.
- `minProcessorVersions`: The minimum processor versions that will be used for the deployment.
  - `android`: The minimum Android version.
  - `ios`: The minimum iOS version.
- `mutability`: The mutability of the deployment. Controls whether the deployment can be modified after creation.
  - `"Immutable"`: The deployment cannot be modified after creation (default).
  - `"Mutable"`: The deployment can be modified after creation.
- `reuseKeysFrom`: An optional array that allows reusing keys from a previous deployment, if that deployment was set to "Mutable". Format: `[MultiOrigin, string, number]` where:
  - First element: The origin chain (currently only `"Acurast"` is supported)
  - Second element: The address of the original deployer
  - Third element: The deployment ID
  - Example: `["Acurast", "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", 123456]`
- `benchmarkFilters` (optional): Minimum benchmark requirements used to filter eligible processors.
  - `minRamTotalBytes`: Minimum total RAM in bytes.
  - `minCpuSingleCoreScore`: Minimum single-core CPU score.
  - `minCpuMultiCoreScore`: Minimum multi-core CPU score.
  - `minStorageAvailBytes`: Minimum available storage in bytes.
  - `poolIds` (advanced): Override compute-pallet benchmark pool IDs.

### Benchmark Filters

You can constrain deployments to processors that satisfy minimum benchmark values.
Benchmark filters can be configured in `acurast.json` and/or passed via deploy flags.

Config example:

```json
{
  "projects": {
    "example": {
      "benchmarkFilters": {
        "minRamTotalBytes": 4000000000,
        "minCpuSingleCoreScore": 1000,
        "minCpuMultiCoreScore": 3000,
        "minStorageAvailBytes": 64000000000
      }
    }
  }
}
```

Deploy flag examples (can be combined):

```bash
acurast deploy --min-memory 4GB --min-cpu-score 1000 --min-storage 64GB --min-cpu-multi-score 3000
```

Notes:

- CLI flags merge with `benchmarkFilters` from `acurast.json`.
- `--min-memory` and `--min-storage` accept human-readable byte sizes (for example `4GB`, `512MiB`).
- During deploy, matcher `check` validates whether enough processors match at the current reward.
- Per-processor address lists are shown from on-chain `acurastMarketplace.assignedProcessors` after match.

#### .env

`ACURAST_MNEMONIC`: The mnemonic used to deploy the app. Make sure the account has some ACU (or cACU for canary network)! You can claim cACU on the [faucet](https://faucet.acurast.com) for canary testing.
`ACURAST_IPFS_URL` (optional): The URL of the IPFS gateway, eg. `https://api.pinata.cloud`.
`ACURAST_IPFS_API_KEY` (optional): The API key to access the IPFS gateway. You can [register here](https://pinata.cloud/) to get an API key.
`ACURAST_RPC` (optional, deprecated): Set an RPC URL to connect to. Kept for backward compatibility — prefer `ACURAST_MAINNET_RPC`.

#### Networks

The CLI supports three networks: `mainnet` (default), `canary`, and `devnet`. Set `"network"` in your `acurast.json` project entry, or pass `--network` to commands that accept it (`acurast deployments ...`).

Each network resolves an RPC endpoint, a matcher URL, and an indexer (with API key). The defaults below ship with the CLI; set the matching env var to override.

| Network | Purpose                          | RPC default                                           | Faucet                       |
| ------- | -------------------------------- | ----------------------------------------------------- | ---------------------------- |
| mainnet | Production, real ACU             | `wss://archive.mainnet.acurast.com`                   | n/a (see docs to get ACU)    |
| canary  | Public test network              | `wss://canarynet-ws-1.acurast-h-server-2.papers.tech` | `https://faucet.acurast.com` |
| devnet  | Internal/staging dev environment | `wss://acurast-devnet-ws.prod.gke.papers.tech`        | n/a (request from Acurast)   |

##### RPC overrides

| Env var               | Network applied to | Default                                                  |
| --------------------- | ------------------ | -------------------------------------------------------- |
| `ACURAST_MAINNET_RPC` | mainnet            | `wss://archive.mainnet.acurast.com`                      |
| `ACURAST_RPC`         | mainnet (legacy)   | same as above; honoured when `ACURAST_MAINNET_RPC` unset |
| `ACURAST_CANARY_RPC`  | canary             | `wss://canarynet-ws-1.acurast-h-server-2.papers.tech`    |
| `ACURAST_DEVNET_RPC`  | devnet             | `wss://acurast-devnet-ws.prod.gke.papers.tech`           |

The connected RPC URL is written to `.acurast/acurast.log` (file log) on every connection — useful when debugging which endpoint a command actually used.

##### Matcher overrides

The matcher API provides live processor pricing. If unset (or unreachable), the CLI falls back to a static fee estimate.

| Env var                   | Network | Default                                             |
| ------------------------- | ------- | --------------------------------------------------- |
| `ACURAST_MAINNET_MATCHER` | mainnet | `https://matcher.mainnet.acurast.com`               |
| `ACURAST_CANARY_MATCHER`  | canary  | `https://matcher.canary.acurast.com`                |
| `ACURAST_DEVNET_MATCHER`  | devnet  | _unset_ — set this if a devnet matcher is available |

##### Indexer overrides

The indexer powers `acurast deployments ls`. Devnet has no public default — set the env vars below if you need to list deployments on devnet.

| Env var                           | Network | Default                                                  |
| --------------------------------- | ------- | -------------------------------------------------------- |
| `ACURAST_MAINNET_INDEXER`         | mainnet | `https://dev.indexer.mainnet.acurast.com/api/v1/rpc`     |
| `ACURAST_MAINNET_INDEXER_API_KEY` | mainnet | _shipped default_                                        |
| `ACURAST_CANARY_INDEXER`          | canary  | `https://dev.indexer.canary.acurast.com/api/v1/rpc`      |
| `ACURAST_CANARY_INDEXER_API_KEY`  | canary  | _shipped default_                                        |
| `ACURAST_DEVNET_INDEXER`          | devnet  | _unset — required for `deployments ls --network devnet`_ |
| `ACURAST_DEVNET_INDEXER_API_KEY`  | devnet  | _unset_                                                  |

##### Example `.env` for devnet

```
ACURAST_MNEMONIC=abandon abandon about ...
ACURAST_DEVNET_RPC=wss://acurast-devnet-ws.prod.gke.papers.tech
ACURAST_DEVNET_MATCHER=https://matcher.devnet.acurast.com
ACURAST_DEVNET_INDEXER=https://dev.indexer.devnet.acurast.com/api/v1/rpc
ACURAST_DEVNET_INDEXER_API_KEY=<your-key>
```

Then in `acurast.json` set `"network": "devnet"` on the project entry.

## Deploy a VPS

`acurast deploy vps` turns a processor into an SSH-able "VPS": it deploys the pinned tunnel bundle from [`@acurast/vps`](https://github.com/Acurast/acurast-typescript-sdk/tree/main/packages/acurast-vps), which runs an Ubuntu rootfs, starts a [Dropbear](https://github.com/mkj/dropbear) SSH server and exposes it through the Acurast reverse tunnel. No `acurast.json` is needed, and nothing is uploaded to IPFS — the bundle is already pinned.

The tunnel keypair is generated locally, so the SSH hostname is known before the deployment even starts: the CLI prints it upfront, waits for the VPS to boot and then prints the ready-to-paste SSH connect command.

```bash
acurast deploy vps \
  --min-memory 2GB \
  --min-storage 10GB \
  --min-compute-score 100 \
  --authorized-ssh-key "ssh-ed25519 AAAA... user@host" \
  --duration 24h
```

Running `acurast deploy vps` without flags starts an interactive wizard that asks for anything missing. `ACURAST_MNEMONIC` must be set (or use `acurast login` for remote signing).

### Options

| Flag                       | Env var                      | Description                                                                                             |
| -------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------- |
| `--image <alias>`           | `VPS_IMAGE`                  | Image preset. Currently `ubuntu` (25.10, proot-distro rootfs, aarch64).                                  |
| `--min-memory <size>`       | `VPS_MIN_MEMORY`             | Minimum total RAM of the processor (e.g. `2GB`).                                                        |
| `--min-storage <size>`      | `VPS_MIN_STORAGE`            | Minimum available storage (e.g. `10GB`).                                                                |
| `--min-compute-score <n>`   | `VPS_MIN_COMPUTE_SCORE`      | Minimum CPU single-core benchmark score.                                                                |
| `--min-cpu-multi-score <n>` | `VPS_MIN_CPU_MULTI_SCORE`    | Minimum CPU multi-core benchmark score.                                                                 |
| `--authorized-ssh-key <k>`  | `VPS_AUTHORIZED_SSH_KEY`     | SSH public key appended to `/root/.ssh/authorized_keys`. Required — the VPS is key-auth only.           |
| `--duration <dur>`          | `VPS_DURATION`               | How long the VPS runs (e.g. `1h`, `24h`, `2d`). Default `24h`.                                          |
| `--callback-url <url>`      | `VPS_CALLBACK_URL`           | Optional webhook receiving `log`/`started`/`error` events as JSON.                                      |
| `--http-port <port>`        | `VPS_HTTP_PORT`              | Also serve plain HTTP from this VPS port on the same tunnel subdomain (>= 1024).                        |
| `--network <net>`           | `VPS_NETWORK`                | `mainnet`, `canary` (default) or `devnet`.                                                              |
| `--max-cost-per-execution`  | `VPS_MAX_COST_PER_EXECUTION` | Reward per execution in the smallest token unit.                                                        |

Flags win over `VPS_*` environment variables (which can live in your `.env`); the wizard only asks for values that neither provides. At the end of the wizard the CLI offers to save your answers to `.env` as `VPS_*` variables, so subsequent runs skip the questions. `--dry-run`, `--non-interactive`, `--exit-early` and `--output json` work like they do for `acurast deploy`.

### Connecting

The tunnel keypair is generated locally and the clientId (the subdomain) is derived from it, so the CLI knows the hostname upfront — it is shown in the deploy summary as `https://<clientId>.<domain>`. After the deployment is submitted, the CLI polls the tunnel until Dropbear answers and then prints the connect command:

```
ssh -o ProxyCommand='openssl s_client -quiet -servername <clientId>.<domain> -connect <clientId>.<domain>:443' root@<clientId>.<domain>
```

SSH is wrapped in TLS behind the tunnel's Let's Encrypt certificate. With `--exit-early` the CLI prints the connect command without waiting. `--callback-url` is optional and additionally delivers `log`/`started`/`error` events to your webhook. With `--http-port`, the same subdomain also serves plain HTTP from that VPS port (protocol multiplexing via sslh).

Requires processors running Acurast v1.26.0 or later (`minProcessorVersions.android` is set automatically).

## Live Code Feature

For easier development of acurast deployments, we added a feature that we call "Live Code". To use this feature, you can dedicate one or multiple processors to run a piece of code for an extended period of time, which can then on-demand execute your code and return the result. This makes development and debugging a lot faster because you can see console.logs and errors.

To get started, you first have to set up a processor to run the live-code deployment. You can do this by running

```
acurast live --setup
```

During setup, you can choose the duration of the deployment.

Follow the instructions in the CLI. There is currently a step where a public key has to be manually copy/pasted from the web-console. This step will soon be fully automated.

After the deployment has started (after 5 minutes), you can then run

```
acurast live
```

This will run your project in the live-processor. It will use the same configuration that was set up during the `acurast init` step.

## Environment Variables

You can use environment variables in Acurast depoyments. The environment variables that are encrypted during deployment and only decrypted when the code is run on the processor. This is useful for storing sensitive information like API keys.

To use environment variables in your project, you first need to add them to the `.env` file like this:

```text
API_KEY=your-api-key
```

To configure which of your deployments make use of the environment variables, edit the `acurast.json` file and add all the environment variables to be included to the `includeEnvironmentVariables` array.

```json
{
  "projects": {
    "tutorial": {
      "projectName": "tutorial",
      "fileUrl": "dist/bundle.js",
      "network": "mainnet",
      "onlyAttestedDevices": true,
      "assignmentStrategy": {
        "type": "Single"
      },
      "execution": {
        "type": "onetime",
        "maxExecutionTimeInMs": 60000
      },
      "maxAllowedStartDelayInMs": 10000,
      "usageLimit": {
        "maxMemory": 0,
        "maxNetworkRequests": 0,
        "maxStorage": 0
      },
      "numberOfReplicas": 1,
      "requiredModules": [],
      "minProcessorReputation": 0,
      "maxCostPerExecution": 1000000000,
      "includeEnvironmentVariables": ["API_KEY"],
      "processorWhitelist": []
    }
  }
}
```

Then, in your code, you can access the environment variables like this:

```typescript
const API_KEY = _STD_.env[API_KEY]
```

When running `acurast deploy`, the environment variables will now automatically be added to the deployment.

When running interval based deployments with multiple executions, the environment variables can be updated between executions. To do that, update the `.env` file and run `acurast deployments <id> -e`. This will update the environment variables for the deployment with the given ID.

## DevTools

Acurast DevTools lets you see live `console.log`, `console.warn`, `console.error`, `console.info`, and `console.debug` output from your processors in a web dashboard.

### Setup

Add `"enableDevtools": true` to your project config in `acurast.json`:

```json
{
  "projects": {
    "my-project": {
      "projectName": "my-project",
      "fileUrl": "dist/bundle.js",
      "enableDevtools": true,
      ...
    }
  }
}
```

Then deploy as usual with `acurast deploy my-project`. After deployment, the CLI prints a DevTools URL with a view key — open it to see your logs.

### Requesting a new view key

View keys are time-limited. If yours has expired, request a new one:

```bash
acurast devtools <deployment-id>
```

### Privacy

Logs are only accessible with a valid view key. The key is scoped to the specific deployment and only the deployment owner can request new keys.

### Environment variables

| Variable                   | Default                            | Description           |
| -------------------------- | ---------------------------------- | --------------------- |
| `ACURAST_DEVTOOLS_URL`     | `https://devtools.acurast.com`     | DevTools frontend URL |
| `ACURAST_DEVTOOLS_API_URL` | `https://api.devtools.acurast.com` | DevTools API URL      |

## Deployment Management

The Acurast CLI provides comprehensive deployment management capabilities, including the ability to update mutable deployments and transfer editor permissions.

### Basic Deployment Commands

```bash
# List all deployments (mainnet)
acurast deployments ls

# List all deployments on canary network
acurast deployments ls --network canary

# View a specific deployment
acurast deployments 123456

# Update environment variables for a deployment
acurast deployments 123456 --update-env-vars

# Clean up old deployments
acurast deployments --cleanup

# Clean up old deployments on canary network
acurast deployments --cleanup --network canary

# Clean up a specific deployment
acurast deployments 123456 --cleanup

# Cancel a deployment (deregister on-chain; same extrinsic as cleanup for a single job)
acurast cancel 123456

# Cancel on canary when no local deployment file exists
acurast cancel 123456 --network canary
```

**Options**:

- `-n, --network <network>`: Network to use (`mainnet`, `canary`, or `devnet`). Defaults to `mainnet`. When working with a specific deployment ID, the network is automatically detected from the deployment file if available. Devnet requires `ACURAST_DEVNET_INDEXER` (and optional API key) for `ls`/`cleanup` flows.
- `-e, --update-env-vars`: Update environment variables for a deployment.
- `-c, --cleanup`: Remove old, finished deployments and return unused funds.

### Updating Mutable Deployments

For deployments that were created with `"mutability": "Mutable"`, you can update the script and transfer editor permissions.

#### Update Deployment Script

**Command**: `acurast deployments update script <deployment-id> <script-ipfs> [options]`

**Arguments**:

- `<deployment-id>`: The deployment ID in format `"origin:address:number"` (e.g., `"Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456"`)
- `<script-ipfs>`: IPFS hash of the new script (e.g., `"ipfs://QmNewScriptHash"`)

**Options**:

- `--dry-run`: Preview the update without applying
- `--force`: Skip confirmation prompts

**Examples**:

```bash
# Update script (dry run)
acurast deployments update script "Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456" "ipfs://QmNewScriptHash" --dry-run

# Update script (actual)
acurast deployments update script "Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456" "ipfs://QmNewScriptHash"
```

**Requirements**:

- The deployment must have `"mutability": "Mutable"`
- You must be the current editor of the deployment
- The script must be uploaded to IPFS and provided as an IPFS hash

#### Transfer Editor Permissions

**Command**: `acurast deployments update editor <deployment-id> <new-editor-address> [options]`

**Arguments**:

- `<deployment-id>`: The deployment ID in format `"origin:address:number"` (e.g., `"Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456"`)
- `<new-editor-address>`: The AccountId32 address of the new editor

**Options**:

- `--dry-run`: Preview the transfer without executing
- `--force`: Skip confirmation prompts

**Examples**:

```bash
# Transfer editor permissions (dry run)
acurast deployments update editor "Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456" "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL" --dry-run

# Transfer editor permissions (actual)
acurast deployments update editor "Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456" "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL"
```

**Requirements**:

- The deployment must have `"mutability": "Mutable"`
- You must be the current editor of the deployment
- The new editor address must be a valid AccountId32 format

### Deployment ID Format

The deployment ID is a unique identifier for each deployment on the Acurast platform. It follows the format:

```
"origin:address:number"
```

**Components**:

- **`origin`**: The chain name where the deployment was created
  - Currently only `"Acurast"` is supported
  - This is case-sensitive
- **`address`**: The AccountId32 address of the original deployer
  - Must be a valid Substrate AccountId32 format (e.g., `5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL`)
  - This is the address that deployed the job initially
- **`number`**: The deployment number (u128)
  - This is a sequential number assigned by the blockchain
  - Must be a positive integer

**Examples**:

```bash
# Valid deployment IDs
"Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123456"
"Acurast:5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY:1"
"Acurast:5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty:999999"

# Invalid deployment IDs
"Acurast:invalid-address:123"  # Invalid address format
"acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:123"  # Wrong case
"Acurast:5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL:-1"  # Negative number
```

**Usage**:

- **All deployment operations** require the full deployment ID format: `"origin:address:number"`
- **Configuration** (reuseKeysFrom): You must use the full format as an array

**Finding your deployment ID**:

1. Run `acurast deployments ls` to see all your deployments
2. The deployment ID will be displayed in the list
3. For advanced operations, use the full format shown in the list

### Validation and Error Handling

The CLI provides comprehensive validation for all deployment management commands:

- **Deployment ID validation**: Ensures proper format and valid components
- **Address validation**: Verifies AccountId32 format for all addresses
- **IPFS hash validation**: Ensures scripts are provided as valid IPFS hashes
- **Permission validation**: Checks that you have the necessary permissions
- **Mutability validation**: Ensures the deployment is mutable before allowing updates

### Safety Features

- **Dry-run mode**: Preview changes before applying them
- **Confirmation prompts**: Require explicit confirmation for destructive operations
- **Error messages**: Clear, descriptive error messages for validation failures
- **Transaction feedback**: Display transaction hashes for successful operations

## Deployment Features

### Mutability

The `mutability` field controls whether a deployment can be modified after it has been created:

- **`"Immutable"`** (default): The deployment cannot be modified after creation. This is the recommended setting for production deployments as it ensures consistency and prevents harmful changes.

- **`"Mutable"`**: The deployment can be modified after creation. This is an advanced feature and should only be used with careful consideration because misuse could result in harmful updates.

### Key Reuse

The `reuseKeysFrom` field allows you to reuse keys from a previous deployment. This is useful when you want to maintain the same cryptographic keys across deployments. To use this, the referenced deployment has to be "Mutable".

**Format**: `[MultiOrigin, string, number]`

- **First element**: The origin chain (currently only `"Acurast"` is supported)
- **Second element**: The address of the original deployer (AccountId32 format)
- **Third element**: The deployment ID (u128 number)

**Example**:

```json
{
  "reuseKeysFrom": [
    "Acurast",
    "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL",
    123456
  ]
}
```

### Instant match

When `assignmentStrategy.type` is `Single`, you can set `assignmentStrategy.instantMatch` to pin planned executions to specific processors (each entry maps to a processor account and a per-entry maximum start delay). Replace the `processor` value with your processor’s SS58 address on the network you deploy to. The example address below is only a placeholder for the correct format.

If `instantMatch` is non-empty, `acurast deploy` skips the market pricing check for that project, since matching is explicit.

```json
{
  "projects": {
    "my-instant-match-project": {
      "projectName": "my-instant-match-project",
      "fileUrl": "examples/canary-test.js",
      "network": "canary",
      "onlyAttestedDevices": true,
      "assignmentStrategy": {
        "type": "Single",
        "instantMatch": [
          {
            "processor": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL",
            "maxAllowedStartDelayInMs": 10000
          }
        ]
      },
      "execution": { "type": "onetime", "maxExecutionTimeInMs": 60000 },
      "maxAllowedStartDelayInMs": 10000,
      "usageLimit": {
        "maxMemory": 0,
        "maxNetworkRequests": 0,
        "maxStorage": 0
      },
      "numberOfReplicas": 1,
      "maxCostPerExecution": 1000000000
    }
  }
}
```

### Shell Runtime

The Shell runtime runs your deployment as a native binary inside a Linux distro image on the processor (PRoot-isolated). This unlocks shell scripts, native tooling, and any language you can ship as a Linux binary.

To use it, set `runtime` to `"Shell"` and provide an `image` (URL + SHA256). The CLI embeds the image reference in `manifest.json` and auto-adds the `"Shell"` required module on-chain.

```json
{
  "projects": {
    "my-shell-project": {
      "projectName": "my-shell-project",
      "fileUrl": "./shell-app",
      "entrypoint": "acurast.sh",
      "runtime": "Shell",
      "image": {
        "url": "https://github.com/termux/proot-distro/releases/download/v4.30.1/ubuntu-questing-aarch64-pd-v4.30.1.tar.xz",
        "sha256": "5ab35b90cd9a9f180656261ba400a135c4c01c2da4b74522118342f985c2d328"
      },
      "restartPolicy": "no",
      "network": "canary",
      "onlyAttestedDevices": true,
      "assignmentStrategy": { "type": "Single" },
      "execution": { "type": "onetime", "maxExecutionTimeInMs": 60000 },
      "maxAllowedStartDelayInMs": 10000,
      "usageLimit": {
        "maxMemory": 0,
        "maxNetworkRequests": 0,
        "maxStorage": 0
      },
      "numberOfReplicas": 1,
      "requiredModules": [],
      "minProcessorReputation": 0,
      "maxCostPerExecution": 5000000000,
      "includeEnvironmentVariables": [],
      "processorWhitelist": []
    }
  }
}
```

The `entrypoint` is the script or binary the processor runs after extracting the image. Environment variables declared in `includeEnvironmentVariables` are injected as standard system env vars (no `_STD_` API). Host services (deployment metadata, signing, browser control) are exposed via a JSON-RPC API on an abstract Unix socket whose name is in the `BRIDGE_SOCKET` env var.

## Development

To contribute to the development of Acurast CLI, follow these steps:

Clone the repository:

```bash
git clone https://github.com/acurast/acurast-cli.git
```

Navigate to the project directory:

```bash
cd acurast-cli
```

Install the dependencies:

```bash
npm install
```

After making your changes, you can run tests using:

```bash
npm run test
```

To test your changes locally:

```bash
npm run setup
```

After this command, `acurast` will be available globally on your computer.

## Contributing

Contributions are welcome! Please fork the repository and submit a pull request.
