# Olenji through npm

This package provides `olenji` and `olenji-bootstrap`. It launches the same Python engine, CLI, service, models and MCP implementation shipped by the pip package. A release tarball includes the exact application wheel and a hashed export of its locked default dependencies. There is no second transcription implementation.

The npm package is `@batikanor/olenji`, maintained by `batikanor`. It is an optional distribution route; the primary Python installation is `uv tool install --python 3.12 "olenji==1.0.2"` from PyPI. That route needs uv but no Node.js/npm and resolves compatible dependencies; npm setup uses its bundled hash-locked default dependencies. The [website](/) and [handbook](/guide/) provide the user guide. The GitHub source repository remains private; both registries distribute the same application source under Apache-2.0. Publication status is recorded separately from these installation instructions.

## Install

Requirements are **Node.js 22.14 or newer** and [uv](https://docs.astral.sh/uv/getting-started/installation/). FFmpeg/ffprobe are needed for media decoding; capture and individual models have their own platform prerequisites reported by `olenji doctor`.

```sh
npm install --global @batikanor/olenji@1.0.2
olenji-bootstrap setup
olenji doctor --json
```

For a supplied release archive, use `npm install --global /absolute/path/batikanor-olenji-1.0.2.tgz` instead.

Installing the npm package runs no setup scripts. The explicit setup command can download CPython and the locked Python dependencies. It never downloads speech models, modifies a system Python installation, or writes a project virtual environment. Python 3.12 is the default; standard CPython 3.11–3.14 is accepted when selected explicitly. Free-threaded builds are rejected before dependency installation and when checking or launching an existing runtime:

```sh
olenji-bootstrap setup --python 3.12 --json
olenji-bootstrap status --json
```

After setup, ordinary commands execute the prepared Python interpreter directly. They do not run uv, resolve packages, check a registry or install anything. Model installation and explicitly enabled cloud operations still follow the application's normal commands and settings. `olenji --version` and initial setup guidance through `olenji --help` work without a prepared interpreter.

To use npm without a global installation, prepare the runtime once, then run the application through npx:

```sh
npm exec --yes --package @batikanor/olenji@1.0.2 -- olenji-bootstrap setup
npx --yes @batikanor/olenji@1.0.2 doctor --json
```

`npx @batikanor/olenji@1.0.2` selects the `olenji` executable from the scoped package’s unscoped name. The installed commands remain `olenji` and `olenji-bootstrap`. The separate `olenji-bootstrap` executable needs the explicit `--package` form above. Running an ordinary command before setup returns `BOOTSTRAP_REQUIRED`; it does not install Python automatically. npm/npx can fetch the requested npm package into its own cache before launching it; that is separate from preparing the Python engine.

The Node launcher is the supported JavaScript runtime. Bun is not required; do not infer Bun support solely from JavaScript syntax compatibility. Any separately executed Bun verification is recorded in the release evidence.

Choose one installation route per machine. Both expose `olenji` on PATH and normally share workspace data. If both are installed, check which executable your shell selects and stop the owned service before switching routes or versions. Matching version strings alone do not distinguish older development archives.

## Persistent runtime and application data

Runtime environments live under the user's persistent application-data directory, separated by OS/architecture and keyed by the package version, wheel SHA-256 and locked-dependency SHA-256. Linux uses the XDG data directory, macOS uses `~/Library/Application Support`, and Windows uses `%LOCALAPPDATA%`. `status --json` reports the actual `python_executable` for an agent or acceptance script that needs the prepared interpreter.

`OLENJI_NPM_HOME` overrides the runtime parent and must be an absolute path. `OLENJI_DATA_DIR` independently selects Olenji's actual sessions, recordings, settings and model storage. These directories have different purposes; removing an npm runtime must not remove application data.

Each environment is created at its final path. Python virtual environments contain absolute paths and [are not intended to be moved](https://docs.python.org/3/library/venv.html). A completed runtime is published only after package version, Python compatibility and import-location checks pass. Dependencies are copied, so deleting uv's cache does not remove installed package files. The runtime continues to depend on its underlying Python installation; keep that interpreter installed while the environment is in use.

An exclusive setup lock prevents concurrent installation into the same release. Ordinary errors and cancellation remove the unpublished candidate and release the lock. If the process is forcibly killed or power is lost, the next attempt reports the lock path and whether its recorded process is still running. Confirm that no setup process is running, remove **only that reported lock file**, and retry. Incomplete candidates are never selected for normal execution. The launcher does not guess that an old lock is safe to steal.

Successful upgrades retain earlier environments. This allows a detached service to finish using its original interpreter. Stop the service before switching application versions, then start it through the intended package. There is no automatic runtime pruning or uninstall hook. Use `olenji-bootstrap status --json` to identify the active environment before any deliberate manual removal. Selecting another Python for an already prepared package requires a separate `OLENJI_NPM_HOME`; an active service's interpreter is never silently replaced.

## Offline setup and failures

```sh
olenji-bootstrap setup --offline --python /absolute/path/to/python --json
```

Offline setup disables Python downloads and network resolution. The selected interpreter and all required distribution artifacts must already be available locally or in uv's cache. A cached environment is reused without reinstalling dependencies. The bundled lock retains cross-platform/Python markers and hashes; only binary dependencies are allowed, and the application wheel is checked before installation. Unsupported hosts fail with the relevant uv or model readiness error rather than compiling arbitrary dependencies implicitly.

Project and user uv configuration files are not loaded. Intentional environment settings such as a corporate registry/proxy can still be supplied; distribution hashes remain mandatory. A package or requirements hash mismatch blocks execution and instructs you to reinstall the package.

Missing setup returns `BOOTSTRAP_REQUIRED`; concurrent setup returns `SETUP_BUSY`; an abandoned lock returns `SETUP_INTERRUPTED`. Other failures distinguish invalid metadata, package integrity, missing uv and incompatible runtime. `--json` uses Olenji's versioned error envelope. MCP and raw-export stdout remain reserved for their protocol or document; startup errors go to stderr on those paths.

## Process behavior

Arguments are passed as an array without a shell, including paths containing spaces and Unicode. The engine runs in isolated Python mode to prevent a user's current directory or `PYTHONPATH` from shadowing the installed application. UTF-8 mode is explicit. stdin/stdout/stderr pass directly to the engine, and child exit codes are preserved. A consumer closing an output pipe is handled quietly. The wrapper forwards termination signals and waits for the child. Captured metadata probes have bounded output and deadlines; POSIX probes own a separate process group, while Windows uses bounded tree termination when the parent is still alive. Node alone cannot recover a Windows descendant tree after its leader has exited, but owned pipe disposal still bounds the probe. Normal service launches are separate and never terminated as a probe group. Native Windows device/process behavior remains part of the cross-platform verification matrix.

During explicit setup, installer subprocesses have their own cancellation ownership. On Linux and macOS, interruption first signals the installer's process group and escalates to forced termination after two seconds if it has not exited; remaining descendants are also ended when the leader exits first. On Windows, cancellation invokes bounded tree termination before ending the leader. Setup waits for the direct installer to exit before removing its unpublished candidate and lock, preserves an existing ready runtime, and returns `SETUP_CANCELLED`. This grace period is an escalation deadline, not a guarantee that an unresponsive operating system will complete process termination within two seconds. Cancellation does not terminate a previously prepared application's detached service.

## Develop and verify the launcher

From this directory:

```sh
npm test
```

The tests use Node's built-in runner and standard-library Python fixtures, without npm dependencies or model downloads. They cover integrity, locked dependencies, exclusive setup, interruption, recovery, preserved runtimes, Unicode, shell-free arguments, cwd/PYTHONPATH isolation, stdout ownership, exit codes and signal forwarding. Set `OLENJI_TEST_PYTHON` to a Python executable when the default `python3`/`python` is unavailable.

The test directory and fixture files are excluded from npm tarballs. The root release builder supplies `vendor/runtime.json`, the wheel and `vendor/requirements.txt`; directly packing or publishing this unprepared source directory produces an incomplete application and is not a release procedure. Publish only the exact built tarball that passed acceptance.

Design references: [uv environments](https://docs.astral.sh/uv/pip/environments/), [uv isolated tool/cache lifetimes](https://docs.astral.sh/uv/concepts/tools/), [uv command options](https://docs.astral.sh/uv/reference/cli/), [Node child processes](https://nodejs.org/api/child_process.html). The persistent environment is intentional because a detached service must outlive an npm invocation or disposable tool cache.
