npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@modelprofile.com/browser-runtime

v5.1.0

Published

Parent-owned, resource-centric Chromium runtime with revisioned attachment fencing, authenticated human and agent control, fail-closed egress, bounded artifacts, and Flex/MCP adapters.

Readme

@modelprofile.com/browser-runtime

Parent-owned, resource-centric Chromium runtime with revisioned attachment fencing, authenticated human and agent control, fail-closed egress, bounded artifacts, and Flex/MCP adapters.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Install

pnpm add @modelprofile.com/browser-runtime

The runtime requires Node.js 24 through 26 on a non-root Linux x64 host. Production browser sessions require a sandbox-capable Chromium installation. The NamedMutex backend uses the statically linked Rust helper packaged with @push.rocks/smartipc; startup fails closed with FENCED when the helper is unavailable.

Resource Model

The Controller owns durable resource and attachment truth. BrowserRuntime owns process-local registrations, fences, capabilities, leases, browser incarnations, artifacts, and its host-runtime ownership lease. Registration never launches Chromium.

import {
  BrowserRuntime,
  type TBrowserCapabilityAuthorizationRequest,
} from '@modelprofile.com/browser-runtime';

const runtime = new BrowserRuntime({
  runtimeDirectory: '/var/lib/example/browser-runtime',
  authorizeCapability: async (binding) => hostPolicy.authorizeBrowser(binding),
  beforeOperation: async (operation) => hostAudit.recordAttempt(operation),
});

try {
  await runtime.start();

  const resource = runtime.createResource({
    projectId: 'project-123',
    attachmentBinding: {
      attachmentAuthorityId: 'controller-attachment-1',
      attachmentRevision: 1,
      sessionId: { harnessId: 'opencode', nativeId: 'session-456' },
    },
  });

  const binding = {
    projectId: resource.projectId,
    browserResourceId: resource.browserResourceId,
    attachmentAuthorityId: resource.attachmentBinding.attachmentAuthorityId,
    attachmentRevision: resource.attachmentBinding.attachmentRevision,
    sessionId: { harnessId: 'opencode', nativeId: 'session-456' },
    actorId: 'agent-456',
    role: 'agent',
    peerId: 'worker-789',
    source: 'mcp',
  } satisfies TBrowserCapabilityAuthorizationRequest;

  const issued = await runtime.issueCapability(binding);

  const lease = await runtime.acquireLease({
    ...binding,
    capabilityToken: issued.capabilityToken,
  });

  try {
    console.log(await lease.executeAgentAction({ action: 'snapshot' }));
  } finally {
    await lease.release();
  }
} finally {
  await runtime.stop();
}

Projects and qualified OpenCode, Flex, and Codex sessions may each own many resources. Agent capabilities use Flex's trusted pipe or an independently authenticated MCP binding for any supported native session. Each resource has one browser incarnation and operation queue shared by its attached agent and multiple human viewers. Joining a viewer never preempts another participant.

registerResource() is idempotent only for the same project/resource key and identical attachment. listResources() reports process-local registration and incarnation metadata. terminateResource() terminates only the current incarnation and preserves registration, attachment, and artifacts. retireResource() permanently fences the process-local registration, revokes and quiesces authority, terminates its incarnation, purges exact-resource artifacts, and unregisters only after cleanup succeeds. The Controller separately owns durable retirement truth and must not rehydrate retired resources. Runtime tombstones and registrations are ephemeral, bounded process state. stop() attempts peer, capability, resource, artifact-store, and ownership cleanup even when an earlier stage fails, then reports all failures together. It removes only the current generation, durably marks its owner metadata relinquished, and releases the native ownership lease when ownership cleanup succeeds. It intentionally leaves runtime.lock and the mutex anchor in place. Failed local slot cleanup remains retryable and blocks a new generation; automatic ownership-loss shutdown performs one additional bounded cleanup attempt. cleanupTimeoutMs defaults to 30,000 milliseconds and accepts values from 100 through 120,000. If that caller-visible deadline expires, stop() rejects with TIMEOUT while Runtime retains cleanup still in flight; a later stop() rejoins it, and start() waits for all prior local cleanup before restarting.

Host Runtime Ownership

The runtime directory must be an owner-only 0700 directory on a trusted local filesystem; NFS and other network filesystems are unsupported. Its permanent runtime.mutex anchor directory is an owner-only 0700 directory on the same filesystem device. Runtime uses @push.rocks/smartipc NamedMutex with a namespace bound to the UID plus the validated runtime-directory device, inode, and path hash. SmartIPC keeps one permanent 0600, single-link anchor file in runtime.mutex and holds a native advisory lock for the complete metadata and generation operation. Clean tryAcquire() contention returns LOCKED. Unsupported native backends, unsafe or changed anchors, native lock failures, and uncertain release return FENCED. Process exit, SIGKILL, and reboot release the advisory lock in the kernel.

runtime.lock is a permanent 0600, single-link regular file retained through an open descriptor while ownership is live. It is metadata and a downgrade fence, not the live mutex, and is never removed by stop(). Version 3.2 and older create-exclusive runtimes therefore remain fenced during and between new-runtime generations. Bounded JSON metadata is overwritten and fsynced through that descriptor. It records the schema, directory identity, UID, boot ID, PID, /proc/self/stat start ticks, generation ID, nonce, and active/relinquished state. Malformed metadata or unsafe directory, anchor, lock, link, ownership, mode, containment, or inspection state fails closed with FENCED.

Each successful start() creates private generations/<generationId>/profiles and generations/<generationId>/artifacts directories. A replacement holding the native mutex may inspect and remove only the generation named by valid metadata. For metadata generations, Runtime does not scan runtime.lock descriptors. It inspects every same-UID process and returns LOCKED when any process, Chromium or otherwise, has an absolute --user-data-dir equal to or below that generation's profile root. Process ownership is classified from all four IDs in /proc/<pid>/status Uid:: exact same-UID processes are inspected, definite other-UID processes are ignored, and mixed or unreadable identity remains indeterminate. Unknown generations and indeterminate inspection remain fenced.

A version 3.2 zero-byte lock uses a separate one-time migration gate. Runtime adopts it only when SmartIPC's consuming kernel exclusivity probe reports no other read/write open description, the lock's birth, change, and modification timestamps are all strictly before the bounded /proc/stat btime, and no same-UID process has --user-data-dir equal to or below the legacy profiles root. The exact original inode, ownership, mode, link count, zero size, and timestamps are revalidated when the lock is reopened after probing. Probe contention is LOCKED; probe or reopen uncertainty is FENCED. O_PATH descriptors do not contend. A same-boot unheld lock is FENCED; this prevents takeover during the old owner's close-before-unlink window. Malformed boot data or ambiguous timestamps are also FENCED.

When version 3.2 stopped cleanly and removed runtime.lock, it may leave empty top-level profiles and artifacts directories. After winning creation of a new lock under the native mutex, Runtime validates those directories as exact private empty roots, performs the same exact-or-descendant profile-process inspection, removes only the validated roots, and publishes the new metadata without applying the stale-lock boot gate. If startup fails before metadata is durably published, Runtime unlinks only that exact process-created lock inode while still holding the native mutex; a preexisting lock is never removed.

Breaking Changes

Shared control replaces exclusive human takeover. Hosts must allow multiple exact participant leases, stop treating chat attachment changes as human-view revocation, and consume the effective viewport returned by setViewport(). Browser destruction remains an explicit resource operation.

The version 3.2 runtime-directory migration is one-way. A cleanly stopped 3.2 runtime that removed its zero-byte lock can be upgraded directly when any remaining top-level profiles and artifacts directories are private and empty. A stale 3.2 lock is recoverable only after reboot, once it conclusively predates the current boot and no legacy holder or profile process remains. The first successful new-runtime start writes permanent metadata and creates runtime.mutex; version 3.2 must not reuse that directory.

To downgrade, first stop the new runtime and verify that no process still uses any generation profile path. Then remove the entire runtime directory, including runtime.lock, runtime.mutex, and generations, and let version 3.2 create a fresh directory. Never delete only the lock or anchor, and never perform this procedure while either runtime generation is active.

Attachment Fencing

Attachment bindings are Controller-owned { attachmentAuthorityId, attachmentRevision, sessionId } values. Any binding with sessionId: null is detached; revision 0 is the initial detached/no-agent-authority state. Reapplying the identical revision and binding is idempotent; lower revisions and conflicting equal revisions fail.

await runtime.applyAttachmentBinding({
  projectId: resource.projectId,
  browserResourceId: resource.browserResourceId,
  attachmentBinding: {
    attachmentAuthorityId: 'controller-attachment-1',
    attachmentRevision: 2,
    sessionId: null,
  },
});

A newer binding fences agent admission, revokes older agent capabilities, and quiesces their active work. Human viewers retain their resource authority and subscriptions. The incarnation is preserved unless an operation cannot quiesce; that failure requires terminating the resource's browser process.

Agent capabilities require the exact current non-detached qualified session. Human capabilities carry no session ID and may be issued while detached. Issuance validates the current attachment binding, but an issued human capability remains valid across attachment changes: hosts must authorize it against its project, resource, actor and peer rather than the resource's later agent assignment.

Capabilities expire after five minutes by default. A host keeping a viewer open can call await lease.renew({ signal }) before lease.expiresAt; the result is the new expiry time in Unix milliseconds. Renewal invokes authorizeCapability again and preserves the exact lease, browser incarnation, frame subscription and attachment identity. expiresInMs optionally selects a lifetime within the configured maximum. An expired, released, revoked or replaced lease cannot be renewed. A denied, cancelled or timed-out renewal leaves the original expiry unchanged. Only one authorization callback per lease may remain unsettled, including after timeout; runtime-wide renewal admission is bounded by maxCapabilities. Hosts must stop scheduling renewal when their viewer disconnects.

Agent actions are exactly navigate, snapshot, screenshot, click, fill, and press. Agents can read or delete screenshots created by their exact lease using readArtifact() and deleteArtifact(). Human leases additionally expose tab lifecycle, viewport, raw input, frame subscription/acknowledgement and refresh, and exact-resource artifact reads/deletes. JavaScript evaluation is not public.

All participants enter one strict resource FIFO. maxQueuedOperationsPerLease defaults to 128 and accepts 1 through 1,024; each participant has that bound, and the resource queue is bounded by its product with maxCapabilitiesPerResource. Overflow fails with QUOTA_EXCEEDED. Releasing a participant cancels only its queued and active work. Resource termination and shutdown cancel everyone. Started uncertain work must quiesce or the exact incarnation is terminated before operation settlement.

setViewport() stores the viewer's preferred width, height and device scale factor and returns IBrowserRuntimeViewportResult with the effective viewport and viewportRevision. The effective values are the componentwise minima across active viewers that have supplied a preference. Unchanged effective sizes do not restart the stream. Removing a viewer recomputes the viewport in the resource FIFO. Held keys and buttons are tracked per participant; leaving releases only inputs that no other participant holds. Viewport and tab/navigation transitions clear held input before changing the target. Resource-owned departure cleanup is bounded and audited as releaseParticipant; it does not call the external beforeOperation gate after the participant has lost access.

beforeOperation is an optional awaited fail-closed gate. It receives the complete immutable authority, operation/capability/lease IDs, action, classification, start time, and an AbortSignal after dequeue but before the browser side effect starts. Classifications are raw-input, frame-stream, viewport, navigation, tab, and agent-action. Hosts that require durable attempt-before-side-effect auditing should persist the attempt there. Rejection denies the operation. The default beforeOperationTimeoutMs is 10,000 milliseconds and accepts values from 100 through 120,000; timeout fails with TIMEOUT. The terminal audit callback remains a best-effort completed/failed notification correlated by the same operation ID and classification and runs after bounded operation cleanup releases or fences the exact reservation.

lease.getAuthority() returns an immutable process-local lease authority containing the runtime authority ID, exported authorityGeneration, incarnation generation, and complete capability binding. Every snapshot also binds the exact capabilityId and leaseId. lease.isAuthorityCurrent(authority) performs an exact synchronous revalidation suitable for a host-owned virtual stream. These values are not durable Controller state and do not replace attachment checks against the Controller database.

Each human participant may have one independent frame subscription with a bounded exact-identity window. maxOutstandingFrames defaults to 4 and accepts 1 through 32. Runtime starts exactly one bounded producer acknowledgement per admitted frame and shares its outcome between subscribers. Viewer acknowledgements and oldest-first eviction retire only that viewer's entry; they never acknowledge the producer a second time. A producer result of accepted: false is a settled result, while rejection, timeout or producer admission overflow fences the failed incarnation. A throwing viewer listener revokes only that participant.

frameAcknowledgementTimeoutMs defaults to 10,000 milliseconds and accepts 100 through 60,000. It bounds producer acknowledgements and each viewer's local window lifetime independently. A late viewer acknowledgement returns false once its entry has expired; it does not stop the browser, revoke another participant, or delay producer delivery.

An oversized frame is dropped, not fatal. maxFrameBytes defaults to 4 MiB and accepts values from 64 KiB through 16 MiB. A frame above the bound is acknowledged toward SmartPuppeteer in the background, never enters the application window, and is reported once on the subscription as { type: 'error', error: { code: 'FRAME_TOO_LARGE', fatal: false, tabId } }. The sequence watermark advances past the dropped frame so later frames remain valid and continue to be delivered.

screencast tunes the Chromium screencast that SmartPuppeteer starts for every incarnation. quality is the JPEG quality from 0 through 100 and defaults to 70. maxWidth and maxHeight accept values from 1 through 4,096 each, their product must not exceed 8,294,400 pixels (SmartPuppeteer's ceiling, so 3,840×2,160 is accepted and 4,096×4,096 is rejected with INVALID_INPUT), they default to 2,560 and 1,600, and they make Chromium scale captured frames to fit. everyNthFrame accepts values from 1 through 60 and defaults to 1. firstFrameTimeoutMs accepts values from 1,000 through 60,000 and is left to SmartPuppeteer's default when omitted. Runtime forwards these values together with maxOutstandingFrames; the defaults keep frames from device-pixel-ratio 2 viewers well below maxFrameBytes.

Human state and error events retain an optional diagnostic message bounded to 2,048 characters. A fatal producer error synchronously invalidates all current participants before their captured subscribers receive the error. Cleanup is coalesced for that exact incarnation and completes before affected operations settle.

humanLease.refreshFrameStream(options?: IBrowserRuntimeOperationOptions): Promise<void> requires that participant's current subscription and enters the shared audited FIFO. It works for a running, open active tab even when its stream is invalidated. Runtime clears old viewer windows, waits for producer acknowledgement work, and validates the returned new-generation boundary against the current tab, viewport, session and incarnation. Every viewer receives the new stream. Missing or replaced subscriptions fail with BUSY; an abandoned initiator returns ABORTED without removing other viewers. A broken producer or invalid refresh boundary fails with FRAME_STREAM_FAILED or FRAME_TOO_LARGE after exact-incarnation cleanup. Caller cancellation preserves a successfully restored stream.

Trusted Pipe And Flex

Trusted framed peers and clients receive the complete authority out of band: project, resource, attachment authority/revision, actor, peer, role, source, qualified session, Flex scope, exact run, and resource-specific channel. Incoming frames cannot select identity. One session may use multiple resource-specific channels concurrently. Framed client/server request work and queued writes are bounded under backpressure.

BrowserRuntimeFlexToolProvider<TScope> resolves only a capability token and exposes the six approved SmartAgent actions. The provider requires its client run ID to match the exact Flex tool-provider context, and every runtime operation hook retains that run ID. The framed server validates the token against its complete trusted binding.

MCP Handler

createBrowserRuntimeMcpHttpHandler() requires independent request authentication to return the complete expected MCP binding. The bearer capability must match it exactly. Identity remains server-owned and no tool input contains a project, resource, authority, revision, session, actor, or peer selector.

The MCP tool list is exactly browser_navigate, browser_snapshot, browser_screenshot, browser_click, browser_fill, and browser_press.

Egress And Artifacts

Each running resource owns one authenticated loopback BrowserEgressProxy carrying immutable projectId and browserResourceId. HTTP, WebSocket Upgrade, and CONNECT share strict public-unicast DNS/IP validation, numeric dialing, bounded lifetimes, and fail-closed policy.

Artifact identity and APIs use (projectId, browserResourceId, artifactId). Keyed project/resource directories prevent caller IDs from entering paths. Admission is serialized across per-resource, per-project, and global count/byte quotas. Reads use no-follow handles and verify size and SHA-256. Screenshot actions return metadata. Direct agent leases can read/delete only artifacts created by that exact lease; other agent and human artifacts remain unavailable. Human artifact access remains scoped to the resource. Read completion revalidates the lease and clears bytes if authority ended during IO. The built-in framed/Flex/MCP action adapters continue to return metadata; hosts can return image content after a scoped lease read. The artifact store accepts an optional opaque owner ID on store() and an expected owner ID on read()/delete(); omitting an expected owner retains its trusted parent API.

Verification

pnpm install
pnpm dedupe
pnpm run build
pnpm run check:test
pnpm test
pnpm run test:real-chrome

The real Chromium check launches two resources in one project and qualified session, verifies distinct generation-scoped private profiles, sandboxed renderer process trees, mandatory confinement, screenshots, confirmed shutdown, and generation deletion.

License and Legal Information

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the contents of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at [email protected].

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.