Natives Architecture
@oh-my-pi/pi-natives is a two-layer package around an ESM loader:
- ESM loader/package entrypoint resolves and loads the correct
.nodeaddon withcreateRequire, validates the release sentinel outside workspace-dev loads, and re-exports generated classes/functions plus enum runtime objects as explicit named ESM exports. - Rust N-API module layer implements the exported functions/classes and emits the generated TypeScript declarations.
This document is the foundation for deeper module-level docs.
Implementation files
packages/natives/native/index.jspackages/natives/native/index.d.tspackages/natives/native/loader-state.jspackages/natives/native/embedded-addon.jspackages/natives/scripts/build-native.tspackages/natives/scripts/embed-native.tspackages/natives/scripts/gen-enums.tspackages/natives/package.jsoncrates/pi-natives/src/lib.rs
Package entrypoint and public surface
packages/natives/package.json points at generated native artifacts:
main:./native/index.jstypes:./native/index.d.tsexports["."].types:./native/index.d.tsexports["."].import:./native/index.js
There is no current packages/natives/src TypeScript wrapper layer. Consumers import functions/classes/enums directly from @oh-my-pi/pi-natives; the type contract is the generated native/index.d.ts plus the explicit named exports generated into native/index.js by scripts/gen-enums.ts.
Current capability groups in the generated API include:
- Search/text/code primitives:
grep,search,hasMatch,fuzzyFind,glob,astGrep,astEdit,blockRangeAt,summarizeCode, text width/slicing/wrapping/sanitization, syntax highlighting, token counting. - Execution/process/terminal primitives:
executeShell,Shell,PtySession,Process, key parsing, bash fixups. - System/media/isolation/conversion primitives: clipboard, SIXEL encoding, HTML-to-Markdown, macOS appearance/power helpers, work profiling, workspace scanning, isolation backend helpers (
iso*).
Loader layer
packages/natives/native/index.js owns runtime addon selection and optional embedded extraction.
Candidate resolution model
- Platform tag is
${process.platform}-${process.arch}. - Supported tags are currently:
linux-x64linux-arm64darwin-x64darwin-arm64win32-x64
- x64 can use CPU variants:
modern(AVX2-capable)baseline(fallback)
- Non-x64 uses the default filename without a variant suffix.
Filename strategy:
- Default:
pi_natives.<platform>-<arch>.node - x64 variant:
pi_natives.<platform>-<arch>-modern.nodeor...-baseline.node - x64 runtime fallback includes the unsuffixed default filename after variant candidates.
Platform-specific variant detection
For x64, variant selection uses:
- Linux:
/proc/cpuinfo - macOS:
sysctl -n machdep.cpu.leaf7_features, thenmachdep.cpu.features - Windows: PowerShell check for
System.Runtime.Intrinsics.X86.Avx2
PI_NATIVE_VARIANT can force modern or baseline; invalid values are ignored.
Binary distribution and extraction model
The published @oh-my-pi/pi-natives package ships only the loader layer in native/: the ESM loader (index.js), generated declarations (index.d.ts), the loader-state.js/.d.ts helpers, and the embedded-addon manifest stub (embedded-addon.js). It carries no .node binaries.
Each platform's prebuilt .node is published as a separate optional-dependency leaf package — @oh-my-pi/pi-natives-<platform>-<arch>, one per supported tag — which the core lists in optionalDependencies at the lockstep version during publish. npm/bun install only the leaf whose os/cpu match the host. The working-tree package keeps built .node files under native/ for local dev; the release-publish rewrite (prepareNativeCorePackage in scripts/ci-release-publish.ts) strips them from the core tarball, and the leaves are generated by packages/natives/scripts/gen-npm-packages.ts (LEAF_TARGETS). Adding a build target therefore requires a matching LEAF_TARGETS entry, or the binary never reaches npm users.
For compiled binaries, loader behavior is:
- Check versioned user cache path:
<getNativesDir()>/<packageVersion>/.... - Check legacy compiled-binary location:
- Windows:
%LOCALAPPDATA%/omp(fallback%USERPROFILE%/AppData/Local/omp) - non-Windows:
~/.local/bin
- Windows:
- Fall back to packaged
native/and executable directory candidates.
getNativesDir() uses $XDG_DATA_HOME/omp/natives when $XDG_DATA_HOME/omp exists; otherwise it uses ~/.omp/natives.
If a populated embedded addon manifest is present, it is also treated as a compiled-binary signal. Current embedded manifests point at a gzip-compressed tar archive (embedded-addons.<tag>.tar.gz) that contains one or more matching .node files. The loader extracts the archive into the versioned cache directory, validates the selected file by size, and prepends that cache path before normal candidate probing.
For npm/bun installs (non-compiled), loader-state.js resolves the platform leaf directory via require.resolve("@oh-my-pi/pi-natives-<tag>/package.json") and probes its .node before the core package's native/ directory and the executable directory. The optional-dependency binary is therefore preferred over any .node left in the core (e.g. a stale local-dev build). On Windows node_modules installs, the loader first stages the selected leaf/core addon into <getNativesDir()>/<packageVersion>/... and prepends that staged path so running processes do not lock the node_modules copy during global updates.
Failure modes
Loader failures are explicit:
- Unsupported platform tag: after failed probing, throws with supported platform list.
- No loadable candidate: throws with all attempted paths and remediation hints.
- Embedded/staging errors: directory/write/archive/staging failures are recorded and included in final load diagnostics if no candidate loads.
- Release mismatch: outside workspace-dev loads, a candidate that loads but lacks the version sentinel export for
package.json#versionis rejected with a reinstall hint.
Rust N-API module layer
crates/pi-natives/src/lib.rs declares exported module ownership:
appearanceastblockclipboardfdfs_cacheglobglob_utilgrephighlighthtmlisokeyslanguage(re-exported frompi_ast)powerprofpsptyshellsixelsummarytasktexttokensutils(crate-private helpers)workspace
N-API exports are generated from Rust #[napi] functions/classes/objects/enums. Snake_case Rust names are exposed as camelCase JavaScript names unless explicitly configured by napi-rs.
Ownership boundaries
- Loader/package ownership (
packages/natives/native,packages/natives/scripts)- runtime binary selection
- CPU variant selection and override handling
- compiled-binary embedded archive extraction
- Windows
node_modulesaddon staging - generated TypeScript declarations and explicit ESM export/enum patching
- Rust ownership (
crates/pi-natives/src)- algorithmic and system-level implementation
- platform-native behavior and performance-sensitive logic
- N-API symbol implementation consumed directly by package callers
- Consumer ownership (
packages/coding-agent,packages/tui)- user-facing policy and fallbacks that are not built into the native API
- higher-level rendering, artifact, shell-session, and command behavior
Runtime flow (high level)
- Consumer imports from
@oh-my-pi/pi-natives. native/index.jscomputes platform/arch/variant and candidate paths.- Optional embedded archive extraction or Windows
node_modulesstaging can prepend a versioned-cache candidate. - Each candidate is
require(...)d; install/compiled loads must expose the package-version sentinel. - The loaded addon object is bound to explicit named ESM exports, including generated enum objects.
- Caller invokes generated N-API functions/classes directly.
Glossary
- Native addon: A
.nodebinary loaded via Node-API (N-API). - Platform tag: Runtime tuple
platform-arch(for exampledarwin-arm64). - Platform leaf package: Per-platform npm package
@oh-my-pi/pi-natives-<tag>that carries one platform's prebuilt.node. The core depends on every leaf viaoptionalDependencies; the package manager installs only the host-matching one (os/cpu). - Variant: x64 CPU-specific build flavor (
modernAVX2,baselinefallback). - Generated binding declaration:
native/index.d.tsemitted by napi-rs duringbuild-native.ts. - Version sentinel: Rust export named from the package version (for example
__piNativesV15_7_2) that lets the loader reject a.nodefrom a different release. - Compiled binary mode: Runtime mode where the CLI is bundled and native addons are resolved from embedded/cache paths before package-local paths.
- Embedded addon: Build artifact metadata and archive reference generated into
native/embedded-addon.jsso compiled binaries can extract matching.nodepayloads.