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

@hsuite/smart-engines-cli

v1.5.1

Published

HSuite CLI for smart-app deployment and management

Readme

@hsuite/smart-engines-cli

hsuite — the developer bootstrap CLI for Smart Engines V3. Takes you from "empty directory" to "smart-app running against the live testnet cluster" in under a minute, then manages the deployment's lifecycle.

npm install -g @hsuite/smart-engines-cli
hsuite init                    # XRPL wallet + faucet + .env.local
hsuite subscribe --env <file>  # paid smart-app subscription on cluster (tier builder|growth|scale|enterprise)

# deployment lifecycle (manifest-driven):
hsuite deploy   --manifest <f> # THE canonical path — fresh deploy AND redeploy
hsuite redeploy --manifest <f> # thin convenience: distinct --app-id / --tag override
hsuite update   --replicas 3   # patch runtime config (cpu/memory/degree/replicas/env)
hsuite suspend | resume | delete
hsuite status [--watch] | list

XRPL-only. The CLI generates an XRPL keypair, funds it via the testnet faucet, and uses it for Web3 challenge-response auth against the cluster. No Hedera credentials needed — the cluster's validator/host pods pay their own HCS fees.


hsuite init

Generate a fresh XRPL testnet wallet, fund it (~1000 testnet XRP via the official Ripple faucet), and write an .env.local with everything the showcase smart-app expects.

hsuite init                                # writes ./.env.local (testnet)
hsuite init --out smart-app/.env.local     # custom output path
hsuite init --network devnet               # devnet faucet instead
hsuite init --no-fund                      # generate wallet only, skip faucet
hsuite init --force                        # overwrite an existing .env.local
hsuite init --gateway https://...          # override the cluster gateway URL

The generated .env.local:

APP_ID=smart-app-showcase-local
APP_NAME=Smart App Showcase (local)

VALIDATOR_URL=https://v3-testnet-gateway.hsuite.network
SMART_HOST_URL=https://v3-testnet-gateway.hsuite.network

XRPL_NETWORK=testnet
XRPL_ADDRESS=r...
XRPL_PUBLIC_KEY=...
XRPL_SEED=s...                  # ⚠️ DO NOT COMMIT

# NestJS dev config
NODE_ENV=development
PORT=3000
API_KEY_ENABLED=false
CORS_ORIGINS=http://localhost:8101,http://localhost:8100,http://localhost:4200
...

# Subscription — run `hsuite subscribe` to register a paid smart-app. Default tier is builder.
SUBSCRIPTION_TIER=builder
# SUBSCRIPTION_APP_ID=          # populated by `hsuite subscribe`

hsuite subscribe

Register a paid smart-app subscription on the cluster. Every connection is paid: pick a tier (builder | growth | scale | enterprise, default builder), the cluster spins up a TSS deposit wallet and returns deposit instructions, and the subscription NFT mints once the HSUITE deposit confirms on-chain. DKG runs so the cluster-issued appId becomes your smart-app's on-chain identity.

hsuite subscribe --env .env.local
hsuite subscribe --env .env.local --tier growth
hsuite subscribe --env .env.local --name "My Smart App"
hsuite subscribe --env .env.local --services database,storage,messaging
hsuite subscribe --env .env.local --gateway https://my-cluster.example.com

Flow:

  1. Reads XRPL_* + APP_NAME from .env.local
  2. Builds a signer using ripple-keypairs.sign
  3. Authenticates via BaasClient.authenticate({chain: 'xrpl', ...}) against the cluster
  4. Calls BaasClient.deployment.init({name, port, services}) — the new four-step deploy flow's step 1 (legacy register() removed in PR-A); the cluster runs the per-entity DKG ceremony and returns the DKG entityId as appId
  5. Appends SUBSCRIPTION_APP_ID=<appId> and APP_ID=<appId> to your .env.local

After this, your smart-app boots in cluster-mode automatically.


Deployment commands

Eight commands take a smart-app from a manifest to a running, manageable deployment on the cluster. They all share base flags:

| Flag | Default | Meaning | |---|---|---| | --env <file> | .env.local | Env file with the XRPL auth creds | | --gateway <url> | https://gateway.testnet.hsuite.network | Public gateway/host URL | | --app-id <id> | DEPLOYED_APP_IDSUBSCRIPTION_APP_ID | App to act on |

Every command constructs exactly one BaasClient ({ hostUrl, appId, pathPrefix: '/host', allowInsecure, timeout }) and authenticates it with the env XRPL signer — connecting straight to the public round-robin gateway (no cluster-discovery factory, whose per-cluster hostnames aren't reachable from a dev machine).

The manifest (one canonical shape)

Source of truth: packages/hsuite-cli/src/_lib/deploy-manifest.ts.

Every smart-app is a NestJS backend, optionally fronted by an ionic SPA. The manifest has ONE shape: a required backend block plus an optional frontend block.

{
  "name": "my-smart-app",
  "services": ["database", "storage", "messaging", "functions"],  // ('auth'|'database'|'storage'|'functions'|'messaging')[]
  "degree": 3,                              // clusters to span (>=3; 3 is the floor)
  "backend": {                              // REQUIRED — the NestJS image
    "port": 3200,                           // backend listen port, 1..65535, NEVER 8080 (reserved for the edge sidecar)
    "tag": "v1",                            // image tag (REQUIRED)
    "replicas": 1,                          // pods per cluster (default 1)
    "context": ".",                         // docker build context (default '.')
    "dockerfile": "Dockerfile",             // default 'Dockerfile'
    "platform": "linux/amd64",              // default 'linux/amd64' (cluster-node arch)
    "build": "yarn build",                  // optional pre-build shell cmd, run in context
    "env": { "NODE_ENV": "production" },    // NON-SECRET overrides only — merged over the auto-forwarded .env.local runtime env (manifest wins)
    "limits": { "cpu": "500m", "memory": "512Mi" }
  },
  "frontend": {                             // OPTIONAL — ionic SPA, served by the EDGE sidecar (NOT the backend)
    "build": "ng build",                    // optional pre-build command
    "dir": "www",                           // dir to tar into the SPA bundle
    "bundlePath": null                      // OR a pre-built tarball (wins over `dir`)
  }
}

Runtime env: auto-forwarded from .env.local (do NOT hand-copy secrets)

hsuite deploy automatically forwards your .env.local runtime creds into the deployed container — so the deployed app runs with the same identity + config it runs with locally. The deployed smart-app authenticates as your own XRPL wallet (the XRPL_SEED in .env.local, whose address holds the subscription NFT); there is no separate app identity. You therefore never hand-copy XRPL_SEED / HEDERA_PRIVATE_KEY / chain creds into a committed manifest — a manual step that, if forgotten, silently shipped a credential-less, open-mode app (/baas/status{"mode":"memory","appId":null}; BaaS routes 503). See issue #1564.

What gets forwarded: the runtime-relevant keys from your .env.local — the same set the smart-app's env schema reads (XRPL_*, SUBSCRIPTION_APP_ID, APP_*, VALIDATOR_URL/SMART_HOST_URL, AI/Discord config, …). Purely deploy-time / CLI-only knobs (e.g. SUBSCRIPTION_NFT_SERIAL, VALIDATOR_API_KEY) are not forwarded. The list lives in packages/hsuite-cli/src/_lib/runtime-env.ts (RUNTIME_ENV_KEYS), mirroring the smart-app schema (apps/showcase/smart-app/src/config/env-validation.ts in the hsuite-ecosystem repo).

Precedence: the forwarded .env.local values are the base; manifest.backend.env is overlaid last and WINS for any key it sets. Use backend.env for explicit non-secret per-deploy overrides (ports, feature flags, Discord/AI endpoints). Secrets flow automatically from .env.local and do not belong in a committed manifest. Everything lands in the app's PQC-encrypted (kyber-aes-v1) per-app customer-env Secret — the pod's runtime env, envFrom- mounted on the backend container. Encryption at rest is the containment boundary; no secret is ever written into a committed file.

Fail-loud: if a deploy would ship the app credential-less (no XRPL_SEED reaching the container) the CLI errors rather than silently booting open mode. An intentional open-mode deploy stays valid via the explicit --allow-open-mode flag, which deliberately withholds the seed from the container (open mode) while still using it locally to sign the required build attestation.

The same forwarding + fail-loud applies to hsuite redeploy.

Backend-only example (no frontend block — the edge proxies all paths to the backend):

{
  "name": "my-api",
  "services": ["database"],
  "degree": 3,
  "backend": { "port": 3200, "tag": "v1" }
}

Relative frontend.dir / frontend.bundlePath (and the frontend build hook) resolve against the backend's build context (the smart-app root) — NOT the directory you ran hsuite from. A bare "public" means <smart-app>/public. degree is validated client-side against the host floor (>= 3) so a bad value fails with a clear CLI error instead of a server 500.

Serving model: the public-vs-edge split

Every deployed customer pod has two containers:

  • The customer backend listens on loopback at backend.port (e.g. 3200). It is NOT exposed at the pod boundary, and 8080 is forbidden for the backend.
  • A platform edge sidecar (Caddy) listens on port 8080 — the pod's exposed/Service port. The edge reverse-proxies API requests to the backend on loopback and serves the SPA.

The ionic SPA is served by the edge sidecar, not the backend. The optional frontend block is tarred and uploaded (uploadFrontend) into the cluster BaaS storage tier, content-addressed by sha256. At pod start a bundle-fetcher init container fetches that bundle into a shared emptyDir, which the edge serves read-only from /srv/spa, falling back to the SPA shell (index.html) for client-side routing. For a backend-only app (no frontend block) the edge proxies all paths to the backend.

The SPA is also commonly baked into the backend image's own public/ — but in the deployed pod it is the edge-served uploaded bundle that the public sees on port 8080.

(Refs: apps/smart-deployer/src/reconciler/caddyfile-renderer.service.ts, apps/smart-deployer/src/reconciler/k8s-resource-builder.service.ts.)

Multi-cluster image distribution

harbor.testnet.hsuite.network is public-DNS round-robin over the 3 cluster ingress IPs, each fronting its own Harbor. A single docker push lands the image on only one cluster. hsuite deploy therefore fans the image out to every cluster Harbor itself, synchronously, BEFORE reconciling: it resolves the registry host's A-records, copies the pushed image to each cluster at the Registry-v2 level (TLS-SNI pinned to the federated hostname, 401/Bearer token auth, blob copy + manifest PUT), then re-verifies the exact pushed digest is served by every cluster and ABORTS the deploy if any cluster can't be made to serve it. This replaces reliance on the (unreliable) Harbor cross-cluster replication mesh for customer images — the mesh is no longer load-bearing. The push-robot credential is BLS-deterministic and identical on all 3 cluster Harbors, which is what lets one credential authenticate the fan-out against every cluster. --skip-distribute opts out (single-cluster / dev registry). (Implementation: packages/hsuite-cli/src/_lib/registry-fanout.ts.)

Deploy strategy (Recreate vs RollingUpdate)

The strategy is driven by replica count (apps/smart-deployer/src/reconciler/k8s-resource-builder.service.ts buildDeployment):

  • Single-replica apps (replicas <= 1) use Recreate. A single-replica tenant CANNOT surge — the per-tenant ResourceQuota only fits one pod — so RollingUpdate would deadlock. Pods are stateless (no RWO PVC), so Recreate-in-place is safe.
  • Multi-replica apps use zero-downtime RollingUpdate{maxSurge:1, maxUnavailable:0}.

The strategy field on the manifest/deploy request is advisory: a recreate request is coerced to RollingUpdate for multi-replica apps (with a warning).

hsuite deploy — THE canonical deploy path

hsuite deploy --manifest <file> is the single, canonical path to deploy a customer smart-app (NestJS backend + optional ionic SPA) across the 3-cluster testnet. It handles BOTH a fresh deploy AND a redeploy of an existing/active app. There is no hand-rolled deploy-*.cjs script and no manual per-cluster docker push — exactly one path: hsuite deploy.

Mint-first / deploy-last: the developer's SUBSCRIPTION_APP_ID IS the deploy target (created + paid by hsuite subscribe; SUBSCRIPTION_APP_ID == DEPLOYED_APP_ID == DKG entityId). deploy allocates nothing — it authenticates as that id and fetches push creds for it (pushCredentials, idempotent).

Flow: resolve SUBSCRIPTION_APP_IDconnectAndAuthpushCredentials → docker build+push (backend) → fan the image out to every cluster Harbor (verify + abort on any miss) → tar + uploadFrontend (frontend) → sign a build attestation → deploy(). Writes DEPLOYED_APP_ID to the env file.

hsuite deploy --manifest ./my-app.json --env .env.local
hsuite deploy --manifest ./my-app.json --strategy recreate
hsuite deploy --manifest ./my-app.json --docker-host unix:///path/docker.sock
hsuite deploy --manifest ./my-app.json --skip-build --skip-push   # image already pushed
hsuite deploy --manifest ./my-app.json --skip-distribute          # single-cluster / dev registry
hsuite deploy --manifest ./my-app.json --subscription-app-id sub_… # override the deploy target

Flags: --manifest <file>, --env <file> (default .env.local), `--project

The docker login uses the init-issued one-time robot creds via execFileSync('docker', ['login', server, '-u', username, '--password-stdin']) — the robot username (robot$project+name) is a discrete argv element and the password is fed on stdin, so the $ is never shell-expanded.

hsuite redeploy — thin convenience

redeploy is NOT a separate required path — hsuite deploy already redeploys an existing/active app. redeploy is a thin convenience for passing a distinct deployed --app-id and/or a --tag override. It rebuilds + pushes the backend image, fans it out to every cluster (same --skip-distribute opt-out), re-uploads the SPA bundle when the manifest carries a frontend block, then deploy()s.

hsuite redeploy --manifest ./my-app.json --tag v2
hsuite redeploy --manifest ./my-app.json --app-id app_… --strategy recreate
hsuite redeploy --manifest ./my-app.json --skip-distribute

hsuite update

Patch runtime config without a new image — at least one field required.

hsuite update --cpu 500m --memory 512Mi
hsuite update --replicas 3 --degree 3
hsuite update --strategy recreate
hsuite update --env-set NODE_ENV=production --env-set LOG_LEVEL=info

hsuite suspend / resume / delete

hsuite suspend                 # scale the runtime to zero
hsuite resume                  # scale it back up
hsuite delete                  # tear down (confirms; --yes to skip, required when non-TTY)
hsuite delete --yes

hsuite status / list

hsuite status                  # state + runtime (runtimeState / replicas / lastError)
hsuite status --watch          # poll until RUNNING / FAILED
hsuite status --json
hsuite list                    # table of {appId, name, status}
hsuite list --json

The deployed appId is appended to .env.local as DEPLOYED_APP_ID.


End-to-end (1-minute bootstrap)

mkdir my-smart-app && cd my-smart-app
npm install -g @hsuite/smart-engines-cli

hsuite init                                  # → .env.local with funded XRPL wallet
hsuite subscribe --env .env.local            # → paid (builder) subscription appId on cluster
cat .env.local | grep XRPL_ADDRESS           # → your wallet address
cat .env.local | grep SUBSCRIPTION_APP_ID    # → your smart-app's DKG entity ID

That's it — you now have:

  • A funded XRPL testnet wallet
  • A registered smart-app on the live Smart Engines V3 testnet cluster
  • An .env.local your NestJS backend can consume directly

What the CLI does NOT do

  • Pay HCS fees. The cluster's validator/host pods do that from their own pod-local Hedera operator accounts. The smart-app never sees Hedera credentials.
  • Confirm the HSUITE deposit for you. subscribe creates the subscription and returns deposit instructions, but you fund the TSS deposit wallet yourself; the subscription NFT mints (and the smart-app goes ACTIVE) only once that deposit confirms on-chain.
  • Configure your smart-app's business logic. If your smart-app does Hedera-side or Solana-side or any other-chain ops as part of its app logic, that's separate from the dev wallet and you configure it in your app's own code/env.

Use programmatically

The hsuite package is a CLI only — its entry point (dist/index.js) is an executable that parses process.argv on load and exposes no importable API. There are no initWallet / subscribeFreeTestnet / deploySmartApp functions to import.

For programmatic access from your own code, use the SDK directly — see Companion packages:

import { /* ... */ } from '@hsuite/smart-engines-sdk';

To automate the CLI itself, shell out to the hsuite binary from your build scripts or CI:

hsuite init --out .env.local
hsuite subscribe --env .env.local --tier builder

Companion packages

  • @hsuite/smart-engines-sdk — the underlying SDK that hsuite wraps. Use it directly when you need finer-grained control over auth, BaaS calls, or chain operations.
  • hsuite-ecosystem/apps/showcase — a reference NestJS backend + Ionic dApp that demonstrate the full integration. Fork it as a starting point.

Peer dependencies

| Package | Why | |---|---| | @hsuite/smart-engines-sdk | Auth + BaaS API surface | | xrpl | XRPL keypair generation + signing | | commander, chalk, ora, dotenv, uuid | CLI ergonomics (UI + env parsing) |

All bundled — npm install -g @hsuite/smart-engines-cli pulls everything.


License

MIT.