Skip to content

Expose memory profiling from installed LLxprt commands #3386

Description

@acoliver

Problem

The memory profiler added by #3230 is available from a source checkout through npm run mem:profile, mem:request, mem:report, and mem:analyze. Those commands are not available to someone running the globally installed llxprt package. The published package ships bin, bundle, index.ts, and selected package files, but it does not ship the root scripts/memory/* entry points.

This blocks diagnosis in the environment where long-session growth is occurring. On 2026-08-27, a globally installed 0.11.0-nightly.260827.354957220 process reached an 8.2 GB physical footprint and an 11 GB peak. macOS attributed 7.6 GB dirty memory to WebKit malloc, with 2.0 GB reclaimable at the sampled checkpoint. The process was already too large for a safe heap snapshot. Periodic JSC samples from process start would have distinguished live-object growth from allocator high-water behavior.

Enabling telemetry.perf.memory helps with process counters, but it does not replace the JSC object histograms, forced-GC checkpoints, guarded snapshots, request lease, growth report, or retainer analysis in scripts/memory/*.

Goal

Make the existing profiling workflow usable from an npm/global installation without requiring a repository checkout. Reuse the current probe, file protocol, lease, permissions, reports, analyzer, and snapshot guard rather than creating a second profiler.

Proposed installed interface

Starting an installed session should be possible with a command such as:

llxprt --memprofile
llxprt --memprofile=15000 --profile-load zai

The no-value form uses the current 15-second default. The numeric form selects the sampling interval in milliseconds. Namespaced options should expose the existing controls without colliding with normal LLxprt arguments:

--memprofile-dir <path>
--memprofile-snapshots
--memprofile-max-heap-mb <n>

The rest of the existing workflow also needs an installed entry point. The exact command shape can follow the CLI's subcommand conventions, for example:

llxprt memprofile request [--heap] [--dir <run>]
llxprt memprofile report [<path-or-run-dir>]
llxprt memprofile analyze <snapshot> [--top <n>] [--min-mb <n>]

Implementation direction

  • Teach the published Node shim at packages/cli/bin/llxprt.mjs to recognize the profiling launch mode before it starts the Bun bundle.
  • Build and publish install-safe profiling entry points under the CLI package's existing bundle or another declared package path.
  • Have the installed profiling launcher start the normal installed CLI entry with Bun's --preload, using the installed probe entry. Do not fork a separate sampling implementation.
  • Reuse argument validation, run-directory creation, .memprofile/latest, lease handling, owner-only permissions, request processing, exit propagation, report rendering, snapshot limits, and heap analysis from scripts/memory/*.
  • Keep normal startup byte-for-byte equivalent at the process argument boundary when profiling is absent.
  • Keep snapshots disabled by default. Preserve the warning and hard refusal when post-GC heap exceeds the configured guard.
  • Make the default output location work for installed use from any current working directory. Continue warning when an explicit directory is outside the protected default location.
  • Update installed-command help and docs/memory-profiling.md with both source-checkout and installed examples.

Acceptance criteria

  1. A packed and globally installed package can start a profiled interactive session with llxprt --memprofile and a configurable sampling interval.
  2. The installed path records periodic JSC heap samples and process memory counters from startup, then prints the existing growth report on exit.
  3. Installed commands can request an immediate forced-GC sample, request a guarded snapshot when snapshots were armed, render a report, and analyze a snapshot.
  4. The installed workflow uses the same file-based request protocol and lease as the source workflow on macOS, Linux, and Windows 11.
  5. Profiling stays opt-in. Normal llxprt startup, arguments, exit codes, signal forwarding, and bundled Bun resolution do not change when profiling is not requested.
  6. Snapshot safety and privacy behavior from Add cross-platform Bun memory diagnostics and guarded heap snapshots #3230 remain intact, including owner-only permissions on POSIX, sensitive-data warnings, disabled-by-default snapshots, atomic publication, and refusal above the heap guard.
  7. Release-install tests pack the real CLI package and exercise profiling startup, argument forwarding, one periodic or requested sample, report generation, and failure behavior from outside the repository.
  8. Tests prove that the published package contains every profiling artifact referenced by the shim and that no runtime import reaches back into repository-only scripts/ paths.

Related work

Metadata

Metadata

Assignees

Labels

ObservabilityIssues related to quotas being able to observe model or provider responses or behavior.installationBugs related to npm install, global install, bin symlinks, and path handlingstartup/install/bundleanything to do with our scripts to run llxprt, the bundle, the packaging

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions