Observed since 21 Oct, 11:36 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
@0xsota/storyx-cli
StoryX CLI — IP lifecycle toolkit for Story Protocol. Built by bernieio a.k.a 0xsota.
Fast IP lifecycle toolkit for Story Protocol — Create, manage, and license IP assets on Story Protocol blockchain with ease.
npm install -g @0xsota/storyx-cli
storyx --version
# 0.1.0-beta.3.1
storyx init
This will:
Example:
? Profile name: my-profile
? Network: Story Aeneid (Testnet)
? RPC URL: https://aeneid.storyrpc.io
? Explorer URL: https://aeneid.storyscan.io
? Enable telemetry: No
? Enter passphrase: ********
? Confirm passphrase: ********
✓ StoryX CLI initialized successfully!
Profile: my-profile
Network: story-aeneid
Address: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
Config: ~/.storyx/config.json
Visit the Story Protocol faucet:
https://faucet.story.foundation
storyx ip:create --title "My First IP" --tags "art,nft"
Output:
✓ IP Asset created successfully!
IP ID: 0x1234567890abcdef...
Transaction: 0xabcdef1234567890...
Explorer: https://aeneid.storyscan.io/tx/0xabcdef...
storyx ip:list --limit 10
storyx initInitialize StoryX CLI configuration (interactive setup).
storyx init
storyx profileManage profiles.
# List all profiles
storyx profile list
# Create new profile
storyx profile create <name>
# Switch profile
storyx profile switch <name>
# Delete profile
storyx profile delete <name>
storyx networkManage network configurations.
# List networks
storyx network list
# Set network
storyx network set --rpc <url> --chain-id <id> --explorer <url>
storyx keysManage private keys.
# Create new key
storyx keys create
# Import existing key
storyx keys import --private-key <key>
# Export key
storyx keys export
storyx ip:createCreate a new IP asset.
storyx ip:create --title <title> [options]
Options:
--title <string> - IP asset title (required)--tags <string> - Comma-separated tags (e.g., "art,music,nft")--metadata-file <path> - Path to metadata JSON file--dry-run - Simulate without executing transactionExample:
storyx ip:create --title "My Artwork" --tags "art,digital" --metadata-file ./metadata.json
storyx ip:listList IP assets.
storyx ip:list [options]
Options:
--owner <address> - Filter by owner address--limit <number> - Maximum results (default: 10)--json - Output as JSONExample:
storyx ip:list --owner 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb --limit 5
storyx ip:showShow IP asset details.
storyx ip:show <ip-id>
Example:
storyx ip:show 0x1234567890abcdef...
Output:
IP Asset Details
================
ID: 0x1234567890abcdef...
Title: My Artwork
Owner: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
Created: 2024-01-15T10:30:00Z
Metadata URI: ipfs://...
Parents: 0
Children: 2
- 0xabcdef1234567890...
- 0x9876543210fedcba...
storyx ip:linkLink IP assets (create derivative relationship).
storyx ip:link --parent <parent-id> --child <child-id> [options]
Options:
--parent <string> - Parent IP asset ID (required)--child <string> - Child IP asset ID (required)--relation <string> - Relationship type: "derivative" or "remix" (default: "derivative")--dry-run - Simulate without executingExample:
storyx ip:link --parent 0x1234... --child 0x5678... --relation derivative
storyx ip:treeDisplay IP asset lineage tree.
storyx ip:tree --id <ip-id> [options]
Options:
--id <string> - Root IP asset ID (required)--depth <number> - Tree depth (default: 10)--format <string> - Output format: "ascii" or "json" (default: "ascii")Example:
storyx ip:tree --id 0x1234... --depth 3
Output:
0x1234567890abcdef... (My Original IP)
├── 0xabcdef1234567890... (Remix #1)
│ └── 0x9876543210fedcba... (Remix #1.1)
└── 0x5678901234abcdef... (Remix #2)
storyx license:templatesList available PIL license templates.
storyx license:templates
Output:
Available License Templates
===========================
Name PIL Type Description
Non-Commercial Social Remixing non-commercial-social-remixing Free to remix and share, but no commercial use
Commercial Use commercial-use Commercial use allowed, no derivatives
Commercial Remix commercial-remix Commercial derivatives with revenue sharing
storyx license:createAttach license to IP asset.
storyx license:create --ip <ip-id> --preset <preset> [options]
Options:
--ip <string> - IP asset ID (required)--preset <string> - License preset: "non-commercial-social-remixing", "commercial-use", "commercial-remix", or "custom"--terms-file <path> - Custom license terms JSON file (for "custom" preset)--dry-run - Simulate without executingExample:
# Use preset
storyx license:create --ip 0x1234... --preset non-commercial-social-remixing
# Custom terms
storyx license:create --ip 0x1234... --preset custom --terms-file ./terms.json
storyx license:applyMint license tokens.
storyx license:apply --ip <ip-id> --license <license-id> [options]
Options:
--ip <string> - IP asset ID (required)--license <string> - License ID (required)--amount <number> - Number of tokens to mint (default: 1)--dry-run - Simulate without executingExample:
storyx license:apply --ip 0x1234... --license 1 --amount 5
storyx scaffold:projectGenerate a new Story Protocol project.
storyx scaffold:project <project-name>
Example:
storyx scaffold:project my-story-app
cd my-story-app
npm install
npm run dev
Generated Structure:
my-story-app/
├── src/
│ └── index.ts # Main entry point with examples
├── .env.example # Environment variables template
├── package.json
├── tsconfig.json
└── README.md
~/.storyx/config.json
{
"defaultProfile": "my-profile",
"telemetry": false,
"profiles": [
{
"name": "my-profile",
"network": "story-aeneid"
}
],
"networks": [
{
"name": "story-aeneid",
"rpcUrl": "https://aeneid.storyrpc.io",
"chainId": 1315,
"explorerUrl": "https://aeneid.storyscan.io",
"spgNftContract": "0xc32A8a0FF3beDDDa58393d022aF433e78739FAbc"
}
]
}
Story Mainnet:
https://mainnet.storyrpc.io1514https://storyscan.io0x98971c660ac20880b60F86Cc3113eBd979eb3aAEStory Aeneid Testnet:
https://aeneid.storyrpc.io1315https://aeneid.storyscan.io0xc32A8a0FF3beDDDa58393d022aF433e78739FAbcStoryX CLI includes three built-in PIL (Programmable IP License) templates:
Use case: Free sharing and remixing, no commercial use
Terms:
Example:
storyx license:create --ip 0x1234... --preset non-commercial-social-remixing
Use case: Commercial use allowed, no derivatives
Terms:
Example:
storyx license:create --ip 0x1234... --preset commercial-use
Use case: Commercial derivatives with revenue sharing
Terms:
Example:
storyx license:create --ip 0x1234... --preset commercial-remix
Create a metadata JSON file:
{
"name": "My Artwork",
"description": "A beautiful digital artwork",
"image": "ipfs://QmX...",
"attributes": [
{
"trait_type": "Artist",
"value": "Bernie"
},
{
"trait_type": "Style",
"value": "Abstract"
}
]
}
Use with IP creation:
storyx ip:create --title "My Artwork" --metadata-file ./metadata.json
Create a terms JSON file:
{
"transferable": true,
"commercialUse": true,
"derivativesAllowed": true,
"derivativesAttribution": true,
"commercialRevShare": 10,
"uri": "https://example.com/license-terms.json"
}
Use with license creation:
storyx license:create --ip 0x1234... --preset custom --terms-file ./terms.json
Test commands without executing transactions:
storyx ip:create --title "Test" --dry-run
storyx ip:link --parent 0x1234... --child 0x5678... --dry-run
storyx license:create --ip 0x1234... --preset commercial-use --dry-run
Get machine-readable output:
storyx ip:list --json > ips.json
storyx ip:tree --id 0x1234... --format json > tree.json
Enable detailed logging:
storyx -v ip:create --title "My IP"
storyx --verbose ip:list
Error: Insufficient funds. Get testnet tokens at: https://faucet.story.foundation
Solution: Visit the faucet and request testnet tokens for your address.
Error: Private key required for write operations. Run: storyx keys import
Solution: Import or create a private key:
storyx keys import --private-key <your-key>
# or
storyx keys create
Error: IP Asset not found: 0x1234...
Solution: Verify the IP asset ID is correct and exists on the network.
Error: Network error. Check your connection and RPC endpoint configuration.
Solution: Check your internet connection and RPC URL:
storyx network list
storyx network set --rpc https://aeneid.storyrpc.io
# 1. Initialize
storyx init
# 2. Create original IP
storyx ip:create --title "Original Artwork" --tags "art,original"
# Output: IP ID: 0xAAA...
# 3. Create derivative IP
storyx ip:create --title "Remix Artwork" --tags "art,remix"
# Output: IP ID: 0xBBB...
# 4. Link derivative to original
storyx ip:link --parent 0xAAA... --child 0xBBB... --relation derivative
# 5. Attach license to original
storyx license:create --ip 0xAAA... --preset commercial-remix
# 6. View IP tree
storyx ip:tree --id 0xAAA... --depth 3
# 7. List all your IPs
storyx ip:list --owner <your-address> --limit 20
# Create testnet profile
storyx profile create testnet
storyx network set --rpc https://aeneid.storyrpc.io --chain-id 1315
# Create mainnet profile
storyx profile create mainnet
storyx network set --rpc https://mainnet.storyrpc.io --chain-id 1514
# Switch between profiles
storyx profile switch testnet
storyx ip:list
storyx profile switch mainnet
storyx ip:list
Contributions are welcome! Please feel free to submit a Pull Request.
# Clone repository
git clone https://github.com/bernieio/storyx-cli.git
cd storyx-cli
# Install dependencies
npm install
# Build
npm run build
# Run locally
npm start
# Run tests
npm test
MIT License - see LICENSE file for details.
Bernie (bernieio / 0xsota)
If you find this tool useful, please consider:
Built with ❤️ for the Story Protocol ecosystem
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
viemEnvironment{
"local_name": "viem",
"alias": false,
"peer_metadata": null
} | ^2.39.0 | runtime |
chalkEnvironment{
"local_name": "chalk",
"alias": false,
"peer_metadata": null
} | ^5.6.2 | runtime |
dotenvEnvironment{
"local_name": "dotenv",
"alias": false,
"peer_metadata": null
} | ^17.2.3 | runtime |
ethersEnvironment{
"local_name": "ethers",
"alias": false,
"peer_metadata": null
} | ^6.15.0 | runtime |
figletEnvironment{
"local_name": "figlet",
"alias": false,
"peer_metadata": null
} | ^1.9.3 | runtime |
inquirerEnvironment{
"local_name": "inquirer",
"alias": false,
"peer_metadata": null
} | ^9.2.15 | runtime |
commanderEnvironment{
"local_name": "commander",
"alias": false,
"peer_metadata": null
} | ^14.0.2 | runtime |
@story-protocol/core-sdkEnvironment{
"local_name": "@story-protocol/core-sdk",
"alias": false,
"peer_metadata": null
} | ^1.4.1 | runtime |
@story-protocol/react-sdkEnvironment{
"local_name": "@story-protocol/react-sdk",
"alias": false,
"peer_metadata": null
} | ^1.1.0-stable | runtime |
jestEnvironment{
"local_name": "jest",
"alias": false,
"peer_metadata": null
} | ^29.7.0 | development |
eslintEnvironment{
"local_name": "eslint",
"alias": false,
"peer_metadata": null
} | ^8.57.0 | development |
nodemonEnvironment{
"local_name": "nodemon",
"alias": false,
"peer_metadata": null
} | ^3.1.11 | development |
ts-jestEnvironment{
"local_name": "ts-jest",
"alias": false,
"peer_metadata": null
} | ^29.2.5 | development |
ts-nodeEnvironment{
"local_name": "ts-node",
"alias": false,
"peer_metadata": null
} | ^10.9.2 | development |
prettierEnvironment{
"local_name": "prettier",
"alias": false,
"peer_metadata": null
} | ^3.3.3 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.9.3 | development |
@types/jestEnvironment{
"local_name": "@types/jest",
"alias": false,
"peer_metadata": null
} | ^29.5.12 | development |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | ^24.10.1 | development |
@types/chalkEnvironment{
"local_name": "@types/chalk",
"alias": false,
"peer_metadata": null
} | ^0.4.31 | development |
@types/dotenvEnvironment{
"local_name": "@types/dotenv",
"alias": false,
"peer_metadata": null
} | ^6.1.1 | development |
@types/nodemonEnvironment{
"local_name": "@types/nodemon",
"alias": false,
"peer_metadata": null
} | ^1.19.6 | development |
@types/inquirerEnvironment{
"local_name": "@types/inquirer",
"alias": false,
"peer_metadata": null
} | ^9.0.7 | development |
@types/commanderEnvironment{
"local_name": "@types/commander",
"alias": false,
"peer_metadata": null
} | ^2.12.0 | development |
eslint-config-prettierEnvironment{
"local_name": "eslint-config-prettier",
"alias": false,
"peer_metadata": null
} | ^9.1.0 | development |
eslint-plugin-prettierEnvironment{
"local_name": "eslint-plugin-prettier",
"alias": false,
"peer_metadata": null
} | ^5.2.1 | development |
@typescript-eslint/parserEnvironment{
"local_name": "@typescript-eslint/parser",
"alias": false,
"peer_metadata": null
} | ^7.18.0 | development |
@typescript-eslint/eslint-pluginEnvironment{
"local_name": "@typescript-eslint/eslint-plugin",
"alias": false,
"peer_metadata": null
} | ^7.18.0 | development |
Source distribution
{
"shasum": "d612dd5adb09a9132764533a926c30ce39a3eaba",
"tarball": "https://registry.npmjs.org/@0xsota/storyx-cli/-/storyx-cli-0.1.0-beta.2.tgz",
"fileCount": 32,
"integrity": "sha512-QPalTg7W73wdJvgCTdWdvtyhFaSt4y8mgMeIu/wP7tbQMrj4JtbhPQnPxmqjXUDSizVEUpmP0/BQHfsab4kEAw==",
"signatures": [
{
"sig": "MEUCIQCsMSb5WdUraTWXRXSd5Y4LjYj+9ckoGW4cJDv7MD9wLAIgG+xYIMIoT+4BhcUMiKCTHTlMNx1c1JOTqVfUttMYs6c=",
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
}
],
"unpackedSize": 108531
}Observed since 21 Oct, 11:36 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:8d42caf61fe34ea5abdcab0e24075f2d90454a7bc610b0a67e21fb465916c4d6