Building Story CLI: From 30-Minute IP Registration to Under 5
Source: Dev.to
The problem that sparked this project
Here’s something that bothered me about Web3 developer tools: they’re often built by experienced blockchain developers for experienced blockchain developers.
In the case of IP registration via blockchain, if you’re a solo creator who just wants to register your artwork, music, or code as intellectual property on‑chain, you’re looking at 15–30 minutes of fumbling through documentation, manually formatting JSON metadata, and praying your transaction doesn’t fail after you’ve already spent gas.
I built Story CLI to fix that.
What I built
Story CLI is a command‑line toolkit for registering IP assets on Story Protocol — a blockchain designed specifically for programmable intellectual property. Instead of writing code or crafting API calls, you get an interactive wizard:
story register ./my-artwork.jpg
The CLI walks you through license selection, handles IPFS uploads, executes the blockchain transaction, and gives you a shareable portfolio visualization of all your registered IP.
Goal: take a 15–30 minute process and compress it to under 5 minutes.

1. The license wizard state machine
One of the trickiest parts was translating legal license configurations into something a human could answer in 30 seconds. Story Protocol uses PIL (Programmable IP License) with multiple parameters—commercial use permissions, derivative rights, royalty percentages.
I mapped this to a three‑question decision tree:
Commercial use? → Yes/No
Allow derivatives? → Yes/No
Revenue share? → 0‑100% (only if commercial + derivatives)
These three questions deterministically map to one of four license configurations:
| Commercial | Derivatives | Result |
|---|---|---|
| No | No | Non‑commercial Only |
| No | Yes | Non‑commercial Derivatives |
| Yes | No | Commercial No‑Derivatives |
| Yes | Yes | Commercial Remix (+ royalty %) |
The state‑machine approach lets me validate answers in real‑time and prevent invalid combinations before they ever hit the blockchain.

2. Fail‑fast everything
Blockchain transactions cost gas, and failed transactions still consume gas. This created a design imperative: validate everything before touching the chain.
- Wallet address format? Checked before any network call.
- IPFS hash format? Validated at input.
- Sufficient balance? Queried before transaction submission.
- Royalty percentage? Bounded 0‑100 % at prompt time.
The philosophy: if something’s going to fail, fail in the first 2 seconds, not after a 30‑second transaction attempt.
3. Three‑part error messages
Every error in Story CLI follows a structure: What went wrong → Why it matters → How to fix it.
✖ Pinata API key not found
IPFS uploads require Pinata authentication for metadata storage.
Run: story config set pinataApiKey YOUR_KEY
Most CLI tools just dump “Error: invalid credentials” and leave you to figure it out. I spent real time ensuring every failure state had actionable guidance.
4. Self‑contained portfolio HTML
After registration, users need to see their IP. I chose Mermaid.js for graph visualization because it lets me generate a single HTML file with everything embedded—CSS, JavaScript, and relationship diagrams.
No server required. Download the file, email it to someone, and open it. It works.
story portfolio
# → generates story-portfolio.html with interactive graphs
The trade‑off was less visual customization than D3.js would offer, but for an MVP, shipping > perfection.
Challenges & what I learned
Challenge 1: SDK documentation gaps
Story Protocol is relatively new. The SDK documentation had gaps—especially around error responses and edge cases. I ended up reading SDK source code directly and building a mock implementation (STORY_CLI_MOCK=true) so I could develop offline without burning testnet ETH.
Lesson: When integrating new SDKs, budget time for exploration. Mock modes aren’t just for testing—they’re essential for iteration speed.
Challenge 2: Terminal UX is harder than it looks
Making a CLI feel “good” requires attention to details you take for granted in web UIs:
- Spinners during async operations (Ora)
- Color‑coded output for visual hierarchy (Chalk)
- Boxed success messages for celebration moments (Boxen)
- Clear prompt validation with inline feedback (Inquirer)
Each library handles a specific UX need. Combining them into a cohesive experience took more iteration than expected.
Lesson: CLI UX is a real discipline. Users notice when it’s done well—they just don’t notice consciously.
Challenge 3: Config file security
Storing API keys and wallet information in ~/.storyrc required thinking about permissions. The config file is created with chmod 600 (owner read/write only), and sensitive values can be overridden via environment variables for CI/CD pipelines.
export STORY_WALLET_PRIVATE_KEY=0x... # Override config file
story register ./asset.png
Lesson: Security isn’t a feature—it’s a constraint that shapes your entire design.
The Tech Stack

Architecture at a glance
flowchart TD
A[User terminal] --> B[Command router (Commander.js)]
B --> C[Register command]
C --> D[License wizard (Inquirer.js)]
C --> E[Metadata prompts]
C --> F[IPFS upload (Pinata SDK)]
C --> G[Blockchain transaction (Story SDK)]
B --> H[Portfolio command]
H --> I[Asset fetching (Story API)]
H --> J[Graph building (Mermaid.js)]
H --> K[HTML rendering]
B --> L[Config command]
L --> M[~/.storyrc management]
B --> N[Status command]
N --> O[Wallet & network info]
Key patterns used
- Command pattern – each CLI command is an isolated handler.
- Facade pattern –
StoryClientwraps the complex SDK. - Singleton pattern –
ConfigManagerprevents redundant file reads. - Fail‑fast validation – errors surface immediately, not after blockchain calls.
Why this matters (Beyond the code)
IP registration on blockchain is one of those “obviously useful” ideas that’s been stuck behind technical barriers. The people who would benefit most—independent artists, open‑source developers, content creators—are often the least equipped to navigate Web3 tooling.
Story CLI is my attempt at a bridge. Not a dumbed‑down version, but a streamlined, secure, and user‑friendly way for creators to claim ownership of their work on‑chain with minimal friction.