@hagicode/hagiscript is the runtime management CLI behind the hagicode-runtime contract. Use it to install, inspect, update, remove, and operate a managed HagiCode runtime without depending on system Node.js, system PM2, or host-global npm packages.
npm install -g @hagicode/hagiscriptPrimary entrypoints:
hagiscripthagicode-runtime(hagiscript runtime ...wrapper)
Node.js 20 or newer is required to run the package itself.
By default, Hagiscript loads runtime/manifest.yaml and manages the runtime under ~/.hagicode/runtime.
<runtime-root>/
program/
bin/
npm/
components/
runtime-data/
config/
logs/
data/
components/
state.json
server/
versions/
server-data/
.pm2/
pm2-runtime/
config/
versions-state.json
The split is intentional:
program/holds managed executables, vendored payloads, wrappers, and the managed npm prefix.runtime-data/holds mutable config, logs, state, and component-specific writable files.server/holds versioned backend payloads for the releasedserverservice.server-data/holds mutable PM2 state and shared launch assets for thatserverservice.
The packaged manifest currently manages:
node- managed Node.js runtimedotnet- managed .NET and ASP.NET Core runtimeserver- released backend package metadata and PM2 launch assets forlib/PCode.Web.dllomniroute- vendored bundled runtimecode-server- vendored bundled runtime
The runtime layout still reserves program/npm/ as the managed npm prefix, but package inventory inside that prefix is not part of the runtime component manifest. Tool installation there is handled separately through hagiscript npm-sync or external provisioning.
Install the full runtime:
hagiscript runtime installRuntime installs reuse a shared download cache by default. Disable it with --no-download-cache, or relocate it with --download-cache-dir <path>.
Install selected components only:
hagiscript runtime install --components node,omniroutePreview planned changes without mutating files:
hagiscript runtime install --dry-run
hagiscript runtime update --check-onlyInspect the canonical runtime state:
hagiscript runtime state
hagiscript runtime state --jsonUpdate or remove managed components:
hagiscript runtime update
hagiscript runtime remove --components code-server --purgeOverride the runtime root or manifest when needed:
hagiscript runtime install --runtime-root /srv/hagicode/runtime
hagiscript runtime state --from-manifest /path/to/runtime-manifest.yaml --jsonIf you prefer the runtime-oriented wrapper:
hagicode-runtime install --runtime-root /srv/hagicode/runtimehagiscript runtime state --json is the canonical inspection surface for automation. It reports:
- resolved runtime root
program/andruntime-data/locations- per-component install status
- per-component runtime data homes
- derived PM2 homes for managed services
- program/data path separation
Use it before and after maintenance work to confirm the expected component set and writable paths.
Typical maintenance flow:
- Check current state:
hagiscript runtime state --json - Apply changes:
hagiscript runtime install,update, orremove - Re-check state to confirm the final layout
- Operate services through
hagiscript pm2 ...
Lifecycle commands print the resolved manifest, managed root, changed component count, skipped entries, and log file path when a log is generated.
Hagiscript manages runtime-scoped PM2 services for:
serveromniroutecode-server
Supported actions:
startrestartstopstatusenv
Examples:
hagiscript pm2 server start
hagiscript pm2 server restart
hagiscript pm2 server status
hagiscript pm2 server env
hagiscript pm2 server env --json
hagiscript pm2 omniroute status
hagiscript pm2 omniroute start
hagiscript pm2 code-server stopThe PM2 flow is runtime-scoped:
- PM2 is resolved from the managed npm prefix, not the host environment.
- Hagiscript resolves the runtime manifest before every PM2 action.
- PM2 runs with the managed Node runtime and managed PATH ordering.
PM2_HOMEis derived from the managed runtime layout, so service state stays inside the runtime data boundary.
This means maintenance scripts should call hagiscript pm2 ... instead of a system pm2 binary, and should ensure pm2 has been installed into the managed npm prefix beforehand.
The packaged runtime manifest treats server as a released-service component. Hagiscript stages released backend payloads under a dedicated versioned server root:
<runtime-root>/server/
versions/
1.2.3/
lib/PCode.Web.dll
lib/PCode.Web.deps.json
lib/PCode.Web.runtimeconfig.json
start.sh (or the platform equivalent from the release package)
Hagiscript keeps mutable launch state for that service in a single shared data home, regardless of how many server versions are installed:
<runtime-root>/server-data/
.pm2/
pm2-runtime/
config/
versions-state.json
hagiscript server install stages a concrete backend version, updates the active-version inventory in versions-state.json, ensures the fixed runtime dependencies, and keeps PM2 launch files under the shared server-data home. hagiscript pm2 server start then resolves the active server version, generates the final PM2 ecosystem/env files under pm2-runtime/, and launches the released backend through the managed dotnet runtime. Use hagiscript pm2 server env to print the exact resolved working directory, PATH ordering, and environment variables that HagiScript will use for that startup flow.
For the Desktop -> Hagiscript -> PM2 environment handoff, including variable ownership and precedence, see docs/desktop-hagiscript-env-contract.md.
Hagiscript can now stage a released backend package and prepare all startup prerequisites from a single command surface:
hagiscript server install
hagiscript server install --package-dir /srv/hagicode/packages
hagiscript server install --archive ./hagicode-1.2.3-linux-x64-nort.zip
hagiscript server install --url https://example.com/hagicode-1.2.3-linux-x64-nort.zip
hagiscript server install --index-url https://index.example.com/hagicode/index.json --index-channel stable
hagiscript server install --github-repo HagiCode-org/releases --tag v1.2.3By default, server install:
- selects or downloads a server archive
- extracts and stages it into
server/versions/<version>/ - installs the fixed runtime dependencies declared by the server contract
- ensures
pm2exists in the managed npm prefix
Inspect and switch the installed server inventory with:
hagiscript server list
hagiscript server use 1.2.3
hagiscript server remove 1.2.2server list shows the active version and every staged payload under server/versions/. server use switches the active payload that hagiscript server start and hagiscript pm2 server ... will resolve. server remove deletes an inactive installed version while leaving the shared server-data directory intact.
Source priority for server install is:
- local archive (
--archive) - local folder (
--package-dir) - direct URL (
--url) - HTTP index (
--index-url, optional--index-channel,--index-version) - GitHub release fallback (
--github-repo,--tag,--asset)
When no explicit source option is provided, Hagiscript first tries the default official HTTP index:
https://index.hagicode.com/server/index.json
If that index cannot be resolved, Hagiscript automatically falls back to GitHub release discovery.
When index mode is used, Hagiscript reads index JSON, picks the best matching asset for current platform/arch, and then downloads from either a direct URL field or the first marked primary entry in downloadSources (falling back to the first source entry).
Once installed, use the higher-level lifecycle wrappers:
hagiscript server start
hagiscript server restart --instance demo
hagiscript server stop --instance demo
hagiscript server status --json
hagiscript server env --instance demo--instance <name> maps to the PM2 name identifier and defaults to hagicode, so one host can run multiple managed runtime roots without colliding app names.
This repository includes a tracked playground/ folder with its own .gitignore, so runtime artifacts created during local validation do not enter git.
All playground scripts use:
- manifest:
./playground/manifest.yaml - runtime root:
./playground/runtime-root
Run the local lifecycle test flow:
npm run playground:runtime:install
npm run playground:runtime:state
npm run playground:server:install
npm run playground:server:start
npm run playground:server:status
npm run playground:server:env
npm run playground:server:stop
npm run playground:runtime:removeAvailable playground scripts:
playground:runtime:installplayground:runtime:stateplayground:runtime:updateplayground:runtime:removeplayground:server:installplayground:server:startplayground:server:statusplayground:server:stopplayground:server:env
Runtime lifecycle scripts and managed services receive a stable environment contract:
HAGICODE_RUNTIME_HOME- runtime program homeHAGICODE_RUNTIME_DATA_HOME- writable runtime data home for the current componentPM2_HOME- PM2 state directory for the current managed servicePATH- rebuilt so managed Node, managed npm, and managed wrappers come first
This contract is what keeps installs, updates, wrappers, and PM2-managed services aligned to the same runtime root.
runtime/manifest.yaml controls the runtime shape. Common override points:
paths.runtimeRootpaths.runtimeHomepaths.runtimeDataRootpaths.componentDataRootpaths.defaultPm2Home- component
runtimeDataDir - service
pm2.appName - service
pm2.cwd - service
pm2.script - service
pm2.args - service
pm2.env - service
pm2.pm2Home
For deployment-specific behavior, keep the packaged manifest as the baseline and pass --from-manifest with an override manifest rather than mutating the installed package in place.
Install a standalone managed Node.js runtime:
hagiscript install-node --target /opt/hagiscript/node
hagiscript install-node --target /opt/hagiscript/node22 --version 22Standalone Node installs also reuse the shared download cache by default. Pass --no-download-cache to force a fresh download, or --download-cache-dir <path> to share a custom cache location across installs.
Validate an existing managed Node.js runtime:
hagiscript check-node --target /opt/hagiscript/nodeSync npm global packages into the managed npm prefix instead of the host environment:
hagiscript npm-sync --manifest ./manifest.json
hagiscript npm-sync --runtime /opt/hagiscript/node --manifest ./manifest.json
hagiscript npm-sync --managed-runtime ~/.hagicode/runtime/program/components/node/runtime --prefix ~/.hagicode/runtime/program/npm --manifest ./manifest.jsonWhen npm-sync has to provision a managed Node runtime first, it uses the same shared download cache by default.
This is the path for installing pm2 and any other scenario-specific global tools. The package list is data, not a built-in runtime component.
Run from repos/hagiscript/:
npm install
npm test
npm run build
npm run pack:checkUseful runtime-focused checks:
npm run integration:runtime-management
npm run integration:runtime-key-path
npm run integration:installed-runtimeThe dedicated runtime key-path flow validates the critical production sequence with real network downloads: runtime install for fixed components, npm-sync for scenario-specific tools in the managed npm prefix, and PM2 lifecycle commands resolved from that managed prefix. Run the base flow with:
npm run integration:runtime-key-pathThe release-oriented key-path mode additionally stages the latest public backend package from GitHub Releases and validates the same managed PM2 contract for server:
HAGISCRIPT_ENABLE_RELEASED_SERVER_TEST=1 npm run integration:runtime-key-pathThe broader runtime-management integration path remains available for the existing end-to-end runtime assertions, including the corresponding released-server mode:
HAGISCRIPT_ENABLE_RELEASED_SERVER_TEST=1 npm run integration:runtime-managementMIT. See LICENSE.