@ar.io/deploy 0.1.0-alpha.20260610213851.5857f96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +753 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.js +5 -0
  5. package/dist/chunks/cache-C1tEeUx2.js +6 -0
  6. package/dist/chunks/cache-C1tEeUx2.js.map +1 -0
  7. package/dist/chunks/display-DRcjDj9k.js +104 -0
  8. package/dist/chunks/display-DRcjDj9k.js.map +1 -0
  9. package/dist/chunks/upload-workflow-DSS5FIa5.js +204 -0
  10. package/dist/chunks/upload-workflow-DSS5FIa5.js.map +1 -0
  11. package/dist/chunks/uploader-B2tC-1Qw.js +472 -0
  12. package/dist/chunks/uploader-B2tC-1Qw.js.map +1 -0
  13. package/dist/commands/deploy.js +238 -0
  14. package/dist/commands/deploy.js.map +1 -0
  15. package/dist/commands/upload.js +126 -0
  16. package/dist/commands/upload.js.map +1 -0
  17. package/dist/constants/flags.js +268 -0
  18. package/dist/constants/flags.js.map +1 -0
  19. package/dist/index.js +2 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/prompts/arns.js +86 -0
  22. package/dist/prompts/arns.js.map +1 -0
  23. package/dist/prompts/deployment.js +27 -0
  24. package/dist/prompts/deployment.js.map +1 -0
  25. package/dist/prompts/wallet.js +55 -0
  26. package/dist/prompts/wallet.js.map +1 -0
  27. package/dist/src/commands/deploy.d.ts +9 -0
  28. package/dist/src/commands/deploy.d.ts.map +1 -0
  29. package/dist/src/commands/upload.d.ts +9 -0
  30. package/dist/src/commands/upload.d.ts.map +1 -0
  31. package/dist/src/constants/cache.d.ts +4 -0
  32. package/dist/src/constants/cache.d.ts.map +1 -0
  33. package/dist/src/constants/flags.d.ts +132 -0
  34. package/dist/src/constants/flags.d.ts.map +1 -0
  35. package/dist/src/index.d.ts +2 -0
  36. package/dist/src/index.d.ts.map +1 -0
  37. package/dist/src/prompts/arns.d.ts +14 -0
  38. package/dist/src/prompts/arns.d.ts.map +1 -0
  39. package/dist/src/prompts/deployment.d.ts +6 -0
  40. package/dist/src/prompts/deployment.d.ts.map +1 -0
  41. package/dist/src/prompts/wallet.d.ts +26 -0
  42. package/dist/src/prompts/wallet.d.ts.map +1 -0
  43. package/dist/src/types/index.d.ts +31 -0
  44. package/dist/src/types/index.d.ts.map +1 -0
  45. package/dist/src/utils/__tests__/cache.test.d.ts +2 -0
  46. package/dist/src/utils/__tests__/cache.test.d.ts.map +1 -0
  47. package/dist/src/utils/__tests__/constants.test.d.ts +2 -0
  48. package/dist/src/utils/__tests__/constants.test.d.ts.map +1 -0
  49. package/dist/src/utils/__tests__/display.test.d.ts +2 -0
  50. package/dist/src/utils/__tests__/display.test.d.ts.map +1 -0
  51. package/dist/src/utils/cache.d.ts +48 -0
  52. package/dist/src/utils/cache.d.ts.map +1 -0
  53. package/dist/src/utils/chalk.d.ts +9 -0
  54. package/dist/src/utils/chalk.d.ts.map +1 -0
  55. package/dist/src/utils/config-resolver.d.ts +72 -0
  56. package/dist/src/utils/config-resolver.d.ts.map +1 -0
  57. package/dist/src/utils/constants.d.ts +4 -0
  58. package/dist/src/utils/constants.d.ts.map +1 -0
  59. package/dist/src/utils/deploy-key.d.ts +15 -0
  60. package/dist/src/utils/deploy-key.d.ts.map +1 -0
  61. package/dist/src/utils/display.d.ts +7 -0
  62. package/dist/src/utils/display.d.ts.map +1 -0
  63. package/dist/src/utils/path.d.ts +5 -0
  64. package/dist/src/utils/path.d.ts.map +1 -0
  65. package/dist/src/utils/signer.d.ts +19 -0
  66. package/dist/src/utils/signer.d.ts.map +1 -0
  67. package/dist/src/utils/solana.d.ts +29 -0
  68. package/dist/src/utils/solana.d.ts.map +1 -0
  69. package/dist/src/utils/upload-types.d.ts +35 -0
  70. package/dist/src/utils/upload-types.d.ts.map +1 -0
  71. package/dist/src/utils/uploader.d.ts +50 -0
  72. package/dist/src/utils/uploader.d.ts.map +1 -0
  73. package/dist/src/utils/validators.d.ts +21 -0
  74. package/dist/src/utils/validators.d.ts.map +1 -0
  75. package/dist/src/workflows/upload-workflow.d.ts +28 -0
  76. package/dist/src/workflows/upload-workflow.d.ts.map +1 -0
  77. package/dist/tests/constants.d.ts +11 -0
  78. package/dist/tests/constants.d.ts.map +1 -0
  79. package/dist/tests/e2e/deploy-command.test.d.ts +2 -0
  80. package/dist/tests/e2e/deploy-command.test.d.ts.map +1 -0
  81. package/dist/tests/global-setup.d.ts +6 -0
  82. package/dist/tests/global-setup.d.ts.map +1 -0
  83. package/dist/tests/mocks/turbo-handlers.d.ts +106 -0
  84. package/dist/tests/mocks/turbo-handlers.d.ts.map +1 -0
  85. package/dist/tests/setup.d.ts +11 -0
  86. package/dist/tests/setup.d.ts.map +1 -0
  87. package/dist/tests/types/payment-service.d.ts +218 -0
  88. package/dist/tests/types/payment-service.d.ts.map +1 -0
  89. package/dist/tests/types/upload-service.d.ts +168 -0
  90. package/dist/tests/types/upload-service.d.ts.map +1 -0
  91. package/dist/tests/unit/deploy-key.test.d.ts +2 -0
  92. package/dist/tests/unit/deploy-key.test.d.ts.map +1 -0
  93. package/dist/tests/unit/signer.test.d.ts +2 -0
  94. package/dist/tests/unit/signer.test.d.ts.map +1 -0
  95. package/dist/tests/unit/solana.test.d.ts +2 -0
  96. package/dist/tests/unit/solana.test.d.ts.map +1 -0
  97. package/dist/tests/unit/uploader-tags.test.d.ts +2 -0
  98. package/dist/tests/unit/uploader-tags.test.d.ts.map +1 -0
  99. package/dist/tests/unit/validators.test.d.ts +2 -0
  100. package/dist/tests/unit/validators.test.d.ts.map +1 -0
  101. package/dist/types/index.js +2 -0
  102. package/dist/types/index.js.map +1 -0
  103. package/dist/utils/config-resolver.js +39 -0
  104. package/dist/utils/config-resolver.js.map +1 -0
  105. package/dist/utils/constants.js +6 -0
  106. package/dist/utils/constants.js.map +1 -0
  107. package/dist/utils/path.js +15 -0
  108. package/dist/utils/path.js.map +1 -0
  109. package/dist/utils/signer.js +45 -0
  110. package/dist/utils/signer.js.map +1 -0
  111. package/dist/utils/uploader.js +5 -0
  112. package/dist/utils/uploader.js.map +1 -0
  113. package/dist/utils/validators.js +43 -0
  114. package/dist/utils/validators.js.map +1 -0
  115. package/dist/workflows/upload-workflow.js +9 -0
  116. package/dist/workflows/upload-workflow.js.map +1 -0
  117. package/package.json +111 -0
package/README.md ADDED
@@ -0,0 +1,753 @@
1
+ # ARIO Deploy
2
+
3
+ `ario-deploy` is a Node.js command-line tool designed to streamline the deployment of web applications to the permaweb using Arweave. It uploads your build folder or a single file, creates Arweave manifests, and can optionally update ArNS (Ar.io Name System) records via ANT (Ar.io Name Token) with the transaction ID.
4
+
5
+ ## Quick Start
6
+
7
+ Deploy your app to Arweave in under a minute:
8
+
9
+ ```bash
10
+ # Install
11
+ npm install -g @ar.io/deploy
12
+
13
+ # Deploy (interactive — prompts for everything)
14
+ ario-deploy deploy
15
+
16
+ # Or one-liner with a Solana wallet + ArNS name
17
+ DEPLOY_KEY=<solana-base58-key> ario-deploy deploy --deploy-folder ./dist --arns-name myapp --sig-type solana
18
+ ```
19
+
20
+ Your app is now permanently live at `https://myapp.ar.io`.
21
+
22
+ ## Table of Contents
23
+
24
+ <!-- toc -->
25
+
26
+ - [Quick Start](#quick-start)
27
+ - [Table of Contents](#table-of-contents)
28
+ - [Features](#features)
29
+ - [Installation](#installation)
30
+ - [Prerequisites](#prerequisites)
31
+ - [Commands](#commands)
32
+ - [On-Demand Payment](#on-demand-payment)
33
+ - [Bundler service](#bundler-service)
34
+ - [Command Options](#command-options)
35
+ - [Deduplication](#deduplication)
36
+ - [Package.json Scripts](#packagejson-scripts)
37
+ - [GitHub Action](#github-action)
38
+ - [CLI in GitHub Actions](#cli-in-github-actions)
39
+ - [Claude Code Integration](#claude-code-integration)
40
+ - [Development](#development)
41
+ - [Security & Best Practices](#security--best-practices)
42
+ - [Troubleshooting](#troubleshooting)
43
+ - [Contributing](#contributing)
44
+ - [Dependencies](#dependencies)
45
+ - [License](#license)
46
+ - [Resources](#resources)
47
+
48
+ <!-- tocstop -->
49
+
50
+ ## Features
51
+
52
+ - **Turbo SDK Integration:** Uses Turbo SDK for fast, reliable file uploads to Arweave
53
+ - **On-Demand Payment:** Pay with ARIO or Base-ETH tokens on-demand during upload
54
+ - **Arweave Manifest v0.2.0:** Creates manifests with fallback support for SPAs
55
+ - **Optional ArNS Updates:** Updates ArNS records via ANT with new transaction IDs
56
+ - **Automated Workflow:** Integrates with GitHub Actions for continuous deployment
57
+ - **Git Hash Tagging:** In CI (GitHub Actions), tags uploaded data items with the deploying commit SHA
58
+ - **404 Fallback Detection:** Automatically detects and sets 404.html as fallback
59
+ - **Network Support:** ArNS updates run against the Solana ARIO programs on `mainnet` or `devnet`, with an optional custom RPC URL
60
+ - **Flexible Deployment:** Supports deploying a folder or a single file
61
+ - **Modern CLI:** Built with oclif for a robust command-line experience
62
+ - **TypeScript:** Fully typed for better developer experience
63
+
64
+ ## Installation
65
+
66
+ Install the package using pnpm (recommended):
67
+
68
+ ```bash
69
+ pnpm add -D @ar.io/deploy
70
+ ```
71
+
72
+ Or with npm:
73
+
74
+ ```bash
75
+ npm install --save-dev @ar.io/deploy
76
+ ```
77
+
78
+ Or with yarn:
79
+
80
+ ```bash
81
+ yarn add --dev @ar.io/deploy
82
+ ```
83
+
84
+ ## Prerequisites
85
+
86
+ A deployment uses up to **two independent keys**:
87
+
88
+ - **Upload key** — pays for the upload. Any supported chain (`--wallet` / `--private-key`, or the `DEPLOY_KEY` env var; chain selected with `--sig-type`).
89
+ - **ArNS authority key** — only needed when updating ArNS. Always a **Solana** key that controls the ArNS name and signs the ANT record update (`--arns-wallet` / `--arns-private-key`, or the `ARNS_KEY` env var).
90
+
91
+ They can be the same Solana wallet or two different wallets — provide each explicitly.
92
+
93
+ ### Upload key (`DEPLOY_KEY`)
94
+
95
+ 1. **Arweave signer (default):** Encode your Arweave wallet key in base64 and set it as `DEPLOY_KEY`:
96
+
97
+ ```bash
98
+ base64 -i wallet.json | pbcopy
99
+ ```
100
+
101
+ 2. **Ethereum/Polygon/KYVE signers:** Use your raw private key (no encoding needed) as `DEPLOY_KEY`.
102
+ 3. **Solana signer:** Use a base58-encoded secret key as `DEPLOY_KEY`, or a `solana-keygen` `id.json` byte-array wallet file via `--wallet`.
103
+
104
+ ### ArNS authority key (`ARNS_KEY`)
105
+
106
+ Set a base58-encoded **Solana** secret key as `ARNS_KEY`, or pass a `solana-keygen` `id.json` file via `--arns-wallet` (or a base58 string via `--arns-private-key`). This key must control the ArNS name being updated.
107
+
108
+ ⚠️ **Important:** Use dedicated wallets for deployments to minimize security risks. Ensure your upload wallet has sufficient Turbo Credits for uploads.
109
+
110
+ ## Commands
111
+
112
+ ### Interactive Mode (Easiest)
113
+
114
+ Run the deploy command without arguments to be guided through all deployment options:
115
+
116
+ ```bash
117
+ ario-deploy deploy
118
+ ```
119
+
120
+ When ArNS details aren't supplied via flags, `deploy` asks whether you want to
121
+ update an ArNS name (defaulting to yes) and, if so, prompts for the details. It
122
+ will guide you through:
123
+
124
+ - Whether to update an ArNS name (and which one)
125
+ - Wallet method (file, string, or environment variable)
126
+ - What to deploy (folder or file)
127
+ - Advanced options (optional: undername, TTL, Solana cluster)
128
+
129
+ Pass `--arns-name` (or `--use-arns`) to skip the ArNS confirmation, or use the
130
+ `upload` command for an upload-only run. In a non-interactive environment (CI,
131
+ or no TTY) `deploy` does not prompt — supply everything via flags or
132
+ `DEPLOY_KEY`.
133
+
134
+ ### Direct Commands
135
+
136
+ Use flags for faster, scriptable deployments:
137
+
138
+ ```bash
139
+ # Basic deployment with wallet file
140
+ ario-deploy deploy --wallet ./wallet.json
141
+
142
+ # Deployment with ArNS update (separate upload key + Solana ArNS authority key)
143
+ ario-deploy deploy --use-arns --arns-name my-app --wallet ./wallet.json --arns-wallet ./arns-id.json
144
+ ```
145
+
146
+ Deploy using private key directly:
147
+
148
+ ```bash
149
+ ario-deploy deploy --private-key "$(cat wallet.json)"
150
+ ```
151
+
152
+ Deploy using environment variable:
153
+
154
+ ```bash
155
+ DEPLOY_KEY=$(base64 -i wallet.json) ario-deploy deploy --deploy-folder ./dist
156
+ ```
157
+
158
+ Deploy a specific folder:
159
+
160
+ ```bash
161
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./build
162
+ ```
163
+
164
+ Deploy a single file:
165
+
166
+ ```bash
167
+ ario-deploy deploy --wallet ./wallet.json --deploy-file ./path/to/file.txt
168
+ ```
169
+
170
+ ### Upload/deploy without ArNS
171
+
172
+ `deploy` uploads without updating ArNS by default. You can also use the `upload` command explicitly for the same Turbo upload, dedupe cache, and payment options as deploy, minus ArNS flags:
173
+
174
+ ```bash
175
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./dist
176
+ ario-deploy upload --wallet ./wallet.json --deploy-folder ./dist
177
+ ario-deploy upload --wallet ./wallet.json --deploy-file ./dist/index.html
178
+ DEPLOY_KEY=$(base64 -i wallet.json) ario-deploy upload --deploy-folder ./dist
179
+ ```
180
+
181
+ ### Advanced Usage
182
+
183
+ Deploy to an undername (subdomain) — the ArNS authority key is a Solana wallet:
184
+
185
+ ```bash
186
+ ario-deploy deploy --use-arns --arns-name my-app --wallet ./wallet.json --arns-wallet ./arns-id.json --undername staging
187
+ ```
188
+
189
+ Deploy with a custom TTL:
190
+
191
+ ```bash
192
+ ario-deploy deploy --use-arns --arns-name my-app --wallet ./wallet.json --arns-wallet ./arns-id.json --ttl-seconds 7200
193
+ ```
194
+
195
+ Update ArNS on devnet (or against a custom RPC):
196
+
197
+ ```bash
198
+ ario-deploy deploy --use-arns --arns-name my-app --wallet ./wallet.json --arns-wallet ./arns-id.json --cluster devnet
199
+ ario-deploy deploy --use-arns --arns-name my-app --wallet ./wallet.json --arns-wallet ./arns-id.json --rpc-url https://my-rpc.example.com
200
+ ```
201
+
202
+ Upload using an Ethereum wallet (file):
203
+
204
+ ```bash
205
+ ario-deploy deploy --sig-type ethereum --wallet ./private-key.txt
206
+ ```
207
+
208
+ Upload using a Solana wallet (base58 private key):
209
+
210
+ ```bash
211
+ ario-deploy deploy --sig-type solana --private-key "<base58-secret-key>"
212
+ ```
213
+
214
+ ## On-Demand Payment
215
+
216
+ Use on-demand payment to automatically fund uploads with ARIO or Base-ETH tokens when your Turbo balance is insufficient:
217
+
218
+ Deploy with ARIO on-demand payment:
219
+
220
+ ```bash
221
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./dist --on-demand ario --max-token-amount 1.5
222
+ ```
223
+
224
+ Deploy with Base-ETH on-demand payment (using Ethereum signer):
225
+
226
+ ```bash
227
+ ario-deploy deploy --sig-type ethereum --private-key "0x..." --on-demand base-eth --max-token-amount 0.1
228
+ ```
229
+
230
+ **On-Demand Payment Options:**
231
+
232
+ - `--on-demand`: Token to use for on-demand payment (`ario` or `base-eth`)
233
+ - `--max-token-amount`: Maximum token amount to spend (in native token units, e.g., `1.5` for 1.5 ARIO or `0.1` for 0.1 ETH)
234
+
235
+ **How it works:**
236
+
237
+ 1. Checks your Turbo balance before upload
238
+ 2. If balance is insufficient, converts tokens to Turbo credits on-demand
239
+ 3. Automatically adds a 10% buffer (`topUpBufferMultiplier: 1.1`) for reliability
240
+ 4. Proceeds with upload once funded
241
+
242
+ **Token compatibility:**
243
+
244
+ - **ARIO**: Works with Arweave signer
245
+ - **Base-ETH**: Works with Ethereum signer (Base Network)
246
+
247
+ ## Bundler service
248
+
249
+ Uploads go through a bundler service that accepts signed data items and posts them to Arweave. By default, ario-deploy uses the [Turbo](https://docs.ardrive.io/docs/turbo/) API and ArDrive’s production bundler (`https://upload.ardrive.io`). **`--uploader`** sets the **base URL** of the bundler service to use (scheme + host; typically no path).
250
+
251
+ | When to use | Example value |
252
+ | ------------------------- | ------------------------------------------------------- |
253
+ | **Default** (omit flag) | ArDrive production bundler — same as Turbo CLI defaults |
254
+ | **Arweave bundler** | `https://turbo.ardrive.io` |
255
+ | **Development / staging** | `https://upload.ardrive.dev` |
256
+ | **Custom or self-hosted** | Your own base URL if it implements the Turbo API |
257
+
258
+ **Examples:**
259
+
260
+ ```bash
261
+ # Deploy using Arweave’s bundler service
262
+ ario-deploy deploy --wallet ./wallet.json --deploy-folder ./dist --uploader https://turbo.ardrive.io
263
+
264
+ ario-deploy upload --wallet ./wallet.json --deploy-folder ./dist --uploader https://turbo.ardrive.io
265
+ ```
266
+
267
+ **Notes:**
268
+
269
+ - Turbo billing and signer behavior follow Turbo.
270
+ - Use a **base URL only** (e.g. `https://turbo.ardrive.io`), not a path to a specific file or route.
271
+
272
+ ## Command Options
273
+
274
+ **`deploy`** (upload by default, optional ArNS update):
275
+
276
+ - `--use-arns`: Update an ArNS/ANT record after upload. When ArNS details aren't supplied and you're in a TTY, `deploy` asks by default.
277
+ - `--arns-name, -n`: The ArNS name to update. Required when using `--use-arns`; also implies ArNS mode.
278
+ - `--cluster, -p`: Solana cluster for ArNS updates. Choices: `mainnet`, `devnet`. Default: `mainnet`
279
+ - `--rpc-url`: Optional Solana RPC URL override for ArNS updates
280
+ - `--deploy-folder, -d`: Folder to deploy. Default: `./dist`
281
+ - `--deploy-file, -f`: Deploy a single file instead of a folder
282
+ - `--undername, -u`: ANT undername to update. Default: `@`
283
+ - `--ttl-seconds, -t`: TTL in seconds for the ANT record (60-86400). Default: `60`
284
+
285
+ Upload key (pays for the upload):
286
+
287
+ - `--sig-type, -s`: Signer type for the upload key. Choices: `arweave`, `ethereum`, `polygon`, `kyve`, `solana`. Default: `arweave`
288
+ - `--wallet, -w`: Path to the upload wallet file (JWK for Arweave, private key for Ethereum/Polygon/KYVE, `solana-keygen` `id.json` for Solana). Falls back to `DEPLOY_KEY`.
289
+ - `--private-key, -k`: Upload private-key string (alternative to `--wallet`). JWK JSON for Arweave, hex for EVM chains, base58 secret key for Solana.
290
+
291
+ ArNS authority key (controls the name, signs the update — always Solana):
292
+
293
+ - `--arns-wallet`: Path to the Solana `solana-keygen` `id.json` wallet that controls the ArNS name. Falls back to `ARNS_KEY`.
294
+ - `--arns-private-key`: Base58 Solana secret key for the ArNS authority (alternative to `--arns-wallet`). Falls back to `ARNS_KEY`.
295
+ - `--on-demand`: Enable on-demand payment with specified token. Choices: `ario`, `base-eth`
296
+ - `--max-token-amount`: Maximum token amount for on-demand payment (used with `--on-demand`)
297
+ - `--no-dedupe`: Disable deduplication (do not cache or reuse previous uploads)
298
+ - `--dedupe-cache-max-entries`: Maximum number of entries to keep in the dedupe cache (LRU). Default: `10000`
299
+ - `--uploader`: Custom Turbo upload service base URL. See the **Bundler service** section.
300
+
301
+ **`upload`** (explicit upload without ArNS): accepts `--deploy-folder`, `--deploy-file`, wallet/signer flags, `--uploader`, `--on-demand` / `--max-token-amount`, and dedupe flags only.
302
+
303
+ ## Deduplication
304
+
305
+ By default, ario-deploy caches your deployment log to prevent uploading duplicate (unchanged) files. This saves both time and upload costs by reusing existing data on Arweave.
306
+
307
+ **How it works:**
308
+
309
+ 1. When you deploy, ario-deploy hashes each file in your build
310
+ 2. It checks the local cache for matching hashes from previous uploads
311
+ 3. Files that haven't changed are skipped - the existing transaction ID is reused
312
+ 4. Only new or modified files are uploaded to Arweave
313
+ 5. The cache is stored locally in `.ario-deploy/transaction-cache.json`
314
+
315
+ **Disable deduplication:**
316
+
317
+ If you need to force a fresh upload of all files (e.g., for debugging or to ensure a completely new deployment):
318
+
319
+ ```bash
320
+ ario-deploy deploy --wallet ./wallet.json --no-dedupe
321
+ ```
322
+
323
+ **Limit cache size:**
324
+
325
+ The dedupe cache uses an LRU (Least Recently Used) eviction strategy. By default, it keeps up to 10,000 entries. You can adjust this limit:
326
+
327
+ ```bash
328
+ # Keep only the last 1000 file entries
329
+ ario-deploy deploy --wallet ./wallet.json --dedupe-cache-max-entries 1000
330
+ ```
331
+
332
+ **Cache location:**
333
+
334
+ The cache file is stored at `.ario-deploy/transaction-cache.json` in your project root. You can:
335
+
336
+ - Add it to `.gitignore` if you don't want to share cache across team members
337
+ - Commit it to share cached transaction IDs with your team (reduces duplicate uploads)
338
+ - Delete it to start fresh: `rm -rf .ario-deploy/`
339
+
340
+ ## Package.json Scripts
341
+
342
+ Add deployment scripts to your `package.json`:
343
+
344
+ ```json
345
+ {
346
+ "scripts": {
347
+ "build": "vite build",
348
+ "deploy": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME>",
349
+ "deploy:staging": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --undername staging",
350
+ "deploy:devnet": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --cluster devnet",
351
+ "deploy:on-demand": "pnpm build && ario-deploy deploy --arns-name <ARNS_NAME> --on-demand ario --max-token-amount 1.5"
352
+ }
353
+ }
354
+ ```
355
+
356
+ These read the upload key from `DEPLOY_KEY` and the Solana ArNS authority key from `ARNS_KEY`. Deploy with:
357
+
358
+ ```bash
359
+ DEPLOY_KEY=$(base64 -i wallet.json) ARNS_KEY=<base58-solana-secret-key> pnpm deploy
360
+ ```
361
+
362
+ Or with on-demand payment:
363
+
364
+ ```bash
365
+ DEPLOY_KEY=$(base64 -i wallet.json) ARNS_KEY=<base58-solana-secret-key> pnpm deploy:on-demand
366
+ ```
367
+
368
+ ## GitHub Action
369
+
370
+ The easiest way to integrate ario-deploy into your CI/CD pipeline is using our official GitHub Action.
371
+
372
+ ### Basic Usage
373
+
374
+ ```yaml
375
+ - uses: ar-io/ar-io-deploy@v1
376
+ with:
377
+ deploy-key: ${{ secrets.DEPLOY_KEY }} # upload key (pays for the upload)
378
+ arns-key: ${{ secrets.ARNS_KEY }} # Solana ArNS authority key
379
+ arns-name: myapp
380
+ deploy-folder: ./dist
381
+ ```
382
+
383
+ ### PR Preview Deployments
384
+
385
+ Automatically deploy preview builds for each pull request. The `preview` mode auto-generates an undername from the PR number and posts a comment with the preview URL:
386
+
387
+ ```yaml
388
+ name: Deploy PR Preview
389
+
390
+ on:
391
+ pull_request:
392
+ types: [opened, synchronize]
393
+
394
+ jobs:
395
+ deploy-preview:
396
+ runs-on: ubuntu-latest
397
+ steps:
398
+ - uses: actions/checkout@v4
399
+
400
+ - name: Setup Node.js
401
+ uses: actions/setup-node@v4
402
+ with:
403
+ node-version: '20'
404
+
405
+ - name: Install dependencies
406
+ run: npm ci
407
+
408
+ - name: Build
409
+ run: npm run build
410
+
411
+ - name: Deploy Preview
412
+ uses: ar-io/ar-io-deploy@v1
413
+ with:
414
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
415
+ arns-key: ${{ secrets.ARNS_KEY }}
416
+ arns-name: myapp
417
+ preview: 'true'
418
+ github-token: ${{ secrets.GITHUB_TOKEN }}
419
+ deploy-folder: ./dist
420
+ ```
421
+
422
+ When `preview` is enabled, the action will:
423
+
424
+ - Auto-generate an undername like `pr-123` from the PR number
425
+ - Post a comment on the PR with the preview URL
426
+ - Update the comment on subsequent pushes instead of creating new ones
427
+
428
+ ### Production Deployment
429
+
430
+ Deploy to your base ArNS name when pushing to main:
431
+
432
+ ```yaml
433
+ name: Deploy to Production
434
+
435
+ on:
436
+ push:
437
+ branches: [main]
438
+
439
+ jobs:
440
+ deploy:
441
+ runs-on: ubuntu-latest
442
+ steps:
443
+ - uses: actions/checkout@v4
444
+
445
+ - name: Setup Node.js
446
+ uses: actions/setup-node@v4
447
+ with:
448
+ node-version: '20'
449
+
450
+ - name: Install dependencies
451
+ run: npm ci
452
+
453
+ - name: Build
454
+ run: npm run build
455
+
456
+ - name: Deploy to Permaweb
457
+ uses: ar-io/ar-io-deploy@v1
458
+ with:
459
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
460
+ arns-key: ${{ secrets.ARNS_KEY }}
461
+ arns-name: myapp
462
+ deploy-folder: ./dist
463
+ ```
464
+
465
+ ### With On-Demand Payment
466
+
467
+ ```yaml
468
+ - name: Deploy with ARIO on-demand
469
+ uses: ar-io/ar-io-deploy@v1
470
+ with:
471
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
472
+ arns-key: ${{ secrets.ARNS_KEY }}
473
+ arns-name: myapp
474
+ deploy-folder: ./dist
475
+ on-demand: ario
476
+ max-token-amount: '2.0'
477
+ ```
478
+
479
+ ### Updating ArNS (Solana)
480
+
481
+ ArNS updates run against the Solana ARIO programs. Provide the Solana ArNS authority key via `arns-key` (a base58 Solana secret key); the upload is still paid for by `deploy-key`. Use `cluster` to target `mainnet` (default) or `devnet`, and `rpc-url` for a custom RPC endpoint.
482
+
483
+ ```yaml
484
+ - name: Deploy and update ArNS
485
+ uses: ar-io/ar-io-deploy@v1
486
+ with:
487
+ deploy-key: ${{ secrets.DEPLOY_KEY }} # upload key
488
+ arns-key: ${{ secrets.ARNS_KEY }} # Solana ArNS authority key
489
+ arns-name: myapp
490
+ deploy-folder: ./dist
491
+ cluster: mainnet
492
+ ```
493
+
494
+ ### Disabling Deduplication
495
+
496
+ By default, the action caches transaction IDs to avoid re-uploading unchanged files. To disable this:
497
+
498
+ ```yaml
499
+ - name: Deploy without dedupe
500
+ uses: ar-io/ar-io-deploy@v1
501
+ with:
502
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
503
+ deploy-folder: ./dist
504
+ no-dedupe: 'true'
505
+ ```
506
+
507
+ You can also limit the cache size:
508
+
509
+ ```yaml
510
+ - name: Deploy with limited cache
511
+ uses: ar-io/ar-io-deploy@v1
512
+ with:
513
+ deploy-key: ${{ secrets.DEPLOY_KEY }}
514
+ deploy-folder: ./dist
515
+ dedupe-cache-max-entries: '1000'
516
+ ```
517
+
518
+ ---
519
+
520
+ ## CLI in GitHub Actions
521
+
522
+ You can also use the CLI directly in your workflows:
523
+
524
+ **Basic Workflow:**
525
+
526
+ ```yaml
527
+ name: Deploy to Permaweb
528
+
529
+ on:
530
+ push:
531
+ branches:
532
+ - main
533
+
534
+ jobs:
535
+ publish:
536
+ runs-on: ubuntu-latest
537
+ steps:
538
+ - uses: actions/checkout@v4
539
+
540
+ - uses: pnpm/action-setup@v3
541
+ with:
542
+ version: 9
543
+
544
+ - uses: actions/setup-node@v4
545
+ with:
546
+ node-version: 20
547
+ cache: 'pnpm'
548
+
549
+ - run: pnpm install
550
+
551
+ - run: pnpm deploy
552
+ env:
553
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
554
+ ```
555
+
556
+ **With On-Demand Payment:**
557
+
558
+ ```yaml
559
+ name: Deploy to Permaweb with On-Demand Payment
560
+
561
+ on:
562
+ push:
563
+ branches:
564
+ - main
565
+
566
+ jobs:
567
+ publish:
568
+ runs-on: ubuntu-latest
569
+ steps:
570
+ - uses: actions/checkout@v4
571
+
572
+ - uses: pnpm/action-setup@v3
573
+ with:
574
+ version: 9
575
+
576
+ - uses: actions/setup-node@v4
577
+ with:
578
+ node-version: 20
579
+ cache: 'pnpm'
580
+
581
+ - run: pnpm install
582
+ - run: pnpm build
583
+
584
+ - name: Deploy with ARIO on-demand
585
+ run: ario-deploy deploy --arns-name my-app --on-demand ario --max-token-amount 2.0
586
+ env:
587
+ DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # upload key (pays for the upload)
588
+ ARNS_KEY: ${{ secrets.ARNS_KEY }} # Solana ArNS authority key
589
+
590
+
591
+ # Or upload with Ethereum and Base-ETH on-demand payment (upload only; ArNS requires Solana):
592
+ # - name: Upload with Base-ETH on-demand
593
+ # run: |
594
+ # ario-deploy upload \
595
+ # --sig-type ethereum \
596
+ # --on-demand base-eth \
597
+ # --max-token-amount 0.2
598
+ # env:
599
+ # DEPLOY_KEY: ${{ secrets.ETH_PRIVATE_KEY }}
600
+ ```
601
+
602
+ ## Claude Code Integration
603
+
604
+ Use [Claude Code](https://claude.ai/code) to deploy your app with natural language. Just say "deploy to ar.io" and Claude handles the rest.
605
+
606
+ ### Add the Skill to Your Project
607
+
608
+ ```bash
609
+ mkdir -p .claude/skills
610
+ curl -o .claude/skills/deploy.md https://raw.githubusercontent.com/ar-io/ar-io-deploy/main/examples/claude-skill/deploy.md
611
+ ```
612
+
613
+ Then in Claude Code, say:
614
+
615
+ - "deploy to ar.io"
616
+ - "deploy my app to arweave"
617
+ - "set up CI/CD for ar.io deployment"
618
+
619
+ Claude will build your project, detect the output folder, and run the deploy with the right flags.
620
+
621
+ ### What the Skill Does
622
+
623
+ 1. **Detects your build folder** (`./dist`, `./build`, `./out`)
624
+ 2. **Checks for credentials** (`DEPLOY_KEY` env var or wallet file)
625
+ 3. **Installs `@ar.io/deploy`** if not already available
626
+ 4. **Runs the deployment** with appropriate flags
627
+ 5. **Reports results** — transaction ID, Arweave URL, ArNS URL
628
+
629
+ See [`examples/claude-skill/`](./examples/claude-skill/) for the full skill file and customization options.
630
+
631
+ ---
632
+
633
+ ## Development
634
+
635
+ ### Setup
636
+
637
+ ```bash
638
+ # Install dependencies
639
+ pnpm install
640
+
641
+ # Build the project
642
+ pnpm build
643
+
644
+ # Run in development mode
645
+ pnpm dev
646
+
647
+ # Run tests
648
+ pnpm test
649
+
650
+ # Run linter
651
+ pnpm lint
652
+
653
+ # Format code
654
+ pnpm format
655
+ ```
656
+
657
+ ### Project Structure
658
+
659
+ ```
660
+ ar-io-deploy/
661
+ ├── src/
662
+ │ ├── commands/ # oclif commands
663
+ │ │ ├── deploy.ts
664
+ │ │ └── upload.ts
665
+ │ ├── types/ # TypeScript type definitions
666
+ │ │ └── index.ts
667
+ │ ├── utils/ # Utility functions
668
+ │ │ ├── constants.ts
669
+ │ │ ├── signer.ts
670
+ │ │ ├── uploader.ts
671
+ │ │ └── __tests__/ # Unit tests
672
+ │ └── index.ts # Main entry point
673
+ ├── bin/ # Executable scripts
674
+ │ ├── run.js
675
+ │ └── dev.js
676
+ ├── .changeset/ # Changesets configuration
677
+ ├── .husky/ # Git hooks
678
+ └── dist/ # Build output
679
+ ```
680
+
681
+ ## Security & Best Practices
682
+
683
+ - **Dedicated Wallet:** Always use a dedicated wallet for deployments to minimize security risks
684
+ - **Wallet Encoding:** Arweave wallets must be base64 encoded to be used in the deployment script
685
+ - **ArNS Name:** Required only when updating an ANT/ArNS target undername or root record
686
+ - **Turbo Credits:** Ensure your wallet has sufficient Turbo Credits, or use on-demand payment for automatic funding
687
+ - **On-Demand Limits:** Set reasonable `--max-token-amount` limits to prevent unexpected costs
688
+ - **Secret Management:** Keep your `DEPLOY_KEY` secret secure and never commit it to your repository
689
+ - **Build Security:** Always check your build for exposed environmental secrets before deployment, as data on Arweave is permanent
690
+
691
+ ## Troubleshooting
692
+
693
+ - **Error: "DEPLOY_KEY environment variable not set":** Verify your base64 encoded wallet is set as the `DEPLOY_KEY` environment variable
694
+ - **Error: "deploy-folder does not exist":** Check that your build folder exists and the path is correct
695
+ - **Error: "deploy-file does not exist":** Check that your build file exists and the path is correct
696
+ - **Error: "ArNS name does not exist":** Verify the ArNS name is correct and exists in the specified network
697
+ - **Upload timeouts:** Files have a timeout for upload. Large files may fail and require optimization
698
+ - **Insufficient Turbo Credits:** Use `--on-demand` with `--max-token-amount` to automatically fund uploads when balance is low
699
+ - **On-demand payment fails:** Ensure your wallet has sufficient tokens (ARIO or Base-ETH) and the token type matches your signer (`ario` with Arweave, `base-eth` with Ethereum)
700
+
701
+ ## Contributing
702
+
703
+ Contributions are welcome! Please follow these guidelines:
704
+
705
+ 1. Fork the repository
706
+ 2. Create a feature branch
707
+ 3. Make your changes
708
+ 4. Run tests and linter: `pnpm test && pnpm lint`
709
+ 5. Create a changeset: `pnpm changeset`
710
+ 6. Commit your changes using conventional commits
711
+ 7. Push and create a pull request
712
+
713
+ ### Conventional Commits
714
+
715
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/). Commit messages should follow this format:
716
+
717
+ ```
718
+ type(scope): subject
719
+
720
+ body (optional)
721
+ ```
722
+
723
+ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
724
+
725
+ ### Changesets
726
+
727
+ We use [changesets](https://github.com/changesets/changesets) for version management. When making changes:
728
+
729
+ ```bash
730
+ pnpm changeset
731
+ ```
732
+
733
+ Follow the prompts to describe your changes.
734
+
735
+ ## Dependencies
736
+
737
+ - **@ar.io/sdk** - For ANT operations and ArNS management on Solana
738
+ - **@ardrive/turbo-sdk** - For fast file uploads to Arweave (and signer types)
739
+ - **@solana/kit** - Solana RPC clients and transaction signers for ArNS updates
740
+ - **bs58** - Base58 encoding/decoding for Solana keys
741
+ - **@oclif/core** - CLI framework
742
+ - **mime-types** - MIME type detection
743
+
744
+ ## License
745
+
746
+ MIT — © Permanent Data Solutions, Inc.
747
+
748
+ ## Resources
749
+
750
+ - [GitHub Repository](https://github.com/ar-io/ar-io-deploy)
751
+ - [Issues](https://github.com/ar-io/ar-io-deploy/issues)
752
+ - [Arweave Documentation](https://docs.arweave.org/)
753
+ - [AR.IO Documentation](https://docs.ar.io/)