New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@ariestools/cli-kit

Package Overview
Dependencies
Maintainers
3
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ariestools/cli-kit

Reusable actor lifecycle core for command-line applications

latest
Source
npmnpm
Version
2.1.0
Version published
Weekly downloads
2.1K
77.39%
Maintainers
3
Weekly downloads
 
Created
Source

@ariestools/cli-kit

Reusable, instance-scoped actor lifecycle primitives for command-line applications.

This package is intentionally independent of XL1 and xyo-chain. The neutral @ariestools/actor-system package owns config parsing, provider resolution, provisioning, actor construction, and the resolved system session. Cli-kit re-exports actor-system's sequentialActorSystemSupervision and supplies launchCliSystem, which makes registration-order startup/readiness and reverse-order shutdown the default CLI policy.

import {
  ActorSystemCatalog,
  createActorSystemProviderRegistry,
} from '@ariestools/actor-system'
import {
  launchCliSystem,
  runCliSystemUntilInterrupt,
} from '@ariestools/cli-kit'
import { nodeProcessHost } from '@ariestools/cli-kit-node'

const session = await launchCliSystem({
  actorRegistry: new ActorSystemCatalog(),
  config,
  providerRegistry: createActorSystemProviderRegistry(),
})

await runCliSystemUntilInterrupt(nodeProcessHost, session)

Compilation can remain explicit when a CLI must inspect or retain its resolved plan before provisioning:

import { compileActorSystem } from '@ariestools/actor-system'
import { launchCompiledCliSystem } from '@ariestools/cli-kit'

const compiled = compileActorSystem({ actorRegistry, config, providerRegistry })
const session = await launchCompiledCliSystem({ actorRegistry, compiled })

Each actor receives its own actor config over the same resolved provider system: the session's config, plan, and provider instances, reached through a locator view limited to that actor's declared dependencies. Only the session holds the owner locator, so an actor cannot register or destroy providers. Existing ManagedActor, ActorSupervisor, and ActorBuilderCatalog APIs remain available for callback-built and pre-configured CLI applications.

The package also provides structural ProcessHost and ProcessIO boundaries for adapting an application's concrete process runtime without importing Node APIs into the core. Arguments, environment values, terminal width, output, prompts, interrupts, and exits are all supplied by the host. Use exitProcess at exit points that occur before the end of a command: production hosts may terminate immediately, while recording hosts receive a ProcessExitError that stops control flow deterministically. RuntimeSession owns one application-supplied stop operation and preserves fail-fast shutdown behavior while making repeated stop requests idempotent. It can also own one structural interrupt binding, coalesce repeated interrupts while the application listener settles, and dispose the binding at the correct manual or interrupt-driven shutdown boundary.

runProcessApplication owns the outermost application failure boundary. It absorbs standardized exit signals that have already been routed through a ProcessHost, hides unexpected error details outside development, and requests exit code one for unhandled failures. An optional mapFailureToExitCode mapper lets the application select a different exit code per failure; it receives the error plus a FailureOrigin ('parse' or 'handler'), returning undefined retains the default one, and intentional ProcessExitError exits are never offered to the mapper. The mapper stays inside the failure boundary: a mapper that throws, or returns a code outside the integer range 0–255, falls back to exit code one instead of escaping the boundary. Concrete process adapters remain separate packages; Node applications can use @ariestools/cli-kit-node.

SYS_EXITS supplies the BSD sysexits.h exit-code vocabulary used across applications (ok, usage, dataErr, noInput, software, ioErr, config), with SysExitCode as the derived literal union. Use it with exitProcess or a mapFailureToExitCode mapper instead of repeating numeric literals.

createCommandCatalog registers ordered command factories against a structural CliApplicationContext. The command type is supplied by the application, so parser-specific types and domain-specific configuration remain outside the core. A catalog is immutable and reusable; each application invocation materializes fresh command objects with its own context.

runServiceUntilInterrupt blocks a long-running command handler until the first host interrupt, then awaits one application-supplied stop cleanup. runCliSystemUntilInterrupt joins either an interrupt or terminal actor failure to one actor-system stop. Successful joins return without requesting exit 0, so caller-owned cleanup after the join can run. Ordinary failures retain the caller’s mapper path; actor and distinct cleanup failures aggregate.

Both helpers accept an optional third InterruptJoinOptions argument. Cleanup has a default 15-second watchdog, starting when the first interrupt or actor failure begins shutdown, including cleanup after listener-registration failure. Set shutdownTimeoutMs: 0 to disable it; other values must be finite and between 0 and 2,147,483,647 milliseconds. The timer bounds cooperative waits; it cannot preempt synchronous blocking, and scheduling stalls can extend elapsed time.

Host supplied to the joinListener during cleanupSecond interruptWatchdog expiry
Full host or explicit exitHostRetained until the join settlesRequest exit 130Request exit 1
Minimal actor host, only onInterruptRetained until settlement/escalationReject with InterruptJoinEscalationErrorReject with InterruptJoinEscalationError
Minimal service host, only onInterruptDisposed before stop, preserving native behaviorHost’s restored default actionReject with InterruptJoinEscalationError

An available synchronous host.exit enables process escalation automatically; exitHost supplies that capability when the interrupt host is minimal. Recording exit boundaries receive the request and the join rejects with ProcessExitError to prevent normal continuation, even if the exit callback completes or rejects cleanup. A minimal host cannot terminate remaining resources: its ordinary InterruptJoinEscalationError.exitCode is suggested status metadata (130 for repeat interruption, 1 for timeout), and the outer failure mapper controls the actual exit. On Node, minimal service disposal restores OS-default signal termination, whose status differs by signal; a second SIGTERM is not explicit exit 130.

await runServiceUntilInterrupt(nodeProcessHost, () => server.close(), {
  shutdownTimeoutMs: 30_000,
})
// Or forward an exit boundary alongside a minimal structural interrupt host:
await runCliSystemUntilInterrupt(minimalHost, session, {
  exitHost: nodeProcessHost,
  shutdownTimeoutMs: 30_000,
})

A deadline or repeat interrupt ends waiting; it does not cancel cleanup. Late failures remain observed. Hard exit can cut off admitted work, database flushes, and buffered output. The budget covers the supplied stop, not earlier startup or cleanup performed by the caller after return. Bound those phases separately or include required cleanup in the supplied stop. A minimal service disposer failure rejects immediately while cleanup is still attempted and observed; its watchdog ends with that early join failure. The join policy owns its binding without changing RuntimeSession’s separate interrupt-coalescing contract.

handleRuntimeInterrupt accepts a synchronous or asynchronous onBeforeStop hook. It awaits cancellation before calling stop, under one shared shutdown watchdog. A thrown/rejected hook is reported and cleanup continues while time remains. Hook time reduces the budget available to cleanup. If the hook hangs past the deadline, exit 1 is requested; late hook settlement is observed and does not start cleanup after that timeout. Disabling the watchdog awaits both phases without a deadline. Timers cannot preempt synchronous event-loop blocking.

GlobalErrorEscalation distinguishes a retained startup notification from fatal-owned cleanup. If an external orderly shutdown starts first, activation or watchdog expiry discards the retained notification. External shutdown must have its own deadline; the escalation interface cannot observe its stop promise immediately. Once fatal cleanup starts, stopping state or a shutdown predicate does not disable the watchdog. Observed fatal-stop settlement clears the timer; stop and exit requests are shared per escalation instance. Exit failures are reported safely without detached rejections or implicit retry. An awaited activation still rejects if its exit request fails.

stopUniqueResource resolves a resource or its creation promise and invokes teardown once across a shared seen set. It preserves method precedence: stop, then destroy, then shutdown when neither earlier method exists. Shutdown-only cleanup is awaited and its failures propagate. Repeated aliases are skipped; the helper does not share the first teardown's completion promise with later callers. Coordinate ownership when resources also have an explicit cleanup path.

redactConfig masks common credential keys including mnemonic, connection string, API key, access/refresh/session/auth tokens, and authorization, plus private-key/secret/password suffixes. Default names and suffixes ignore case and snake/hyphen separators. Extra keyNames use the same normalization; replacement suffix patterns see original key spelling and run without global or sticky state, leaving the supplied regex untouched. Public seed and token metadata remain visible unless explicitly selected. Plain objects and arrays are copied; non-plain objects remain outside the traversal.

String values now remove the entire URL userinfo component by default, including under arbitrary keys and inside arrays. For example, https://user:password@HOST/path?keep=1 becomes https://HOST/path?keep=1. The original configuration is unchanged; retain it for connections and use the returned copy only for diagnostics. This deliberately hides usernames as well as passwords. { urlCredentials: 'preserve' } opts into the former string behavior while keeping credential-key masks.

redactUrlCredentials(value) exposes that diagnostic string transformation separately. It handles complete hierarchical scheme://authority and //authority values, preserving the remaining bytes without URL canonicalization. Ambiguous credential-bearing authorities and noncanonical network-scheme values containing @ are masked entirely. It does not validate URLs or sanitize embedded prose, opaque URIs, query/fragment/path secrets, object keys, or non-plain URL instances. Credential-looking malformed values can lose all diagnostic detail. URL work scans strings during config output; no performance benchmark is claimed.

Application shell pattern (reference)

The public package @xyo-network/lifehash-indexer is the golden template for a product CLI on this kit:

  • Bin / process boundary — runProcessApplication + createNodeProcessHost (or nodeProcessHost) so the library bundle stays free of process side effects.
  • Yargs adapter — runYargsApplication with an app-owned configure* helper that applies rejectUnknownCommands, .strictOptions(), help/version, and host.io.columns wrapping.
  • Command catalog — createCommandCatalog over a CliApplicationContext that at least carries host, so tests inject a recording ProcessHost without touching process.
  • Failure policy — a FailureExitCodeMapper that maps parse vs handler failures onto SYS_EXITS (usage / config / software, …).
  • Domain commands — yargs CommandModule factories that take context and never import Node process globals for env/argv/exit.

Sibling shells that follow the same shape include @xyo-network/webble-cli and @xyo-network/webble-dapp. Actor-heavy CLIs (for example @xyo-network/xl1-cli-lib) layer createActorBuilderCatalog, ManagedActor, and RuntimeSession on top of the same process boundary.

Lifecycle guarantees

  • Config-driven launches resolve and provision one provider system shared by every actor context.
  • launchCliSystem defaults resident actors to registration-order startup/readiness and reverse-order shutdown.
  • runCliSystemUntilInterrupt stops once on process interrupt or resident actor failure, returns on clean interrupt cleanup, and retains actor/cleanup errors unless policy escalation ends the join first.
  • Actors start sequentially in registration order.
  • A failed startup first invokes the failing actor's optional, status-independent shutdown, then rolls back every actor that already started in reverse order.
  • Readiness is observed in registration order with an optional supervisor-wide timeout.
  • Shutdown runs in reverse startup order and is idempotent.
  • A failed normal stop uses the actor's optional shutdown fallback.
  • Shutdown attempts every started actor before reporting aggregated failures.
  • A runtime session invokes its stop delegate once and shares one stop promise.
  • Runtime stop failures retain and rethrow the original value without wrapping.
  • A runtime session accepts at most one interrupt binding while active.
  • Repeated interrupts share one listener promise and retain the binding until that listener settles.
  • Manual shutdown disposes its interrupt binding before cleanup begins.
  • Process applications absorb host-routed exits and map unexpected failures to exit code one, or to the code selected by an application-supplied mapper.
  • Command catalogs preserve registration order and reject blank or duplicate ids.
  • Command factories receive the exact per-application context and are invoked again for each materialization.
  • Service-until-interrupt disposes its host listener before stop and surfaces stop failures to the caller.

License

LGPL-3.0-only

Keywords

ariestools

FAQs

Package last updated on 06 Oct 2026

Related posts