{"id":49328926,"url":"https://github.com/arkerone/lanterna","last_synced_at":"2026-06-12T13:00:58.271Z","repository":{"id":353599347,"uuid":"1211638309","full_name":"arkerone/lanterna","owner":"arkerone","description":"🏮Agent-first Node.js profiler: structured CPU, memory, and async profiling optimized for AI analysis, leak investigation, and performance debugging.","archived":false,"fork":false,"pushed_at":"2026-05-29T21:43:07.000Z","size":2321,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T23:15:02.546Z","etag":null,"topics":["agent-first","ai","ai-agents","cpu-profiler","developper-tools","nodejs","profiler","skills"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arkerone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-15T15:39:59.000Z","updated_at":"2026-05-29T21:42:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/arkerone/lanterna","commit_stats":null,"previous_names":["arkerone/lanterna"],"tags_count":58,"template":false,"template_full_name":null,"purl":"pkg:github/arkerone/lanterna","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkerone%2Flanterna","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkerone%2Flanterna/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkerone%2Flanterna/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkerone%2Flanterna/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arkerone","download_url":"https://codeload.github.com/arkerone/lanterna/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkerone%2Flanterna/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34245218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-first","ai","ai-agents","cpu-profiler","developper-tools","nodejs","profiler","skills"],"created_at":"2026-04-26T21:04:21.470Z","updated_at":"2026-06-12T13:00:58.246Z","avatar_url":"https://github.com/arkerone.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/icon.png\" alt=\"Lanterna\" width=\"220\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eLanterna\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eAgent-first Node.js CPU, memory \u0026 experimental async profiler.\u003c/strong\u003e\u003cbr /\u003e\n  Spawns or attaches to your program, captures selected profile kinds plus timed runtime signals,\u003cbr /\u003e\n  and emits a structured JSON report that humans \u003cem\u003eand\u003c/em\u003e AI agents can act on directly.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@lanterna-profiler/cli\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@lanterna-profiler/cli.svg\" alt=\"npm version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://skills.sh/arkerone/lanterna\"\u003e\u003cimg src=\"https://skills.sh/b/arkerone/lanterna\" alt=\"skills.sh\" /\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/node/v/@lanterna-profiler/cli.svg\" alt=\"Node.js version\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\" /\u003e\n\u003c/p\u003e\n\n---\n\n\u003e Lanterna is built so its output is **useful to an AI agent**, not just a human reader. Instead of a flamegraph, you get a categorized, correlated, and actionable `LanternaReport` — ready to pipe into an LLM or a CLI tool.\n\n## Why Lanterna?\n\nMost Node.js profilers were designed for a human staring at a flamegraph. That's a problem when an AI agent is doing the investigation: a flamegraph isn't parseable, hot stacks aren't categorized, and \"what should I fix first?\" requires a human to interpret the visual.\n\nLanterna takes a different stance:\n\n- **Structured JSON, not pixels.** The `LanternaReport` is a stable schema — hotspots, allocators, async chains, GC pauses, event-loop lag, and findings — that an agent can read, correlate, and act on directly.\n- **Detectors, not just data.** 19 built-in detectors emit categorized `findings` (sync crypto, blocking I/O, deopt loops, memory growth, orphan async resources, …) with `confidence` and `proofLevel` so consumers know when to trust a hypothesis vs. require corroboration.\n- **CPU + memory + async in one capture.** Combine kinds in a single run; cross-kind detectors like `alloc-in-hot-path` and `hot-async-context` surface the highest-priority fixes (something flamegraph tools can't represent).\n- **Spawn or attach.** Profile a CLI, a server under load, or a live production process — same report shape, same detector surface.\n\n### Compared to other Node.js profilers\n\n| Tool | Primary output | CPU | Memory | Async | Findings / detectors | Agent-friendly |\n| --- | --- | :-: | :-: | :-: | :-: | :-: |\n| **Lanterna** | Structured JSON (+ text/markdown/agent renderers) | ✅ | ✅ | ✅ (experimental) | ✅ 19 built-in, pluggable | ✅ |\n| `node --prof` / `--cpu-prof` | V8 isolate log / `.cpuprofile` | ✅ | — | — | — | ⚠️ raw, post-processing required |\n| [0x](https://github.com/davidmarkclements/0x) | HTML flamegraph | ✅ | — | — | — | ❌ |\n| [Clinic.js](https://github.com/clinicjs/node-clinic) (Doctor / Flame / Bubbleprof) | HTML dashboards | ✅ | ⚠️ via Doctor | ⚠️ via Bubbleprof | ⚠️ heuristic recommendations | ❌ |\n| Chrome DevTools (inspector) | Interactive UI | ✅ | ✅ | ⚠️ stack-only | — | ❌ |\n\nWhen to reach for something else:\n- **You want a flamegraph for human inspection.** 0x and Chrome DevTools are purpose-built for that.\n- **You're already on Clinic.js's Doctor diagnostics workflow.** Clinic does well as a one-shot human triage.\n- **You need raw V8 internals (deoptimization traces, ICs, etc.).** Use `--prof` and the V8 tooling directly.\n\nLanterna is the right fit when the consumer of the report is **an agent or an automated pipeline** that needs categorized signals, not pixels.\n\n## What you get\n\n- **Three capture modes** — `lanterna run` to spawn \u0026 profile a command, `lanterna attach` to connect to a live process via the inspector, and programmatic in-process self-profiling via [`profileInProcess()`](docs/programmatic-api.md#self-profiling-profileinprocess) for a service that profiles itself. `lanterna ps` lists live `node`/`nodejs` processes (table or JSON) when you need to find a PID first.\n- **Regression diffs** — `lanterna diff before.json after.json` compares two reports (added / removed / changed findings + headline CPU/memory deltas) and emits a `regressed` flag for CI gates and agents. See [docs/diffing-reports.md](docs/diffing-reports.md).\n- **Three profile kinds** — opt in with `--kind`: `cpu` (V8 sampling profiler, default), `memory` (heap allocation profile + RSS series), and `async` (experimental async-resource profiling). Combine kinds by repeating `--kind` (`--kind cpu --kind memory`) or using commas (`--kind cpu,memory`).\n- **Enriched `LanternaReport`** — categorized hotspots, hot stacks, GC pauses, event-loop lag, allocator ranking, async chains, capture-integrity flags.\n- **19 built-in detectors** across CPU, memory, and async kinds, including 3 cross-kind detectors (`alloc-in-hot-path`, `hot-async-context`, `event-loop-blocked-async`) — see the [Built-in detectors](#built-in-detectors) section below.\n- **Stable JSON schema** with finding `confidence` and `proofLevel` fields so consumers can distinguish direct sampled evidence from heuristics.\n- **Extensible** — ship your own detectors and profile kinds as plugins.\n\n## 60-second example\n\n```bash\n# Install\nnpm install -g @lanterna-profiler/cli\n# or run without installing\nnpx -y @lanterna-profiler/cli --help\n\n# Profile a CLI script for 30 s and read the report\nlanterna run --duration 30s --output report.json -- node app.js\nlanterna report report.json --format text\nlanterna report report.json --format agent --output report.agent.md\n\n# Profile a server with representative load\nlanterna run \\\n  --duration 30s \\\n  --wait-for-url http://127.0.0.1:3000/health \\\n  --workload \"npx -y autocannon http://127.0.0.1:3000\" \\\n  --output report.json \\\n  -- node server.js\n\n# Memory leak hunt with start/end heap snapshot\nlanterna run --kind memory --heap-snapshot-analysis --duration 60s -- node app.js\n\n# Confirm a fix: capture again, then diff against the baseline\nlanterna diff report.json report.after.json --format agent\n```\n\n`Ctrl+C` stops profiling early **and still emits a final report**.\n\n## Built-in detectors\n\nLanterna ships 19 detectors out of the box, including 3 cross-kind detectors (`alloc-in-hot-path` for `cpu + memory`, `hot-async-context` and `event-loop-blocked-async` for `cpu + async`). Each emits a `Finding` in the report with `confidence` and `proofLevel` so consumers can distinguish direct sampled evidence from heuristics.\n\nMost built-in detectors are stable in the example E2E suite. `deopt-loop`, `deep-async-chain`, and `hot-async-context` are treated as best-effort verification targets because they depend on V8 trace timing or async/CPU correlation; when present, agent output marks that evidence as caveated.\n\n**CPU kind** (9)\n\n| ID | What it flags |\n| --- | --- |\n| `sync-crypto-on-hot-path` | Synchronous `crypto` calls (`pbkdf2Sync`, `randomBytesSync`, …) dominating CPU |\n| `blocking-io` | Synchronous `fs` / `zlib` / `dns` calls on hot stacks |\n| `json-on-hot-path` | `JSON.parse` / `JSON.stringify` dominating CPU |\n| `excessive-gc` | High GC pause time relative to wall time |\n| `event-loop-stall` | Long event-loop lag spikes correlated with stack samples |\n| `deopt-loop` | V8 deoptimisation cycles repeatedly hit on the same function |\n| `require-in-hot-path` | Dynamic `require()` resolved on hot stacks (cold-start surprise) |\n| `node-modules-hotspot` | A third-party dependency dominating CPU |\n| `cpu-hotspot` | Generic fallback: hot user-code frames not explained by any other detector |\n\n**Memory kind** (4)\n\n| ID | What it flags |\n| --- | --- |\n| `memory-growth` | Sustained heap / RSS growth over the capture window |\n| `large-allocator` | A single allocator responsible for a dominant share of bytes |\n| `external-buffer-pressure` | Off-heap pressure (Buffers, ArrayBuffers) |\n| `alloc-in-hot-path` | Allocators that are also CPU hot stacks — double impact, top-priority fix (cross-kind: requires both `cpu` and `memory`, auto-skips otherwise) |\n\n**Async kind** (experimental, 6)\n\n| ID | What it flags |\n| --- | --- |\n| `long-await` | `await` expressions exceeding the wait-time threshold |\n| `orphan-async-resource` | Async resources created but never resolved / destroyed |\n| `deep-async-chain` | Recursive promise/await chains where the same user frame repeats across async creation stacks |\n| `microtask-flood` | Microtask queue saturation starving the event loop |\n| `hot-async-context` | Async contexts dominating CPU (cross-kind: requires both `cpu` and `async`, auto-skips otherwise) |\n| `event-loop-blocked-async` | An async op's wait overlaps an event-loop stall — latency is a blocked loop, not slow I/O; anchored on the synchronous CPU frame (cross-kind: requires both `cpu` and `async`, auto-skips otherwise) |\n\nBuilt-in thresholds are exported as `DETECTOR_THRESHOLDS` for detector authors — see [docs/extending/detectors.md](docs/extending/detectors.md#thresholds). `.lanterna.json` configures capture options and plugin loading; see [docs/configuration.md](docs/configuration.md). To ship your own detectors, see [docs/extending/detectors.md](docs/extending/detectors.md).\n\n## Requirements\n\n| Environment | Minimum | Why |\n| --- | --- | --- |\n| Node.js running Lanterna | `\u003e= 22` | Active LTS lines (22, 24). |\n| Node.js running the **profiled program** | `\u003e= 12` | Needs `monitorEventLoopDelay` and `PerformanceObserver` GC entries. |\n\nThe profiled target must support the V8 inspector. If the inspector cannot start, Lanterna fails fast — it never silently falls back to a weaker mode.\n\n## Packages\n\n| Package | What it is |\n| --- | --- |\n| [`@lanterna-profiler/cli`](packages/cli) | The `lanterna` binary. |\n| [`@lanterna-profiler/core`](packages/core) | Capture orchestration, profile kinds, analysis pipeline, report builder. |\n| [`@lanterna-profiler/detectors`](packages/detectors) | Default detector pack for CPU, memory and async kinds, plus plugin helpers. |\n\n## Documentation\n\nStart here, then dive into whichever topic you need:\n\n- **[docs/getting-started.md](docs/getting-started.md)** — install, first capture, reading the output.\n- **[docs/cli.md](docs/cli.md)** — full CLI reference and option groups.\n- **[docs/configuration.md](docs/configuration.md)** — `.lanterna.json` reference.\n- **[docs/programmatic-api.md](docs/programmatic-api.md)** — `runProfile`, `attachProfile`, low-level capture and analysis APIs.\n- **[docs/report-schema.md](docs/report-schema.md)** — `LanternaReport` shape (schema v2).\n- **[docs/reading-a-report.md](docs/reading-a-report.md)** — interpretation playbook and common mistakes.\n- **[docs/diffing-reports.md](docs/diffing-reports.md)** — `lanterna diff` for regression diffs between two reports.\n- **[docs/signal-quality.md](docs/signal-quality.md)** — confidence, integrity flags, degradation modes.\n- **[docs/security-and-privacy.md](docs/security-and-privacy.md)** — inspector, plugin, report, and heap-snapshot trust model.\n- **[docs/architecture.md](docs/architecture.md)** — capture flow and enrichment pipeline.\n- **[docs/troubleshooting.md](docs/troubleshooting.md)** — symptom-keyed fixes.\n- **[docs/performance-overhead.md](docs/performance-overhead.md)** — measured startup cost and steady-state overhead per kind.\n- **[docs/testing-and-coverage.md](docs/testing-and-coverage.md)** — test layers, coverage gate, and known instrumentation coverage gaps.\n\nPer-kind details:\n\n- **[docs/kinds/cpu.md](docs/kinds/cpu.md)** — CPU kind, hotspots, event loop, GC, deopts.\n- **[docs/kinds/memory.md](docs/kinds/memory.md)** — memory kind, allocators, RSS series, heap snapshots.\n- **[docs/kinds/async.md](docs/kinds/async.md)** — async kind (experimental), instrumentation modes, attach caveats.\n\nExtending Lanterna:\n\n- **[docs/extending/detectors.md](docs/extending/detectors.md)** — write a finding detector.\n- **[docs/extending/profile-kinds.md](docs/extending/profile-kinds.md)** — write a brand-new profile kind.\n- **[docs/extending/plugin-loading.md](docs/extending/plugin-loading.md)** — how plugins are discovered and packaged.\n\nRunnable examples:\n\n- **[examples/](examples)** — a standalone workload for every built-in detector (one pathology each), plus a realistic HTTP server with several at once. Together they cover all 19 findings and double as an end-to-end verification suite (`npm run test:e2e`).\n\nFor agents (Claude Code skill):\n\n- **[skills/lanterna-profiler/SKILL.md](skills/lanterna-profiler/SKILL.md)** — the agent-oriented profiling workflow.\n\nInstall the skill into an agent workspace with:\n\n```bash\nnpx skills add arkerone/lanterna --skill lanterna-profiler\n```\n\n## Repository layout\n\n```text\npackages/\n  core/       @lanterna-profiler/core       — capture orchestration, kinds, pipeline, report\n  detectors/  @lanterna-profiler/detectors  — default detector pack (CPU + memory + async) and plugin helpers\n  cli/        @lanterna-profiler/cli        — `lanterna` binary\ndocs/                                       — human documentation\nskills/lanterna-profiler/                   — agent workflow for Claude Code\n```\n\nDependency direction: `cli → core`, `cli → detectors`, `detectors → core`. `core` never imports `detectors`.\n\n## Development\n\n```bash\nnpm install\nnpm run build       # builds all three packages\nnpm test            # runs every package's vitest suite\nnpm run test:e2e:smoke\n```\n\nPer-package work: `npm run build -w @lanterna-profiler/core`, `npm test -w @lanterna-profiler/cli`, etc.\n\nTests use Vitest and cover frame classification, hotspot aggregation, detector evidence attribution, and live profiling paths — including short-lived processes and real event-loop stall correlation.\n\n## Changelog\n\nEach package ships its own changelog, generated by [Changesets](https://github.com/changesets/changesets):\n\n- [`packages/cli/CHANGELOG.md`](packages/cli/CHANGELOG.md)\n- [`packages/core/CHANGELOG.md`](packages/core/CHANGELOG.md)\n- [`packages/detectors/CHANGELOG.md`](packages/detectors/CHANGELOG.md)\n\n## License\n\n[MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farkerone%2Flanterna","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farkerone%2Flanterna","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farkerone%2Flanterna/lists"}