Skip to content
Website

Marketplace

A marketplace is a JSON file at a URL someone chose — GitHub raw, a gist, anywhere HTTPS serves it. You add it by name and URL. No marketplace-specific server is required, no account, no submission queue, nobody who approves what goes in it.

What it lists is bundles — a named collection of platform elements from one git repository: agents, tools, dashboards, LLM and embedding backends, hive services, triggers, a project scaffold. A bundle can carry all of these or just one — a bundle whose only element is a dashboard is what people mean when they say “app.”

Why it’s built this wayEnterprise interest

Section titled “Why it’s built this way”

Installing software off the internet is normally a leap of faith: you trust a registry to have vetted the thing, or a vendor not to have changed what’s behind the link since you looked. A marketplace entry sidesteps most of that: it names a git repository and one commit, in full — not a branch, not a tag, a 40-character hash. Installing clones exactly that commit. Later pushes to the repository’s branch don’t change what you get; moving onto newer code is marketplace update, a separate act you take once you’ve seen what changed.

And installing doesn’t run anything. A dashboard or a hive service lands inert and needs marketplace start to come up; a trigger lands with its own enabled toggle forced off, whatever the repository says; an agent, a tool, a backend and a project scaffold are inert by construction — they’re just files nothing calls until something else in the store references them. You can install a bundle you found in a random gist and read every file it brought before any of it runs.

Terminal window
adi-mono marketplace add adi https://raw.githubusercontent.com/adi-family/marketplace/main/apps/marketplace.json
adi-mono marketplace sync
adi-mono marketplace apps

add takes a name and a URL and writes them to ~/.adi/mono/marketplace/sources.toml; the official marketplace is there by default, under the name store. sync is the only command that touches the network on the listing side — it fetches every source’s manifest and caches it under marketplace/cache/<name>.json. install reads the cached manifest entry, not a fresh fetch of it: the bundle you saw when you last synced is the bundle you get, even if the manifest has since changed. Only the repository itself is fetched, at install time, by git, against the commit that cached entry pins.

Terminal window
adi-mono marketplace install adi/crm-suite --new-project "Sales CRM"
adi-mono marketplace install adi/crm-suite/agents/sales-bot --project sales-crm

Install the whole bundle, or address one element by appending /<kind>/<name>, taken verbatim from the repository. Everything lands inert. Bring up what needs bringing up with:

Terminal window
adi-mono marketplace start <dashboard-id> # from `marketplace apps`
adi-mono marketplace start adi/crm-suite/services/queue --project sales-crm # a parked hive service

A dashboard element starts like any dashboard, by the id marketplace apps lists for it. A hive service lands as a file the supervisor never reads until you start it — starting is what copies its definition into the live hive.yaml. Uninstalling one element is the mirror, scoped the same way:

Terminal window
adi-mono marketplace uninstall adi/crm-suite/agents/sales-bot --project sales-crm

Where an install goesExpert areaEnterprise interest

Section titled “Where an install goes”

Every install is filed under a scope: a project, or the machine’s global scope. This isn’t just organizational — it’s what lets you install the same bundle twice. In the global scope, a tool, an LLM backend and a project scaffold must land under their exact published id or the install is refused (a sibling agent’s bin_tools names a tool by that id, and silently renaming it would point that reference at a stranger’s script instead) — so two bundles installed globally collide on those ids and the second is refused. Installed into a project each, an id collision instead mints a suffix (csv-import-2), and the install rewrites that copy’s own internal references — bin_tools, backends[].backend, project — to match what actually landed.

That’s why --project / --new-project is the recommended destination, and why the panel asks for one by default rather than pre-selecting global. The CLI has no such nudge: leaving off both --project and --new-project installs globally. Whichever way you land there, an agent, a tool or a backend installed globally is reachable by everything else on the machine, and a second copy of the same bundle can’t join it.

An agent, a dashboard, a trigger or a hive service has no such reference pointing at it, so those mint a fresh id on collision the ordinary way (crm, crm-2) in either scope.

UpdateEnterprise interest

Section titled “Update”
Terminal window
adi-mono marketplace update adi/crm-suite --project sales-crm
adi-mono marketplace update adi/crm-suite --project sales-crm --force-element agents/sales-bot

Update is a fast-forward, applied per element. An element you haven’t touched moves onto the new pin. An element whose live copy no longer matches what was last installed — you edited it — is left alone and reported, not overwritten; --force-element <kind>/<name> overwrites that one element anyway, losing your edit. Your own commits on top of an install are never walked over without you saying so.

There’s no single “uninstall this bundle” verb — marketplace uninstall <marketplace>/<slug>/<kind>/<name> (add --project, as shown above, for a project-scoped install) removes one element at a time, by that kind’s own ordinary path, dashboards included: it archives the directory and deletes it in one call, no separate trip to Dashboards needed. A bundle isn’t a container you pull out as a unit — it’s a set of ordinary things that happen to share where they came from, and removing them stays that granular.

The one real exception is the legacy single-dashboard bundle — a repository with no kind directories at all, which installs as a plain dashboard with its own .git clone. It carries no marketplace ledger for marketplace uninstall to act on, so it still goes through Archive → Delete on the Dashboards page, exactly as v1 always has.

A bundle never carries a secret’s value — only the name of one it needs, the same way a hand-written agent or backend already can (Secrets). Installing reads every secret name the bundle’s elements declare and checks it against what’s actually set on this machine; a missing one shows up as a note on the install, not a blocker. Nothing is created and nothing is prompted for: an agent missing a secret it wants simply runs without it, same as if you’d forgotten to attach one by hand.

PublishingExpert areaEnterprise interest

Section titled “Publishing”

A bundle is an ordinary git repository, laid out by kind — every directory optional:

agents/<name>.toml # an agent definition
tools/<name>.{sh,ts} # a tool script
dashboards/<name>/ # a dashboard — frontend/index.ts, backend/index.ts
llm/<name>.toml # an LLM backend
embeddings/<name>.toml # an embedding backend
services/<name>.yaml # one hive service
triggers/<name>.toml # a trigger definition
project/config.toml # the bundle's own project scaffold — at most one

Each file is written in exactly the shape the store already reads elsewhere — an agents/<name>.toml is the same AgentManifest shape you’d hand-write for an agent, a services/<name>.yaml the same ServiceSpec shape as Hive. There’s no bundle-specific schema to learn beyond the directory layout itself. One rule applies to every element: no Rust source and no compiled binary anywhere in the tree — a Cargo.toml, a .rs file, or an ELF/Mach-O/PE binary refuses the install outright. What the store runs is a script, a config file, or a container it supervises; a compiled artifact isn’t one of those.

Add an entry to your manifest and host it anywhere over HTTPS:

{
"name": "My starter bundles",
"bundles": [
{
"slug": "crm-suite",
"name": "CRM suite",
"description": "A follow-up agent, its import tool, and the dashboard that watches both.",
"repo": "https://github.com/you/crm-suite.git",
"commit": "9f2c1d4e5a6b7c8d9e0f1a2b3c4d5e6f70819a2b",
"elements": [
{ "kind": "agent", "name": "sales-bot", "description": "Drafts the follow-up." },
{ "kind": "tool", "name": "csv-import", "description": "Loads a contacts export." },
{ "kind": "dashboard", "name": "crm", "description": "The list itself." }
]
}
]
}

repo and commit are the two fields that matter: commit is a full 40-hex hash, checked with git rev-parse HEAD after you’ve pushed. elements is an optional preview — what a listing shows before anyone’s cloned anything — and it’s advisory, not binding: what actually installs is read off the pinned commit’s own tree. Shipping a new version is one line, changing commit (and version, for readers); nothing on anyone else’s machine moves until they run update themselves.

See Building a marketplace bundle to package two agents and a dashboard, publish the bundle, and update two installs independently.