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

@tantawowa/hosanna-tools

v3.29.1

Published

The repository instructions use TantaWowa's ClickUp workflow skills, Matt Pocock's engineering skills, and pstack's `unslop` skill. Install them once on each developer machine:

Readme

hosanna-tools

Agent skills

The repository instructions use TantaWowa's ClickUp workflow skills, Matt Pocock's engineering skills, and pstack's unslop skill. Install them once on each developer machine:

npx -y skills add TantaWowa/hosanna-tools --global --skill work-on-ticket hope-platform-planning hope-platform-architecture-ownership --agent '*' --full-depth --yes
npx -y skills add mattpocock/skills --global --all
npx -y skills add cursor/plugins --global --skill unslop --agent '*' --full-depth --yes

The first command requires GitHub access to the private hosanna-tools repository. The install does not grant ClickUp access, so connect the team's ClickUp integration in your agent before using work-on-ticket. Start a new Codex, Cursor, or Claude Code session after installing. Run npx -y skills update --global --yes to update the installed skills later.

Documentation

  • MCP debuggerhst mcp:start, debugger tools, commands by use case, examples, and RASP certification capture.
  • Video capture — standalone, agent-driven, and test-run recording for Apple simulators, physical-TV capture cards, and macOS windows.
  • Browser, Tizen, and webOS — canonical commands, desktop previews, package/device workflows, vendor trust, and CSP/LAN policy.
  • docs/README.md — index of docs in this repo (MCP + source-map note).
  • hosanna-ui (separate repo): docs/README.md for agentic debugging and links back to this README.

To use the tool

npm install -g @tantawowa/hosanna-tools

Note, if you are developing hosanna-tools, you will install the package locally.

npm install . -g # path to the hosanna-tools directory

Hosanna source install modes

Client projects can switch between private Keygen source tarballs, an embedded copy, a shared local checkout, and the legacy git/local modes:

hst config source                                                        # show current mode and immutable install identity
hst config source keygen --sdk-version latest --install                  # newest valid private publication across all lanes
hst config source keygen --sdk-version v1.29.1 --install                 # pin an exact immutable production release
hst config source embedded --source-path ../hosanna-ui --install         # filtered, reproducible copy
hst config source shared --source-path ../hosanna-ui --install           # portable relative link for local development
hst config source git --install                                           # legacy git checkout
hst config source local                                                   # caller-provided LOCAL_SDK checkout

Keygen mode writes distribution: "keygen", flavour: "fullSource", and no platform list to hosanna.json. Bare latest means the newest valid published full-source release by Keygen publication time, whether it came from a nightly, manual, or tag run. @latest remains the stable-lane alias and @nightly remains the development-lane alias. Exact versions are immutable pins. The same HSC_LICENSE_KEY used by the compiler authorizes source installation; there is no separate Hosanna source-license environment variable.

Local shared, embedded, and local selections are private developer overrides. They do not rewrite hosanna.json: Git projects store the selection in worktree-specific Git metadata, so activating a local checkout cannot dirty the project or leak a machine path into a commit. hst config source and hst env check prominently report the active override, resolved checkout, and the committed distribution/version it temporarily supersedes. Running hst sdk:install or hst framework:update while an override is active preserves the local checkout. Select keygen or git with --install --replace-existing to clear the override and return to the committed source.

Use --replace-existing with --install when switching an existing project between modes. Replacement is refused for an unrecognized or modified source root; --force is required for a dirty git checkout. Embedded installs exclude repository/build/secret state, write a content-hash manifest, and never modify the source checkout. Shared installs validate the source and create a relative symlink. Granular flavours and platform subsets are deliberately rejected with NOT SUPPORTED YET — use flavour "fullSource".

Embedding as a library

Hosanna Tools can also be imported by app build chains. The CLI remains available as hst, but package imports are library-safe and do not parse CLI arguments or call process.exit during import. Public wrappers for process-oriented commands use no-exit mode where supported, so API callers receive structured results or thrown errors instead of forced process termination.

import { buildConfig, capture, compiler, env, generate, roku, secrets } from '@tantawowa/hosanna-tools';

await generate.all({
  rootFolder: './src',
  generatedFolder: './src-generated',
  mode: 'runtime',
});

await buildConfig.resolve({
  env: 'dev',
  platform: 'roku',
  out: 'assets/meta/build-config.json',
});

await compiler.install({ version: '0.33.7' });
await roku.package({ env: 'prod', prebuild: 'npm run roku:build:prod' });

const recording = await capture.start({ platform: 'ios', device: 'iPhone 17 Pro' });
// Drive the app manually, through MCP, or through another automation API.
await recording.stop();

Common build-script replacements:

| CLI command | Programmatic API | | --- | --- | | npx hst generate:all --rootFolder ./src | await generate.all({ rootFolder: './src' }) | | npx hst generate:clean | await generate.clean() | | npx hst build-config:resolve --env dev --platform roku --out assets/meta/build-config.json | await buildConfig.resolve({ env: 'dev', platform: 'roku', out: 'assets/meta/build-config.json' }) | | npx hst compiler:install 0.33.7 | await compiler.install({ version: '0.33.7' }) | | npx hst roku:package --env prod --prebuild 'npm run roku:build:prod' | await roku.package({ env: 'prod', prebuild: 'npm run roku:build:prod' }) | | npx hst capture ios --device 'iPhone 17 Pro' | await capture.start({ platform: 'ios', device: 'iPhone 17 Pro' }) | | npx hst secrets:check | await secrets.check({ cwd: process.cwd() }) | | npx hst env check | await env.check({ cwd: process.cwd() }) | | npx hst doctor | await env.check({ cwd: process.cwd() }) | | npx hst doctor --fix | await env.check({ cwd: process.cwd(), fix: true }) |

Long-running APIs such as dev.run, debugger.start, mcp.start, and RASP-owned certification capture workflows keep the same operational behavior as the corresponding CLI commands: they start services, attach to debuggers, or wait for user/session activity. mcp.start and dev.run are wired for programmatic no-exit behavior through the top-level API.

Installable Browser builds

hosannaPwaPlugin is a build-only Vite plugin for the generic install shell. The host application supplies its identity, artwork, launch selection, offline page, and network-only routes; Hosanna Tools emits the manifest, registration module, versioned service worker, and validated icon copies.

import { hosannaPwaPlugin } from '@tantawowa/hosanna-tools/vite';

hosannaPwaPlugin({
  manifest: {
    id: '/',
    name: 'Example',
    shortName: 'Example',
    startUrl: '/?app=example&expression=phone',
    scope: '/',
    backgroundColor: '#ffffff',
    themeColor: '#123456',
    icons: [{
      src: '/pwa-icons/icon-512.png',
      source: 'platforms/web/icons/icon-512.png',
      sizes: '512x512',
      type: 'image/png',
      purpose: 'any',
    }],
  },
  serviceWorker: {
    offlineFallback: { url: '/offline.html', source: 'platforms/web/offline.html' },
    networkOnly: ['/api', '/assets/meta/'],
  },
});

Navigation remains network-first and falls back only to the supplied offline page. Streaming media and configured API/runtime paths are never cached. Only the exact content-hashed static outputs in the current Vite bundle use the runtime cache.

Precompiled AppConfig and static asset bundles

Projects enable the compiler in .hosanna-tools/run.json. Normal hst run and hst build plans then compile before starting or packaging the target:

{
  "defaults": {
    "appConfigCompiler": {
      "enabled": true,
      "shapeDelivery": "bundled",
      "fontDelivery": "bundled",
      "bundleOutputDir": "public/asset-bundles",
      "assetUrlRoot": "/asset-bundles",
      "staticBundleManifest": "asset-bundles/static-bundles.json"
    }
  }
}

staticBundleManifest is optional. It adds scoped image, mask, JSON, media, or other project-owned assets to the same precompile step:

{
  "schemaVersion": 1,
  "bundles": [
    {
      "bundleId": "sample-home",
      "cacheBundleId": "sample-shared",
      "sourceDir": "sample-assets",
      "assets": [
        "content/home.json",
        "images/hero.jpg",
        {
          "source": "images/mask.png",
          "fileName": "masks/home.png",
          "required": true
        }
      ]
    }
  ]
}

Paths are relative to the manifest. assetsFile may replace or supplement the inline assets array; it accepts either an array or an object containing an assets array. Existing descriptor-shaped source lists are accepted by using each entry's fileName as its source.

Generated descriptors use sha256:<digest> versions derived from asset contents, keys, required flags, bundle/cache ids, and optional revisions. Descriptors that share a cacheBundleId also share one aggregate version, so loading a second scoped descriptor cannot invalidate assets retained by the first. Compiler ledgers remove stale owned files. Missing required sources fail before the application starts; optional missing sources are omitted. Re-running the command preserves byte-identical output and does not rewrite unchanged files.

Useful commands:

npx hst app-config:compile --expression tv --platform web \
  --static-bundle-manifest asset-bundles/static-bundles.json
npx hst run browser dev emulator --rebuild-app-config
npx hst app-config:clean --expression tv --platform web \
  --static-bundle-manifest asset-bundles/static-bundles.json

Getting started

Ensure you have Node.js 24.17.0.

run npm install to install all dependencies

Install ts-node globally:

  npm install -g ts-node

Ensure you have hosanna compiler (hsc) installed globally. Tantawowa Ltd will provide you with the compiler.

Requirements

  • Node.js 24.17.0
  • Python installed
  • *nix operating system (BSD, macOS, Unix, WSL)
  • Visual Studio Code or any MS Language Server Protocol (LSP) supported editor (only VS Code is officially supported by Tantawowa Ltd.)

Note: Windows is not supported directly. Developers can use WSL on Windows to meet the requirements. For more information, refer to the WSL installation guide and the VS Code WSL guide.

Development Workflow

Editing code

  1. Use vscode
  2. Ensure you have installed the package locally
    npm install . -g # path to the hosanna-tools directory
  3. Open this folder in vscode
  4. Run Npm Watch
  5. Open a javascript debugging terminal
  6. Run the hosanna server in a terminal, with Javscript debugging (i.e. Javascript Debug Terminal)

Developer Process

Before checking in your changes, ensure the following steps are completed:

  1. Run the linter: Ensure your code adheres to the project's coding standards by running the linter:

    npm run lint
  2. Run tests: Verify that all tests pass to ensure your changes do not introduce regressions:

    npm test
  3. Commit your changes: Once the linter and tests pass, commit your changes with a meaningful commit message.

Following these steps helps maintain code quality and stability across the project.

Releasing

See RELEASE.md for the full release process.

Quick reference:

npm run release -- patch   # 2.14.0 → 2.14.1
npm run release -- minor   # 2.14.0 → 2.15.0
npm run release -- major   # 2.14.0 → 3.0.0

For tokenless agent releases, dispatch Release Patch or Release Minor in GitHub Actions. Both wrappers invoke the OIDC-trusted release.yml workflow on main; agents do not need npm credentials.

CLI: configure-hosanna-url

  • purpose: Updates hosanna.json with a new Hosanna UI Git URL under the git-url key.
  • usage:
    • hst configure-hosanna-url https://github.com/YourOrg/hosanna-ui.git
    • HOSANNA_UI_GIT_URL=https://github.com/YourOrg/hosanna-ui.git hst configure-hosanna-url
  • behavior:
    • If no positional gitUrl is provided, the command falls back to the HOSANNA_UI_GIT_URL environment variable.
    • If neither is provided, it prints a message and leaves hosanna.json unchanged.
    • On success, it prints a sanitized URL (protocol + host + path) for logs.

Hosanna Tools CLI

Hosanna Tools is a comprehensive CLI toolset for the Hosanna framework that provides commands for development, building, deployment, and CI/CD operations.

CLI Command Groups

The CLI commands are organized into logical groups using colon-separated namespacing:

Development Commands

  • run - Canonical cross-platform app launcher. Bare interactive runs show one destination picker; explicit platform options include Browser, Samsung Tizen, LG webOS, Roku, Apple, and Android hosts.
  • build - Build/package without device discovery, deployment, launch, browser opening, or log streaming. Successful Tizen/webOS builds print their absolute .wgt/.ipk path.
  • device:setup <tizen|webos> - Guided, dry-runnable vendor setup: connect/authorize Samsung with SDB and verify an external signing profile, or register an LG ares alias and optionally run the official interactive key flow. HST never stores keys, certificates, or passphrases.
  • capture - Record an Apple simulator, a physical-TV capture-card input, or a macOS screen/window. The default timeout is 180 seconds; use --timeout to override it.
  • target:list - List launch targets for humans or agents, including web emulators, sims, and physical devices.
  • dev:start - Run dev processes: vite, generator watch, and optional debugger
  • debugger:start - Start the command debugger WebSocket proxy (only one debugger is needed for multiple apps; if the port is already in use, a friendly message is shown instead of crashing)

Examples:

hst run
hst run --last
hst run browser dev emulator
hst run tizen dev emulator
hst run webos dev emulator
hst build tizen dev device --signing-profile samsung-tv-dev
hst build webos dev device
hst run tizen dev device "Samsung living room" --signing-profile samsung-tv-dev
hst run webos dev device "LG living room"
hst run --platform roku --target emulator
hst run --platform ios --target emulator
hst run --platform android --target emulator
hst run --platform apple-tv --target emulator
hst run --platform android-tv --target emulator
hst run --platform ios --target sim --device "iPhone 17 Pro"
hst run --platform ios --target device --device "George iPhone" --no-logs
hst run --platform android --target sim --device "Pixel_8" --no-logs
hst run --platform android --target device --device "RF8M62694QT" --no-logs
hst run --platform android-tv --target sim --device "Television_1080p" --no-logs
hst run --platform apple-tv --target sim --device "Apple TV 4K"
hst run --platform roku --target device --device "Living Room"
hst run --platform roku --target device --device "Living Room" --replace
hst target:list --platform ios --target device --json
hst target:list --platform android --target sim --json
hst target:list --platform android-tv --target sim --json
hst target:list --platform apple-tv --target sim --json
hst target:list --form-factor tv --json

Bare hst run in an interactive terminal discovers runnable web previews, vendor simulators, and online physical devices, then presents one flat destination picker. The last selection is placed first, so pressing Enter repeats it; hst run --last skips discovery and immediately uses that remembered destination. The selection is stored in the user-level ~/.hosanna-tools/run.json, preserving existing defaults. Explicit commands remain deterministic, and non-interactive runs never open the picker.

browser is the canonical public platform; legacy platform input web is normalized to browser. emulator is the public desktop-preview target and HST retains internal target kind web. For Tizen and webOS, emulator mode launches the target-specific Vite config so compile-time initializers are selected; it is not a vendor simulator. --target sim launches a real vendor virtual device only for supported Apple/Android platforms. --target device launches or deploys to physical local hardware. Device/sim runs record the target and refuse to overwrite a recorded session or safe-to-kill occupied resource in non-interactive mode unless --replace is passed. Tizen/webOS previews cannot reuse a Browser session because their compiled alias graphs differ. Preferred run defaults live in .hosanna-tools/run.json, and friendly device aliases live in .hosanna-tools/devices.json or ~/.hosanna-tools/devices.json; signing keys and device passphrases remain in vendor stores.

HST starts new Android virtual devices with the Android Emulator's recommended auto graphics mode. Set HS_ANDROID_EMULATOR_GPU to an emulator-supported mode such as host or software when a machine needs an explicit performance or compatibility override. HST reads this setting only when it starts the AVD; stop and restart an already-running emulator through HST after changing it. The value is passed directly to the installed emulator, so its available modes remain authoritative.

Roku Commands (roku:*) - Roku Deployment & Packaging

  • roku:run - Deploy a Roku app to a device (supports .zip file or folder)
  • roku:command - Send a Hosanna command to an installed channel through Roku ECP
  • roku:package - Package and sign a Roku channel using roku-deploy. Source zips over 4 MiB warn by default; signed packages over 4 MiB fail.
  • roku:map-stack - Resolve Roku .brs stack traces, compile errors, and crash snippets to original TypeScript locations using .brs.map files

The package-size limit defaults to Roku's 4 MiB certification limit. Set a different limit with --max-pkg-size-mb, or explicitly allow an oversized signed package with --ignorePkgTooBig (--ignore-pkg-too-big is equivalent). Oversized source zips remain warnings because the signed .pkg is the release artifact Roku certifies.

hst roku:package --max-pkg-size-mb 4
hst roku:package --ignorePkgTooBig

Send a command to the sideloaded dev channel (the default app ID):

hst roku:command clearRegistry --device 192.168.1.50
hst roku:command clearRegistry --device "Living Room" --yes

The device can also come from ROKU_IP or the preferred/default Roku in .hosanna-tools/devices.json. Destructive commands such as clearRegistry prompt for confirmation unless --yes is passed. Use --app-id for another installed channel and --dry-run to print the encoded ECP request without sending it:

hst roku:command clearRegistry --app-id 8518 --dry-run

Resolve pasted Roku output:

pbpaste | hst roku:map-stack --source-map-root platforms/roku/src

Resolve a saved crash report or a single line:

hst roku:map-stack --file crash.txt --source-map-root platforms/roku/src
hst roku:map-stack --text "file/line: pkg:/components/source_0.brs(7475)"

Supported inputs include file/line: pkg:/components/source_0.brs(7475), at ... (pkg:/components/source_1.brs:6636), in pkg:/components/source_3.brs(4710), and bare generated references such as source_10.brs:8211. See docs/roku-map-stack.md.

Generate Commands (generate:*) - Code Generation

  • generate:all - Generate structs and command handler maps
  • generate:structs - Generate structs only for the specified files
  • generate:clean - Clean generated files in the generated folder

Setup Commands

  • sdk:install - Install the SDK by creating hosanna.json
  • compiler:install - Install or update the Hosanna compiler (hsc)
  • compiler:status - Print local compiler status for this project
  • compiler:list - List compiler versions known from local config, install, and cache
  • template:create - Create a new template app with the Hosanna SDK

Build Config Commands (build-config) - Runtime Configuration

  • build-config:resolve - Resolve build-config/base.json, env/platform overlays, secrets, and optional developer profiles into the canonical runtime build-config.json

Production JavaScript bundles strip console.* calls by default. Configure this through the normal overlay chain with build.stripLogs: set it to false in build-config/prod.json to retain production logs, or in build-config/prod.apple.json / build-config/prod.web.json for a platform-only exception. Non-production environments keep logs unless their overlay explicitly enables stripping. Apple prod builds use Xcode Release; other environments continue to use Debug.

Native Apple and Android phone/TV builds also emit a descriptor for the final packaged code bytes. See Packaged code bundle descriptors for version precedence, deterministic artifact paths, and the integrity-versus-authenticity security boundary.

Roku builds also populate assetServer.baseUrl when an overlay does not define it. hst run uses the resolved project Vite port and a reachable LAN IPv4 address. Override either the complete URL with HS_ASSET_SERVER_BASE_URL, or its parts with HS_ASSET_SERVER_HOST and HS_ASSET_SERVER_PORT; the equivalent HOSANNA_ASSET_SERVER_* names are also accepted. Explicit build-config overlays remain authoritative. The legacy game.assetBaseUrl setting is generated independently for backward compatibility.

Tizen/webOS builds prefer exact target overlays and fall back to the matching Web overlay only when the exact file is absent. Physical development builds resolve remote-debug loopback hosts to a reachable LAN address; override with HS_REMOTE_DEBUG_HOST. Production TV builds force remote debugging off. Exact non-secret service origins can be supplied with --connect-origin or HS_TV_CONNECT_ORIGINS; unresolved package tokens and wildcard origins fail staging. See Browser, Tizen, and webOS.

Native builds can resolve config immediately before the platform build:

npx hst build-config:resolve --env dev --platform roku --out assets/meta/build-config.json
npm run roku:build

HS_ENV=dev HS_PLATFORM=android npx hst build-config:resolve --out assets/meta/build-config.json
npm run android:build-code

HS_ENV=dev HS_PLATFORM=apple HS_BUILD_PROFILE=george npx hst build-config:resolve --out assets/meta/build-config.json
npm run apple:build-code

CI Commands (ci:*) - Continuous Integration

  • ci:project-actions --base <ref> [--head <ref>] - Select hst.json prScopeRules actions for changed files; add --run to execute matched npm scripts
  • ci:extract-pkg-key - Extract signing key from an existing signed Roku package as base64
  • config set --git-url - Configure hosanna.json git-url from argument or environment

Project-specific PR rules belong in hst.json; SDK source/version settings remain in hosanna.json:

{
  "prScopeRules": [
    {
      "name": "collection view performance check",
      "globs": ["src/hosanna-list/**", "src/hosanna-ui/views/lib/BaseView.ts"],
      "actions": [
        { "kind": "npm", "command": "regression:collectionView" }
      ]
    }
  ]
}

Rules and actions run in declaration order. Repeated identical actions are run once. The command emits matched, matched_rules, and actions through GITHUB_OUTPUT when that environment variable is present. This first version supports npm actions; the action object is intentionally extensible for future consumers.

Build Config Commands (build-config:*) - Build/runtime config

  • build-config:resolve - Merge build config overlays into assets/meta/build-config.json
  • build-config:restore-secrets - Restore ignored secrets/*.json overlays from BUILD_CONFIG_SECRETS_*_BASE64

Secrets Commands (secrets:*) - Portable .secrets files

  • secrets:list - Print key names from .secrets (or --template for .secrets.example); --format json
  • secrets:check - Compare .secrets to the template; report missing, empty, and extra keys; --strict fails on extras
  • secrets:exec - Load .secrets into the environment and run a command after --
  • secrets:init - Copy .secrets.example to .secrets when missing

Shared options: --file (secrets path), --template (template path for check / init / list --template), --format text|json.

Environment Commands (env ...) - Environment Management

  • doctor - Run the same read-only checks as env check, including required app packages
  • doctor --fix - Run the same repair path as env fix
  • env check - Print environment information and run checks
  • env fix - Check and repair environment issues
  • env prepare-gitignore - Ensure .gitignore contains required entries

Hosanna consumer dependencies

The installed SDK owns its app dependency contract in hosanna-ui/hosanna-consumer-dependencies.json:

{
  "schemaVersion": 1,
  "dependencies": { "lottie-web": "^5.13.0" },
  "devDependencies": { "@types/crypto-js": "^4.2.2" }
}

Both maps are required. hst doctor and hst env check validate the exact manifest, the app's direct package.json declarations, and the versions actually available through the app's Node resolution path (including a workspace-hoisted install). An older SDK without the manifest is reported as a supported legacy install with no requirements.

hst doctor --fix and hst env fix add missing requirements and run one app-root npm install. The repair is additive to the app's dependency set: it does not remove unrelated packages. It may move a compatible required package out of devDependencies or optionalDependencies so a runtime requirement is installed reliably. Existing compatible app ranges are preserved. An existing range that can select versions outside the SDK's required range is reported as a conflict and is not overwritten.

Projects that select another package manager or ship its lockfile are left for that package manager to repair. Workspace members are audited, but automatic repair is blocked so an ancestor lockfile is never changed without a matching rollback snapshot; run the workspace's package manager from its root instead. If npm install fails, or the installed versions still fail the audit afterward, package.json and npm lockfiles (package-lock.json and npm-shrinkwrap.json) are restored to their original contents. SDK installs and updates—including Git, Keygen, local, embedded, and shared source modes—run the same reconciliation after the new SDK is ready, so a framework upgrade cannot leave new app requirements undeclared.

Library callers can inspect or run the same focused operation through env.dependencies.audit({ projectRoot }) and env.dependencies.reconcile({ projectRoot }); both return structured audit and repair results without exiting the process.

Framework Source Symlinks (semver-keyed registry)

hst symlinks framework source folders from the hosanna-ui/ checkout into the project (src/hosanna-ui -> ../hosanna-ui/src/hosanna-ui, etc.). Which folders get linked is decided by a semver-keyed registry: an entry applies when the installed framework version is >= its key, and the highest applicable key wins. The installed version is read from hosanna-ui/package.json (prerelease suffixes are ignored, so 1.31.0-next counts as 1.31.0) — this works for tags, branches, @latest, and LOCAL_SDK alike.

Built-in defaults (src/updater/symlink-registry.ts):

| Installed hosanna-ui version | Symlinks under src/ | |---|---| | >= 1.0.0 | hosanna-bridge-core, hosanna-bridge-http, hosanna-bridge-lib, hosanna-bridge-targets, hosanna-list, hosanna-ui |

Prefer folder existence over version gates when adding registry entries: a checkout's package.json version can lag the tag it was cut from (hosanna-ui v1.28.3 reads 1.28.1-next), and folders absent from a checkout are already skipped safely at sync time.

hst env check always prints the active set, the matched registry version, and the source (built-in, hosanna.json override, + N extra). hst env fix creates missing links, repairs wrong targets, and removes obsolete ones — with no git/network access when only symlinks are wrong. Symlinks are also re-synced as part of every SDK update.

Adding folders (symlink-extra-folders) — the common customization. Appends to the resolved defaults; cannot break them. Folder names are forgiving ("hosanna-game/", "hosanna-game", and "src/hosanna-game" are equivalent):

{
  "git-url": "[email protected]:TantaWowa/hosanna-ui.git",
  "sdk-version": "v1.31.0",
  "symlink-extra-folders": ["hosanna-game/", "hosanna-game-examples/"]
}

Use this for game projects (hosanna-game, hosanna-game-examples) or when a project wants the example rigs (hosanna-ui-examples). Removing an entry makes its symlink obsolete; the next env fix cleans it up.

Replacing the registry (symlink-registry) — rare; total control. A valid key fully replaces the built-in registry (extras still append on top). Folders absent from the set become obsolete and are removed by --fix, so list everything the project needs:

{
  "symlink-registry": {
    "1.0.0":  ["hosanna-bridge-http/", "hosanna-bridge-lib/", "hosanna-bridge-targets/", "hosanna-list/", "hosanna-ui/"],
    "1.31.0": ["hosanna-bridge-http/", "hosanna-bridge-lib/", "hosanna-bridge-core/", "hosanna-bridge-targets/", "hosanna-list/", "hosanna-ui/"]
  }
}

An invalid symlink-registry/symlink-extra-folders value falls back to the built-in registry and is reported as an issue by hst env check — a typo cannot silently break an install.

Safety rules:

  • A registry folder that does not exist in the checkout is skipped with a warning, never an error (older framework versions predate some folders).
  • Obsolete cleanup only ever deletes symlinks at known framework paths (registry union, extras, retired folders such as src/hosanna-game). Real directories and files are never deleted; env fix reports them for manual handling instead.
  • .gitignore (via env prepare-gitignore or any SDK update) covers the union of the built-in registry, any override, and any extras for the project.

MCP Debugging Commands (mcp:start, mcp:stop) - AI Agent Debugging

  • mcp:start - Start the Hosanna MCP server for AI agent debugging
  • mcp:stop - Stop the Hosanna MCP server

Cursor and MCP: Cursor does not magically attach to a terminal hst mcp:start. Add Hosanna as a Command MCP server (project .cursor/mcp.json or Cursor Settings → MCP → Add Custom MCP) so Cursor spawns hosanna-mcp over stdio. Start the command debugger/app explicitly with hst run browser dev emulator, hst run tizen dev emulator, hst run webos dev emulator, or hst run roku dev device.

Deterministic UI testing

Applications own regular Vitest suites. Global setup comes from @tantawowa/hosanna-tools/testing/vitest; worker fixtures and matchers come from @tantawowa/hosanna-tools/testing/vitest/fixture; shared lifecycle, types, and helpers come from @tantawowa/hosanna-tools/testing. There is no HST test CLI or recording/replay format.

Add createHosannaReporter(config) from @tantawowa/hosanna-tools/testing/vitest/reporter to the application's Vitest reporters. Every run then writes a self-contained JSON and HTML report under test-results/<testRunId>/, updates test-results/latest.json and test-results/latest.html, and includes every Vitest result plus any named visual proofs captured by the tests.

Tests can record the complete owned browser, supported Apple simulator, or Roku device run:

defineHosannaTestConfig({
  // ...
  video: true,
  // Browser: video: { size: { width: 1280, height: 720 } },
  // Native/device: video: { timeoutSeconds: 300, videoDevice: 'USB Video' },
});

The finalized recording is written below test-results/<testRunId>/<platform>-<target>/ and embedded in the HTML report. Browser targets use Playwright WebM. iOS/Apple TV simulators use simctl MP4. Physical Roku, Tizen, and webOS targets use AVFoundation or a configured macOS screen/window source; HST does not claim vendor-native TV recording. Native/device capture defaults to 180 seconds; override it with timeoutSeconds. This is a review artifact, not a replay format or executable test source.

import { defineConfig } from 'vitest/config';
import { createHosannaReporter } from '@tantawowa/hosanna-tools/testing/vitest/reporter';
import hosannaTestConfig from './integration/hosanna-test.config';

export default defineConfig({
  reporters: ['default', createHosannaReporter(hosannaTestConfig)],
});

Use hs.proof.capture(...) at meaningful acceptance moments. A proof contains the target screenshot and the inspected screen/focus/control state used to understand it; hierarchy and scoped logs are optional. Proofs are evidence in the report, not an assertion by themselves:

const poster = hs.image.inCollectionCell({
  collectionId: 'collectionView',
  rowSettingsKey: 'rows.regular',
  cellIndex: 0,
  imageId: 'poster',
});
await poster.waitForLoaded({ requireBitmapSize: true });
await expect(poster).toBeLoadedImage({ requireBitmapSize: true });

await hs.proof.capture('programme-focused', {
  controls: {
    programmeCard: hs.control.byId('programmeCard'),
  },
  images: { poster },
  includeLogs: true,
});

Image readiness requires a non-empty URI, loadStatus: "ready", positive rendered dimensions, and positive decoded bitmap dimensions by default. Explicit loadWidth/loadHeight assertions remain available for controls that request a fixed decode size; zero is valid when the runtime decodes at the source size. hs.image.byId(...), hs.image.within(...), and semantic hs.image.inCollectionCell(...) locators work across browser, Roku, and later native drivers.

Screenshots and proofs wait for the command-plane hierarchy and focus to remain stable for 300ms by default, then allow a short platform render-settle window. Consecutive screenshots are also spaced automatically. Override this only for known platform behaviour through the test config's screenshot settings or per-capture options; failure diagnostics bypass the stable-frame wait so they can still capture broken states.

Custom test ports must be unique. Keep the Vite and browser CDP ports outside the debugger's dynamic app allocation range; the launcher validates this before starting any processes and reports the conflicting range.

Keep structural and state assertions as the default correctness checks. Use hs.screenshot.match(...) only for an explicit visual regression whose target-specific baseline and tolerance are intentionally maintained. Set HS_UPDATE_SCREENSHOTS=1 only after reviewing a candidate: update mode creates missing baselines, replaces existing baselines even when the old comparison differs, and treats the captured frame as the new passing expectation. Failure diagnostics and proof artifacts are separated below test-results/<testRunId>/<platform>-<target>/.

buildConfig supplies a non-secret overlay that is merged last for the owned test launch. It may be a target-aware factory, so browser emulation can enable deterministic mocks while a physical Roku keeps its real platform services. The launcher and resolver both reject test overlays for prod:

defineHosannaTestConfig({
  // ...
  environment: 'test',
  buildConfig: ({ platform, target }) => ({
    remoteDebug: { isEnabled: true },
    ...(target === 'web'
      ? { channelStore: { testMode: { enabled: true } } }
      : {}),
  }),
});

Use createHosannaTestTarget(config) with Vitest's standard conditional APIs. Selectors accept one platform or a set, and distinguish browser, simulator, and physical-device targets:

const target = createHosannaTestTarget(config);

test.runIf(target.matches({ platform: 'roku', target: 'device' }))('Roku only', async ({ hs }) => {});
test.runIf(target.matches({ platform: ['ios', 'android'], target: 'sim' }))('mobile simulators', async ({ hs }) => {});
test.runIf(target.matches({ target: 'web' }))('all browser flavours', async ({ hs }) => {});

Browser Channel Store emulation supports per-test success, cancelled, and failed outcomes when channelStore.testMode.enabled is present in the test overlay. Set it from a named precondition with hs.mocks.channelStore.setPurchaseOutcome(...). This API refuses physical-device targets. Roku purchase tests use Roku Pay billing testing, a linked Roku test user, and real Channel Store/OS purchase screens; keep them opt-in and serial.

For Roku device suites, the launcher builds and deploys before the test launch, then relaunches through ECP with the exact test run ID and a debugger address reachable from the device. Configure the device IP and developer password in the application test config/environment. HS_TEST_DEBUG_HOST overrides automatic LAN address selection when needed. Physical Roku input, held keys, deep links, screenshots, and logs use their device transports; the committed Vitest source remains the same API used by browser tests.

Usage Examples

# Development workflow
hst run browser dev emulator      # Canonical Browser host
hst run tizen dev emulator        # Desktop Tizen composition preview
hst run webos dev emulator        # Desktop webOS composition preview
hst build tizen dev device --signing-profile samsung-tv-dev
hst build webos dev device
hst run tizen dev device "Samsung living room" --signing-profile samsung-tv-dev
hst run webos dev device "LG living room"
hst run --platform roku --target emulator
hst run --platform ios --target emulator
hst run --platform android --target emulator
hst run --platform apple-tv --target emulator
hst run --platform android-tv --target emulator
hst run --platform ios --target sim --device "iPhone 17 Pro"
hst run --platform ios --target device --device "George iPhone" --no-logs
hst run --platform android --target sim --device "Pixel_8" --no-logs
hst run --platform android --target device --device "RF8M62694QT" --no-logs
hst run --platform android-tv --target sim --device "Television_1080p" --no-logs
hst run --platform apple-tv --target sim --device "Apple TV 4K"
hst run --platform roku --target device --device "Living Room"
hst run --platform roku --target device --device "Living Room" --replace
hst target:list --platform ios --target device --json
hst target:list --platform android --target sim --json
hst target:list --platform android-tv --target sim --json
hst target:list --platform apple-tv --target sim --json
hst target:list --form-factor tv --json
hst generate:all --watch          # Generate code with file watching
hst dev:start                    # Lower-level dev server task used by hst run

# Building and packaging
hst roku:package --ip 192.168.1.10  # Package and deploy; signed .pkg must be <= 4 MiB
hst generate:clean              # Clean generated files

# Setup and installation
hst sdk:install                 # Initialize Hosanna SDK
hst compiler:install           # Install Hosanna compiler
hst template:create           # Create new template app

# CI/CD operations
hst ci:extract-pkg-key myapp.pkg  # Extract signing key for CI
hst build-config:restore-secrets
hst build-config:resolve --env prod --platform roku --out assets/meta/build-config.json

# Secrets (.secrets / .secrets.example)
hst secrets:list
hst secrets:list --template --format json
hst secrets:check --strict
hst secrets:exec -- npm run build
hst secrets:init

# Environment management
hst doctor                   # Read-only environment and package audit
hst doctor --fix             # Repair issues and install missing requirements
hst env fix                  # Check and fix environment issues
hst env prepare-gitignore      # Update .gitignore

# MCP debugging (AI agent integration)
hst debugger:start               # Start debug proxy (required)
hst mcp:start                    # Start MCP server for Cursor/Claude

# Application-owned UI tests
npm run test:ui
npm run test:ui -- auth/login.test.ts
HS_TEST_PLATFORM=roku HS_TEST_TARGET=device npm run test:ui

MCP Debugging & Deterministic UI Tests

Hosanna Tools includes an MCP server for interactive AI-assisted debugging. Deterministic UI tests run in an application's Vitest process and use the separate @tantawowa/hosanna-tools/testing export; MCP is only an authoring aid.

Cursor Settings → MCP (Hosanna debugger)

Use Type: Command (not URL). Cursor spawns one long-lived process and speaks MCP over stdin/stdout.

| Field | Suggested value | |--------|------------------| | Name | hosanna-debugger (or any stable label) | | Type | Command | | Command | hosanna-mcp if @tantawowa/hosanna-tools is on your PATH (e.g. npm install -g or project node_modules/.bin). Otherwise use npx and put the package + binary in Arguments (see JSON below). | | Arguments | Usually empty when Command is hosanna-mcp. With npx: -y --package=@tantawowa/hosanna-tools hosanna-mcp (one token per argv if the UI supports a list; otherwise a single line matching the JSON args array). | | Environment | Optional; defaults match hst debugger:start. Use only if you use non-default ports. |

Equivalent ~/.cursor/mcp.json or .cursor/mcp.json (project) entry:

{
  "mcpServers": {
    "hosanna-debugger": {
      "command": "hosanna-mcp",
      "args": []
    }
  }
}

npx without a global install (same as one row in the UI: command npx, args as listed):

{
  "mcpServers": {
    "hosanna-debugger": {
      "command": "npx",
      "args": ["-y", "--package=@tantawowa/hosanna-tools", "hosanna-mcp"]
    }
  }
}

Environment variables (add under "env" in JSON, or Key / Value in the UI) when ports differ from the debugger:

| Key | Typical value | |-----|----------------| | HOSANNA_MANAGEMENT_PORT | 59150 | | HOSANNA_MANAGEMENT_HOST | localhost | | HOSANNA_EXTENSION_PORT | 59153 (must match hst debugger:start) |

After saving, enable the server in the MCP list. hst mcp:start is still useful in a terminal for manual runs; Cursor agents use the configured MCP spawn instead.

Quick Start

# 1. Start the debug proxy for an interactive MCP debugging session
hst debugger:start

# 2. Start your Hosanna app with remote debugging enabled

# 3. For AI debugging (Cursor, Claude Code):
#    Add MCP server (see "Cursor Settings → MCP" above) or hst mcp:start in a terminal

# 4. Run committed deterministic tests from the application repository:
npm run test:ui

See also

Documentation at the top of this README (MCP README, docs/README.md, hosanna-ui docs/README.md).

To debug

  • Run the hosanna server in a terminal, with Javscript debugging (i.e. Javascript Debug Terminal)
  • Run the hosanna tool in a terminal: breakpoint debugging will be available