Docs
Selling an item
A listing describes something reusable: where it lives, what it does, under what licence and at what price. Buyers' plans pick it up when its capabilities match their goal. On the hosted app you publish through a form, an import or the API. On a self-hosted node a listing is a signed item you publish from the CLI.
Where you can sell today. You can publish, import and version listings on the hosted app, free or with a price. Nobody can buy a paid listing there yet: checkout, orders, earnings and payouts are coming soon, and the files of a paid listing stay locked, except files the owner marks as previews. Escrow, delivery and payout work only on a self-hosted node or in the simulator, and there they run in test mode: no real money moves. Bundled listings labelled DEMO are examples with placeholder addresses. Never send funds to them.
What you can list
On the hosted app: repo, skill, harness, mcp_server, model, dataset, prompt or template. On a node: any item kind except paper, which includes design. Free and paid listings use the same form. A price of zero means free: it never enters escrow and earns no fee. A price above zero means every buyer deposits it into escrow first. Escrow runs in test mode only, so no real money changes hands yet.
List what you own or are licensed to resell. Do not list someone else's open-source project as yours. Free items found on GitHub, the MCP registry and Hugging Face already appear in plans without any action from you.
Publish on the hosted app
Sign in, then open /app/new (or Publish in the app). Everything on the form can be edited after you publish, except the kind and the URL name. If you belong to an organization, a Publish as menu lets you choose it as the owner; you need the write role or higher there.
| Field | Required | Description |
|---|---|---|
kind | Yes | One of the eight kinds above. Cannot be changed later. |
title | Yes | Up to 120 characters. Shown in lists and search. |
slug | Derived from the title | The name in the URL: /app/OWNER/SLUG. Lowercase letters, digits, dots, underscores and hyphens, up to 100 characters. Cannot be changed later. A taken name is refused, including the name of an item that was deleted. |
summary | In the form | Up to 280 characters. Say what it does. Title, summary, tags and capabilities are what search reads. |
license | In the form | One of: MIT, Apache-2.0, BSD-3-Clause, BSD-2-Clause, ISC, MPL-2.0, LGPL-3.0, GPL-3.0, AGPL-3.0, CC0-1.0, CC-BY-4.0, CC-BY-SA-4.0, CC-BY-NC-4.0, Unlicense, OpenRAIL, Commercial-Single-Project, Commercial-Team, Proprietary, UNKNOWN. Declared by you and not checked. |
capabilities | No, up to 8 in the form | Ids from the capability list. They feed the planner and the capability filter on Explore. |
tags | No | Up to 20 tags of up to 40 characters. |
visibility | Default public | public is listed and searchable. unlisted is reachable by URL only. private is visible to you and to organization members. |
pricing_model, price_cents | Default free | free, fixed or pwyw (pay what you want, with a minimum). A price runs from $1.00 to $1,000.00. Paid listings need a verified email address. |
source_url, homepage_url | No | Where the code lives and where its documentation is. |
install | No | For an MCP server, the command, arguments, environment placeholders or URL; for anything else, one install command. Shown on the item page. Up to 4 KB. Use placeholders such as <your-api-key> and never paste a secret: this text is public. |
readme | No | Markdown, up to 100,000 characters. Images must be https links. |
The form saves an unpublished draft in your browser and checks the URL name as you type. The same listing can be created with POST /api/items and a token that has the write scope. Only kind and title are required there, and the API does not require a licence, so a listing made without one is stored as UNKNOWN. You can publish 30 new listings and import 20 repositories per hour.
Import from GitHub
Open /app/new/import and paste a public repository link such as https://github.com/owner/repo. The Worker reads the repository's name, description, licence, topics, star count, homepage and README from GitHub, creates a public listing and takes you to it. Check it afterwards: you can edit everything except the kind and the URL name.
- The kind is
mcp_serverwhen the repository has the topicmcp-server, otherwiserepo. You can choose another kind before importing. - Capabilities are inferred from the name, description, topics and README, unless you pick up to eight yourself.
- The licence is taken from GitHub when it is on the list above, otherwise
UNKNOWN. That adds risk to every plan that uses the listing, so set it if you know it. - The install command is set to
git cloneof the repository. The GitHub star count is shown as GitHub stars. - Code files, issues and releases stay on GitHub. Add files later as a version. Private repositories cannot be imported, and importing the same repository twice under one owner is refused.
- The API call is
POST /api/items/importwith{"url": "https://github.com/owner/repo"}and optionalowner,kindandcapabilities.
Versions and files
A listing can exist without files, as an index entry that points at its source. To host files, add a version from the item's Release page, or while publishing in the form. A version is an immutable snapshot of its files.
- The version is a semantic version such as
1.2.0. Publishing the same number twice is refused. - Limits per version: 100 files, 512 KB per file and 2 MB in total. Paths cannot contain
..or start with/. - The content hash is a SHA-256 over the sorted paths and file hashes, shown with the version. You can yank a version: it stays reachable but is no longer chosen as the latest.
- Anyone can fetch a free public listing's files:
GET /api/items/OWNER/SLUG/bundlereturns the latest version as JSON, andGET /api/items/OWNER/SLUG/raw/VERSION/PATHreturns one file. - Publishing from a script:
POST /api/items/OWNER/SLUG/versionswith{"version", "changelog", "files": [{"path", "content"}]}. Use a token with thewritescope. See API tokens.
The Use this menu on an item page also shows a reuseforge pull OWNER/SLUG command. The command line tool behind it is in the repository (cli/, version 0.1.0) and is not installed from the site, so use the REST bundle line from the same menu.
Listings on a self-hosted node
The sections from here to the end of the page describe a self-hosted node, where a listing is a signed item (the node calls it a block, so its CLI, routes and JSON fields keep that word) and the escrow steps work in test mode.
Item fields
| Field | Required | Description |
|---|---|---|
name | Yes | Display name. Together with your key it makes the item id, so renaming creates a new item. |
kind | Yes | repo, skill, harness, mcp_server, dataset, design or model. |
summary | Yes | What it does, in one or two plain sentences. Name, summary and capabilities are what search and the planner read. |
url | Yes | Where the code or listing lives. Shown to buyers; only http and https links are made clickable. |
capabilities | No, but needed to be planned | List of capability tags. Tags are lowercased and hyphenated. A declared capability is the strongest match signal. |
license | No | SPDX id such as MIT, or a commercial label. Default UNKNOWN, which adds risk. |
price_usd | No | 0 for free. Never negative. |
payout | For any rail but the simulated one | Map of rail to address. See Payout addresses. |
version | No | Free text, default 0.0.0. |
content_hash | Recommended for paid listings | The git commit or tarball hash the price refers to. Buyers compare what they receive to it. |
signals | No | Numbers that feed quality: tests_pass_rate (0 to 1), stars, downloads, citations. Self-reported until verified. |
project_id | No | Id of a crowdfunded build whose unit holders should share this item's revenue. |
Set by the system, ignored if you send them: owner (your public key, from the signature), id, rating and rating_count.
Publish an item from the CLI
{
"name": "invoice-extractor",
"kind": "skill",
"summary": "Extracts line items, totals and tax ids from PDF invoices into JSON.",
"url": "https://github.com/acme/invoice-extractor",
"capabilities": ["document-parsing", "data-analysis"],
"license": "MIT",
"price_usd": 18,
"version": "1.2.0",
"content_hash": "sha256:9f2c1e0a",
"payout": { "usdc-base": "0x0000000000000000000000000000000000000001" },
"signals": { "tests_pass_rate": 0.96 }
}python -m repoblock publish block.json --as acme # signs with the key "acme" and prints the block--as names one of the identities in your node's key folder, created on first use. A running node does not see CLI writes until it restarts. To publish into a running node, post the same JSON, plus an identity field, to POST /api/blocks. Publishing again under the same name and key replaces the earlier version.
Licences
The licence is what you declare, on the hosted app and on a node. ReuseForge does not scan your code or confirm the declaration. Be accurate:
- An
UNKNOWNor missing licence adds 0.4 risk to every plan that uses the item. Declaring a real licence is the cheapest way to rank higher. - For paid code, state the terms you grant in the repository and in the delivery. The bundled demo listings use the label
Commercial-Single-Projectto mean one project per purchase. ReuseForge does not define or enforce that term for you. - The planner does not yet check that the licences of the items in one plan are compatible with each other. That check is open work. Buyers are told each item's licence and have to read them.
Payout addresses
In test mode nothing is sent to these addresses. payout maps a rail id to the address that should receive your money on that rail: usdc-base (an address on Base), usdt-ethereum (an Ethereum address), btc (a Bitcoin address). Give one per rail you accept.
- The simulated rail needs no address. It pays to your public key.
- On any other rail, a buyer cannot create an order for your item unless it has an address for that rail.
- The address is copied into each order when it is created. Changing your listing later does not change orders already in flight.
- On-chain transfers cannot be undone. A wrong address loses the money. Test with a small price first, once real rails are enabled.
Delivery
When a buyer's deposit is confirmed, you have until the delivery deadline (7 days by default) to deliver every paid item in that order. Delivering means signing a step that records an access link (by default your listing url) and the content hash from your listing. The link might be an invite to a private repository or a signed download. Make sure the buyer can reach it. Only you can mark your own item delivered.
curl -s -X POST http://127.0.0.1:8420/api/orders/ORDER_ID/deliver \
-d '{"identity":"acme","access":"https://github.com/acme/invoice-extractor/invitations"}'There is no order inbox on a self-hosted node yet. You hear about an order from the buyer, or by reading the ledger at GET /api/events. If an order has several sellers and one is late, the whole order is refunded, so deliver early.
Show test evidence
A tests_pass_rate you type into the listing is a claim. Anyone can replace it with a signed result from actually running your tests:
python -m repoblock verify BLK_ID # default: python -m unittest discover -q
python -m repoblock verify BLK_ID --cmd "make test" # your own test commandIt clones the item's url (a plain https git URL), runs the command in a throwaway folder with a timeout, reads the result, and appends a signed block.attest event with the pass rate and test count. The newest attestation replaces the claim in the item's quality score.
- The result reader understands
unittestoutput (Ran N tests). If your runner prints no such line, the test count is 0 and the rate is recorded as 0, even if the command passed. Make your test command print a summary in that form. - The clone times out after 120 seconds and the tests after 300.
- Verify runs the repository's code on your machine. Read the sandbox warning before running it on anything you do not control.
Fees and getting paid
You receive the listed price minus the network fee (1% by default on a self-hosted node), rounded down to the cent. Today this is a record in test mode, not money: on the simulated rail it is a balance in memory, and a node does not send on-chain payouts. The record is made when the order is released, and you do not need to ask. If the order is refunded after a dispute or a missed deadline, you are paid nothing for it. Free listings never pay a fee. The hosted app takes no orders yet, and its earnings page is coming soon. For hosted-app fees see Pricing.
Reviews and reputation
On the hosted app any signed-in user except the owner can leave one review per listing, rated 1 to 5, and the owner can reply. A review is marked as a verified purchase only after an order for the item is released, which cannot happen yet. On a node, buyers can rate an item from 1 to 5, but only if their own order for that item was released. The score is an average pulled toward 3 until an item has several reviews, so a single rating cannot make or break a listing. It feeds directly into quality.
A new listing has no reviews and carries a small extra risk (0.2) for that reason. Good descriptions, a real licence, a content hash and an independent test attestation are what move it up in the meantime.
Updating and retracting
- On the hosted app, edit the listing from its Settings tab and add versions from its Release tab. You can archive a listing or transfer it to an organization you own.
- On a node, publish again with the same
nameand key to ship a new version. The latest publish wins. - A new price applies to new orders only.
- Retracting is a signed
block.retractevent. The CLI does not expose it yet; callRegistry.retractfrom Python.
Last updated: