Set up and run an installed Sequence
July 18, 2026 ยท View on GitHub
This is the canonical installed/package-projected workflow for a Node.js Sequence. It keeps
the Sequence project separate from the Hub and uses only the published sth and si command
surfaces. The Process Adapter is used for the local example.
1. Create the Sequence package
A deployable Node.js Sequence needs a package.json, an entrypoint in main, and a Node engine
declaration. Keep compiled output and production dependencies in the package that is sent to the
Hub.
{
"name": "hello-sequence",
"version": "1.0.0",
"main": "dist/index.js",
"engines": { "node": ">=18" },
"scripts": {
"build": "tsc -p tsconfig.json",
"test": "node --test"
},
"dependencies": {
"@scramjet/sequence-types": "^1.1.0"
}
}
For example, src/index.ts can export the application function:
import type { SequenceAppContext } from "@scramjet/sequence-types";
import type { Readable } from "node:stream";
export default async function (this: SequenceAppContext, input: Readable) {
const values: unknown[] = [];
for await (const value of input) values.push(value);
return { count: values.length };
}
The corresponding project-local workflow is:
npm install
npm run build
npm test
The build must leave the file named by main at dist/index.js.
Install production dependencies before archiving
The Hub does not install dependencies. The package archive must include the production
node_modules/ directory. After the build, install only runtime dependencies:
npm install --production
# or, for Bun:
# bun install --production
This creates or updates node_modules/ with only the packages listed under dependencies
in package.json.
Create the deployable archive
Use the CLI packager to create the archive. The packager includes every file and directory
in the project folder, including node_modules/, subject to .siignore rules (see below):
si sequence pack . -o hello-sequence.tar.gz
The equivalent npm pack command also produces a .tgz, but npm excludes node_modules/
by default. To use npm pack, list bundled dependencies explicitly in package.json with
the "files" field or
"bundledDependencies".
The CLI packager (si sequence pack) is the recommended tool because it includes
node_modules/ without extra configuration.
Ignoring files with .siignore
The CLI respects a .siignore file in the package root, using the same glob syntax as
.gitignore. Exclude build artifacts, source maps, and test fixtures to reduce archive size:
# .siignore
src/
tsconfig.json
node_modules/.cache
test/
*.map
Do not exclude the node_modules/ directory itself. The Hub does not install
dependencies, so the entire production node_modules/ must be present in the archive at
deploy time.
2. Install the Hub and CLI
Install the published runtime and CLI on the host/operator machine:
npm install -g @scramjet/sth @scramjet/cli
sth --help
si --version
These are installed command entrypoints. A repository checkout, workspace build, or repository test command is not required to deploy the package artifact.
3. Start a minimal local Hub
Create the local storage directory and start a standalone Hub with the Process Adapter bound to loopback:
Hub terminal
Run the Hub in the foreground and leave this terminal attached to it:
mkdir -p sequence-store
sth \
--runtime-adapter process \
--hostname 127.0.0.1 \
--port 8000 \
--sequences-root "$PWD/sequence-store"
The equivalent configuration-file values are runtimeAdapter: "process",
host.hostname: "127.0.0.1", host.port: 8000, and sequencesRoot set to the absolute
sequence-store path. The --sequences-root directory is where the Process Adapter stores
uploaded Sequences; it is not the source project directory.
Do not replace readiness with a fixed sleep. The compatibility status route reports the Hub's
startup contract as ready: true:
Readiness terminal
In a second terminal, wait for the Hub's readiness response:
timeout 60s sh -c '
until curl --fail --silent http://127.0.0.1:8000/api/v1/status |
node -e "let s=\"\"; process.stdin.on(\"data\", c => s += c).on(\"end\", () => process.exit(JSON.parse(s).ready === true ? 0 : 1))";
do :; done
'
4. Upload and start
Point si at the local Hub (this is also its default target), then deploy the packaged artifact.
sequence deploy uploads and starts; use sequence send followed by sequence start when the
two operations must be separate.
Deploy/start terminal
In the terminal used for CLI operations, point si at the local Hub and deploy:
si config set apiUrl http://127.0.0.1:8000
si sequence deploy ./hello-sequence.tar.gz
For separate upload/start:
si sequence send ./hello-sequence.tar.gz
si sequence start <sequence-id>
The deploy/start response contains the Instance ID. Inspect and control that Instance with the installed CLI:
Instance API terminal
Use the returned Instance ID to inspect and control the running Instance:
si instance list
si instance info <instance-id>
si instance log <instance-id>
si instance input <instance-id>
si instance stdout <instance-id>
si instance stop <instance-id> 10000
Use --config-file, --config-string, --args, --input-topic, or --output-topic on
si sequence start/si sequence deploy when the Sequence needs startup configuration, arguments,
or topic routing.
Hub, Manager, and Space paths
There are three distinct execution scopes:
-
Direct Hub:
sitargetshttp://127.0.0.1:8000; the Hub stores the package, starts its Runner, and owns the Instance. -
Manager-routed: point the same installed CLI at the Manager with
si config set apiUrl http://manager-host:8200. The Manager routes upload/start/control operations to a connected Hub; the Runner still executes on that Hub. The Hub must first be connected using the deployment's verified Manager/verser2 configuration; do not assume that starting a Manager alone connects a Hub. -
Sequence Hub/Space requests: code running in an Instance uses
this.hubClient()for the current Hub andthis.spaceClient()for Manager/Space operations. These are request paths from the Sequence, not alternate local Hub startup commands:const hubHealth = await this.hubClient().health.get(); const spaceHubs = await this.spaceClient().hubs.get();spaceClient()is routed through the connected Hub's Space proxy. Hub and Space scopes remain separate, and a Space path requires a connected Manager/Space deployment and its authentication and TLS configuration.
See Choosing a sequence communication path for the scope and delivery rules, and Filtering local object data for a consumer for a small application example.