Cloud|

@k2b/cloud

Cloud resource picker

Choose a permission-filtered Cloud resource through Universal Search and keep its stable reference.

openCloudResourcePicker@k2b/cloud/browser/resource-picker

Backend-required resource selection through the authenticated Universal Search catalog.

Real search providers and permissions required

The picker discovers live resources and tag filters through authenticated Universal Search. Choose a result, inspect its preview, then confirm with Add. On small screens, Details opens the preview. The catalog shows this contract without inventing authorized resources.

TSX

Copy
import { openCloudResourcePicker } from "@k2b/cloud/browser/resource-picker";
const selected = await openCloudResourcePicker({
title: "Add Cloud reference",
excludeRefs: currentReferences,
requireReader: true,
});
if (selected) {
await saveReference(selected.ref, selected.title);
}

The Cloud resource picker lets a user choose one permission-filtered Universal Search result and returns the result with its stable CloudResourceRef. The application decides what the selection means and how to persist it.

Use the Cloud resource picker

Use the picker when a browser interaction needs a reference to a resource owned by any searchable Cloud application. Use requireReader when the consumer must later resolve the selected ref through its canonical reader. Use initialAppId to start within one application and excludeRefs to prevent duplicate selections.

Do not use it for application-local exhaustive browsing or as an authorization check. The owning search provider authorizes every result, and the consuming service must still authorize later reads or mutations.

Import

ts
import { openCloudResourcePicker } from "@k2b/cloud/browser/resource-picker";

Selection ownership

The picker owns its dialog, search input, tag filters, loading, error states, and result selection. A click or Enter selects a result; Add confirms it. It returns the selected search item or undefined when the dialog closes without a selection.

Store selected.ref as the durable identity. Treat the returned title, preview, metadata, and links as presentation data that may change.

Available options are:

  • title and placeholder for task-specific copy;
  • initialAppId to start within one searchable application, shown as a removable scope chip;
  • scope: { appId, tag?, label, icon? } to narrow the search on the server by app and optional search tag, shown as a removable chip with its label and icon; takes precedence over initialAppId;
  • query to prefill the search text;
  • excludeRefs to hide resources already selected;
  • requireReader to show only Types with a canonical reader.

An app scope starts searching at once, even with empty text. Scope filtering happens before the per-app result limit, so other resource kinds cannot crowd out matches as they can with the browser-only resourceType filter. requireReader still applies within the scope.

Presentation

The picker starts with a search field and a few tag suggestions. All filters or typing # opens the full filter list in the result area. Aliases remain searchable without appearing as duplicate filters. No application dropdown or nested autocomplete menu is shown.

While a request starts, the spinner replaces the search icon. Quiet tag placeholders reserve the suggestion row so opening the dialog does not shift its layout.

Desktop results share the dialog with a preview that starts at its top edge. From the first search character until the input is cleared, the dialog keeps its width, top position, and height; arriving results scroll inside it instead of resizing it. Small screens show one column with an optional Details view. Below 48rem the picker is a full-screen sheet: the whole width, from below the status bar to the bottom edge, rounded at the top, while global search keeps its floating card. The result list uses ScrollArea fades. Each application's results appear as it answers and are appended below earlier ones; a quiet line below the results names the applications still searching or one that did not answer, with Try again for that application alone. “No matches” appears only after every application has answered; a picker narrowed to one application says Mail: no matches for “invoice”. Previous results remain visible until the new search shows its first results, but cannot be added for the new query.

Accessibility

The dialog provides its title as its accessible name, moves focus into the search interaction, and supports closing with Escape. Arrow keys navigate results or tag suggestions. Enter selects, Tab moves focus normally, and Add confirms the resource. Escape first leaves tag discovery or mobile details, then closes the dialog. Use a task-specific title when the surrounding workflow needs more context than “Choose Cloud resource.”

Runtime

Call the picker from browser code. It uses the authenticated /api/search route and discovers the current application catalog from the running Cloud installation. Search providers remain responsible for permission-filtering every result. requireReader filters capabilities; it does not grant access or replace authorization.

Example

ts
const selected = await openCloudResourcePicker({
  title: "Add Cloud reference",
  excludeRefs: currentReferences,
  requireReader: true,
});

if (selected) {
  await saveReference(selected.ref, selected.title);
}

See Universal Search for provider registration, resource refs, tags, readers, and authorization.

Connect a coding agent

The Cloud skill provides compact working instructions. MCP supplies exact current documentation when details matter.

CLI command
bunx skills add https://docs.example.com

This command installs the working instructions published by this website in the selected coding agent.

For exact, current details, also connect the MCP server through one of the agent tabs.

Installation uses the open-source Vercel Skills CLI.

The skill and MCP complement each other: the skill describes workflows, while MCP supplies current documentation.