Skip to content

Updated

View MarkdownOpen in ChatGPTOpen in Claude

Widget CLI

The package is @glasshome/widget-cli; the binary is glasshome-widget. Scaffolded projects pin it in devDependencies behind a "widget": "glasshome-widget" script alias, so commands below read bun widget <command> (project-local, kept current with bun update). Elsewhere use bunx @glasshome/widget-cli@latest <command>; without @latest, bunx can reuse a stale cached version.

Version requirements

Hub enforces a minimum CLI version, currently 0.5.0, served from /api/widgets/cli-version. CLIs 0.4.14 and newer fetch it on login and publish and hard-stop below the floor with an actionable message instead of a cryptic OAuth or HTTP error; older CLIs lack the check, so the floor only protects clients that can read it.

On a “widget CLI is no longer supported” error, update:

# one-off, no install:
bunx @glasshome/widget-cli@latest publish

# or update the project dev dependency:
bun add -D @glasshome/widget-cli@latest

Two auth flows

connect authenticates against your local Dash instance for live testing; login against GlassHome Hub for publishing. Tokens are stored separately and are not interchangeable.

Commands

bunx @glasshome/widget-cli@latest createalso the default command outside a project

Scaffolds a widget project: package.json, vite.config.ts, tsconfig, and a starter widget whose details it prompts for (no extra add call needed). Run it outside an existing project.

Prompts for a name and description, then creates src/{name}/index.tsx and src/{name}/manifest.json.

Builds each widget into a self-contained JS bundle in dist/ and generates dist/registry.json with metadata for all widgets.

Checks manifests, bundle sizes, and registry consistency. Pass a name to check one widget, omit for all.

Prints the project header, local registry summary, and per-widget metadata + bundle size.

Live testing against a running Dash instance; widgets hot-reload as you edit. Full sequence in Local Testing Workflow. Auth is an OAuth device-code flow against the local Dash instance; approve in the browser and the CLI stores a host-scoped bearer token. Distinct from login, which targets GlassHome Hub.

--re-authForce a fresh device-authorization flow, discarding stored credentials.

Validates, prompts for scope/widget/version (or takes flags), then builds and uploads via a presigned R2 URL. Runs login automatically if no token is found. Scopes come from GET /api/widgets/scopes: your personal scope (your username) plus any org scopes you can publish to. See Publishing Scopes.

--name <widget>Publish only the named widget.
--bump keep|patch|minor|majorPre-pick the version bump; updates version in the widget’s manifest.
--scope <scope>Pre-pick the publishing scope (e.g. @my-team).

Authenticates with GlassHome Hub via OAuth PKCE (not local Dash): opens a browser, listens on http://127.0.0.1:9274/callback (120 s timeout), stores the token locally. publish runs it automatically when no token is present.

Moves the project to a newer @glasshome/widget-sdk and syncs the sdkVersion in every manifest.json to what is then installed. In a standalone project: bun adds the SDK at latest (or --to <version>) into whichever section already declares it, which also pulls in the @glasshome/ui it peers, then syncs the manifests and re-runs bun widget validate. In a monorepo workspace (a package.json with a workspaces field at or above the project): reads the SDK version from the workspace package, runs bun install from the root, syncs every manifest, then re-runs bun widget validate.

Rewrites widgets’ raw-Zod config (z.object, widgetFields) to the defineConfig + field.* API. Assistive, not lossy: fields it cannot translate stay raw Zod and are reported as manual TODOs; validation is never dropped.

--name <widget>Migrate only the named widget.
--dryPreview without writing.

Global flag

Use --dir <path> with any project-scoped command (add, build, validate, info, connect, publish, upgrade, migrate) to point at a different widget project directory. create ignores it; it scaffolds into a new directory under the current working directory.

Local Testing Workflow

What connect does, in order:

  • Builds all widgets.
  • Runs the OAuth device-code flow against the Dash URL (browser opens to the Dash approval page).
  • Uploads each bundle to the Dash API under the local scope.
  • Registers the widgets via the Dash internal tRPC endpoint and enables dev mode.
  • Watches src/; on save, rebuilds and re-uploads the affected widget.
  • On Ctrl+C, unregisters the widgets and exits.

No local HTTP server is started; Dash talks to its own API for the bundle bytes.