@artblocks/abx-cli 0.1.0-alpha.4 → 0.1.0-alpha.40

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 (180) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/assets/renderer-scaffold/README.md +29 -11
  3. package/assets/renderer-scaffold/foundry.toml +1 -0
  4. package/assets/renderer-scaffold/remappings.txt +1 -1
  5. package/assets/renderer-scaffold/script/DeployHooks.s.sol +24 -0
  6. package/assets/renderer-scaffold/src/MyHooks.sol +20 -0
  7. package/assets/renderer-scaffold/src/MyRenderer.sol +4 -4
  8. package/assets/renderer-scaffold/src/MyTraits.sol +2 -2
  9. package/assets/renderer-scaffold/test/MyRenderer.t.sol +60 -3
  10. package/dist/bin.d.ts +26 -0
  11. package/dist/bin.d.ts.map +1 -0
  12. package/dist/bin.js +63 -0
  13. package/dist/bin.js.map +1 -0
  14. package/dist/capabilities.d.ts +94 -0
  15. package/dist/capabilities.d.ts.map +1 -0
  16. package/dist/capabilities.js +135 -0
  17. package/dist/capabilities.js.map +1 -0
  18. package/dist/commands/auth.d.ts +54 -0
  19. package/dist/commands/auth.d.ts.map +1 -0
  20. package/dist/commands/auth.js +447 -0
  21. package/dist/commands/auth.js.map +1 -0
  22. package/dist/commands/deploy.d.ts +242 -0
  23. package/dist/commands/deploy.d.ts.map +1 -0
  24. package/dist/commands/deploy.js +4763 -0
  25. package/dist/commands/deploy.js.map +1 -0
  26. package/dist/commands/feedback.d.ts +7 -0
  27. package/dist/commands/feedback.d.ts.map +1 -0
  28. package/dist/commands/feedback.js +147 -0
  29. package/dist/commands/feedback.js.map +1 -0
  30. package/dist/commands/project.d.ts +257 -0
  31. package/dist/commands/project.d.ts.map +1 -0
  32. package/dist/commands/project.js +1414 -0
  33. package/dist/commands/project.js.map +1 -0
  34. package/dist/commands/reads.d.ts +64 -0
  35. package/dist/commands/reads.d.ts.map +1 -0
  36. package/dist/commands/reads.js +701 -0
  37. package/dist/commands/reads.js.map +1 -0
  38. package/dist/commands/scaffold.d.ts +89 -0
  39. package/dist/commands/scaffold.d.ts.map +1 -0
  40. package/dist/commands/scaffold.js +733 -0
  41. package/dist/commands/scaffold.js.map +1 -0
  42. package/dist/commands/service.d.ts +67 -0
  43. package/dist/commands/service.d.ts.map +1 -0
  44. package/dist/commands/service.js +741 -0
  45. package/dist/commands/service.js.map +1 -0
  46. package/dist/commands/storage.d.ts +51 -0
  47. package/dist/commands/storage.d.ts.map +1 -0
  48. package/dist/commands/storage.js +370 -0
  49. package/dist/commands/storage.js.map +1 -0
  50. package/dist/commands/submit-app.d.ts +59 -0
  51. package/dist/commands/submit-app.d.ts.map +1 -0
  52. package/dist/commands/submit-app.js +513 -0
  53. package/dist/commands/submit-app.js.map +1 -0
  54. package/dist/config.d.ts +90 -2
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +284 -11
  57. package/dist/config.js.map +1 -1
  58. package/dist/conformance.d.ts +31 -0
  59. package/dist/conformance.d.ts.map +1 -0
  60. package/dist/conformance.js +390 -0
  61. package/dist/conformance.js.map +1 -0
  62. package/dist/contract-read-error.d.ts +5 -0
  63. package/dist/contract-read-error.d.ts.map +1 -0
  64. package/dist/contract-read-error.js +37 -0
  65. package/dist/contract-read-error.js.map +1 -0
  66. package/dist/deps.d.ts +6 -39
  67. package/dist/deps.d.ts.map +1 -1
  68. package/dist/deps.js +4 -68
  69. package/dist/deps.js.map +1 -1
  70. package/dist/errors.d.ts +20 -0
  71. package/dist/errors.d.ts.map +1 -0
  72. package/dist/errors.js +25 -0
  73. package/dist/errors.js.map +1 -0
  74. package/dist/flag-allowlists.d.ts +53 -0
  75. package/dist/flag-allowlists.d.ts.map +1 -0
  76. package/dist/flag-allowlists.js +180 -0
  77. package/dist/flag-allowlists.js.map +1 -0
  78. package/dist/flags.d.ts +41 -0
  79. package/dist/flags.d.ts.map +1 -1
  80. package/dist/flags.js +111 -1
  81. package/dist/flags.js.map +1 -1
  82. package/dist/jsonout.d.ts +37 -0
  83. package/dist/jsonout.d.ts.map +1 -0
  84. package/dist/jsonout.js +68 -0
  85. package/dist/jsonout.js.map +1 -0
  86. package/dist/kind.d.ts +57 -0
  87. package/dist/kind.d.ts.map +1 -0
  88. package/dist/kind.js +122 -0
  89. package/dist/kind.js.map +1 -0
  90. package/dist/main.js +747 -4838
  91. package/dist/main.js.map +1 -1
  92. package/dist/mintpage.d.ts +17 -2
  93. package/dist/mintpage.d.ts.map +1 -1
  94. package/dist/mintpage.js +241 -54
  95. package/dist/mintpage.js.map +1 -1
  96. package/dist/output.d.ts +179 -0
  97. package/dist/output.d.ts.map +1 -0
  98. package/dist/output.js +780 -0
  99. package/dist/output.js.map +1 -0
  100. package/dist/ownerops.d.ts +312 -57
  101. package/dist/ownerops.d.ts.map +1 -1
  102. package/dist/ownerops.js +1808 -357
  103. package/dist/ownerops.js.map +1 -1
  104. package/dist/preview.d.ts +23 -5
  105. package/dist/preview.d.ts.map +1 -1
  106. package/dist/preview.js +95 -43
  107. package/dist/preview.js.map +1 -1
  108. package/dist/prompt.d.ts +17 -0
  109. package/dist/prompt.d.ts.map +1 -0
  110. package/dist/prompt.js +19 -0
  111. package/dist/prompt.js.map +1 -0
  112. package/dist/provision.d.ts +3 -13
  113. package/dist/provision.d.ts.map +1 -1
  114. package/dist/provision.js +19 -21
  115. package/dist/provision.js.map +1 -1
  116. package/dist/remote.d.ts +157 -52
  117. package/dist/remote.d.ts.map +1 -1
  118. package/dist/remote.js +435 -46
  119. package/dist/remote.js.map +1 -1
  120. package/dist/riskgate.d.ts +62 -0
  121. package/dist/riskgate.d.ts.map +1 -0
  122. package/dist/riskgate.js +234 -0
  123. package/dist/riskgate.js.map +1 -0
  124. package/dist/scaffold.d.ts +12 -0
  125. package/dist/scaffold.d.ts.map +1 -0
  126. package/dist/scaffold.js +56 -0
  127. package/dist/scaffold.js.map +1 -0
  128. package/dist/schema.d.ts +36 -1
  129. package/dist/schema.d.ts.map +1 -1
  130. package/dist/schema.js +121 -26
  131. package/dist/schema.js.map +1 -1
  132. package/dist/script-chunks.d.ts +8 -0
  133. package/dist/script-chunks.d.ts.map +1 -0
  134. package/dist/script-chunks.js +35 -0
  135. package/dist/script-chunks.js.map +1 -0
  136. package/dist/served.d.ts +30 -0
  137. package/dist/served.d.ts.map +1 -0
  138. package/dist/served.js +112 -0
  139. package/dist/served.js.map +1 -0
  140. package/dist/signer.d.ts +13 -0
  141. package/dist/signer.d.ts.map +1 -1
  142. package/dist/signer.js +84 -15
  143. package/dist/signer.js.map +1 -1
  144. package/dist/update-check.d.ts +86 -5
  145. package/dist/update-check.d.ts.map +1 -1
  146. package/dist/update-check.js +161 -20
  147. package/dist/update-check.js.map +1 -1
  148. package/package.json +13 -12
  149. package/skill/SKILL.md +179 -347
  150. package/skill/agents/openai.yaml +4 -0
  151. package/skill/reference/capabilities.md +188 -0
  152. package/skill/reference/code.md +211 -0
  153. package/skill/reference/creator-token.md +94 -0
  154. package/skill/reference/deploy.md +167 -0
  155. package/skill/reference/diagnose.md +165 -0
  156. package/skill/reference/hosting.md +161 -94
  157. package/skill/reference/operate.md +181 -0
  158. package/skill/reference/services.md +121 -0
  159. package/skill/reference/setup.md +140 -36
  160. package/assets/renderer-scaffold/src/interfaces/IAbxFieldRenderer.sol +0 -32
  161. package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +0 -26
  162. package/dist/inspect.d.ts +0 -48
  163. package/dist/inspect.d.ts.map +0 -1
  164. package/dist/inspect.js +0 -184
  165. package/dist/inspect.js.map +0 -1
  166. package/dist/migrate.d.ts +0 -65
  167. package/dist/migrate.d.ts.map +0 -1
  168. package/dist/migrate.js +0 -180
  169. package/dist/migrate.js.map +0 -1
  170. package/dist/onchain-uri.d.ts +0 -97
  171. package/dist/onchain-uri.d.ts.map +0 -1
  172. package/dist/onchain-uri.js +0 -243
  173. package/dist/onchain-uri.js.map +0 -1
  174. package/dist/upload.d.ts +0 -28
  175. package/dist/upload.d.ts.map +0 -1
  176. package/dist/upload.js +0 -41
  177. package/dist/upload.js.map +0 -1
  178. package/skill/reference/code-projects.md +0 -246
  179. package/skill/reference/operating.md +0 -116
  180. package/skill/reference/troubleshooting.md +0 -28
package/skill/SKILL.md CHANGED
@@ -1,352 +1,184 @@
1
1
  ---
2
- name: abx-self-host
3
- description: Launch and operate a self-hosted ABX NFT end to end with the ABX CLI (`abx`) on testnet — a 1/1 (`abx deploy`), a multi-token Series from a folder of media (`abx deploy-series`), or a generative/code drop (`abx deploy-code`). Covers on-chain vs off-chain metadata, storage custody (local disk, S3/R2, IPFS, Arweave), deploy + mint (now or pre-warmed at a predicted address), rendered thumbnails and on-chain traits for code art, primary sales via the shared fixed-price minter, and owner ops (transfer, refresh, re-point URIs, royalties, lock fields, pause/unpause, supply cap, delegate minting). Use when the user wants to self-host an ABX project, take an image to an NFT on testnet, deploy a collection from a folder of images, launch generative/code art, mint or run a primary sale, refresh a listing, operate a project they launched, choose a storage backend, or stand up hosting they own.
4
- compatibility: Drives the abx CLI (@artblocks/abx-cli). Co-versioned with it install/refresh with `abx skill install` so this skill matches the CLI's `abx version`. Requires Node 22.5+.
2
+ name: abx
3
+ description: >-
4
+ Use the ABX CLI (`abx`) to plan, launch, host, inspect, and operate ABX NFT projects on supported
5
+ testnets: static 1/1s, image series, editions, JavaScript/code drops, and Solidity-rendered projects.
6
+ Covers on-chain and off-chain content, managed or self-hosted resolvers, storage, minting and sales,
7
+ PostParams, hooks, custom minters, migrations, feedback, locks, and capability questions. Use for
8
+ requests to create, deploy, mint, host, serve, verify, repair, migrate, report ABX feedback, or
9
+ change an ABX collection, or to determine whether ABX supports a mechanic.
10
+ compatibility: Drives @artblocks/abx-cli on Node 22.13+. Co-versioned with the CLI; install or refresh with `abx skill install`.
5
11
  metadata:
6
- version: "0.1.0-alpha.4"
12
+ version: "0.1.0-alpha.40"
7
13
  ---
8
14
 
9
- # ABX Self-Host Toolkit (`abx`)
10
-
11
- L3 agentic surface: image → live self-hosted NFT the creator owns — a **1/1** (`abx deploy`) or a multi-token **Series** from a folder (`abx deploy-series`, see [Series](#series-multi-token-drops)) — and operate it after, with no central service in the loop. Wraps `@artblocks/abx-sdk`.
12
-
13
- **You drive this for a creator.** Do the mechanical work yourself; surface only genuine decisions, each a simple choice + a recommendation. If *you* hold the signing wallet (an agent releasing its own work), you *are* the human — pick defaults, run the hot lane.
14
-
15
- ## Read first (every session)
16
-
17
- - **YOU run the `abx` commands — never tell the creator to run one.** You have a shell; use it. Run `doctor`, `ls`, `--dry-run`, `tokenuri`, `state`, `refresh`, `balance`, etc. yourself and read the output — don't paste a command and wait for them to run it or copy back results. The creator's hands-on steps are approving in their **browser wallet** (`--sign`), giving you a value you asked for (their address, a name), and **looking at the art in `abx preview`** — you run that command, but the URL it prints is theirs to open and play with ([Phase 0](#phase-0--make-the-work-first-skip-every-gate-below-until-its-good)). Even "next steps" after a deploy: **run the read-only ones** (`tokenuri` to prove it resolves) and **offer to run** the actions (`refresh`, `unpause`, `mint`) — don't hand over a list of commands to run. Exceptions: a genuinely interactive/again-in-their-env command (an OS login, `gcloud auth`), and the **in-chain Solidity lane's Foundry step** (`forge build/test/deploy` a renderer — `abx` never compiles/deploys Solidity; see [Code projects](#code-projects-generative--code-based-drops)) — then run it if you have the tool, else hand it over.
18
- - **Skill ⇄ CLI version must match.** This skill is co-versioned with the `abx` CLI. Run `abx version` and compare it to this file's frontmatter `metadata.version` (top of SKILL.md). If they differ, this skill is stale for the installed CLI — run `abx skill install` to resync, then reload the skill before continuing. (`abx` also prints a drift nudge on its own when it notices.)
19
- - **Resolve the CLI before you install anything — local beats global.** Probe `npx --no-install abx version` (project-local), then `abx version` (global); only install if both miss, and default to the **project-local** `npm install --save-dev @artblocks/abx-cli`. The package is `@artblocks/abx-cli`; `@artblocks/abx-sdk` is the library and ships no binary. Full ladder + why `--no-install` matters → [Setup](#setup--environment).
20
- - **`abx doctor` first, always** — full preflight (Node, pnpm, RPC, signing key, storage). Fix any ✗ before deploying ([Setup](#setup--environment)). A missing public-base-url is not a "set up IPFS" signal: for tiny art go on-chain, for larger art pick an off-chain backend — see [Quick start](#quick-start).
21
- - **Never collect secrets in chat.** Keys, `PINATA_JWT`, S3 secrets → the project's `.env`. The Arweave/Turbo key is a CLI-managed file (`.abx-self-host/arweave-key.json`) — never paste it. Name the var/file; never take the value.
22
- - **Testnet only today** — every launch is on a testnet: **Base Sepolia by default** (`ABX_CHAIN` unset), with **Sepolia** also shipped (`ABX_CHAIN=sepolia`). Say "testnet"; don't imply mainnet. **Testnet IS the preview + e2e environment**: it runs the *real* wiring (renderers, generator, on-chain tokenURI assembly), so a creator should deploy there, inspect the actual result (`abx tokenuri` / the live view / `abx verify`), confirm it looks right, and only *then* go to mainnet — no separate local "preview" is as faithful as the real testnet drop, and a testnet deploy is ~free + ~minutes. **One cross-chain gotcha: on-chain library deps (`--dep p5@…`) resolve to on-chain bytes only where an Art Blocks dependency registry exists — that's Sepolia, NOT Base Sepolia.** A no-dependency script (vanilla JS/GLSL) goes fully on-chain on either; a drop that needs a registry-hosted library on-chain must target `ABX_CHAIN=sepolia` (or run the resolver lane).
23
- - **Scope today = ERC-721 on testnet.** The shipped token standard is **ERC-721** (a 1/1, or a **Series** for many tokens), on Base Sepolia (default) or Sepolia via `ABX_CHAIN`. There is **no `--chain` flag (pick the chain with `ABX_CHAIN`) and no `--erc1155`/`--standard` flag** — don't invent one; mainnet + ERC-1155 are roadmap, not something you flip here. Map the ask to what ships: **"an edition of N" / "N copies"** → an ERC-721 **Series** (`abx deploy-series`, N tokens; for a priced sale of one piece, a 1-token Series). If a creator needs a true ERC-1155 shared-supply edition or an unsupported chain, say plainly it's not in the toolkit today rather than fabricating a recipe.
24
- - **Is the work finished yet?** If the creator is still *making* the piece, you're in **[Phase 0](#phase-0--make-the-work-first-skip-every-gate-below-until-its-good)** — iterate on the art and keep every deploy question off the table until they say ship. The gates below apply to launching something that already exists.
25
- - **Two gates decide everything: (1) demo or real? (2) who signs?** Settle both first *once there's something to launch*.
26
- - **Confirm the full config before any on-chain write** ([readout](#confirm-before-sending)); wait for go-ahead. Never invent a field silently (name/symbol from filename, an auto description) — show it, flag it `inferred`.
27
- - **Safe to explore:** `abx <cmd> --help` and `abx deploy --dry-run` never send. You never run a real write just to learn flags.
28
- - **`deploy` returns; `demo`/`serve`/`preview` block** (they serve) — background them or warn. Background `abx preview` and relay its URL, then keep working while the creator looks; `--shoot` is the one preview mode that exits on its own.
29
-
30
- ## Which command what are you launching?
31
-
32
- Route by the **content** first, then apply the gates below. The three paths differ most in what you have to *keep running* and where the thumbnail comes from:
33
-
34
- | You have | Command | `tokenURI` resolves | Thumbnail (marketplace still) |
35
- |---|---|---|---|
36
- | **one image** (a 1/1) | `abx deploy` | on-chain (tiny art) or off-chain — **no server possible** | the image itself |
37
- | **a folder of images** | `abx deploy-series` | same — on-chain or off-chain, **no server possible** | each image itself |
38
- | **a program** (generative / code) | `abx deploy-code` | **a resolver you run** (live seed + PostParam injection) — OR `--onchain-uri` (tokenURI on-chain; the canonical generator computes the live view) | **rendered off-chain** by the effect runner, else a placeholder |
39
-
40
- **The dividing line is static art vs a running program.** Static art is self-resolving (the file *is* the thumbnail, nothing to keep running); **a code project's thumbnail is *rendered* off-chain, so it ALWAYS needs a public home you provide (`--image-base` bucket, or a resolver) — settle that infra fork with the creator FIRST** (details in [Code projects](#code-projects-generative--code-based-drops)). Nail the project type before the gates.
41
-
42
- **Planning a priced primary sale? Decide 1/1 vs Series BEFORE deploying — it's irreversible.** The shared fixed-price minter sells a **Series** (mint-on-purchase); a plain `abx deploy` **1/1 has no minter/pause/payee**, so its only post-mint move is `abx transfer` (settle an off-chain sale). To run a native fixed-price sale of even a *single* piece, deploy it as a **1-token Series** (`abx deploy-series --count 1`), not a 1/1. abx has **no secondary-listing feature** — reselling a held token means an external marketplace or a manual `transfer`. Full detail: [operating.md → Selling](reference/operating.md#selling--the-shared-fixed-price-minter).
43
-
44
- ## Phase 0 make the work first (skip every gate below until it's good)
45
-
46
- **If the creator is still making the piece, you are in the studio, not in a deploy. Stay there until they say ship.** The gates and decisions below are for *launching* something that already exists — reaching for them while someone is still designing is the single most common way this skill feels wrong to use. A real session: the creator said *"I want to work on one with you"* and got asked about metadata resolution, hosting, and wallet ownership before a single pixel existed. They had to push back with *"let's work on actually designing the piece together first."* Don't make them.
47
-
48
- **Which mode are you in?**
49
- - **They handed you a finished file** (`sketch.js`, a build dir, an image folder) skip this section, go to [Gate 1](#gate-1--demo-or-real-launch).
50
- - **They brought an idea, a reference, a vibe, or "let's make one together"** → Phase 0. The deploy is a footnote at the end of an afternoon of work; treat it that way.
51
-
52
- **During Phase 0, these are OFF the table** — do not ask, do not "just quickly confirm," do not pre-emptively lay out the tradeoffs: hosting/lane, thumbnails, traits-on-chain, storage permanence, wallet address, supply cap, royalties, mint count, name/symbol. Every one of them is answerable in five minutes *after* the art is right, and asking early reads as pressure to ship something half-made. The **one** exception is a constraint that changes what you'd *write*: if they want an on-chain library (`p5`), say early that on-chain deps mean `ABX_CHAIN=sepolia` — that's an authoring constraint, not a deploy decision.
53
-
54
- **The loop** depth + the `--shoot` details [reference/code-projects.md → Studio loop](reference/code-projects.md#studio-loop--iterate-on-the-art-before-you-deploy-anything):
55
-
56
- 1. **Write against the real runtime contract from the first draft** — `abx.tokenData.seed` for randomness, `abx.traits({…})` for features. Not `Math.random()` "for now": a piece prototyped on `Math.random()` looks finished and then deploys as N identical tokens, and retrofitting the seed late means re-tuning every visual you just approved.
57
- 2. **Run `abx preview --script art.js` and give the creator the URL.** It serves the *same document the generator serves* (real `abx.js`, real tokenData) on `localhost:8788`, so they get a seed shuffle, real inputs for every `--schema` PostParam, a live traits readout, and `/grid` for N seeds at once. **This is the one place you hand over a link instead of running it for them** — the art is theirs to judge, and an animated piece cannot be judged from a screenshot. Don't hand-roll a preview page; a stub you write yourself will run a sketch that reads its seed wrong.
58
- 3. **Edit and tell them to refresh.** The program is re-read from disk per render no restart, no watcher. To check your own work between rounds (you have no browser), `abx preview --script art.js --shoot ./frames` renders the same document headlessly and flags the two silent killers: no traits reported, or identical traits across every seed.
59
- 4. **Take feedback and go again.** Expect several rounds. Rounds are the point "add faces to the shapes" is a normal Phase 0 request, not scope creep.
60
-
61
- **Exit only on an explicit ship signal** ("let's deploy this", "I'm happy with it"). Then run `abx inspect <script>` and open the deploy decisions — and say plainly that some are irreversible, so it's worth a few minutes ([Code projects](#code-projects-generative--code-based-drops)). If *you* feel the pull to start the deploy conversation while they're still iterating: don't. Ask what they want to try next.
62
-
63
- ## Gate 1 demo or real launch?
64
-
65
- | | **Demo** (`abx demo`) | **Real launch** (`abx deploy` → operate) |
66
- |---|---|---|
67
- | Art | generative-from-address | the creator's `--image` |
68
- | Storage | `fs` (throwaway) | a permanence decision |
69
- | Host URL | `localhost:8787` | a public URL baked on-chain (off-chain custody only) |
70
- | Key | any funded testnet key (the active `ABX_CHAIN`) | the wallet that should **own** it |
71
- | Decisions | none just run it | the framework below |
72
-
73
- Just want to see it work? `abx demo`, skip the rest.
74
-
75
- ## Gate 2 who signs? (three lanes)
76
-
77
- Every write builds an unsigned tx; pick the lane by stakes:
78
-
79
- | Lane | Flag | Signs | Use when |
80
- |---|---|---|---|
81
- | **Hot** | default (or `--send`) | env key, in-process | autonomous agent · testnet · low value |
82
- | **Wallet** | `--sign` | human's own wallet (MetaMask/Ledger) | real value · key shouldn't touch `.env` |
83
- | **Cold** | `--unsigned` | multisig / offline signer | a Safe / advanced setup |
84
-
85
- - **Lane detection:** you hold the key + low stakes → hot. Human owns the valuable wallet wallet. Multisig → cold. Beyond throwaway testnet, lead with `--sign`.
86
- - **Missing key is a fork, not a blocker.** If you'd pick hot but `.env` has no key, offer both: add a funded key, or `--sign` in a browser wallet.
87
- - **On the wallet lane, ALWAYS ask "which wallet will you connect?" and pass `--for <addr>` — don't offer a "just connect whatever" path.** The connecting wallet becomes owner + mint recipient + royalty receiver, so `--for` pins it and makes the sign page + CLI refuse a mismatched wallet (a real session skipped this and let a random connected wallet own the collection). All three deploy commands **warn on `--sign` without `--for`** (*"whichever wallet connects becomes owner + royalty receiver + mint recipient — pass --for to PIN it"*); treat that as a prompt to get the address, not to proceed.
88
- - **`--for` is a DEPLOY concern, not an owner-op one.** It pins who *becomes* the owner at deploy. Post-launch owner ops (`set-royalty`, `transfer`, `minter configure`, `set-minter`, `pause`, …) already sign as the contract's **current on-chain owner** — the wallet lane targets that automatically — so `--for` isn't needed there (passing it is harmless but ignored). Just connect the owner wallet.
89
-
90
- **⚠ `--sign` BLOCKS until the human signs — ALWAYS background it with `--sign-url-file`, NEVER foreground.** Foreground hangs your whole turn (you can't read the URL or talk to the human) and looks frozen. The #1 way agents break the wallet lane. The flow:
91
-
92
- 1. Background-run `--sign --sign-url-file <path>` (e.g. `/tmp/abx-sign-url`).
93
- 2. Read the URL from that file (fallback: grep output for `ABX_SIGN_URL=`) **every time — never assume the port**. Each op gets a fresh server; if the friendly port (8799) is still busy it auto-falls back to a different one, so the file is the source of truth. Server binds in ~1–2s; poll a couple times.
94
- 3. Relay: "Open `<url>`, connect your wallet, approve." Don't auto-open (node may be remote). Multi-tx → tell them it's N approvals in one session.
95
- 4. Human approves; only the signed tx hash returns.
96
- 5. Let the background command finish (it signs + confirms + re-indexes), then report. Don't kill it.
97
-
98
- **⚠ Run wallet-lane ops ONE AT A TIME — never start the next `--sign` op until the previous background command has finished (step 5).** Each op is its own process serving its own page; overlapping them means the human can land on the *previous* action's page, which (having already completed) shows "done" instantly — that "done" is the last op, not the new one. If a session is genuinely stuck (human never signs), the next op will open a *fresh, different* URL — so relay the new URL from the file and tell them to open that one, not the old tab.
99
-
100
- - **Sign page is operation-aware** — shows decoded intent ("Transfer #0 → 0x…"), gates on network + signing wallet + the tx, and the CLI refuses a mismatched signer server-side too.
101
- - **Multi-tx signs in ONE session** (hot + wallet only). `--onchain-image` stages bytes before the deploy that references them; the human connects once and walks `Transaction 1 of N`. Cold can't (staging is interactive) — `--unsigned --onchain-image` errors; use `--send`/`--sign`.
102
- - **Keep tx count low and say it up front.** A configured token deploys in one tx; `--onchain-image` adds staging tx(s); several owner edits collapse into one atomic `multicall`.
103
- - **Off-chain storage uploads are NOT wallet approvals — never count them as signatures.** An IPFS upload (Pinata `PINATA_JWT`) or a managed-key Arweave upload happens *before* signing with **no wallet prompt**; only **on-chain staging + the deploy** are approvals. So an off-chain IPFS/Arweave deploy is **one** wallet approval (the deploy). Say it that way — *"1 approval (the deploy); your N images upload to IPFS first, no signature"* — don't fold uploads into the MetaMask count (the classic "2 txs, approve both" mistake). *Exception:* `--storage-signer eth --sign` makes each upload a `personal_sign` in the same session (no gas) — then, and only then, they're approvals too.
104
-
105
- ## Quick start
106
-
107
- **Custody is the master call; resolve it before signing/identity.** The rule, by size:
108
-
109
- | Art size | Default | Why |
110
- |---|---|---|
111
- | **Tiny** (≲ 24 KB/file, ≲ 256 KB total) | fully **on-chain** (`--onchain-image --compress fastlz`) | no host, renders forever, cheaper *at this size* |
112
- | **Bigger / photographic** (most PNG/JPEG) | image **off-chain**, JSON on-chain (`--onchain-uri --backend arweave`) | on-chain is ~200 gas/byte → far more expensive here; Arweave is pay-once permanent |
113
-
114
- On-chain's edge past tiny is self-resolution/permanence, **never cost** — don't call it "cheaper" above the thresholds. The CLI warns when an on-chain image exceeds them.
115
-
116
- **When the user names off-chain custody for tiny art ("deploy it as an IPFS NFT"), lead with the on-chain recommendation in your *first* reply** — don't bury it, and don't collect resolver-URL details for a path you're about to advise against. "For a 2.4 KB SVG I'd go fully on-chain — no server, renders forever, cheaper. Want that, or IPFS?" Then let them choose (you surface the better default; you don't override the request). Defaulting to "IPFS" for tiny art is what lands it at a broken localhost URI.
117
-
118
- Tiny-art path:
119
- 1. **Confirm identity** (name, symbol, `--description`, royalty, owner) via the [readout](#confirm-before-sending).
120
- 2. **Deploy + mint in one go:**
121
- ```bash
122
- abx deploy --image art.svg --name "…" --symbol … --description "…" --onchain-image --compress fastlz [--sign --for 0x…]
123
- ```
124
- = staging tx(s) + one deploy-that-mints. **Mint at deploy — no `--no-mint`** (nothing to warm).
125
- 3. **Prove + finish:** `abx tokenuri <addr>` (reads metadata straight from chain) · `abx refresh <addr>` (nudge marketplaces) · lock later once it resolves: `abx lock-field <addr> --field image` then `abx lock-uri <addr>`.
126
-
127
- For large/dynamic media, off-chain custody, or operating an existing project, use the framework + reference files below.
128
-
129
- ## Series (multi-token drops)
130
-
131
- One contract, **N tokens**, static creator metadata — a folder of media → a collection. **Everything from the 1/1 applies per token** (custody, on-chain vs off-chain, signing lanes, identity, locking, warming); only the three points below are new. Reach for it when there's more than one piece; a single image is `abx deploy`.
132
-
133
- ```bash
134
- abx deploy-series --dir <media-dir> --name "…" --symbol … [--onchain-uri --backend arweave|ipfs|cloud | --onchain-image --compress fastlz | --onchain-uri | --public-base-url https://…] [--mint-all | --mint-count N | --no-mint]
135
- ```
136
- **Quick start — a folder of photos, permanent, no server:**
137
- ```bash
138
- abx deploy-series --dir ./photos --name "My Series" --symbol MS --onchain-uri --backend arweave --mint-all --sign
139
- ```
140
- Files natural-sort into **tokens `0…N-1`** (`--count N` uses the first N); a token's metadata is its token id. `--dry-run` and the [readout](#confirm-before-sending) work identically (token count + mint plan). **Content placement is per token — the same custody call as a 1/1 (see [Decisions](#decisions-real-launch)).** The one Series-specific win: a **same-extension folder** uploads as ONE directory/manifest → a single collection `url-template` (O(1) on-chain, any size); mixed extensions fall back to per-token `url` fields (still no server). `cloud` needs `--public-base`. **Per-token traits: `--attributes <file.json>`** — a JSON **array** indexed by token id, or an **object** keyed by filename / token id (each value an attributes array or a `{name:value}` map). **Lane-aware, exactly like the 1/1's traits**: off-chain operator metadata by default (resolver-served, editable later via `abx add <addr> --attributes`), inlined **on-chain** when the token resolves on-chain (`--onchain-uri`) or you pass `--traits-onchain` — small/medium collections; a huge series sets on-chain traits post-deploy via `set-field` under a gas budget. *(For **generative** traits computed from a seed, that's a code project — `abx.traits()` / `--attributes-renderer` — not a static Series.)*
141
-
142
- ## Code projects (generative / code-based drops)
143
-
144
- A **program is the content** (`abx deploy-code` → a `SeriesCode`): output is a function of live on-chain state (`tokenData`: coordinates + `seed` + PostParams), injected at view time. Everything from a [Series](#series-multi-token-drops) applies (mint order, lanes, identity, supply cap, minter, pause). This section is the **decision tree**; the operating depth — what to keep running, the resume loop, verify steps, render ops, lane internals, the arweave delay, selling — lives in **[reference/code-projects.md](reference/code-projects.md)**.
145
-
146
- **Infra fork FIRST (before any lane talk): a code project's thumbnail is *rendered* off-chain, so it ALWAYS needs a PUBLIC home you provide — there is NO zero-infrastructure code drop, and "fully on-chain" does NOT mean "nothing to run."** Settle the shape with the creator up front:
147
- - **Off-chain resolver** (`--public-base-url` + an effects runner, ~a few $/mo) — **the default for a drop you'll sell.** Auto-renders every mint + param change, serves traits with no Solidity, and stays **maneuverable** (metadata/serving evolve with no on-chain surgery) while marketplaces fetch a **small** `tokenURI`.
148
- - **Fully on-chain** (`--onchain-uri --image-base <a bucket you own>`) — maximal durability, no always-on service. Trade-offs: the whole ~200KB+ doc rides each `tokenURI` (some marketplace/indexer reads choke), **manual** stills (`abx render`), on-chain traits need a deployed renderer, later changes are on-chain re-points. Choose it deliberately when permanence outweighs maneuverability. *(The one zero-infra-AND-on-chain exception: the in-chain **Solidity** lane below.)*
149
-
150
- **Writing the program yourself (the creator brought an *idea*, not a file)? There's ONE runtime contract — get it right or the drop is silently broken** (seed never injects → every token identical; traits empty). The program reads state via **`abx.tokenData`** (a flat object: `.seed`, and each `--schema` key flat, e.g. `.palette`) and reports traits via **`abx.traits({…})`** — never an invented global (`window.tokenData`, `window.tokenTraits`) and never "defensively across variants." `abx.traits()` is the ONLY thing captured into `attributes`, on the resolver lane too. Verify with `abx inspect` (its **PostParams** + **Traits** lines reflect what the program actually reads/reports — if they're empty but you intended a param/traits, you read it the wrong way), THEN pick a lane. Full contract: [reference/code-projects.md → Authoring the program](reference/code-projects.md#authoring-the-program--the-abxjs-runtime-contract-get-this-right-first).
151
-
152
- **Run `abx inspect <script>` before proposing any lane, then adopt the recommended lane it prints — don't hand-assemble a different flag set.** (Exception: the in-chain **Solidity-render** lane below has no JS script to inspect — go straight to it. `abx inspect` only analyzes a JS file.) A code project has surfaces that each must land *somewhere public* — the fatal mistake (seen in real sessions) is picking *“fully on-chain, no server!”* and only discovering, one at a time after deploy, that it carries no thumbnail, no traits, and dropped a PostParam. **These are all DEPLOY-TIME decisions — an on-chain field with no pointer CANNOT be backfilled** (least of all to localhost). `abx inspect` and `deploy-code --dry-run` print a **Surfaces block** grading each one; **every ⚠ there is a marketplace-facing hole you must close before deploy — trust it over your own read.** Resolve all of them into ONE coherent lane with the creator BEFORE you collect identity or show a config:
153
-
154
- | Surface | On-chain | Off-chain |
155
- |---|---|---|
156
- | **tokenURI + animation** | `--onchain-uri` — *if* script + every dep fit one `tokenURI` eth_call (`abx inspect` estimates) | a resolver (`--public-base-url`) |
157
- | **thumbnail (`image`)** | ❌ never computed on-chain — needs a public destination: `--image-base <S3/R2/CDN you own>`. **No destination ⇒ placeholder FOREVER + orphaned render, not backfillable. Never localhost.** | a resolver's `/image` |
158
- | **traits (`attributes`)** | a Solidity `--attributes-renderer 0x…` you **DEPLOY** (fork `SeedTraitsRenderer`) — **not a free flag or guessable address** (`deploy-code` refuses a codeless one; "ports to Solidity" ≠ "deployed") | a resolver stitches the JS `abx.traits()` |
159
- | **PostParams** | declare EVERY key the script reads: `--schema key:Type:Auth` (a palette collectors set = `palette:HexColor:TokenOwner`) — else silently dropped at render | — |
160
-
161
- **The resolver is the pivot: choosing *no resolver* forecloses the off-chain column for thumbnail + traits.** (On `--onchain-uri`, an unauthenticated Etherscan "Read Contract" can hit its gas cap on the big doc and look like a revert — expected; verify with `abx tokenuri`, never `abx index --full` to "fix" it. Diagnosis depth → [reference/troubleshooting.md](reference/troubleshooting.md).)
162
-
163
- **Pick your code lane** (all `abx deploy-code`):
164
-
165
- | Your sketch | Flags | Result |
166
- |---|---|---|
167
- | Vanilla JS, no libraries | `--script f.js --onchain-uri` | **fully on-chain** — resolves from any RPC forever |
168
- | Script + a library on-chain (e.g. `p5@1.0.0`, **Sepolia only** — needs the AB dependency registry, absent on Base Sepolia) | `--script f.js --onchain-uri --dep p5@1.0.0` | **fully on-chain** — *iff the dep report says “ON-CHAIN bytes available”* |
169
- | Script + a CDN-only library, or very large params | `--script f.js --public-base-url https://…` | **resolver lane** — you host a resolver; live metadata |
170
- | A pre-built app (webpack/vite output) | `--code-dir build/` (+ `--onchain-uri` or `--public-base-url`) | **no server to run**, gateway-served → **never** chain-complete (8KB param budget) |
171
- | A **Solidity renderer** (SVG on-chain, from seed+params) | `--image-renderer 0x<svg> [--attributes-renderer 0x<traits>] --onchain-uri` (**no `--script`**) | **truly in-chain** — image + traits computed on-chain, tokenURI on-chain, **zero infra** |
172
-
173
- **⭐ In-chain Solidity lane — recommend on-chain `tokenURI` without hesitation.** The artwork is a Solidity `IAbxFieldRenderer` returning an SVG from seed+params (not a JS program), wired `--image-renderer 0x… [--attributes-renderer 0x…] --onchain-uri` with **no `--script`/`--code-dir`**: image AND traits computed on-chain, `tokenURI` assembled on-chain — **genuinely nothing to run** (a small SVG, so the large-`tokenURI` caveat doesn't apply). **NOT no-code, though**: the renderer is a contract the creator compiles + deploys with Foundry. **`abx scaffold-renderer <dir>`** writes a ready-to-build project (worked renderer + coherent traits + the interfaces with invariants + never-revert tests + deploy script); they `forge test`, deploy, and hand the address to `--image-renderer 0x…` (which verifies code-at-address, never compiles/deploys Solidity). Not comfortable with Solidity? Steer to the resolver or (tiny static SVG) `--onchain-image`. Depth → [reference/code-projects.md](reference/code-projects.md#in-chain-solidity-svg--the-zero-dependency-lane) · interface/invariants → https://abx.docs.artblocks.io/protocol/renderers/.
174
-
175
- ## Decisions (real launch)
176
-
177
- Master call is **custody × mutability**:
178
-
179
- | | **Mutable** (name/desc/traits may change) | **Immutable** (never changes) |
180
- |---|---|---|
181
- | **Tiny static** (≲ 24 KB/file, ≲ 256 KB total) | **on-chain renderer** — `--onchain-image --compress fastlz`. No host, mutable via `set-field`, permanent. | on-chain renderer + `lock-field` + `lock-uri` once it resolves. |
182
- | **Bigger / dynamic** (most PNG/JPEG) | **image off-chain, JSON on-chain, no server** — `--onchain-uri --backend arweave` (or `ipfs`). Renderer assembles JSON pointing at the bytes; many files → one `url-template` (O(1)). For metadata you edit often, a **hosted resolver** instead (`abx deploy-resolver`, [hosting.md](reference/hosting.md)). Not fully on-chain (~200 gas/byte). | image off-chain (Arweave = permanent) + on-chain renderer + `lock-field`/`lock-uri`. Or a frozen `ipfs://` override + `lock-uri`. |
183
-
184
- **Four patterns, by where bytes live × how `tokenURI` resolves:**
185
- 1. **Fully on-chain** (`--onchain-image`) — bytes + JSON on-chain. Tiny art only.
186
- 2. **Image off-chain, JSON on-chain, no server** (`--onchain-uri --backend arweave|ipfs|cloud`) — the sweet spot for static art. Arweave/IPFS (permanent, content-addressed) or your S3/CDN (`--backend cloud --public-base <url>`; centralized, mutable). Many files → one `url-template`.
187
- 3. **Hosted resolver** (`--public-base-url` + `abx deploy-resolver`) — for mutable/dynamic metadata; you run a node.
188
- 4. **Inline SVG on-chain** — self-contained vector art inlined into `tokenURI`. For a **1/1** that's `abx deploy … --onchain-uri`; for a **Series** of tiny SVGs use `abx deploy-series … --onchain-image --compress fastlz` (bare `--onchain-uri` on a folder does NOT inline the images — it's the image-custody flag `--onchain-image` that puts SVG bytes on-chain per token).
189
-
190
- **Picking IPFS (or Arweave) does NOT mean running a server.** The `--onchain-uri --backend ipfs|arweave` path (pattern 2) bakes the image's public **gateway** URL into on-chain JSON — a pinning service's read endpoint (a *dedicated* Pinata gateway for IPFS), not a resolver you host. So when a creator chooses IPFS, **default to this no-server path** — image on IPFS, JSON on-chain, nothing to keep running (just keep the pin alive). You only need a **hosted resolver** (pattern 3) if they want *freely editable* metadata. Never present IPFS as blocked on "a public URL" or "a server always online": the gateway belongs to the pinning service and the JSON lives on-chain. (The one real input IPFS needs is `PINATA_JWT` in `.env` for pinning — that's an API upload, not a host.)
191
-
192
- **No-server tradeoff (patterns 1, 2, 4):** with the on-chain renderer only the *image* is off-chain — any **description / traits / animation_url live on-chain** (gas to write, permanent, lockable), vs a hosted resolver where they're free to edit. Cheap (a shared value is **one collection-scope field**, not one per token — the renderer falls back token→collection), but the creator should choose "no server" knowing their text metadata is on-chain.
193
-
194
- Get decisions 1–2 right before deploy (image commitment + resolver URL are written then; re-pointable, but):
195
-
196
- **1. Storage permanence** — where bytes live. Not irreversible: bytes are content-addressed by their on-chain keccak, so start on one backend and move later (`abx verify` confirms the hash). Don't let it block a first deploy.
197
- - `arweave` = pay-once permanent, no recurring fee. `cloud` (S3/R2) = durable, you maintain it. `ipfs` = decentralized, you pin it. `fs` = zero-config start, dies with the disk → move before it matters.
198
- - **`arweave` is nearly as easy as `fs` for small art** — Turbo default: **under 100 KB free, no setup** (a managed `.abx-self-host/arweave-key.json` minted on first upload; back it up with `abx storage backup-key`). Choose per command with `--backend` (stateless, no config file); a backend missing its secret falls back to `fs`.
199
- - **Who pays is a lane (`--storage-signer`)** — Turbo credits attach to an identity (managed key · `.env` key · browser wallet). **Before any top-up, check BOTH balances** (`abx storage balance --backend arweave` shows the managed key AND the wallet — spend the wallet's credits if present). On an upload error surface it verbatim — `…already been uploaded…` is *success* (dedup); don't reflexively top-up or switch to IPFS. Full lanes + failure playbook → [hosting.md](reference/hosting.md#arweave-via-turbo--the-easy-permanent-path-read-before-quoting-setup).
200
-
201
- **2. Public host URL** — where the resolver runs (**off-chain custody only**). Baked into `tokenURI` at deploy, so the CLI **refuses an off-chain deploy without a public URL** (`ABX_PUBLIC_BASE_URL` or `--public-base-url https://…`) and **never bakes localhost** (that token resolves for no one). No exceptions.
202
- - **First ask whether you need a host at all** — tiny art is cheaper and more durable on-chain (no host). For bigger art, Arweave (no host to run) beats a resolver unless you need mutability or serve many files.
203
- - **Tunnels (ngrok/cloudflared) are preview-only — never bake one on-chain** (dies on sleep, rotates on restart). A real launch puts the resolver on a host you control under your own domain (move = a DNS re-point).
204
-
205
- **3. Identity** — `--name`, `--symbol`, `--royalty-bps` (default 500 = 5%), `--description "…"`, `--external-url <url>` (both served in the metadata — set them or the description is boilerplate). Owner + royalty receiver = the deploying wallet. These default to off-chain operator metadata (editable via `abx add <addr> --description "…"`). For a description that should outlast any node, add `--description-onchain` (or later `abx set-field <addr> --field description --text "…"`) → on-chain, freezable via `lock-field`; the resolver prefers the on-chain value. This is the per-field on-chain model — any field on-chain or off, one active `representation` (inline · reader · keccak256 · arweave · ipfs · url). Background: [metadata model](https://abx.docs.artblocks.io/protocol/metadata/).
206
- - **Credit + license** — deploy flags `--artist "…"` · `--license "…"` (also `--display-notes`, `--artist-links`) bake authorship + rights ON-CHAIN in the deploy tx (all three deploy commands); or set/change them later with `abx set-field <addr> --collection --field artist|license --text "…"`. Reserved collection fields served in `contractURI`, on any type (1/1 · Series · code). Detail: [operating.md → Authorship + rights](reference/operating.md#authorship--rights-credit--license).
207
- - **Propose a real name/symbol and confirm — never silently bake a generic folder-name guess.** A folder called `series`/`images`/`photos` infers junk ("Series" / "SRS"), and the CLI *refuses* demo defaults without `--name`/`--symbol` precisely because on-chain identity is effectively permanent. Suggest a specific title + a short ticker-style symbol drawn from the actual work, and get an explicit yes before deploying. Inference is a suggestion to confirm, not a default to ship — if the folder name is generic, say so and ask rather than proposing it.
208
-
209
- **4. Image placement** — `--image <path>` (png · jpg · gif · svg · webp). The on-chain keccak256 (`image` field) anchors integrity; size is bounded by the backend, not the chain.
210
- - *Off-chain:* the served `image` is the backend's **gateway HTTPS URL** (`https://<gateway>/ipfs/<cid>`), not raw `ipfs://` (wallets/marketplaces can't render that). So off-chain needs a pinning service + a **public** gateway — with Pinata use a **dedicated** gateway (`--gateway https://<you>.mypinata.cloud`); a local kubo gateway is preview-only. The keccak stays the anchor → move gateways without a tx.
211
- - *Fully on-chain:* `abx set-field <addr> --field image --file <path> [--compress fastlz]` splits into SSTORE2 chunks behind the shared reader; or bake it in with `abx deploy --image <path> --onchain-image [--compress fastlz]`.
212
-
213
- **Inline vs reader — default to the reader for real artwork.** `--onchain-uri` alone inlines the SVG (1 tx, ~700 gas/byte); `--onchain-image --compress fastlz` stages via SSTORE2 + a small `reader` pointer (~200 gas/byte, +1 tx) — **cheaper above ~0.5 KB** and widening with size. So: tiny (<~0.5 KB, a one-line SVG/short text) → `--onchain-uri` inline; real artwork (a few KB+) → `--onchain-image --compress fastlz`. **Never `--compress gzip` for an on-chain-rendered token** — gzip decodes off-chain only, breaking `--onchain-uri`; use fastlz (it decodes *in* the reader).
214
-
215
- **5. On-chain vs off-chain resolution** — by default `tokenURI`/`contractURI` point at your resolver. `--onchain-uri` = JSON assembled *on-chain* by the shared `AbxMetadataRenderer`, self-resolving forever — so it pairs with on-chain content, cost-effective only for tiny art (thresholds above).
216
- - **Fully on-chain = no server.** Don't stand one up; never cite a localhost URL. **Prove it with `abx tokenuri <addr>`** (reads `tokenURI(0)` over RPC, no `serve`). `abx serve` is only for off-chain-resolving tokens.
217
- - **The off-chain `tokenURI` is a base, not a per-token URL** — the contract stores a base and derives `{base}/{chainId}/{address}/{tokenId}`. Set via `--public-base-url` or `set-token-uri --uri <base>` later.
218
- - **Don't default to a frozen `ipfs://` tokenURI** — every edit then = re-pin + on-chain re-point, and the event spine stops driving the token (exiting the spec). Right only for true immutability, then lock it (`set-token-uri --override ipfs://<cid>` then `lock-uri`).
219
- - **Store ≠ lock; lock last.** On-chain ≠ frozen. Deploy unlocked, confirm it resolves in production, *then* freeze. Two locks: `lock-field <addr> --field <name>` (a value) + `lock-uri <addr>` (how it resolves). Both = provably immutable. A deliberate follow-up, not the first deploy.
220
-
221
- **6. When to mint** → [Deploy strategy](#deploy-strategy--when-to-mint).
222
-
223
- ## Confirm before sending
224
-
225
- Run `abx deploy --dry-run` for real values, present **this exact shape** — one row per on-chain value — then wait for go-ahead. **Mirror the dry-run's values; don't compose your own.**
226
-
227
- ```
228
- Deploy config — confirm before I send (everything below is written on-chain):
229
-
230
- Name Donuts & Cake ⚠ inferred from filename — confirm or rename
231
- Symbol DONUTS ⚠ inferred — confirm
232
- Description "<the creator's words>" ⚠ I have nothing from you — give me a line, or I deploy with none
233
- Traits none ⚠ none written — add --traits "Key=Value" or skip
234
- Image donuts-cake.svg · 2.4 KB → reader (fastlz, 1 chunk) · on-chain
235
- Resolution on-chain via renderer 0x5F36…1829 — no server, no localhost
236
- Royalty 5% (500 bps) → 0x0248…b13C (default; confirm rate + receiver)
237
- Owner 0x0248…b13C (the deploying wallet)
238
- Mint token #0 → owner, at deploy
239
- Address 0x2619…9Da9 (salt-pinned: --salt 0x…)
240
- Locking deploying UNLOCKED — lock later, after verifying it resolves
241
- Transactions stage image (1) + deploy + mint (1) = 2
242
-
243
- Reply to change anything, or say go.
244
- ```
245
-
246
- Rules:
247
- - **The readout is a contract: what's shown is *exactly* what deploys.** Every value = a flag you pass. Not going on-chain → the row says `none`, never an invented placeholder.
248
- - **Every line must be *verified*, never aspirational — a value that depends on an external contract that must already exist** (`--attributes-renderer`, `--minter`, a `0x…` `--dep`, a gateway) **may appear as committed only once the dry-run confirms it resolves.** Never bake in a guessed/placeholder address; if it's unverified, show it `⚠ requires <X> — not yet deployed/verified` or leave the surface out. (The real-session trap: presenting "Traits computed on-chain via `--attributes-renderer 0x…`" off a *guessed* address — `deploy-code` now refuses an address with no code, so trust the dry-run over the assumption.)
249
- - **Flag every inferred/defaulted value** with `⚠` + where it came from (name/symbol from filename, royalty default, owner = signing key).
250
- - **The description is the one people forget** — never deploy an auto-written or empty description quietly. State what's written and whether it's on-chain (`--description-onchain`) or off. For a real piece, ask for the creator's words.
251
- - **Traits are the creator's** (the OpenSea `attributes` array) — ask (`--traits "Background=Blue"` or `--attributes file.json`); never invent traits, never put protocol facts there. Off-chain by default; `--traits-onchain` to commit them.
252
- - **Show real values** — the real name, description, address + pinned salt, chunk/tx count from the dry-run.
253
- - Adapt rows to the config (off-chain shows storage backend + host URL instead of the renderer; `--no-mint` shows a deferred mint) — but always one row per written value, always the ⚠ flags, always an explicit confirm.
254
-
255
- ## Deploy strategy — when to mint
256
-
257
- The deploy address is **deterministic** — a pure function of `(factory, salt)`, knowable before signing (`abx predict`). So you can warm the resolver at that exact address first → the moment a marketplace sees the mint it fetches live metadata, not a cached blank. Minting is optional at deploy (`--no-mint`); there's a one-shot `abx mint`.
258
-
259
- | Path | When | Flow |
15
+ # ABX
16
+
17
+ Use `abx` as the execution and truth surface. Help, capability output, dry runs, on-chain reads, and
18
+ typed errors outrank remembered prose.
19
+
20
+ ## Non-negotiable rules
21
+
22
+ - Never read or print `.env`, private keys, RPC URLs, provider tokens, storage credentials, wallet
23
+ session URLs, or Arweave JWK contents. Use `abx doctor`, `abx remote`, and `abx storage show` to
24
+ inspect configuration safely.
25
+ - Use `pnpm abx …` inside the ABX source repository. Use `abx …` in a creator project or installed
26
+ environment. Run `abx version` if provenance is uncertain.
27
+ - Operate only on chains reported by `abx capabilities`; the toolkit is testnet-only today. Select
28
+ the chain with `ABX_CHAIN=<chain>`; there is deliberately no `--chain` flag.
29
+ - Run `abx help <command>` immediately before composing a non-trivial command. Do not recover flag
30
+ syntax from this skill.
31
+ - Never infer that a capability is absent because a flag is absent. Run `abx capabilities --json`,
32
+ identify a native lane or extension seam, and read [capabilities.md](reference/capabilities.md).
33
+ - Never hand-roll transactions, nonces, retry loops, resolver URLs, or contract-type detection when
34
+ the CLI exposes the operation. One EOA must have one serialized write sequence.
35
+ - Never send, mint, transfer, lower a cap, change authority, or apply a lock until the human confirms
36
+ the exact action. Locks, ownership transfers, and several deploy choices are irreversible.
37
+ - Never submit feedback, project data, logs, or agent/session context to ABX or a remote provider
38
+ until the human reviews the preview and approves that specific report. Redact credentials and
39
+ unrelated personal or project information. `abx feedback` previews by default; `--yes` sends.
40
+ - Never fold `abx submit-app` into deployment. Listing is a separate, optional post-deploy action.
41
+
42
+ ## Use the lifecycle
43
+
44
+ Follow this state machine instead of accumulating retries:
45
+
46
+ 1. **Discover** identify the working directory, CLI provenance/version, active chain, artifacts,
47
+ existing contract addresses, configured remote, and signer preference. Run `abx doctor` for a
48
+ deployment or unfamiliar environment.
49
+ 2. **Classify surfaces** — decide collection shape, runtime, required public surfaces, custody,
50
+ resolution, authority, mutability, and mint/sale timing. Use the model below.
51
+ 3. **Inspect** — run `abx capabilities --json`; for code run `abx inspect` and `abx preview`. For an
52
+ existing collection run `abx state`, `abx tokens`, `abx tokenuri`, and `abx verify` as relevant.
53
+ 4. **Plan** — use the selected deploy command with `--dry-run --json`. Read its normalized shape,
54
+ addresses, surface warnings, transaction count, storage activity, and irreversible choices back
55
+ to the creator. A dry run may perform read-only network probes; it must not send or store.
56
+ 5. **Confirm** confirm name, symbol, token standard, code-capable/static type, burnability,
57
+ ERC-721C/ERC-1155C enrollment, edition arithmetic, royalty ceiling, signer, costs, public URLs,
58
+ initial mint, and every requested lock.
59
+ 6. **Execute** — let the CLI sign and serialize the operation. Do not start a second write process
60
+ with the same EOA. Honor structured lifecycle states and terminal errors.
61
+ 7. **Verify** — verify the contract and each promised surface from its canonical path. Use on-chain
62
+ reads for self-resolving metadata and `abx verify`/remote status for hosted surfaces. Mint token 0
63
+ before expecting token-specific renders.
64
+ 8. **Operate**configure sales, publish renders, migrate, refresh marketplaces, transfer authority,
65
+ or lock only after verification. Record the contract address, chain, deploy block, custody,
66
+ resolution, owner powers, and remaining mutable surfaces.
67
+
68
+ When diagnosing, identify the current state and choose one next transition. Read
69
+ [diagnose.md](reference/diagnose.md); do not build a ladder of speculative retries.
70
+
71
+ ## Model the project by independent dimensions
72
+
73
+ Keep these concepts separate. Most bad ABX plans collapse two of them into “hosting.”
74
+
75
+ | Dimension | Decide |
76
+ |---|---|
77
+ | **Collection shape** | one work; N unique works; one or N ids with limited/open copies |
78
+ | **Runtime** | static media; JavaScript program; build directory; Solidity field renderer |
79
+ | **Public surfaces** | metadata, image, animation, traits, attachments, PostParams |
80
+ | **Custody** | on-chain bytes, Arweave, IPFS, cloud, or local development storage |
81
+ | **Resolution** | on-chain renderer, hosted resolver, or on-chain JSON pointing at external media |
82
+ | **Rendering** | no derived render, one-shot stills, continuous effects, or Solidity-computed fields |
83
+ | **Authority** | owner, token holder, delegated address, minter, hook, transfer validator |
84
+ | **Mutability** | editable values/pointers, governed values, and the locks applied after verification |
85
+
86
+ Use precise language:
87
+
88
+ - **On-chain bytes** describes custody. **Self-resolving** describes resolution.
89
+ - **Chain-complete** means the requested document has no off-chain dependency. It does not promise
90
+ immutability or that every third-party RPC can execute a large read.
91
+ - **Locked** names a particular stored value or pointer. It does not prove that code behind a proxy
92
+ is immutable or that every output input is frozen.
93
+ - Marketplace refresh re-fetches a projection; it does not mutate canonical state.
94
+
95
+ ## Choose the native deployment family
96
+
97
+ Run `abx capabilities --json` for the current matrix, then load [deploy.md](reference/deploy.md).
98
+
99
+ | Intent | Command | Default contract shape |
260
100
  |---|---|---|
261
- | **Express** *(default)* | demo, or pre-mint to your own wallet | `deploy` (mints #0) `serve` → `refresh` |
262
- | **Careful** *(real launch, off-chain resolver)* | metadata live the instant it's listable | `deploy --no-mint` `serve` (warm) → verify → `mint` → `refresh` |
263
- | **Primary sale** | token issued at point of sale | `deploy --no-mint` settle off-chain `mint --to <buyer>` → `refresh` |
264
-
265
- - **Fully on-chain mint at deploy; do NOT add `--no-mint`.** The careful path warms an *off-chain resolver*; a fully on-chain token has none (the renderer resolves the instant the contract exists). Deferring buys nothing and adds a tx. Defer an on-chain mint only for a genuine primary sale.
266
- - **`abx predict [--salt 0x..] [--for 0x..]`** pre-computes the address. No `--salt` → reserves a fresh, front-run-proof salt to the deployer; pass `--salt` for a vanity/known address. The salt's leading 20 bytes are an access guard: zero ⇒ anyone may deploy; non-zero ⇒ only that signer.
267
- - **The address depends on the salt — preview one, you MUST pin it.** Without `--salt`, every invocation (incl. `--dry-run`) reserves a *fresh* salt → a plain `deploy` lands at a different address than the dry-run showed. `--dry-run` prints the exact `--salt …` it used; pass that same salt to the real deploy. Never quote a previewed address without pinning its salt.
268
- - **`abx refresh <addr>`** asks marketplaces to re-index. We emit **ERC-4906** on URI changes so 4906-aware marketplaces self-refresh; `refresh` is the fallback (+ genesis mint). With `OPENSEA_API_KEY` it calls OpenSea directly; else it prints the links to click.
269
- - **There is no "add it to a marketplace" step — don't offer one.** Marketplaces discover the collection from chain (the mint + ERC-4906); `abx refresh` is the only nudge. Suggesting a manual listing implies work that doesn't exist.
270
- - A `--no-mint` deploy reconstructs + serves normally (dashboard shows #0 "not yet minted"; metadata/image already resolve).
271
- - **Etherscan source is already verified** your deploys are EIP-1167 clones Etherscan auto-recognizes as proxies of the verified implementation.
272
-
273
- ## What a token carries files beyond the image (the data plane)
274
-
275
- A token is **not "just a picture."** It anchors **named, typed files** ("artifacts"), and the served metadata JSON carries an **`artifacts`** list — the *complete* set of the token's files, each `{key, mimeType, uri}`. The `image` / `animation_url` are just reserved members of that same set; alongside them a token can carry a hi-res master, a certificate, source files, a README — any number of named files. (Background: [data plane](https://abx.docs.artblocks.io/protocol/data-plane/).)
276
-
277
- ```json
278
- "artifacts": [
279
- { "key": "image", "mimeType": "image/svg+xml", "uri": "…/image" },
280
- { "key": "print", "mimeType": "image/tiff", "uri": "ipfs://Qm…/master.tiff" },
281
- { "key": "readme", "mimeType": "text/markdown; charset=utf-8", "uri": "ar://…/README.md" }
282
- ]
283
- ```
284
-
285
- - **Attach a file:** `abx attach <addr> <key> <ipfs://… | ar://… | https://…>` — `<key>` is any name you choose (`print`, `certificate`, `stems`, `readme`) and becomes the manifest entry's key. The representation is **auto-detected** from the URI scheme; the `mimeType` is declared from the file **extension** (`…/master.tiff` → `image/tiff`), so point the URI at the file itself. Tiny bytes with no external host can go **on-chain** with `--file <path>`. Token scope by default; `--collection` for a collection-wide file. Any signing lane; `--dry-run` previews. It's one file per call, run **after deploy**.
286
- - **Don't have a URL yet? Upload first.** `attach` takes a locator you already host. `abx storage upload <path> --backend arweave|ipfs` uploads one file and prints a locator that **keeps the filename** (so the declared type survives) plus the ready-to-run `attach` line (Arweave = pay-once permanent; the same backends `deploy` uses; `--dry-run` to preview without uploading). Full flow: `abx storage upload master.tiff --backend arweave` → copy the printed locator → `abx attach <addr> print <that-locator>`.
287
- - **`artifacts` is COMPUTED, never a field you set.** The resolver/renderer assembles the list from your fields — setting a field literally named `artifacts` is refused. You attach one file per key; the manifest builds itself.
288
- - **The complete listing is a resolver surface.** A resolver serves the full `artifacts` list at `/t/<chainId>/<addr>/<id>`, and `/data/<key>` fetches each file. The bare on-chain `tokenURI` enumerates **reserved fields only** (there's no on-chain enumeration of arbitrary keys) — so a project that must surface extra files to consumers today runs a resolver (attached files are still stored on-chain + keccak-anchored regardless).
289
- - **Effect outputs are artifacts too.** A code project's effect runner publishes `render/image`, `render/traits`, and any extra declared output (e.g. a hi-res `render/print`) into the same manifest automatically, at the current settled state — files appear as tokens are minted and params change (see [code-projects](reference/code-projects.md)).
290
- - **Not the same as a Series.** `deploy-series` makes **N separate tokens, one file each**. The data plane is how **one** token holds several named files. Depth (representations, verify, reserved keys, on-chain-vs-resolver) → [operating.md](reference/operating.md#attaching-files--the-data-plane).
291
- - **Set expectations honestly (say it up front).** No mainstream marketplace (OpenSea/Blur) shows a "files" tab **today** — they render `image`/`animation_url` only. Attached files are a durable, cryptographically-anchored part of the token *now*, read by **data-plane-aware tools and any resolver**; broad marketplace display is future adoption. So a creator verifies an attach by **curling their resolver's listing**, not by refreshing OpenSea (which won't show it).
292
-
293
- ## After launch tell the creator (durability + owner care)
294
-
295
- Once it's live, cover these in plain language; don't wait to be asked.
296
-
297
- - **Durability depends on the backend.** Arweave = **pay once, kept for centuries** (a storage endowment funds ~200 years; resolves as long as the network + any gateway are up) — nothing to renew. IPFS/Pinata = **the creator must keep it pinned** — the image serves through their gateway, and if pinning lapses the bytes can disappear. `cloud`/`fs` = they maintain them. Say which one this drop uses and what it implies. For a real drop, lead toward Arweave (or start elsewhere and re-host later — bytes are keccak-anchored, so re-upload to the new backend + re-point with `set-field`, verified by `abx verify`).
298
- - **Moving backend/gateway later is an owner-signed on-chain edit.** The on-chain keccak anchors the bytes so they're portable, but re-pointing (`set-field`/`migrate`) is a tx from the **owner** wallet — so that wallet must stay secure and reachable.
299
- - **Owner-wallet hygiene (suggest as follow-ons).** The owner wallet controls mint, royalties, URIs, and ownership itself. Recommend: a hardware/dedicated wallet over a throwaway hot key; for anything valuable, hand ownership to a multisig (`abx set-admin <addr> --to <safe>`); and **back up `.abx-self-host/arweave-key.json`** — it holds any prepaid Turbo credits, lose it and they're stranded.
300
-
301
- ## Setup + environment
302
-
303
- `abx` needs **Node 22.5** at runtime (the projection store uses built-in SQLite).
304
-
305
- ### Find `abx` before you install it local first, then global
306
-
307
- **Resolve in this order and use the first hit.** Don't jump to a global install; a project-local CLI is pinned in the creator's `package.json` (reproducible, and what `abx skill install` version-locks against), so it wins whenever it exists:
308
-
309
- ```bash
310
- npx --no-install abx version # 1. project-local (./node_modules/.bin/abx) PREFER this
311
- abx version # 2. a global install already on PATH
312
- ```
313
-
314
- - **`--no-install` is mandatory on that probe.** The bare `abx` name on npm is an **unrelated squatted package** — a plain `npx abx` with nothing local would *download that*, not this CLI. `--no-install` makes the probe fail cleanly instead.
315
- - In the **abx source repo** (contributor), neither applies: use `pnpm abx <cmd>`, which runs the live `tsx` source.
316
-
317
- **Nothing found → install.** The package is **`@artblocks/abx-cli`** (not `@artblocks/abx-sdk` — that's the library, and installing it gets you no `abx` binary; a real session lost a cycle to exactly that mistake):
318
-
319
- | Situation | Install | Then invoke as |
320
- |---|---|---|
321
- | The creator has a project dir (a `package.json`) **default** | `npm install --save-dev @artblocks/abx-cli` | `npx abx …` |
322
- | No project, or they asked for a machine-wide tool | `npm install -g @artblocks/abx-cli` | `abx …` |
323
-
324
- Ask before installing **globally** it's a machine-wide change to their PATH, and the per-project install is the reversible one. A project install needs no permission beyond the usual.
325
-
326
- Whichever you land on, **keep using that same invocation for every command in the session** (`npx abx …` vs `abx …`) — don't mix them, or you'll silently drive two different CLI versions. Then run `abx doctor` (preflight: signing key/wallet, RPC, canonical factory, storage).
327
-
328
- `.env` (in the creator's project dir) = **secrets only**:
329
- - **Signing:** a key (`SEPOLIA_FUNDED_PK` / `ABX_DEPLOYER_PK` / `SEPOLIA_WALLET_PK`) is needed ONLY for hot/unattended signing. If the creator owns a wallet, prefer **`--sign`** — no key in `.env`. `doctor`'s missing-key ✗ is **not fatal** on the `--sign` path.
330
- - `ABX_RPC_URLS`, `ABX_PUBLIC_BASE_URL` (hosted-resolver custody only), optional `OPENSEA_API_KEY`, optional `ABX_RESOLVER_ADMIN_TOKEN` (`deploy-resolver` generates it), plus any backend secret.
331
-
332
- <sub>Working from the abx **source repo** (contributor)? `pnpm install`, then `pnpm abx <cmd>` or `pnpm sandbox`. Every command below is identical.</sub>
333
-
334
- **Indexing reads the event log via `eth_getLogs` from the contract's deploy block** — the CLI records it at deploy and forwards it to a resolver on `add` (discovering it on-chain for a contract it didn't deploy here). So a normal deploy→index scans a small, recent window and is fast on **any** RPC, and re-index is incremental (resumes from the last block). It **auto-chunks**, so a range cap never yields *wrong* state — but don't wave a cap away: a **from-genesis** or long-span reconstruction, or a resolver serving many code projects under load, is slow and rate-limit-prone on a getLogs-**range-capped** endpoint. `abx doctor` rates each endpoint and flags a capped one — treat that as a real infra signal, and give a resolver you'll run under load a range-generous **archive** RPC. **If indexing is slow, or a hosted resolver won't serve, check the scan floor FIRST (is it scanning from block 0?), not the RPC tier** — that mis-diagnosis is a known trap. RPC deep-dive + troubleshooting → [reference/setup.md](reference/setup.md).
335
-
336
- ## Reference files
337
-
338
- - **Public docs — the human-facing companion** at **https://abx.docs.artblocks.io** (quickstart, guides, the CLI/SDK reference, the protocol model). This skill is YOUR operating manual and stays authoritative for how to drive the CLI; the docs site is what you **link the creator to** for background/onboarding, and a place you can read if you want the protocol rationale behind a command. Don't send the creator commands to run (you run them) — send them the docs to *read*.
339
- - **Code projects — operating depth** (what to keep running, the resume loop, verify-it-resolves, render ops, `--onchain-uri`/`--image-base`/traits internals, arweave delay, `deploy-code` flags, mint timing/pause/supply) **[reference/code-projects.md](reference/code-projects.md)**
340
- - **Operating an existing project** (owner ops, **artist credit + license fields**, **attaching files / the data plane**, selling via the shared minter, `abx mint-page`, moving hosting, resolverresolver `migrate`) → **[reference/operating.md](reference/operating.md)**
341
- - **Hosting infrastructure** (storage backends, Turbo lanes + failure playbook, `deploy-resolver`, `deploy-effects`, local-vs-remote stores, token API routes, Docker) **[reference/hosting.md](reference/hosting.md)**
342
- - **Environment detail** (RPC selection + failover, multi-chain, troubleshooting) → **[reference/setup.md](reference/setup.md)**
343
- - **Troubleshooting "my NFT looks wrong"** (gray placeholder, stale-on-marketplace, tokenURI reverts, localhost baked, "not registered") — diagnose before acting → **[reference/troubleshooting.md](reference/troubleshooting.md)**
344
-
345
- ## Guarantees
346
-
347
- - **Reconstruction from chain alone** — deterministic, idempotent; delete the projection, replay yields identical state.
348
- - **Trust = the factory** — a clone is canonical only when the ownerless factory's `isAbxClone` confirms it (the `AbxDeployed` beacon is discovery, and spoofable).
349
- - **Content is verifiable** — the on-chain keccak256 lets anyone re-hash the served bytes (the `verify` route), zero trust in the node.
350
- - **Keys stay with their owner** — the wallet lane signs in the user's own wallet; the CLI never sees the key. Runtime data lives in `./.abx-self-host/` (gitignored).
351
-
352
- Protocol model + full docs → **https://abx.docs.artblocks.io** ([protocol](https://abx.docs.artblocks.io/protocol/), [using ABX](https://abx.docs.artblocks.io/using-abx/), [CLI/SDK reference](https://abx.docs.artblocks.io/reference/)).
101
+ | One static work | `abx deploy` | ERC-721 1/1 |
102
+ | Folder of distinct static works | `abx deploy-series` | ERC-721 Series |
103
+ | Program or state-derived work | `abx deploy-code` | ERC-721 SeriesCode |
104
+ | One program, each token carries its own data | `deploy-code --script` + `<key>:Bytes:Creator` | SeriesCode + payload param |
105
+ | Copies of any family | add `--copies <n|open>` | corresponding ERC-1155 edition |
106
+
107
+ Important boundaries:
108
+
109
+ - `deploy-code --copies` supports `--script`, dependencies, and Solidity image/attributes renderers.
110
+ It does not currently support `--code-dir`, `--image-base`, or `--resume`.
111
+ - `--onchain-image` works for static 721s and editions in hot or wallet-signing lanes. It cannot be
112
+ prepared as one cold `--unsigned` bundle because staged transactions depend on prior receipts.
113
+ - A code project may need no public host when its image/traits are computed by Solidity renderers.
114
+ A JavaScript program still needs a deliberate marketplace-image plan even when its animation is
115
+ chain-complete.
116
+ - Content size is not a fixed refusal. The CLI measures write cost and the active RPC's read reach.
117
+ State the measured reach; never generalize it to every marketplace endpoint.
118
+
119
+ ## Treat public surfaces as an acceptance test
120
+
121
+ Before deploying, write down the promised value for each applicable row:
122
+
123
+ | Surface | Verify with |
124
+ |---|---|
125
+ | Contract identity and owner powers | `abx state <addr>` and the deploy readout |
126
+ | Token metadata | `abx tokenuri <addr> --token <id>` |
127
+ | Collection metadata | `abx contracturi <addr>` |
128
+ | Image | decoded metadata plus a successful fetch or on-chain field provenance |
129
+ | Animation/live view | the decoded `animation_url`, loaded with a real minted token |
130
+ | Marketplace traits | decoded `attributes`, not merely console output from the program |
131
+ | Parameters and values | `abx state` for schemas; `abx tokens --json` for token values |
132
+ | Attached artifacts | resolver metadata and `/data/<key>`; attachments are not enumerable in bare on-chain metadata |
133
+ | Byte integrity | `abx verify <addr>` |
134
+ | Hosted lifecycle | `abx status --remote <name> --watch` or provider status |
135
+
136
+ Do not call a launch complete because the transaction mined. Complete it when every promised surface
137
+ has the expected provenance and is retrievable through the path collectors will use.
138
+
139
+ ## Confirm irreversible and shared-state choices
140
+
141
+ Before any real deploy, say these choices explicitly when relevant:
142
+
143
+ - The contract family and ERC-721 versus ERC-1155 edition shape cannot be changed later.
144
+ - Hooks and PostParams require a code-capable contract. A static image contract cannot gain them.
145
+ - `--burnable` and creator-token enrollment are deploy-time choices.
146
+ - A royalty cap only moves downward.
147
+ - Edition arithmetic is **number of ids × copies per id**. For one work with 100 copies, use one id;
148
+ do not accidentally create the code default's multiple-id space.
149
+ - An ERC-721 Series cap is lifetime minted ids: burning never reopens a slot. An ERC-1155 edition's
150
+ per-id cap is live supply: when burnable, a burned copy may be minted again.
151
+ - PostParams on an edition are stored per id, not per physical copy. A holder-authorized value is
152
+ shared by all holders of that id, and the last valid writer wins.
153
+ - Metadata, URI, script, dependency, hook, schema/value, and authority locks are distinct. Verify
154
+ first and lock last.
155
+
156
+ ## Use capability classification, not optimism or refusal
157
+
158
+ Classify an unusual request as exactly one of:
159
+
160
+ 1. **Native** — a documented CLI lane performs it.
161
+ 2. **Extension** a custom minter, configure/transfer/augment hook, field renderer, or seed source
162
+ performs it while the token remains a canonical factory clone.
163
+ 3. **Unsupported or foreclosed** — the capability contract lists it, or the existing collection's
164
+ irreversible type/flags already exclude it.
165
+ 4. **Unknown** — no route has been proven. Inspect code/help/contracts and report uncertainty; do not
166
+ turn absence from a no-list into a promise.
167
+
168
+ Custom Solidity is built and deployed outside `abx`; `abx scaffold-renderer` supplies a Foundry
169
+ starting point. Read [capabilities.md](reference/capabilities.md) before designing a custom mechanic.
170
+
171
+ ## Load only the reference needed
172
+
173
+ - Environment, installation, signer lanes, and safe setup → [setup.md](reference/setup.md)
174
+ - Static projects, editions, placement, costs, and deploy confirmation → [deploy.md](reference/deploy.md)
175
+ - Programs, renderers, thumbnails, traits, PostParams, seeds, and dependencies → [code.md](reference/code.md)
176
+ - First-party hosted services, OAuth device login, and core/provider feedback → [services.md](reference/services.md)
177
+ - Generic remotes, self-hosted resolvers/effects, storage, lifecycle, and migration → [hosting.md](reference/hosting.md)
178
+ - Existing-project reads, mint/sales, fields, transfers, authority, and locks [operate.md](reference/operate.md)
179
+ - Failure classification, resume, RPC/storage/rendering faults, and retry discipline → [diagnose.md](reference/diagnose.md)
180
+ - Capability questions, extension seams, mechanics, and hard boundaries → [capabilities.md](reference/capabilities.md)
181
+ - ERC-721C/ERC-1155C enrollment and validator operations → [creator-token.md](reference/creator-token.md)
182
+
183
+ Read every reference applicable to the requested workflow before sending a real transaction. Do not
184
+ load unrelated references merely because they exist.