The VibeHunt Protocol
Version: 0.2 draft · Status: for discussion · Updated: 2026-04
VibeHunt is an open protocol for software discovery without gatekeepers. Builders publish manifests describing what their software does. Users search the registry — either by browsing or by describing what they're looking for — and real users star what works.
This document is the v0.2 draft. It defines three JSON-LD primitives — Need, Capability, and Star — plus an identity & verification scheme and a small constraint vocabulary. Implementations should treat fields not described here as forwards-compatible extension points.
1. Goals
- No gatekeeper. Anyone can publish a Capability manifest. The protocol does not designate any party as authoritative for what is or is not "good" software.
- Manifests are positive declarations only. Capabilities claim what they satisfy and how to reach the software. They never list weaknesses, "not for" audiences, or explicit violations. Honesty comes from verifiable identity (§5), not from self-deprecation — claims you can't make falsely don't need balancing flaws.
- Discovery is dual-mode. Users can browse the registry's index of Capabilities directly, or describe a structured Need and receive ranked matches. Neither mode is privileged.
- Identity is verifiable but not centralized. Capabilities can be cryptographically tied to the domain or key of the publisher. There is no central registry of identities.
2. Conceptual model
The protocol has three primitives that form a closed loop:
Need— a structured description of what someone's looking for. Free-text intent plus structured context (category, constraints, scale, what success looks like). Published by humans or agents.Capability— a manifest published by software, describing what it does, with honest tradeoffs.Star— a signed signal from a real user that a Capability works. Like a GitHub star, but cryptographically authentic. (Phase 2 — defined in §6 but not yet produced or verified by reference clients.)
The matching loop:
Need → resolver finds Capabilities whose `solves` entries match
→ ranked by trust-weighted Stars
→ user picks one, uses it, emits a new Star
→ graph gets smarter
3. The Need schema
A Need describes what someone is looking for in enough structured detail that matching can do useful work, while still leaving room for free-text intent.
{
"@context": "https://vibehunt.tech/v1",
"@type": "Need",
"id": "need:2026-04-30:01HX3F0WQ7",
"intent": "I want a notes app that stores everything as plain Markdown files I can edit with any other tool.",
"context": {
"category": "notes-writing",
"constraints": [
"core:local-first",
"core:plain-text-storage",
"core:no-subscription"
],
"scale": "single-user"
},
"successLooksLike": "All my notes are .md files in a folder I control, syncable with any sync tool.",
"declarer": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSrz5tw3xJqHpVjUv",
"declaredAt": "2026-04-30T14:22:00Z"
}
Field reference:
id— must start withneed:. The remainder is opaque; clients that persist Needs should generate IDs that are unique within their namespace (e.g. ULID or content-hash).intent— required. 10–500 characters of free-text human-written description.context.category— required. One category ID from the category vocabulary. Single value per Need.context.constraints— array of namespaced terms (namespace:term). Allcore:terms are defined in the vocabulary. Other namespaces are allowed but unrecognized terms are ignored by reference matchers.context.scale— optional. One of"single-user" | "team" | "org" | "public".successLooksLike— optional. Concrete description of the outcome the declarer wants. Used by matchers as a soft signal alongsideintent.declarer— optional DID. Anonymous Needs are allowed in v0.declaredAt— optional ISO 8601 timestamp.
4. The Capability schema
A Capability is a positive declaration: what the software is, what it claims to satisfy, and how to reach it. It must declare at least one solves entry. The protocol carries no negative claims — a Capability never lists weaknesses, "not for" audiences, or explicit violations. Honesty is enforced through verification (§5), not through self-deprecation. If the software doesn't claim a constraint, requiring that constraint excludes it.
{
"@context": "https://vibehunt.tech/v1",
"@type": "Capability",
"id": "cap:example:logseq",
"software": {
"name": "Logseq",
"category": "notes-writing",
"homepage": "https://logseq.com",
"source": "https://github.com/logseq/logseq",
"license": "AGPL-3.0",
"packageRefs": ["flathub:com.logseq.Logseq", "brew:--cask logseq"],
"description": "A privacy-first, open-source outliner-style knowledge graph with plain-text storage."
},
"solves": [
{
"intent": "Capture interconnected notes as outlines, with bidirectional links over local Markdown files.",
"constraintsSatisfied": [
"core:local-first",
"core:plain-text-storage",
"core:libre"
],
"scale": ["single-user"]
}
],
"maturity": "stable",
"maintainer": "did:web:logseq.com"
}
Field reference:
id— must start withcap:. In production, IDs SHOULD be derivable from the publisher's identity (e.g.did:web:logseq.com#notes) so the ID itself proves origin. Thecap:example:*namespace is reserved for non-authoritative example data.software.category— required. One category ID from the category vocabulary. Capabilities pick a single primary category; v0 does not support multiple.software.homepage— required. The canonical URL where a human can land to learn about or acquire the software. May be a marketing site, a GitHub repository, a Flathub page, etc.software.source— optional repository URL.software.description— optional one-sentence summary used by clients on listing surfaces.software.image— optional URL to a representative image (logo, screenshot, hero). When absent, clients SHOULD fall back to theog:imageof the homepage. Aspect ratio of 16:9 is recommended.software.packageRefs— array ofscheme:identifierstrings (flathub:,brew:,npm:,mas:,apt:, etc.). Useful for direct install links and verification.solves[]— required, at least one entry. Each entry describes one shape of Need the software claims to address.solves[].constraintsSatisfied— terms the software guarantees (e.g.core:local-first). Absence of a term is not a denial — it simply means the Capability makes no claim. Matching treats absent terms as "does not meet" for any Need that requires them.
maturity— one of"experimental" | "beta" | "stable" | "maintained" | "abandoned". Self-declared.maintainer— optional DID identifying the maintainer. Required for domain-verification (§5).source— provenance of the manifest. One of"publisher" | "example" | "imported". Defaults to"publisher"— a manifest authored by the maintainer of the software."example"is curation by a registry to populate the index without claiming the entry is authoritative."imported"is derived from a third-party source (e.g. Product Hunt) and SHOULD includeattribution. Registries SHOULD treat any non-publisherentry as superseded the moment a verifiedpublishermanifest arrives for the samesoftware.homepagehostname.attribution— optional. Required whensourceis"imported".{ source: string, url?: string, importedAt?: ISO-8601 }describing where the manifest came from.
5. Identity & verification
The protocol uses two DID methods:
did:web:DOMAIN— the DID is the domain. Domain control is the proof.did:key:...— a self-asserted public key. Proves cryptographic continuity but not who holds the key.
A Capability is domain-verified if all of the following hold:
maintaineris adid:web:DOMAIN.- The hostname of
software.homepagematchesDOMAIN. - The Capability's canonical manifest is reachable at
https://DOMAIN/.well-known/vibehunt/[slug].json, where[slug]is the Capability's ID after the final#separator. - The fetched manifest has the same
idandmaintaineras the version being verified.
If all four hold, the Capability is rendered with a domain-verified badge. Capabilities with a did:key: maintainer and a valid signature are rendered as key-attested (a weaker claim). Anything else is rendered as unverified.
This scheme is decentralized: no party in the protocol decides who is real. The only proof that counts is the ability to serve content at a specific URL on the publisher's domain — the same trust signal that backs did:web itself.
How to verify your Capability
If you publish software at your-domain.com:
- Set
maintainertodid:web:your-domain.comin your Capability manifest. - Set the Capability
idtocap:your-domain.com#thing-name. - Save the JSON-LD file and serve it at
https://your-domain.com/.well-known/vibehunt/thing-name.json. - Submit the manifest URL to the registry. The registry fetches it, validates the schema, and confirms the URL's hostname matches the DID.
That's the whole onboarding. No platform approval queue, no fee, no DNS records to add — just one file deployed alongside your existing site.
Why this and not DNS TXT?
An earlier draft of the protocol used a DNS TXT record for verification. We dropped it because publishers already need to host the manifest somewhere, and the URL where it's hosted is a domain-control proof equivalent to DNS — adding a separate DNS step was redundant. The path .well-known/vibehunt/ is a recommended convention (parallel to .well-known/security.txt, .well-known/openpgpkey/, etc.) so registries can find manifests predictably.
6. The Star schema
Stars are signed user signals that a Capability worked for them. vibehunt.tech produces and verifies Stars in v0; other registries are encouraged to do the same.
{
"@context": "https://vibehunt.tech/v1",
"@type": "Star",
"id": "star:01HX3FQK2A",
"capability": "cap:example:logseq",
"starrer": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSrz5tw3xJqHpVjUv",
"starredAt": "2026-05-12T09:18:00Z",
"notes": "Migrated 4 years of notes from Bear; daily-journal mode replaced my time-tracking spreadsheet.",
"signature": "z3jQH..."
}
A Star is a signed positive signal — like a GitHub star, but the signature ties it to a verifiable identity (did:key: or did:web:). The trust graph that ranks Capabilities by aggregated Stars and starrer reputation is out of scope for v0.
Reference implementation note
vibehunt.tech v0 implements Stars using WebAuthn/passkeys: the user's did:key is derived from a passkey credential ID, the WebAuthn assertion fills signature, and the registry stores (credentialId → publicKey, did) to verify subsequent assertions. This sidesteps the friction of generating and managing did:key private keys in browsers in exchange for a registry that's the trust root for a Star's signature (rather than the Star being self-verifiable from starrer alone). Other registries MAY adopt the same convention or implement direct did:key signing per the canonical schema.
7. Matching
A reference resolver matches Needs against Capabilities in two stages:
- Hard filter. Reject any Capability whose
solves[]does not satisfy every constraint the Need requires. Absence of a term inconstraintsSatisfiedis treated as "does not meet" — Capabilities cannot satisfy a constraint by silence. - Soft ranking. Rank surviving Capabilities by a weighted combination of:
- Semantic similarity between
Need.intent(andsuccessLooksLike) and eachsolves[].intent, computed via embeddings. - Category match between
Need.context.categoryandCapability.software.category(an exact-match boost rather than a hard filter). - Constraint overlap beyond the hard filter (more shared constraints = better fit).
- Maturity as a small tiebreaker (
stableandmaintainedrank aboveexperimental).
- Semantic similarity between
Reference clients SHOULD return the top N matches with score breakdowns so users can see why each Capability was surfaced.
8. Identifiers
| Prefix | Used for | Format hint |
|---|---|---|
need: | Needs | need: + opaque (ULID, content hash, etc.) |
cap: | Capabilities | cap: + opaque, or did:web:DOMAIN#name for verified caps |
star: | Stars | star: + opaque |
The cap:example:* namespace is reserved for non-authoritative example data and MUST NOT be used in production registries.
9. Registries & publishing
A registry is a directory of Capability pointers. It is not a content host. Publishers serve their own manifests at URLs they control; the registry stores (manifestUrl, lastFetched, lastVerified, indexedManifest) tuples and re-fetches on a schedule.
No accounts
There is no account system in the protocol. Identity is entirely carried by did:web: (domain-anchored) or did:key: (key-anchored). To publish, you don't sign up — you submit a URL.
Submission flow
- Author the manifest. The vibehunt.tech
/publishpage is one tool for this; the MCPvibehunt_draft_manifesttool is another. Any tool that produces conformant JSON-LD works. - Host the manifest at a URL on the domain the manifest claims (recommended path:
https://DOMAIN/.well-known/vibehunt/[slug].json). - Submit the URL to a registry. vibehunt.tech accepts submissions over HTTP at
POST /api/submitand via the MCP toolvibehunt_submit_capability; other registries may use other channels. - Indexed — the registry fetches the manifest, runs verification (§5), and adds the Capability to its index if checks pass.
Re-verification
Registries SHOULD re-fetch indexed manifests periodically (suggested: weekly). If a manifest stops resolving or its id / maintainer no longer match, the Capability falls out of verified status and is removed from default views.
Multiple registries
The protocol explicitly supports multiple independent registries. A publisher can submit the same manifest URL to as many registries as they like; each independently verifies. There is no canonical registry — vibehunt.tech is one, others are encouraged.
10. Clients
The protocol is intentionally client-agnostic. The vibehunt.tech website is one client; anyone can build others — agents, CLIs, IDE extensions, alternate registries — that speak the same JSON-LD primitives.
MCP server
vibehunt.tech exposes a Model Context Protocol endpoint at https://vibehunt.tech/api/mcp over Streamable HTTP. Any MCP-compatible client (Claude Desktop, Cursor, Cline, agentic coding tools) can connect to it and gain six tools:
vibehunt_search— find software matching a described needvibehunt_get_capability— fetch a full Capability manifestvibehunt_list_categories— enumerate the standard categoriesvibehunt_list_constraints— enumerate thecore:vocabulary with plain-English labelsvibehunt_draft_manifest— generate a publishable Capability manifest plus the.well-knownURL the publisher must host it at to verify the domainvibehunt_submit_capability— submit a hosted manifest URL; the server fetches, verifies, and indexes it live
The publish-side tools are particularly significant: an AI agent that just helped a user build software can produce a manifest, walk the user through hosting it, and index it in the registry — closing the loop between vibe-coded creation and discoverability.
// Add to your MCP client config (Claude Desktop, Cursor, etc.)
{
"mcpServers": {
"vibehunt": {
"url": "https://vibehunt.tech/api/mcp"
}
}
}
11. JSON-LD context
The canonical context document is served at https://vibehunt.tech/v1/context.jsonld. Documents that conform to this spec MUST set @context to that URL exactly.
12. Versioning & future work
This is v0.2 of the protocol. v0.1 used the names Problem and Attestation for what are now called Need and Star; the rename was made before the protocol had any audience to break. Breaking changes from v0.2 onwards will increment the major version in the @context URL (e.g. https://vibehunt.tech/v2). Additive changes will not.
Known future work:
- The trust graph weighting Capabilities by aggregated Stars and starrer reputation.
- Collections (curated bundles of Capabilities) as a fourth primitive.
- A standard feed format so registries can syndicate new Capabilities.
- Signed Capabilities (separate from
did:webdomain proofs) for individual builders without a domain.
Comments and proposals are tracked in the public spec issue tracker (link forthcoming).