# Browsing + installing

The Hub tab is the entry point for finding + installing other people's work. Search, filter by kind, open an item card, hit install. The whole flow is sign-in-gated; the underlying primitives are also MCP-callable so the assistant can browse on your behalf.

## Opening the Hub

Three paths to the same place:

- **Topbar cloud icon** — the cloud cluster's first icon. Opens the Hub tab.
- **Knowledge rail panel → Open Hub button** — contextual when you're already browsing the KB.
- **MCP / palette** — `hub.open {}` (action id `hub.open`). Pops the same tab.

The Hub is a regular IDE module — it lives in tabs alongside Builders, book readers, editors. You can have it open and a Builder open simultaneously, drag a Hub-installed sample into the Builder without leaving the IDE.

## Anatomy of the tab

Top to bottom:

- **Search bar** — free-text. Matches against title, description, tags. Case-insensitive substring match.
- **Kind filter chips** — narrow to one of `builder`, `dsp`, `lib`, `book`, `sample-pack`, `node-pack`, `project`. Multi-select.
- **Sort affordance** — recency (default) or star count.
- **Results grid** — cards, each carrying title, kind badge, owner handle, tags, star count, fork count, license.

Click a card to open the **item detail** — description, version history, artifacts, license, install / fork / star buttons.

## Search via MCP

The same search the UI runs:

```yaml
actions:
  - action_id: hub.search
    input:
      kind: book
      q: faustwave
    save_as: hits
    label: "▶ 1. Search public books matching 'faustwave'"
  - action_id: hub.item.get
    input:
      item_id: "{{hits.data.0.id}}"
    save_as: top
    label: "▶ 2. Fetch the top result's full detail"
```

> 🟦 **HANDS-FREE PATH**: step 1 returns a `{ data, total, page, limit, totalPages }` envelope; `data[0]` is the top hit (a summary). Step 2 fetches the full ItemDto for that item, including the artifact URLs you'd download for an install. The `hub.search` schema accepts `q` (free text against title + description), `kind`, and `tags` — all optional. Empty input = list everything.

## Installing

From the item detail, click **Install**. Or via MCP:

```
hub.install { item_id: "<id from hub.search>" }
```

The action is kind-aware — you don't pass `kind`. Behaviour per kind:

| Kind | What happens on install |
|---|---|
| `builder` | **Saves the `.builder` into your project's `assets/` folder** (Documents → PROJECT; no editor tab opens). Idempotent by title. Add it to the mixer via "+ ADD AUDIO" / "+ ADD FX", open it from PROJECT to edit, or use the install toast's "Open in Builder" action. |
| `dsp` | Opens the `.dsp` source in a Faust DSP module. |
| `lib` | Lands in the project's `assets/` as `<owner>-<slug>.lib` — the owner prefix keeps two libraries of the same name apart in libfaust's flat VFS namespace. The IDE mounts it straight away, so `import("<owner>-<slug>.lib")` resolves immediately, and re-mounts it on every start. Rename with `project.file.rename` if you want a shorter import. |
| `book` | Fetches the manifest + bundle, parses `## sections`, indexes them into the local KB's `community` corpus with `packId` provenance for book-scoped search. Available immediately in the Book Reader (§ `book.open`). |
| `sample-pack` | Fetches the audio artifact, writes bytes to the local sample store via `samples.ensureFromBytes` (sha-keyed; idempotent). Available in any `soundfile` node by sha. |
| `node-pack` | Drops the `.nodepack.json` manifest + companion files into `userData/node-packs/`. The Builder's node picker shows the new kinds on next refresh. |
| `project` | Imports the `.fwproject.zip` as a new project. Server-suggested name on slug collision (e.g. `my-techno-set (2)`). |

## Inspecting before installing

For a heavyweight or unfamiliar item, peek before installing:

```
1. hub.item.get   { item_id: "<id from hub.search>" }   → full ItemDto incl. artifacts
2. hub.items.user { username: "<its owner.username>" }  → the author's other work
3. hub.install    { item_id: "<id>" }                   → OK, install
```

(Not a click-chain — the item id comes from your own `hub.search`.)

Step 1 returns the full ItemDto including `latestVersion.artifacts[].downloadUrl` for direct artifact fetching (useful if you want to inspect a `.builder` graph in your editor before installing). Step 2 lets you see other items by the same author — useful for vetting (a prolific publisher whose other items look good is less risky than a one-off mystery upload).

## Browsing another user's catalogue

```yaml
actions:
  - action_id: hub.items.user
    input:
      username: mani
    save_as: their_kb
    label: "▶ List @mani's public + unlisted items"
```

Returns public + unlisted items (private items stay invisible). Useful for catalogue browsing by author.

## Starring

Star items you find useful — stars surface in search ranking and signal to other users "this is worth looking at":

```
hub.star.set { item_id: "<id from hub.search>", starred: true }
```

Returns the new starCount. Idempotent both ways (re-starring or re-unstarring is a no-op).

## The book install loop

A book install does more than file movement — it indexes the content into your local KB so the AI assistant can ground in it. After installing a book:

1. The `kb` corpus gains its sections (find them via `kb.search { corpus: "community", query: "..." }`).
2. The Knowledge rail panel's *Installed Packs* list grows by one row.
3. The pack is available to the Book Reader — `book.open { book_id }` opens a Reader tab.
4. The assistant can scope to the pack's content for ground-truth answers about it.

This IS how the FaustWave manual you're reading works in practice — each pack installs, its sections index, the Reader opens, the assistant grounds in the content when you ask it about FaustWave.

## Common moves

- **"Show me popular Builders"** — `hub.search { kind: "builder" }`. Without a `q` filter you get the most-recent.
- **"Install everything from one user"** — `hub.items.user { username }` then iterate `hub.install` per `item.id`. (Mind that `lib` installs each pop a dialog.)
- **"Vet then install"** — `hub.item.get { item_id }`, inspect `latestVersion.changelog`, install if it looks good.
- **"Unstar something I starred by accident"** — `hub.star.set { item_id, starred: false }`.

## Common gotchas

- **`lib` install blocks on the file dialog** — when scripting library installs in an action chain, the chain pauses until you accept / cancel the dialog. Plan accordingly.
- **Re-installing the same `book` upgrades it** — doesn't duplicate. The local KB store keys by book_id so installing v3 of a pack you have at v1 simply replaces the indexed sections with v3's.
- **`hub.install { item_id }` errors out if you're not signed in** — sign in first, or the call returns an auth error.
- **`hub.search` returns a page of results** — the response envelope carries `total` / `page` / `totalPages`, so check `total` before assuming you've seen everything.

Next section: publishing + iterating — the `hub.publish` flow, version uploads, forks, the My Items view, and the safety rails (delete, account.delete).
