npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aistrike-dev/ui-shell-dev

v3.5.0

Published

A Vite plugin that serves the AiStrike UI shell from your micro front-end's dev server, plus a dev-token CLI.

Readme

@aistrike-dev/ui-shell-dev

Serves the AiStrike UI shell from your micro front-end's (MFE's) own Vite dev server, and mints dev tokens.

Setup

Install it as a devDependency, next to @aistrike-dev/ui-shell-sdk, and add shellDevHost() after mfe():

import { mfe } from '@aistrike-dev/ui-shell-sdk/vite';
import { shellDevHost } from '@aistrike-dev/ui-shell-dev/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [mfe({ id: 'hello' }), shellDevHost()],
});

vite now runs the shell as it is deployed: a console and a cell on two origins.

  • The console is your Vite server: the shell at / with a minted dev session.
  • The cell is a server on its own port: the console's plus 1000 (5103 → 6103), or any free port when that is past 65535 or taken. shellDevHost({ cellPort }) pins it; a pinned port that is taken is logged and the cell does not start. It forwards each domain's /<id>/ui/… and /<id>/api/…, WebSockets included, to the server that has it: your MFE (this Vite server) and the built-in MFEs, nothing else.
  • The dev token's cell claim names the cell on the address the browser used, so the shell loads every domain from it cross-origin, with CORS and the bearer token, exactly as from https://<cell>/<id> when deployed. Your MFE's HMR runs through the cell too.

Your dev server serves the cell's layout: mfe() puts the MFE under the Vite base /<id>/ui/latest/ and answers /<id>/api/… as /api/…, so your mock API keeps its /api/ paths.

To see your MFE beside other domains' dev servers, use the ui-shell repository's dev server (pnpm --filter @aistrike-dev/ui-shell dev), whose cell forwards to every server its shell.dev.json lists.

Built-in MFEs

The package carries prebuilt copies of the MFEs that ship with the shell (assistant, settings and home) with their mock APIs, and the plugin serves each on its port (assistant 5104, settings 5101, home 5102), behind the cell. You get the whole frame (Home, Settings, the assistant pane on ⌘I / Ctrl+I) with nothing else running.

  • A server already listening on one of those ports wins: the plugin leaves that port alone, so a real dev server for that MFE (with HMR) is used instead. A port freed later is taken over on the next page load.
  • A real dev server for one of them started after this one fails, because the bundled copy holds its port. Start the one you are editing first, or restart this server after starting it.
  • shellDevHost({ platform: false }) serves none; shellDevHost({ platform: ['assistant'] }) only those listed.
  • The copies are as old as the package (in this repository, the last pnpm nx build dev-host).

Keep Vite's server.allowedHosts at its default: the plugin names the cell in the dev token on the request's Host address, which is only safe while Vite rejects unknown hosts. The cell applies the same rule itself: it answers only a Host of localhost, *.localhost or an IP address, and 403 to anything else. The cell is plain HTTP, so serve the console over HTTP too: the shell loads the cell over the console's own protocol.

shell.dev.json

Read from the Vite root when present (or from the plugin's devFile option).

{
  "domains": [{ "id": "hello", "nav": { "label": "Hello" } }],
  "idleTimeoutMs": 0,
  "claims": { "permissions": ["hello:read"] }
}

A domain's route prefix is always /<id>, so a domain has no route key, and the shell has no profiles, so the file has no profile key: a leftover one of either stops the dev server with a message to delete it. The ids shell, preferences, commands, api, assets, ui, config, signin and webhooks are reserved.

domains names your own domain when the shell does not compile it in (a devPort is accepted and ignored); naming another domain, or an overrides or cell key, stops the dev server. idleTimeoutMs defaults to 0 (idle timeout off), and claims is merged over the default dev claims (cell is the plugin's, not the file's). The plugin's claims, ttlMs and noToken options win over the file. "lab": true shows Octopus UI's Design Lab (its live controls for the open design questions, in a Picture-in-Picture window) over your pages, so you can judge them on your own screens. "lab": { "designSystem": "../octopus-ui" } also names an Octopus checkout (relative to the Vite root): Lock in then writes a work-loop item into its .backlog/, through Octopus's Lock-in plugin (@aistrike-dev/ui/lab/vite, loaded from the installed @aistrike-dev/ui). Without one, or when the path is not an Octopus checkout, Lock in downloads the same item instead.

Legacy bridge (temporary)

legacyBridgeDev() signs you in through the old app and passes API calls to its backend, until real sign-in exists (docs/superpowers/specs/2026-11-09-console-migration-design.md, section 6). Add it beside shellDevHost():

import { legacyBridgeDev, shellDevHost } from '@aistrike-dev/ui-shell-dev/vite';

export default defineConfig({
  plugins: [react(), mfe({ id: 'alerts' }), shellDevHost(), legacyBridgeDev()],
});

Set its variables in the environment or in .env.local (do not commit it). For preview:

LEGACY_BRIDGE_ORGS=preview
LEGACY_BRIDGE_DEFAULT_ORG=preview
LEGACY_BRIDGE_PRODUCT_DOMAIN=aistrike.com
LEGACY_BRIDGE_API_HOST=backend.preview.aistrike.com

| Variable | Value | | --- | --- | | LEGACY_BRIDGE_ORGS | The org slugs to sign in to, comma-separated. next-auth for an org is at https://<org>.<product domain>. | | LEGACY_BRIDGE_DEFAULT_ORG | The org a sign-in without ?org= uses. | | LEGACY_BRIDGE_PRODUCT_DOMAIN | The domain the org hosts are under. | | LEGACY_BRIDGE_API_HOST | The old app's API host. | | LEGACY_BRIDGE_REFRESH_INTERVAL | Optional. Seconds a session is reported to live, so the shell refreshes on this interval. Default 600. |

With the plugin, the dev host starts signed out, the dev cell forwards /legacy-bridge/api/… to it, and the shell page names that URL in the aistrike-legacy-bridge-base meta tag. The dev server does not start without the 4 required variables. app-development needs the VPN; preview does not.

Commands

aistrike-shell token [--claims <path>] [--ttl 30d|12h|45m|90s] [--out <path>] [--json]

token mints a dev token and prints it (or { token, session } with --json), optionally writing it to --out.

The package's own e2e (pnpm nx e2e dev-host) serves the settings MFE on port 5101, with the bundled home and assistant on 5102 and 5104; it fails loudly if a dev server already occupies 5101, and stop any on 5102 or 5104 first. It also checks that npm pack would publish the bundled copies.

Opening / in dev lands on your own MFE (the plugin injects landing with your domain id; shell.dev.json may set landing to another domain id; an id that is not in the shell's domain list falls back to /home). A domain that is neither bundled nor running shows as failed in the rail.

aistrike-shell serve --shell-dir <devhost build> [--config shell.dev.json] [--port 3000] [--cell-port 4000]

serve is the ui-shell repository's dev server: the console and a cell whose shell.dev.json lists where each domain runs, { "cell": { "domains": [{ "id": "lab", "nav": { "label": "Lab" }, "at": 5103 }] } } (at a port or an http: origin: the cell forwards over HTTP; nav only for a domain the shell does not compile in). Its console and cell answer only localhost, *.localhost and IP addresses. Every compiled domain not listed is the built-in MFE. A deployed cell ("cell": "https://…") is refused until the shell can sign in to it.

Checking Fast Refresh (spike 1)

This is a manual check; no automated test covers it. From the repository root:

  1. pnpm nx build dev-host once (builds the shell and copies it into the dev host package).
  2. pnpm --filter @aistrike-dev/app-settings dev.
  3. Open http://localhost:5101/settings/profile.
  4. Edit apps/settings/src/ProfilePage.tsx (for example, the Profile heading) and save.
  5. Confirm the page updates without a full reload: text typed into a field beforehand is still there.

The dev token

The dev token is signed with a dev-only key stored under ~/.config/aistrike-shell/. It exists so the shell has a session locally. Deployed environments never trust it.