.cursor/skills/0g-storage/SKILL.md
Integrate 0G decentralized storage using Go/TypeScript SDKs. Use when uploading, downloading, or managing files and key-value data on 0G Storage.
npx skillsauth add fabianferno/caas 0g-storageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Integrate 0G's decentralized storage — 95% cheaper than AWS S3, with 200 MBPS retrieval, erasure coding, and both immutable (Log) and mutable (KV) storage layers.
# Clone starter kit
git clone https://github.com/0gfoundation/0g-storage-ts-starter-kit
cd 0g-storage-ts-starter-kit && pnpm install
cp .env.example .env # Add your PRIVATE_KEY
pnpm run upload -- ./file.txt
pnpm add @0gfoundation/0g-ts-sdk ethers
import { ZgFile, Indexer, MemData } from '@0gfoundation/0g-ts-sdk';
import { ethers } from 'ethers';
// Turbo indexer (recommended):
const RPC_URL = 'https://evmrpc-testnet.0g.ai'; // or https://evmrpc.0g.ai for mainnet
const INDEXER_RPC = 'https://indexer-storage-testnet-turbo.0g.ai'; // or https://indexer-storage-turbo.0g.ai for mainnet
const provider = new ethers.JsonRpcProvider(RPC_URL);
const signer = new ethers.Wallet('YOUR_PRIVATE_KEY', provider);
const indexer = new Indexer(INDEXER_RPC);
async function uploadFile(filePath: string) {
const file = await ZgFile.fromFilePath(filePath);
const [tree, treeErr] = await file.merkleTree();
if (treeErr) throw new Error(`Merkle tree error: ${treeErr}`);
console.log("Root Hash:", tree?.rootHash());
const [tx, uploadErr] = await indexer.upload(file, RPC_URL, signer);
if (uploadErr) throw new Error(`Upload error: ${uploadErr}`);
await file.close();
return tx;
}
const data = new TextEncoder().encode('Hello, 0G Storage!');
const memData = new MemData(data);
const [tree, treeErr] = await memData.merkleTree();
const [tx, err] = await indexer.upload(memData, RPC_URL, signer);
async function downloadFile(rootHash: string, outputPath: string) {
const err = await indexer.download(rootHash, outputPath, true); // withProof=true
if (err) throw new Error(`Download error: ${err}`);
}
import { Batcher, KvClient } from '@0gfoundation/0g-ts-sdk';
// Upload KV data
async function uploadToKV(streamId: string, key: string, value: string) {
const [nodes, err] = await indexer.selectNodes(1);
if (err) throw new Error(`Error selecting nodes: ${err}`);
const batcher = new Batcher(1, nodes, flowContract, RPC_URL);
const keyBytes = Uint8Array.from(Buffer.from(key, 'utf-8'));
const valueBytes = Uint8Array.from(Buffer.from(value, 'utf-8'));
batcher.streamDataBuilder.set(streamId, keyBytes, valueBytes);
const [tx, batchErr] = await batcher.exec();
if (batchErr) throw new Error(`Batch execution error: ${batchErr}`);
}
import { Blob as ZgBlob, Indexer } from '@0gfoundation/0g-ts-sdk';
import { BrowserProvider } from 'ethers';
const provider = new BrowserProvider(window.ethereum);
await provider.send('eth_requestAccounts', []);
const signer = await provider.getSigner();
const zgBlob = new ZgBlob(fileInput.files[0]);
const [tree, treeErr] = await zgBlob.merkleTree();
const indexer = new Indexer(INDEXER_RPC);
const [tx, err] = await indexer.upload(zgBlob, RPC_URL, signer);
Note: Browser downloads need
StorageNode.downloadSegmentByTxSeq()— see starter kitweb/src/storage.ts. Vite/Webpack require Node.js polyfills (vite-plugin-node-polyfills).
go get github.com/0gfoundation/0g-storage-client
import (
"github.com/0gfoundation/0g-storage-client/common/blockchain"
"github.com/0gfoundation/0g-storage-client/indexer"
"github.com/0gfoundation/0g-storage-client/transfer"
"github.com/0gfoundation/0g-storage-client/core"
)
w3client := blockchain.MustNewWeb3(evmRpc, privateKey)
defer w3client.Close()
indexerClient, _ := indexer.NewClient(indRpc, indexer.IndexerClientOption{})
// Upload
file, _ := core.Open(filePath)
defer file.Close()
opt := transfer.UploadOption{
ExpectedReplica: 1, TaskSize: 10, SkipTx: true,
FinalityRequired: transfer.TransactionPacked,
FastMode: true, Method: "min", FullTrusted: true,
}
txHashes, roots, _ := indexerClient.SplitableUpload(ctx, w3client, file, 4*1024*1024*1024, opt)
// Download
indexerClient.Download(ctx, rootHash.String(), outputPath, true)
0x62D4144dB0F0a6fBBaeb6296c785C71B3D57C5260xCd01c5Cd953971CE4C2c9bFb95610236a7F414fe0x457aC76B58ffcDc118AABD6DbC63ff90728808700x22E03a6A89B950F1c82ec5e74F8eCa321a1052960x00A9E9604b0538e06b268Fb297Df333337f9593b0xA97B57b4BdFEA2D0a25e535bd849ad4e6C440A69development
Guides integration and answers about the Ethereum Name Service using official ENS documentation. Use when working with ENS, .eth names, resolvers, reverse resolution, primary names, text records, multichain ENS, CCIP Read, Name Wrapper, ENSIPs, SIWE with ENS, subgraphs, or ENS DAO governance docs.
testing
Entry point for the 0G (Zero Gravity) decentralized AI stack. Use when the user mentions 0G, 0g labs, Galileo testnet, 0g chain, 0g storage, 0g compute, 0g DA, INFT, ERC-7857, DePIN, or alignment nodes; route to the focused skill below or official docs.
development
Build INFTs (Intelligent NFTs) with ERC-7857 for tokenizing AI agents. Use when creating, transferring, or integrating AI agent NFTs with encrypted intelligence.
devops
0G DePIN GPU infrastructure via io.net and Aethir. Use when leveraging decentralized GPU networks for AI compute or understanding 0G's infrastructure partners.