# Deploying with CLI \[Build, simulate, and deploy Newton policies with newton-cli, then wire a tested PolicyClient with Foundry and cast]

This guide starts from a scaffolded Newton policy, proves its allow and deny behavior locally, deploys independent Policy contracts, and then wires an existing PolicyClient.

:::warning
Deployment uploads artifacts and sends transactions. Finish local simulation first, review the target chain and transactions, and use a funded testnet signer before broadcasting.
:::

## Prerequisites

* `newton-cli`: `curl -L cli.newton.xyz | sh && newtup`
* A policy created with `newton-cli policy scaffold`
* A tested contract that inherits `NewtonPolicyClient`
* A target chain, funded deployer, and RPC endpoint
* Foundry (`forge` and `cast`) for PolicyClient deployment and wiring

Run the toolchain check before building:

```bash
newtup
newton-cli --version
newton-cli doctor
```

Dashboard login is not required to scaffold, build, or simulate locally.

## Credential handling

Provide deploy credentials through the current process environment or `~/.newton/.env`:

```bash
export CHAIN_ID=11155111
export RPC_URL=https://your-sepolia-rpc.example
export PRIVATE_KEY=0xYourDeploymentKey
```

Do not commit populated credentials or source a project-local `.env`. Never paste private keys, JWTs, API keys, or credential-bearing RPC URLs into chat with a coding agent.

Provide any CLI upload credentials through your secret manager or protected shell environment. Gateway SDK examples use `NEWTON_API_KEY`, a separate application environment-variable name.

## Step 1 — Build the policy

Given a scaffolded directory such as `policies/transfer-limit`:

```bash
newton-cli policy build -p policies/transfer-limit
```

Use the CLI build command instead of invoking `jco componentize` directly. It validates the expected policy files and writes compiled artifacts under `dist/`.

## Step 2 — Simulate allow and deny

Configure `configs/intent.json`, `configs/wasm_args.json`, and `configs/params.json`, then run:

```bash
newton-cli policy simulate -p policies/transfer-limit
```

Run at least one expected allow case and one expected deny case. When the WASM provider calls `getSecrets()`, pass a non-production fixture stored outside tracked source:

```bash
newton-cli policy simulate -p policies/transfer-limit \
  --secrets-file /secure/local-fixtures/transfer-limit-secrets.json
```

Local WASM output is available to Rego under `data.wasm.*`; policy parameters are under `data.params.*`; the transaction intent is `input`.

Do not deploy until both cases match the intended policy.

## Step 3 — Review deployment configuration

`policy scaffold` creates the non-secret file `configs/deployment.toml`. Review its chain and expiration settings before deployment. Environment variables and explicit CLI flags override the file.

The policy directory should now include:

```text
policies/transfer-limit/
  policy.js
  policy.rego
  params_schema.json
  configs/
    deployment.toml
    intent.json
    params.json
    wasm_args.json
  dist/
    policy.wasm
    policy.rego
```

## Step 4 — Deploy each policy

Deploy each independent policy and record its artifact CIDs, code hash, address, receipt, and deployed bytecode.

```bash
newton-cli policy deploy -p policies/transfer-limit
```

### Pure-Rego artifacts

A pure-Rego policy needs no dummy WASM or separately deployed PolicyData contract. The pinned factory takes these fields:

| Field | Value |
|---|---|
| `entrypoint` | The policy's Rego entrypoint |
| `policyCid` | CID of the exact Rego bytes |
| `schemaCid` | Policy parameter schema CID |
| `wasmCid` | Empty string for pure-Rego |
| `secretsSchemaCid` | Empty string for pure-Rego |
| `metadataCid` | Policy metadata CID |
| `owner` | Policy owner address |
| `policyCodeHash` | Keccak-256 of the exact Rego bytes |

For an oracle-backed policy, `wasmCid` and optional `secretsSchemaCid` belong to that Policy contract. Each policy owns at most one WASM module.

:::warning
Mainnet policy usage requires allowlisting by the Newton team. Before deploying or using policies on mainnet, [reach out through the intake form](https://newton.xyz/intake-form).
:::

## Step 5 — Deploy the PolicyClient

The PolicyClient is application code, not something `registerClient` creates. Implement and test it with Foundry first, then deploy it with the local deployer as initial owner:

```bash
forge build
forge test
forge script script/DeployPolicyClient.s.sol:DeployPolicyClient \
  --rpc-url "$RPC_URL" \
  --broadcast
```

Resolve current protocol addresses for the target chain rather than copying constants from an old guide:

```bash
newton-cli --chain-id "$CHAIN_ID" deployments show
```

## Step 6 — Bind policy and parameters

While the local deployer owns the client, replace its complete policy set with one call. Set `POLICY_0`, `POLICY_1`, and the client address to reviewed deployments. Each params file must match its policy schema.

```bash
PARAMS_0=$(cast from-utf8 "$(cat policies/first/configs/params.json)")
PARAMS_1=$(cast from-utf8 "$(cat policies/second/configs/params.json)")
cast send "$POLICY_CLIENT" \
  'setPolicies((address,(bytes,uint32))[])' \
  "[($POLICY_0,($PARAMS_0,25)),($POLICY_1,($PARAMS_1,25))]" \
  --rpc-url "$RPC_URL" --private-key "$PRIVATE_KEY"
cast call "$POLICY_CLIENT" \
  'getPolicySetSnapshot()(bytes32,uint64,(address,(bytes,uint32))[])' \
  --rpc-url "$RPC_URL"
```

The expiry of 25 blocks is illustrative. Choose an application-appropriate window. Record the returned ID, revision, and ordered specs together. Every replacement, including an identical one, advances the revision and invalidates old attestations.

## Step 7 — Transfer ownership for dashboard operations

Gateway secrets and client-scoped live evaluation authorize against `PolicyClient.getOwner()`. If the dashboard login wallet must own the client, transfer after policy binding is complete:

```bash
cast send 0xPOLICY_CLIENT \
  "setPolicyClientOwner(address)" 0xDASHBOARD_LOGIN_WALLET \
  --rpc-url "$RPC_URL" \
  --private-key "$PRIVATE_KEY"
```

Verify `getOwner()` on-chain. `PolicyClientRegistry.setClientOwner` changes the registry record; it is not a substitute for `setPolicyClientOwner` on the contract.

:::warning
After ownership transfer, only the new owner can call `setPolicies`. That owner can replace the complete set and its parameters on the same client; a new client is not required for routine configuration changes.
:::

## Step 8 — Register with the dashboard user (coming soon)

:::note
PolicyClient registration is temporarily omitted from this guide. After [newt-foundation/newton-prover-avs#771](https://github.com/newt-foundation/newton-prover-avs/pull/771) lands in a stable `newton-cli` release, `newton-cli policy-client register` will open the dashboard so the dashboard user can sign and register the client. The exact released command and verification steps will be added here then.
:::

## Step 9 — Upload secrets when used

For oracle-backed policies, verify the Policy contract's `secretsSchemaCid`, client ownership, and schema-valid secrets before upload. Secrets are scoped to the policy address and client. Use [the gateway secrets API](/developers/reference/rpc-api#newt_storeencryptedsecrets) for the selected policy-set release.

Pure-Rego policies skip this step. Keep secrets outside tracked source and never print them while diagnosing uploads.

## Step 10 — Verify before live evaluation

Check these values on-chain:

* PolicyClient TaskManager matches the target Newton deployment
* `getPolicySetSnapshot()` returns the expected nonzero ID, revision, and ordered policies
* Each policy has the intended params and nonzero `expireAfter`
* `getOwner()` is the expected wallet
* Registry record matches the dashboard user when registration is available and required
* Client-scoped secrets exist when the WASM provider requires them

Use `@newton-xyz/sdk` `evaluateIntentDirect` for a live direct-attestation flow. The browser wallet signs the exact EIP-712 intent; a server Route Handler supplies `NEWTON_API_KEY`. See [Frontend SDK Integration](/developers/guides/frontend-sdk-integration).

After the first live evaluation, confirm the task was recorded against the right PolicyClient with the [Explorer API](/developers/reference/explorer-api), using the same `NEWTON_API_KEY`:

```bash
curl -sS https://explorer.api.newton.xyz/v1/task/$TASK_ID \
  -H "Authorization: Bearer $NEWTON_API_KEY" \
  -H "X-Protocol-Network: testnet" \
  | jq '{policy_client_address, policy_id, evaluation_result, error}'
```

`policy_client_address` and `policy_id` should match what you bound in Step 6.

## Agent-assisted deployment

Newton Agent Skills automate the same local-first sequence and preserve policy and client state in handoff files. They still pause before uploads, broadcasts, ownership transfer, dashboard registration when available, gateway evaluation, and the first attested application transaction.

<Card icon="terminal" to="/developers/overview/agent-quickstart" title="Build with an Agent">
  Start from a product brief and review each live checkpoint
</Card>

<Card icon="shield" to="/developers/guides/smart-contract-integration" title="Smart Contract Integration">
  Implement and test the PolicyClient before deployment
</Card>

<Card icon="window" to="/developers/guides/frontend-sdk-integration" title="Frontend SDK Integration">
  Sign in the browser, evaluate on the server, and submit only on allow
</Card>
