@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 --yesThe 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 debugger —
hst 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.mdfor agentic debugging and links back to this README.
To use the tool
npm install -g @tantawowa/hosanna-toolsNote, if you are developing hosanna-tools, you will install the package locally.
npm install . -g # path to the hosanna-tools directoryHosanna 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 checkoutKeygen 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.jsonGetting started
Ensure you have Node.js 24.17.0.
run npm install to install all dependencies
Install ts-node globally:
npm install -g ts-nodeEnsure 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
- Use vscode
- Ensure you have installed the package locally
npm install . -g # path to the hosanna-tools directory - Open this folder in vscode
- Run Npm Watch
- Open a javascript debugging terminal
- 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:
Run the linter: Ensure your code adheres to the project's coding standards by running the linter:
npm run lintRun tests: Verify that all tests pass to ensure your changes do not introduce regressions:
npm testCommit 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.0For 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.jsonwith a new Hosanna UI Git URL under thegit-urlkey. - usage:
hst configure-hosanna-url https://github.com/YourOrg/hosanna-ui.gitHOSANNA_UI_GIT_URL=https://github.com/YourOrg/hosanna-ui.git hst configure-hosanna-url
- behavior:
- If no positional
gitUrlis provided, the command falls back to theHOSANNA_UI_GIT_URLenvironment variable. - If neither is provided, it prints a message and leaves
hosanna.jsonunchanged. - On success, it prints a sanitized URL (protocol + host + path) for logs.
- If no positional
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/.ipkpath.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--timeoutto 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 debuggerdebugger: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 --jsonBare 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 ECProku: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.brsstack traces, compile errors, and crash snippets to original TypeScript locations using.brs.mapfiles
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 --ignorePkgTooBigSend 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" --yesThe 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-runResolve pasted Roku output:
pbpaste | hst roku:map-stack --source-map-root platforms/roku/srcResolve 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 mapsgenerate:structs- Generate structs only for the specified filesgenerate:clean- Clean generated files in the generated folder
Setup Commands
sdk:install- Install the SDK by creating hosanna.jsoncompiler:install- Install or update the Hosanna compiler (hsc)compiler:status- Print local compiler status for this projectcompiler:list- List compiler versions known from local config, install, and cachetemplate:create- Create a new template app with the Hosanna SDK
Build Config Commands (build-config) - Runtime Configuration
build-config:resolve- Resolvebuild-config/base.json, env/platform overlays, secrets, and optional developer profiles into the canonical runtimebuild-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-codeCI Commands (ci:*) - Continuous Integration
ci:project-actions --base <ref> [--head <ref>]- Selecthst.jsonprScopeRulesactions for changed files; add--runto execute matched npm scriptsci:extract-pkg-key- Extract signing key from an existing signed Roku package as base64config 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 intoassets/meta/build-config.jsonbuild-config:restore-secrets- Restore ignoredsecrets/*.jsonoverlays fromBUILD_CONFIG_SECRETS_*_BASE64
Secrets Commands (secrets:*) - Portable .secrets files
secrets:list- Print key names from.secrets(or--templatefor.secrets.example);--format jsonsecrets:check- Compare.secretsto the template; report missing, empty, and extra keys;--strictfails on extrassecrets:exec- Load.secretsinto the environment and run a command after--secrets:init- Copy.secrets.exampleto.secretswhen 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 asenv check, including required app packagesdoctor --fix- Run the same repair path asenv fixenv check- Print environment information and run checksenv fix- Check and repair environment issuesenv 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 fixreports them for manual handling instead. .gitignore(viaenv prepare-gitignoreor 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 debuggingmcp: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:uiMCP 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:uiSee 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
