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

opfs-extended

v0.1.6

Published

A typed filesystem layer over OPFS for client-side agentic workflows

Readme

opfs-extended

A typed filesystem layer over the browser's Origin Private File System (OPFS), built primarily for client-side agentic workflows. Gives AI agents and autonomous tools a persistent, sandboxed filesystem they can read, write, stream, and watch — entirely in the browser with no server required.

Provides a familiar IFS interface with metadata, permissions, watch events, batch operations, and cross-tab sync.

Features

  • Full filesystem API - read, write, append, copy, move, remove, mkdir, stat, exists
  • Streaming - readable and writable streams for large file I/O
  • Metadata - attach arbitrary JSON metadata to any file or directory
  • Directory permissions - read/write guards per directory
  • Watch events - path-scoped subscriptions with cross-tab sync via BroadcastChannel
  • Batch operations - transactional multi-file writes
  • Query - filter directory entries by metadata
  • Mount scoping - create chroot-style views into subdirectories
  • Metadata repair (fsck) - rebuild .meta from actual OPFS state when corrupted or lost
  • Zero dependencies - pure browser APIs only

Quick start

pnpm add opfs-extended
import { createRoot } from 'opfs-extended'

// Create a root backed by an OPFS subdirectory
const root = await createRoot('my-app')
const fs = root.mount()

// Or mount the actual OPFS root
import { createRootFromHandle } from 'opfs-extended'
const handle = await navigator.storage.getDirectory()
const root = await createRootFromHandle('root', handle)
const fs = root.mount()

API

IFS

The filesystem interface returned by root.mount():

// Reading
await fs.readFile('/data.bin')        // ArrayBuffer
await fs.readTextFile('/notes.txt')   // string
await fs.exists('/notes.txt')         // boolean
await fs.stat('/notes.txt')           // FileStat
await fs.ls('/')                      // FileEntry[]
await fs.readDir('/')                 // string[]

// Writing
await fs.writeFile('/hello.txt', 'world')
await fs.writeFile('/data.bin', arrayBuffer)
await fs.appendFile('/log.txt', 'new line\n')
await fs.mkdir('/deep/nested/dir', { recursive: true })

// Copy, move, remove
await fs.copyFile('/a.txt', '/b.txt')
await fs.moveFile('/old.txt', '/new.txt')
await fs.remove('/dir', { recursive: true })

// Metadata
await fs.setMeta('/file.txt', { tags: ['important'], author: 'alice' })
const meta = await fs.getMeta('/file.txt')

// Permissions
await fs.setPermissions('/secret', { write: false })

// Query
const docs = await fs.query('/docs', entry => entry.meta.tags?.includes('draft'))

// Batch (transactional)
await fs.batch(async (tx) => {
  await tx.writeFile('/a.txt', 'hello')
  await tx.writeFile('/b.txt', 'world')
})

// Streaming
const readable = await fs.createReadStream('/large-file.bin')
const reader = readable.getReader()
while (true) {
  const { done, value } = await reader.read()
  if (done) break
  // process value (Uint8Array chunks)
}

const writable = await fs.createWriteStream('/output.bin', { meta: { type: 'export' } })
await writable.write('hello ')
await writable.write(new Uint8Array([0x01, 0x02]))
await writable.close()  // updates metadata and fires watch event

// Watch (path-scoped - watches directory and all descendants)
const unsub = fs.watch('/', (events) => {
  for (const e of events) {
    console.log(e.type, e.path)  // 'create' '/docs/new.txt'
  }
})

IRoot

const fs = root.mount()           // mount at root
const scoped = root.mount('/sub') // chroot-style scoped view
const stats = await root.usage()  // { totalSize, fileCount, directoryCount }
await root.destroy()              // delete everything

// Repair metadata — scan OPFS and rebuild .meta files
const result = await root.fsck()  // { repaired: 2, entries: 15 }

// Auto-repair on mount
const root = await createRoot('my-app', { autoRepair: true })

Watch events

Watchers are path-scoped. A watcher on / receives events from any descendant path. Events include the full path of the affected entry:

interface WatchEvent {
  type: 'create' | 'update' | 'delete'
  entry: FileEntry
  name: string   // filename
  path: string   // full path
}

Events sync across browser tabs via BroadcastChannel.

Playground

An interactive playground is included for exploring the API:

pnpm install
pnpm dev

The playground provides:

  • File tree with drag-and-drop move and file import
  • Text editor with save
  • File download/export
  • Metadata and permissions editors
  • Bash console (via just-bash) for CLI-style interaction
  • Filename and metadata search (meta:tags=component)
  • Event log with full event data
  • Usage stats
  • Multi-tab sync indicator
  • Seed data button for quick demo setup

Development

pnpm install
pnpm dev              # playground dev server
pnpm test             # run tests
pnpm typecheck        # typecheck library
pnpm typecheck:playground  # typecheck playground
pnpm build            # build library

Architecture

  • src/root.ts - Root management, OPFS handle wrapping, subscriber dispatch
  • src/mount.ts - IFS implementation scoped to a mount path
  • src/stream.ts - TrackedWritableStream with metadata updates on close
  • src/meta.ts - .meta file read/write with Web Locks
  • src/batch.ts - Transactional batch operations
  • src/broadcast.ts - Cross-tab event sync via BroadcastChannel
  • src/types.ts - All type definitions
  • playground/ - Interactive playground app