diff --git a/modules/autobase-discovery-cli.md b/modules/autobase-discovery-cli.md
new file mode 100644
index 0000000..7e2b769
--- /dev/null
+++ b/modules/autobase-discovery-cli.md
@@ -0,0 +1,378 @@
+# autobase-discovery-cli - Service Discovery for Autobase
+
+## Overview
+
+autobase-discovery-cli is a command-line interface for autobase-discovery, providing tools to run discovery servers and query service information from Autobase databases. It enables decentralized service discovery by leveraging the Autobase multi-writer architecture.
+
+### Key Features
+
+- **Server mode**: Run a discovery service that indexes Autobase entries
+- **Client queries**: List services by name from the discovery database
+- **Secure RPC**: Public-key authenticated remote procedure calls
+- **Real-time updates**: Database key stabilizes as indexers process entries
+- **JSON logging**: Structured logs compatible with pino ecosystem
+
+### Use Cases
+
+- **Service registry**: Discover microservices in distributed systems
+- **Peer discovery**: Find nodes in P2P networks
+- **Dynamic configuration**: Query runtime service endpoints
+- **Multi-tenant discovery**: Isolate services by namespace
+
+## Architecture
+
+```mermaid
+graph TB
+ subgraph "Discovery Server"
+ CLI[autodiscovery CLI]
+ RPC[RPC Server
Auth-required]
+ INDEXER[Autobase Indexer]
+ DB[Discovery Database]
+ end
+
+ subgraph "Clients"
+ CLIENT[autodiscovery-client]
+ QUERY[List Services Query]
+ end
+
+ subgraph "Autobase Network"
+ AB[Autobase Writers]
+ INPUT[Service Entries]
+ end
+
+ AB -->|Replicate| INDEXER
+ INPUT --> AB
+ INDEXER --> DB
+ DB --> CLI
+ CLI --> RPC
+ CLIENT --> QUERY
+ QUERY -->|RPC| RPC
+```
+
+## Installation
+
+```bash
+npm install -g autobase-discovery-cli
+```
+
+## Quick Start
+
+### Run Discovery Server
+
+```bash
+# Generate a keypair for secure RPC
+# (Use hypercore-sign or similar to generate keys)
+autodiscovery run | pino-pretty
+```
+
+The server will output:
+- RPC server's public key
+- Discovery database key (updates as indexers process)
+
+### Query Services (Client)
+
+```bash
+# List all instances of a service
+autodiscovery-client list
+```
+
+## CLI Reference
+
+### Server Commands
+
+#### `autodiscovery run `
+
+Start the discovery server.
+
+**Parameters:**
+- `rpc-allowed-public-key`: Public key authorized to make RPC calls
+
+**Output:**
+- RPC server public key
+- Database key (stabilizes after first indexer entry)
+
+**Logging:**
+```bash
+# JSON format (default)
+autodiscovery run
+
+# Human-readable
+autodiscovery run | pino-pretty
+```
+
+**Note:** The database key updates as new indexers are processed. Add at least one entry to stabilize the initial database key.
+
+### Client Commands
+
+#### `autodiscovery-client list `
+
+List all discovered instances of a service.
+
+**Parameters:**
+- `database-key`: The discovery database key
+- `service-name`: Name of the service to query
+
+**Output:**
+```
+service-instance-1 192.168.1.100:8080
+service-instance-2 192.168.1.101:8080
+```
+
+#### `autodiscovery-client --help`
+
+Show all available commands and options.
+
+## Complete Examples
+
+### Example 1: Service Discovery Setup
+
+```bash
+# 1. Generate RPC keypair (signer)
+hypercore-sign generate-keys
+# Note the public key: ocmjxpzg...
+
+# 2. Start discovery server
+autodiscovery run ocmjxpzghcx5gbhkky7qubn5pr4fpcxwr5mu4hjw43dqs3qhid3y | pino-pretty
+
+# Output:
+# Server public key: abc123...
+# Database key: def456...
+# Waiting for indexers...
+
+# 3. Add a service entry to Autobase (via your app)
+# (See autobase-discovery module for API)
+
+# 4. Query for services
+autodiscovery-client list def456... api-gateway
+
+# Output:
+# api-gateway-prod-1 10.0.1.10:3000
+# api-gateway-prod-2 10.0.1.11:3000
+```
+
+### Example 2: Multi-Service Discovery
+
+```bash
+# Terminal 1: Run discovery server
+export RPC_PUBKEY="ocmjxpzghcx5gbhkky7qubn5pr4fpcxwr5mu4hjw43dqs3qhid3y"
+autodiscovery run $RPC_PUBKEY 2>&1 | tee discovery.log | pino-pretty
+
+# Extract database key from logs (after first entry)
+DB_KEY=$(grep "Database key" discovery.log | tail -1 | awk '{print $3}')
+
+# Terminal 2: Query different services
+autodiscovery-client list $DB_KEY user-service
+autodiscovery-client list $DB_KEY payment-service
+autodiscovery-client list $DB_KEY notification-service
+```
+
+### Example 3: Integration Script
+
+```bash
+#!/bin/bash
+# start-discovery.sh
+
+RPC_KEY="${RPC_KEY:-$(cat ~/.discovery-rpc-key.pub)}"
+LOG_FILE="/var/log/discovery.log"
+
+# Start server with log rotation
+autodiscovery run "$RPC_KEY" >> "$LOG_FILE" 2>&1 &
+PID=$!
+
+# Wait for database key
+for i in {1..30}; do
+ DB_KEY=$(grep -o 'Database key: [a-f0-9]*' "$LOG_FILE" | tail -1 | awk '{print $3}')
+ if [ -n "$DB_KEY" ]; then
+ echo "Discovery server ready"
+ echo "Database key: $DB_KEY"
+ echo $DB_KEY > /run/discovery-db-key
+ break
+ fi
+ sleep 1
+done
+
+echo $PID > /run/discovery.pid
+```
+
+### Example 4: Client Wrapper
+
+```js
+#!/usr/bin/env node
+const { execSync } = require('child_process')
+
+class DiscoveryClient {
+ constructor(dbKey) {
+ this.dbKey = dbKey
+ }
+
+ list(serviceName) {
+ try {
+ const output = execSync(
+ `autodiscovery-client list ${this.dbKey} ${serviceName}`,
+ { encoding: 'utf8' }
+ )
+
+ return output.trim().split('\n').map(line => {
+ const [name, address] = line.trim().split(/\s+/)
+ return { name, address }
+ })
+ } catch (err) {
+ console.error('Query failed:', err.message)
+ return []
+ }
+ }
+
+ getServiceUrl(serviceName, index = 0) {
+ const instances = this.list(serviceName)
+ if (instances.length === 0) {
+ throw new Error(`No instances found for service: ${serviceName}`)
+ }
+ return instances[index % instances.length].address
+ }
+}
+
+// Usage
+const client = new DiscoveryClient(process.env.DISCOVERY_DB_KEY)
+
+const userServiceUrl = client.getServiceUrl('user-service')
+console.log(`User service: http://${userServiceUrl}`)
+
+const allGateways = client.list('api-gateway')
+console.log(`Found ${allGateways.length} API gateways`)
+```
+
+## Security
+
+### RPC Authentication
+
+The discovery server requires a public key for RPC authentication:
+
+```bash
+# Generate keypair
+hypercore-sign generate-keys
+
+# Use public key when starting server
+autodiscovery run
+
+# Only clients with matching secret key can query
+```
+
+### Network Security
+
+- Run behind firewall for internal networks
+- Use TLS for public deployments
+- Rotate RPC keys periodically
+
+## Integration with Autobase
+
+### Service Entry Format
+
+Entries written to Autobase for discovery:
+
+```js
+{
+ type: 'service-announcement',
+ name: 'user-service',
+ instance: 'user-service-prod-1',
+ address: '10.0.1.10:3000',
+ metadata: {
+ version: '2.1.0',
+ region: 'us-east-1',
+ health: 'healthy'
+ },
+ timestamp: Date.now()
+}
+```
+
+### Indexer Configuration
+
+The discovery server indexes these entries:
+
+```js
+// In your Autobase setup
+const Autobase = require('autobase')
+const DiscoveryIndexer = require('autobase-discovery')
+
+const base = new Autobase(store, key, {
+ async apply(nodes, view, base) {
+ for (const node of nodes) {
+ if (node.value.type === 'service-announcement') {
+ await view.insert(node.value)
+ }
+ }
+ }
+})
+```
+
+## Best Practices
+
+### Database Key Management
+
+```bash
+# Wait for key stabilization
+start_server() {
+ autodiscovery run $RPC_KEY &
+ SERVER_PID=$!
+
+ # Wait for database key
+ while [ -z "$DB_KEY" ]; do
+ sleep 1
+ DB_KEY=$(get_db_key_from_logs)
+ done
+
+ # Store for clients
+ echo $DB_KEY > /etc/discovery/db-key
+}
+```
+
+### Monitoring
+
+```bash
+# Check server health
+check_discovery() {
+ if pgrep -f "autodiscovery run" > /dev/null; then
+ echo "Server running"
+
+ # Test query
+ DB_KEY=$(cat /etc/discovery/db-key)
+ autodiscovery-client list $DB_KEY health-check > /dev/null && \
+ echo "Query OK" || echo "Query failed"
+ else
+ echo "Server not running"
+ fi
+}
+```
+
+### Log Analysis
+
+```bash
+# Parse discovery events
+cat /var/log/discovery.log | pino-pretty | grep -E "(announce|unannounce|query)"
+
+# Monitor for errors
+tail -f /var/log/discovery.log | jq 'select(.level >= 50)'
+```
+
+## Troubleshooting
+
+### Database Key Keeps Changing
+
+**Cause:** Not enough entries processed by indexers
+**Solution:** Add at least one entry to stabilize the key
+
+### RPC Authentication Fails
+
+**Cause:** Wrong public key or key mismatch
+**Solution:** Verify keys match between server and client
+
+### No Services Found
+
+**Cause:** Services not announcing or wrong database key
+**Solution:** Check Autobase entries and database key
+
+## License
+
+Apache-2.0
+
+---
+**Module Type**: CLI Tool | **Ecosystem Role**: Service Discovery | **Dependencies**: autobase-discovery, Autobase
diff --git a/modules/bare-addon.md b/modules/bare-addon.md
new file mode 100644
index 0000000..48ff4fb
--- /dev/null
+++ b/modules/bare-addon.md
@@ -0,0 +1,139 @@
+# bare-addon - Native Addon Template
+
+## Overview
+
+**bare-addon** is a template repository for creating Bare native addons. It provides the build infrastructure for compiling C/C++ native bindings for use with the Bare JavaScript runtime.
+
+## Quick Start
+
+### Creating a New Addon
+
+1. Use this repository as a template on GitHub
+2. Clone your new repository
+3. Implement your native code in `binding.c`
+4. Build and publish
+
+## Building
+
+### Install Build Tool
+
+```bash
+npm i -g bare-make
+```
+
+### Generate Build System
+
+```bash
+# Generate (run once per checkout)
+bare-make generate
+
+# Debug build
+bare-make generate --debug
+
+# Regenerate (after toolchain updates)
+bare-make generate --no-cache
+```
+
+### Compile
+
+```bash
+# Build bindings
+bare-make build
+
+# Install to prebuilds/
+bare-make install
+
+# Link for development (faster iteration)
+bare-make install --link
+```
+
+## Project Structure
+
+```
+my-addon/
+├── binding.c # Native bindings
+├── CMakeLists.txt # Build configuration
+├── package.json # Package manifest
+├── prebuilds/ # Compiled binaries
+│ ├── darwin-arm64/
+│ ├── linux-x64/
+│ └── win32-x64/
+└── .github/
+ └── workflows/
+ └── prebuild.yml # CI/CD workflow
+```
+
+## Adding Dependencies
+
+### External Native Libraries
+
+Use `cmake-fetch` to include native libraries:
+
+```bash
+npm i -D cmake-fetch
+```
+
+```cmake
+# CMakeLists.txt
+find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
+
+fetch_package("github:holepunchto/liburl")
+
+target_link_libraries(
+ ${bare_addon}
+ PUBLIC
+ url
+)
+```
+
+## Publishing
+
+### Version Bump
+
+```bash
+npm version
+git push
+git push --tags
+```
+
+### Automated Prebuilds
+
+```bash
+# Trigger CI workflow
+gh workflow run prebuild --ref
+
+# Watch progress
+gh run watch
+
+# Download prebuilds
+gh run download --name prebuilds --dir prebuilds
+```
+
+### Manual Publish
+
+```bash
+# Verify prebuilds exist
+ls prebuilds/
+
+# Publish to npm
+npm publish
+```
+
+## Troubleshooting
+
+### Cache Issues
+
+Check cache state:
+```bash
+bare --print 'Bare.Addon.cache'
+```
+
+Clear by bumping version in `package.json`.
+
+## License
+
+Apache-2.0
+
+---
+
+**Module Type**: Template | **Ecosystem Role**: Native Addon Development | **Build Tool**: bare-make
diff --git a/modules/bare-boot.md b/modules/bare-boot.md
new file mode 100644
index 0000000..7c8a69e
--- /dev/null
+++ b/modules/bare-boot.md
@@ -0,0 +1,19 @@
+# bare-boot - Boot Drive Loader
+
+## Overview
+
+**bare-boot** boots drives in the Bare runtime. It provides the mechanism for loading and initializing Bare applications from various drive sources.
+
+## Usage
+
+```js
+const boot = require('bare-boot')
+```
+
+## License
+
+Apache-2.0
+
+---
+
+**Module Type**: Core Runtime | **Ecosystem Role**: Application Bootstrapping | **Used With**: Bare
diff --git a/modules/bare-build.md b/modules/bare-build.md
new file mode 100644
index 0000000..b891b20
--- /dev/null
+++ b/modules/bare-build.md
@@ -0,0 +1,199 @@
+# bare-build - Application Builder for Bare
+
+## Overview
+
+**bare-build** packages JavaScript applications as native application bundles or standalone executables for desktop and mobile platforms. It supports building for Linux, macOS, Windows, Android, and iOS with platform-specific packaging formats.
+
+## Supported Platforms & Formats
+
+| Platform | Unpackaged | Packaged | Standalone |
+|----------|-----------|----------|------------|
+| Linux | .AppDir | .AppImage | ELF executable |
+| Android | .apk | .aab | ELF executable |
+| macOS | .app | .pkg | Mach-O executable |
+| iOS | .app | .pkg | Mach-O executable |
+| Windows | Directory | .msix | PE executable |
+
+## Quick Start
+
+### CLI Usage
+
+```bash
+# Build for current platform
+bare-build app.js
+
+# Build for multiple platforms
+bare-build \
+ --host darwin-arm64 \
+ --host darwin-x64 \
+ --host linux-x64 \
+ --icon icon.icns \
+ --identifier com.example.App \
+ app.js
+
+# Build standalone executable
+bare-build --standalone app.js
+
+# Build with packaging
+bare-build --package app.js
+```
+
+### Programmatic Usage
+
+```js
+const build = require('bare-build')
+
+for await (const resource of build('/path/to/app.js', {
+ base: '/path/to/',
+ hosts: ['darwin-arm64', 'darwin-x64'],
+ icon: 'icon.icns',
+ identifier: 'com.example.App',
+ standalone: true
+})) {
+ console.log('Built:', resource)
+}
+```
+
+## Configuration Options
+
+```js
+{
+ // Application metadata
+ name: 'MyApp',
+ version: '1.0.0',
+ author: 'Author Name',
+ description: 'Application description',
+
+ // Application identity
+ identifier: 'com.example.app',
+ icon: 'path/to/icon',
+
+ // Build configuration
+ base: '.', // Base path
+ hosts: ['darwin-arm64'], // Target platforms
+ out: './dist', // Output directory
+
+ // Runtime options
+ runtime: 'bare-gtk/runtime', // Alternative runtime
+
+ // Build modes
+ standalone: false, // Standalone executable
+ package: false, // Package for distribution
+ sign: false, // Sign the application
+
+ // macOS signing
+ identity: 'Apple Development',
+ entitlements: 'path/to/entitlements',
+ hardenedRuntime: false,
+
+ // Windows signing
+ subject: 'CN=Publisher',
+ thumbprint: 'cert-thumbprint',
+
+ // Linux signing
+ key: 'gpg-key-id',
+
+ // Android signing
+ keystore: 'path/to/keystore',
+ keystorePassword: 'password'
+}
+```
+
+## Runtimes
+
+### Portable Runtimes (Default)
+Suitable for CLI applications, runs the Bare I/O event loop only.
+
+### Native Runtimes (GUI Applications)
+For native GUI apps requiring system event loop integration:
+
+| Platform | Runtime | CLI Flag |
+|----------|---------|----------|
+| Linux | bare-gtk | `--runtime bare-gtk/runtime` |
+| Android | bare-ndk | `--runtime bare-ndk/runtime` |
+| macOS | bare-app-kit | `--runtime bare-app-kit/runtime` |
+| iOS | bare-ui-kit | `--runtime bare-ui-kit/runtime` |
+| Windows | bare-win-ui | `--runtime bare-win-ui/runtime` |
+
+## CLI Flags
+
+```bash
+bare-build [flags]
+
+--name, -n Application name
+--author Author name
+--description Application description
+--icon, -i Application icon
+--identifier Unique identifier (e.g., com.example.app)
+--manifest Platform-specific manifest
+--resources Additional resources
+--base Base path (default: .)
+--host Target host (can specify multiple)
+--out, -o Output directory
+--runtime Runtime specifier
+--standalone Build standalone executable
+--package Package for distribution
+--sign Sign the application
+--identity macOS signing identity
+--entitlements macOS entitlements file
+--hardened-runtime Enable macOS hardened runtime
+--subject Windows signing subject
+--thumbprint Windows certificate thumbprint
+--key Linux GPG signing key
+--keystore Android keystore path
+--keystore-password Android keystore password
+```
+
+## Examples
+
+### Build Cross-Platform CLI Tool
+
+```bash
+bare-build \
+ --name "MyCLI" \
+ --identifier com.example.mycli \
+ --host darwin-arm64 \
+ --host darwin-x64 \
+ --host linux-x64 \
+ --host win32-x64 \
+ --standalone \
+ cli.js
+```
+
+### Build macOS GUI App
+
+```bash
+bare-build \
+ --name "MyApp" \
+ --identifier com.example.myapp \
+ --icon assets/icon.icns \
+ --runtime bare-app-kit/runtime \
+ --host darwin-arm64 \
+ --host darwin-x64 \
+ --package \
+ --sign \
+ --identity "Developer ID Application" \
+ app.js
+```
+
+### Build Android App
+
+```bash
+bare-build \
+ --name "MyAndroidApp" \
+ --identifier com.example.android \
+ --icon assets/icon.png \
+ --runtime bare-ndk/runtime \
+ --host android-arm64 \
+ --keystore release.keystore \
+ --keystore-password $KEYSTORE_PASSWORD \
+ app.js
+```
+
+## License
+
+Apache-2.0
+
+---
+
+**Module Type**: Build Tool | **Ecosystem Role**: Application Packaging | **Used By**: Bare CLI
diff --git a/modules/bare-delta.md b/modules/bare-delta.md
new file mode 100644
index 0000000..c497bd0
--- /dev/null
+++ b/modules/bare-delta.md
@@ -0,0 +1,558 @@
+# bare-delta - Binary Delta Compression for Bare
+
+## Overview
+
+bare-delta provides binary patch creation and application for the Bare runtime. It implements an enhanced version of Fossil SCM's delta compression algorithm with SIMD acceleration and zstd compression support, enabling efficient binary diffing for incremental updates.
+
+### Key Features
+
+- **Binary patching**: Create minimal patches between file versions
+- **Fossil SCM algorithm**: Proven delta compression with enhancements
+- **SIMD acceleration**: Hardware-accelerated hash computations
+- **zstd compression**: Optional patch compression for smaller sizes
+- **Sync/Async APIs**: Both blocking and non-blocking interfaces
+- **Batch operations**: Apply multiple patches sequentially
+
+### Use Cases
+
+- **Application updates**: Incremental binary patches for software distribution
+- **Version control**: Efficient storage of file revisions
+- **Backup systems**: Store only changed portions of files
+- **Sync protocols**: Minimize data transfer for updates
+- **Delta compression**: Reduce bandwidth and storage requirements
+
+## Architecture
+
+```mermaid
+graph LR
+ subgraph "Patch Creation"
+ ORIG[Original Data]
+ MOD[Modified Data]
+ DELTA[Delta Algorithm
Fossil SCM + SIMD]
+ PATCH[Binary Patch
Optional zstd]
+ end
+
+ subgraph "Patch Application"
+ ORIG2[Original Data]
+ PATCH2[Patch]
+ APPLY[Apply Algorithm]
+ RESULT[Reconstructed Data]
+ end
+
+ ORIG --> DELTA
+ MOD --> DELTA
+ DELTA --> PATCH
+ ORIG2 --> APPLY
+ PATCH2 --> APPLY
+ APPLY --> RESULT
+```
+
+### Algorithm Enhancements
+
+1. **SIMD Optimization**: Parallel hash computation using modern CPU instructions
+2. **Compact Encoding**: Replaced Fossil's base-64 integers with compact-encoding
+3. **zstd Integration**: Optional compression for patches
+4. **Streaming Support**: Memory-efficient processing of large files
+
+## Installation
+
+```bash
+npm install bare-delta
+```
+
+## Quick Start
+
+### Create and Apply a Patch
+
+```js
+const { create, apply } = require('bare-delta')
+
+const original = Buffer.from('Hello world!')
+const modified = Buffer.from('Hello Bare world!')
+
+// Create patch
+const patch = await create(original, modified)
+console.log(`Patch size: ${patch.length} bytes`)
+
+// Apply patch
+const result = await apply(original, patch)
+console.log(result.toString()) // 'Hello Bare world!'
+```
+
+### Synchronous API
+
+```js
+const { createSync, applySync } = require('bare-delta')
+
+const patch = createSync(original, modified)
+const result = applySync(original, patch)
+```
+
+### Batch Patch Application
+
+```js
+const { applyBatch } = require('bare-delta')
+
+// Apply multiple patches in sequence
+const patches = [patch1, patch2, patch3]
+const finalResult = await applyBatch(original, patches)
+```
+
+## API Reference
+
+### Async API
+
+#### `create(original, modified[, options])`
+
+Creates a binary patch between two buffers.
+
+**Parameters:**
+- `original` (Buffer | Uint8Array): Original data
+- `modified` (Buffer | Uint8Array): Modified data
+- `options` (object, optional):
+ - `hashWindowSize` (number): Hash window size, must be power of 2 (default: 16)
+ - `searchDepth` (number): Maximum search depth for matches (default: 250)
+ - `compressed` (boolean): Whether to compress the patch with zstd (default: false)
+
+**Returns:** Promise - The binary patch
+
+#### `apply(original, patch)`
+
+Applies a binary patch to reconstruct modified data. Auto-detects compression.
+
+**Parameters:**
+- `original` (Buffer | Uint8Array): Original data
+- `patch` (Buffer | Uint8Array): Patch from `create()`
+
+**Returns:** Promise - Reconstructed data
+
+#### `applyBatch(original, patches)`
+
+Applies multiple patches sequentially.
+
+**Parameters:**
+- `original` (Buffer | Uint8Array): Original data
+- `patches` (Array): Patches to apply in order
+
+**Returns:** Promise - Final reconstructed data
+
+### Sync API
+
+#### `createSync(original, modified[, options])`
+
+Synchronous version of `create()`.
+
+**Returns:** Buffer
+
+#### `applySync(original, patch)`
+
+Synchronous version of `apply()`.
+
+**Returns:** Buffer
+
+#### `applyBatchSync(original, patches)`
+
+Synchronous version of `applyBatch()`.
+
+**Returns:** Buffer
+
+## Complete Examples
+
+### Example 1: File Versioning System
+
+```js
+const { createSync, applySync } = require('bare-delta')
+const fs = require('bare-fs')
+
+class VersionedFile {
+ constructor(basePath) {
+ this.basePath = basePath
+ this.versions = []
+ }
+
+ saveVersion(data) {
+ if (this.versions.length === 0) {
+ // First version: store full file
+ fs.writeFileSync(`${this.basePath}.v0`, data)
+ this.versions.push({ type: 'full', size: data.length })
+ } else {
+ // Subsequent versions: store delta
+ const prevVersion = this.versions.length - 1
+ const prevData = this.loadVersion(prevVersion)
+
+ const patch = createSync(prevData, data, { compressed: true })
+ fs.writeFileSync(`${this.basePath}.v${this.versions.length}.patch`, patch)
+
+ this.versions.push({
+ type: 'delta',
+ size: patch.length,
+ parent: prevVersion
+ })
+ }
+
+ return this.versions.length - 1
+ }
+
+ loadVersion(versionNum) {
+ if (versionNum === 0) {
+ return fs.readFileSync(`${this.basePath}.v0`)
+ }
+
+ // Reconstruct by applying deltas
+ let result = this.loadVersion(0)
+
+ for (let i = 1; i <= versionNum; i++) {
+ const patch = fs.readFileSync(`${this.basePath}.v${i}.patch`)
+ result = applySync(result, patch)
+ }
+
+ return result
+ }
+
+ getStorageStats() {
+ const fullSize = this.versions[0]?.size || 0
+ const deltaSizes = this.versions
+ .filter(v => v.type === 'delta')
+ .reduce((sum, v) => sum + v.size, 0)
+
+ return {
+ versions: this.versions.length,
+ fullStorage: fullSize + deltaSizes,
+ spaceSaved: fullSize * (this.versions.length - 1) - deltaSizes
+ }
+ }
+}
+
+// Usage
+const file = new VersionedFile('/tmp/myfile')
+
+file.saveVersion(Buffer.from('Version 1 content'))
+file.saveVersion(Buffer.from('Version 2 with some changes'))
+file.saveVersion(Buffer.from('Version 3 more updates here'))
+
+console.log(file.getStorageStats())
+```
+
+### Example 2: Incremental Backup
+
+```js
+const { create, apply } = require('bare-delta')
+const fs = require('bare-fs')
+const path = require('bare-path')
+
+class IncrementalBackup {
+ constructor(backupDir) {
+ this.backupDir = backupDir
+ this.manifest = this.loadManifest()
+ }
+
+ loadManifest() {
+ try {
+ return JSON.parse(fs.readFileSync(
+ path.join(this.backupDir, 'manifest.json'),
+ 'utf8'
+ ))
+ } catch {
+ return { snapshots: [] }
+ }
+ }
+
+ async createSnapshot(sourceDir, snapshotName) {
+ const snapshotDir = path.join(this.backupDir, snapshotName)
+ fs.mkdirSync(snapshotDir, { recursive: true })
+
+ const files = fs.readdirSync(sourceDir)
+ const lastSnapshot = this.manifest.snapshots[this.manifest.snapshots.length - 1]
+
+ for (const file of files) {
+ const sourcePath = path.join(sourceDir, file)
+ const currentData = fs.readFileSync(sourcePath)
+
+ if (lastSnapshot) {
+ const prevPath = path.join(this.backupDir, lastSnapshot.name, file)
+
+ if (fs.existsSync(prevPath)) {
+ const prevData = fs.readFileSync(prevPath)
+ const patch = await create(prevData, currentData, { compressed: true })
+
+ if (patch.length < currentData.length * 0.5) {
+ // Store delta if it's smaller than 50% of file
+ fs.writeFileSync(
+ path.join(snapshotDir, `${file}.delta`),
+ patch
+ )
+ continue
+ }
+ }
+ }
+
+ // Store full file
+ fs.writeFileSync(path.join(snapshotDir, file), currentData)
+ }
+
+ this.manifest.snapshots.push({
+ name: snapshotName,
+ timestamp: Date.now()
+ })
+
+ fs.writeFileSync(
+ path.join(this.backupDir, 'manifest.json'),
+ JSON.stringify(this.manifest, null, 2)
+ )
+
+ return snapshotName
+ }
+
+ async restore(snapshotName, targetDir) {
+ const snapshotIndex = this.manifest.snapshots.findIndex(
+ s => s.name === snapshotName
+ )
+
+ if (snapshotIndex === -1) {
+ throw new Error(`Snapshot ${snapshotName} not found`)
+ }
+
+ fs.mkdirSync(targetDir, { recursive: true })
+
+ // Reconstruct by applying all deltas up to target
+ const files = new Map()
+
+ for (let i = 0; i <= snapshotIndex; i++) {
+ const snapshot = this.manifest.snapshots[i]
+ const snapshotDir = path.join(this.backupDir, snapshot.name)
+
+ for (const entry of fs.readdirSync(snapshotDir)) {
+ if (entry.endsWith('.delta')) {
+ const filename = entry.slice(0, -6)
+ const prevData = files.get(filename) || Buffer.alloc(0)
+ const patch = fs.readFileSync(path.join(snapshotDir, entry))
+ files.set(filename, await apply(prevData, patch))
+ } else {
+ files.set(entry, fs.readFileSync(path.join(snapshotDir, entry)))
+ }
+ }
+ }
+
+ // Write restored files
+ for (const [filename, data] of files) {
+ fs.writeFileSync(path.join(targetDir, filename), data)
+ }
+ }
+}
+
+// Usage
+const backup = new IncrementalBackup('/backups/myapp')
+await backup.createSnapshot('/app/data', 'snapshot-1')
+await backup.createSnapshot('/app/data', 'snapshot-2')
+await backup.restore('snapshot-2', '/restore/target')
+```
+
+### Example 3: Network-Sync Protocol
+
+```js
+const { create, applyBatch } = require('bare-delta')
+
+class DeltaSyncProtocol {
+ constructor() {
+ this.localVersions = new Map() // file -> { hash, data }
+ }
+
+ async generateSyncRequest(files) {
+ return files.map(file => ({
+ path: file,
+ hash: this.localVersions.get(file)?.hash || null
+ }))
+ }
+
+ async processSyncResponse(requests, remoteFiles) {
+ const patches = []
+
+ for (const req of requests) {
+ const remote = remoteFiles.find(f => f.path === req.path)
+
+ if (!remote) {
+ patches.push({ path: req.path, action: 'delete' })
+ } else if (req.hash !== remote.hash) {
+ const local = this.localVersions.get(req.path)
+
+ if (local) {
+ // Create delta
+ const patch = await create(local.data, remote.data, {
+ compressed: true
+ })
+ patches.push({
+ path: req.path,
+ action: 'patch',
+ patch: patch,
+ originalHash: req.hash,
+ newHash: remote.hash
+ })
+ } else {
+ // New file
+ patches.push({
+ path: req.path,
+ action: 'full',
+ data: remote.data,
+ hash: remote.hash
+ })
+ }
+ }
+ }
+
+ return patches
+ }
+
+ applyPatches(patches) {
+ for (const p of patches) {
+ switch (p.action) {
+ case 'delete':
+ this.localVersions.delete(p.path)
+ break
+ case 'full':
+ this.localVersions.set(p.path, {
+ hash: p.hash,
+ data: p.data
+ })
+ break
+ case 'patch':
+ const local = this.localVersions.get(p.path)
+ if (local && this.hash(local.data) === p.originalHash) {
+ const newData = await apply(local.data, p.patch)
+ this.localVersions.set(p.path, {
+ hash: p.newHash,
+ data: newData
+ })
+ }
+ break
+ }
+ }
+ }
+
+ hash(data) {
+ // Simple hash for demo
+ return require('bare-crypto').createHash('sha256')
+ .update(data)
+ .digest('hex')
+ }
+}
+```
+
+## Configuration Options
+
+### Tuning Parameters
+
+```js
+// Fast but less optimal patches
+const fast = await create(original, modified, {
+ hashWindowSize: 32,
+ searchDepth: 100,
+ compressed: false
+})
+
+// Slow but optimal patches
+const optimal = await create(original, modified, {
+ hashWindowSize: 8,
+ searchDepth: 1000,
+ compressed: true
+})
+
+// Balanced (defaults)
+const balanced = await create(original, modified)
+```
+
+### Parameter Guide
+
+| Parameter | Effect | Range |
+|-----------|--------|-------|
+| `hashWindowSize` | Larger = faster, less precise | 8-64 (power of 2) |
+| `searchDepth` | Higher = better matches, slower | 100-1000 |
+| `compressed` | zstd compression | true/false |
+
+## Performance Characteristics
+
+- **Speed**: 50-200 MB/s for patch creation (depends on options)
+- **Memory**: O(n) where n is original file size
+- **Patch size**: Typically 5-20% of changed data
+- **Compression**: zstd adds 10-30% CPU but 20-50% size reduction
+
+## Best Practices
+
+### When to Use Deltas
+
+```js
+// Good: Large files with small changes
+const largeFile = fs.readFileSync('database.db')
+const modified = applyChanges(largeFile)
+const patch = createSync(largeFile, modified)
+// Patch will be small
+
+// Bad: Completely different data
+const unrelated = Buffer.from('totally different content')
+const patch = createSync(largeFile, unrelated)
+// Patch may be larger than modified file!
+```
+
+### Error Handling
+
+```js
+const { create, apply } = require('bare-delta')
+
+try {
+ const patch = await create(original, modified)
+
+ if (patch.length >= modified.length) {
+ console.warn('Delta larger than full file, storing full instead')
+ return modified
+ }
+
+ return patch
+} catch (err) {
+ console.error('Delta creation failed:', err)
+ // Fallback to full file
+ return modified
+}
+```
+
+### Streaming Large Files
+
+```js
+const { create } = require('bare-delta')
+
+// For very large files, process in chunks
+async function* createDeltaStream(originalPath, modifiedPath, chunkSize = 10 * 1024 * 1024) {
+ const original = fs.openSync(originalPath, 'r')
+ const modified = fs.openSync(modifiedPath, 'r')
+
+ let offset = 0
+
+ while (true) {
+ const origChunk = Buffer.alloc(chunkSize)
+ const modChunk = Buffer.alloc(chunkSize)
+
+ const origRead = fs.readSync(original, origChunk, 0, chunkSize, offset)
+ const modRead = fs.readSync(modified, modChunk, 0, chunkSize, offset)
+
+ if (origRead === 0 && modRead === 0) break
+
+ const patch = await create(
+ origChunk.slice(0, origRead),
+ modChunk.slice(0, modRead)
+ )
+
+ yield { offset, patch }
+ offset += chunkSize
+ }
+
+ fs.closeSync(original)
+ fs.closeSync(modified)
+}
+```
+
+## License
+
+Apache-2.0
+
+This project incorporates code from Fossil SCM's delta compression algorithm, licensed under BSD-2-Clause.
+
+---
+**Module Type**: Algorithm/Utility | **Ecosystem Role**: Data Compression | **Dependencies**: compact-encoding, zstd (optional)
diff --git a/modules/bare-dev.md b/modules/bare-dev.md
new file mode 100644
index 0000000..b45f4d8
--- /dev/null
+++ b/modules/bare-dev.md
@@ -0,0 +1,19 @@
+# bare-dev - Development Tooling for Bare
+
+## Overview
+
+**bare-dev** provides development tooling for the Bare JavaScript runtime. It includes utilities for debugging, testing, and developing Bare applications.
+
+## Usage
+
+```js
+const dev = require('bare-dev')
+```
+
+## License
+
+Apache-2.0
+
+---
+
+**Module Type**: Dev Tool | **Ecosystem Role**: Development Utilities | **Part Of**: Bare Ecosystem
diff --git a/modules/bare-encoding.md b/modules/bare-encoding.md
new file mode 100644
index 0000000..bc5891f
--- /dev/null
+++ b/modules/bare-encoding.md
@@ -0,0 +1,541 @@
+# bare-encoding - Text Encoding for Bare
+
+## Overview
+
+bare-encoding provides WHATWG-compliant text encoding interfaces for the Bare runtime. It implements the standard `TextEncoder` and `TextDecoder` APIs, enabling consistent string-to-binary and binary-to-string conversions across Bare applications.
+
+### Key Features
+
+- **WHATWG compliant**: Standard TextEncoder/TextDecoder APIs
+- **UTF-8 support**: Full UTF-8 encoding and decoding
+- **Streaming support**: Process data incrementally
+- **Bare integration**: Optimized for Bare runtime environment
+- **Lightweight**: Minimal overhead implementation
+
+### Use Cases
+
+- **Text processing**: Convert between strings and binary data
+- **Network protocols**: Encode/decode text-based protocols
+- **File I/O**: Read and write text files
+- **JSON processing**: Handle text encodings in data interchange
+- **Internationalization**: Support for multilingual text
+
+## Installation
+
+```bash
+npm install bare-encoding
+```
+
+## Quick Start
+
+### Basic Encoding
+
+```js
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+
+// Encode string to Uint8Array
+const encoder = new TextEncoder()
+const encoded = encoder.encode('Hello, 世界!')
+console.log(encoded) // Uint8Array [72, 101, 108, 108, 111, ...]
+
+// Decode Uint8Array to string
+const decoder = new TextDecoder()
+const decoded = decoder.decode(encoded)
+console.log(decoded) // 'Hello, 世界!'
+```
+
+### Working with Buffers
+
+```js
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+
+// Encode to Buffer-compatible format
+const text = 'Bare runtime is fast!'
+const encoder = new TextEncoder()
+const uint8Array = encoder.encode(text)
+
+// Convert to Buffer if needed
+const buffer = Buffer.from(uint8Array)
+
+// Decode back
+const decoder = new TextDecoder()
+const result = decoder.decode(buffer)
+console.log(result) // 'Bare runtime is fast!'
+```
+
+## API Reference
+
+### TextEncoder
+
+Standard WHATWG TextEncoder implementation.
+
+#### `new TextEncoder()`
+
+Create a new TextEncoder instance.
+
+#### `encoder.encode(text)`
+
+Encode a string to UTF-8 bytes.
+
+**Parameters:**
+- `text` (string): String to encode
+
+**Returns:** Uint8Array - Encoded bytes
+
+**Example:**
+```js
+const encoder = new TextEncoder()
+const bytes = encoder.encode('Hello, World!')
+// Uint8Array(13) [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]
+```
+
+#### `encoder.encodeInto(text, destination)`
+
+Encode a string directly into a pre-allocated buffer.
+
+**Parameters:**
+- `text` (string): String to encode
+- `destination` (Uint8Array): Target buffer
+
+**Returns:** object with `read` and `written` properties
+
+**Example:**
+```js
+const encoder = new TextEncoder()
+const buffer = new Uint8Array(100)
+const result = encoder.encodeInto('Hello', buffer)
+console.log(result) // { read: 5, written: 5 }
+```
+
+### TextDecoder
+
+Standard WHATWG TextDecoder implementation.
+
+#### `new TextDecoder([label[, options]])`
+
+Create a new TextDecoder instance.
+
+**Parameters:**
+- `label` (string, optional): Encoding label (default: 'utf-8')
+- `options` (object, optional):
+ - `fatal` (boolean): Throw on invalid data (default: false)
+ - `ignoreBOM` (boolean): Ignore byte order marker (default: false)
+
+#### `decoder.decode([input[, options]])`
+
+Decode binary data to a string.
+
+**Parameters:**
+- `input` (BufferSource, optional): Data to decode
+- `options` (object, optional):
+ - `stream` (boolean): Process in streaming mode (default: false)
+
+**Returns:** string - Decoded text
+
+**Example:**
+```js
+const decoder = new TextDecoder()
+const bytes = new Uint8Array([72, 101, 108, 108, 111])
+const text = decoder.decode(bytes)
+console.log(text) // 'Hello'
+```
+
+## Complete Examples
+
+### Example 1: Network Protocol Handler
+
+```js
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+
+class TextProtocol {
+ constructor() {
+ this.encoder = new TextEncoder()
+ this.decoder = new TextDecoder()
+ this.buffer = new Uint8Array(0)
+ }
+
+ encodeMessage(message) {
+ const json = JSON.stringify(message)
+ const payload = this.encoder.encode(json)
+
+ // Add length header
+ const length = new Uint8Array(4)
+ new DataView(length.buffer).setUint32(0, payload.length, false)
+
+ const result = new Uint8Array(length.length + payload.length)
+ result.set(length, 0)
+ result.set(payload, 4)
+
+ return result
+ }
+
+ decodeMessages(data) {
+ // Append to buffer
+ const newBuffer = new Uint8Array(this.buffer.length + data.length)
+ newBuffer.set(this.buffer, 0)
+ newBuffer.set(data, this.buffer.length)
+ this.buffer = newBuffer
+
+ const messages = []
+ let offset = 0
+
+ while (offset + 4 <= this.buffer.length) {
+ const length = new DataView(this.buffer.buffer).getUint32(offset, false)
+
+ if (offset + 4 + length > this.buffer.length) {
+ break // Incomplete message
+ }
+
+ const payload = this.buffer.slice(offset + 4, offset + 4 + length)
+ const text = this.decoder.decode(payload)
+ messages.push(JSON.parse(text))
+
+ offset += 4 + length
+ }
+
+ // Keep remaining incomplete data
+ this.buffer = this.buffer.slice(offset)
+
+ return messages
+ }
+}
+
+// Usage
+const protocol = new TextProtocol()
+
+const message1 = { type: 'hello', data: 'world' }
+const message2 = { type: 'ping', timestamp: Date.now() }
+
+const encoded = protocol.encodeMessage(message1)
+const more = protocol.encodeMessage(message2)
+
+const combined = new Uint8Array(encoded.length + more.length)
+combined.set(encoded, 0)
+combined.set(more, encoded.length)
+
+const decoded = protocol.decodeMessages(combined)
+console.log(decoded) // [ { type: 'hello', ... }, { type: 'ping', ... } ]
+```
+
+### Example 2: File Reader/Writer
+
+```js
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+const fs = require('bare-fs')
+
+class TextFile {
+ constructor(path) {
+ this.path = path
+ this.encoder = new TextEncoder()
+ this.decoder = new TextDecoder()
+ }
+
+ write(text, encoding = 'utf-8') {
+ const data = this.encoder.encode(text)
+ fs.writeFileSync(this.path, Buffer.from(data))
+ }
+
+ read() {
+ const buffer = fs.readFileSync(this.path)
+ return this.decoder.decode(buffer)
+ }
+
+ append(text) {
+ const data = this.encoder.encode(text)
+ const existing = this.exists() ? fs.readFileSync(this.path) : Buffer.alloc(0)
+ const combined = Buffer.concat([existing, Buffer.from(data)])
+ fs.writeFileSync(this.path, combined)
+ }
+
+ exists() {
+ try {
+ fs.accessSync(this.path)
+ return true
+ } catch {
+ return false
+ }
+ }
+
+ readLines() {
+ const text = this.read()
+ return text.split('\n')
+ }
+
+ writeLines(lines) {
+ const text = lines.join('\n')
+ this.write(text)
+ }
+}
+
+// Usage
+const file = new TextFile('/tmp/myfile.txt')
+
+file.write('Hello, World!\nThis is line 2.')
+console.log(file.read())
+
+file.append('\nAppended line.')
+console.log(file.readLines())
+```
+
+### Example 3: Config File Handler
+
+```js
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+const fs = require('bare-fs')
+
+class ConfigFile {
+ constructor(path) {
+ this.path = path
+ this.encoder = new TextEncoder()
+ this.decoder = new TextDecoder()
+ this.cache = null
+ }
+
+ load() {
+ try {
+ const data = fs.readFileSync(this.path)
+ const text = this.decoder.decode(data)
+ this.cache = JSON.parse(text)
+ return this.cache
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ this.cache = {}
+ return this.cache
+ }
+ throw err
+ }
+ }
+
+ save(config) {
+ const text = JSON.stringify(config, null, 2)
+ const data = this.encoder.encode(text)
+ fs.writeFileSync(this.path, Buffer.from(data))
+ this.cache = config
+ }
+
+ get(key, defaultValue = undefined) {
+ if (!this.cache) this.load()
+ return this.cache[key] !== undefined ? this.cache[key] : defaultValue
+ }
+
+ set(key, value) {
+ if (!this.cache) this.load()
+ this.cache[key] = value
+ this.save(this.cache)
+ }
+
+ delete(key) {
+ if (!this.cache) this.load()
+ delete this.cache[key]
+ this.save(this.cache)
+ }
+}
+
+// Usage
+const config = new ConfigFile('/tmp/app-config.json')
+
+config.set('theme', 'dark')
+config.set('notifications', true)
+config.set('language', 'en')
+
+console.log(config.get('theme')) // 'dark'
+console.log(config.get('volume', 100)) // 100 (default)
+
+const all = config.load()
+console.log(all)
+```
+
+### Example 4: Streaming Text Processor
+
+```js
+const { TextDecoder } = require('bare-encoding')
+const stream = require('bare-stream')
+
+class StreamingTextProcessor extends stream.Transform {
+ constructor(options = {}) {
+ super(options)
+ this.decoder = new TextDecoder('utf-8', { fatal: false })
+ this.buffer = ''
+ this.delimiter = options.delimiter || '\n'
+ }
+
+ _transform(chunk, encoding, callback) {
+ // Decode binary chunk to text
+ const text = this.decoder.decode(chunk, { stream: true })
+ this.buffer += text
+
+ // Process complete lines
+ let delimiterIndex
+ while ((delimiterIndex = this.buffer.indexOf(this.delimiter)) !== -1) {
+ const line = this.buffer.slice(0, delimiterIndex)
+ this.buffer = this.buffer.slice(delimiterIndex + 1)
+
+ // Process line
+ const processed = this.processLine(line)
+ this.push(processed)
+ }
+
+ callback()
+ }
+
+ _flush(callback) {
+ // Process any remaining data
+ if (this.buffer.length > 0) {
+ const processed = this.processLine(this.buffer)
+ this.push(processed)
+ }
+ callback()
+ }
+
+ processLine(line) {
+ // Override in subclass for custom processing
+ return line.toUpperCase() + this.delimiter
+ }
+}
+
+// Usage
+const processor = new StreamingTextProcessor()
+
+processor.on('data', (chunk) => {
+ console.log('Processed:', chunk.toString())
+})
+
+// Simulate incoming data
+const encoder = new (require('bare-encoding').TextEncoder)()
+processor.write(encoder.encode('hello world\n'))
+processor.write(encoder.encode('line two\n'))
+processor.write(encoder.encode('partial'))
+processor.end(encoder.encode(' completion\n'))
+```
+
+## Integration with Other Modules
+
+### With bare-fetch
+
+```js
+const fetch = require('bare-fetch')
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+
+async function fetchText(url) {
+ const response = await fetch(url)
+ const bytes = await response.bytes()
+ const decoder = new TextDecoder()
+ return decoder.decode(bytes)
+}
+
+async function postText(url, text) {
+ const encoder = new TextEncoder()
+ const body = encoder.encode(text)
+
+ return fetch(url, {
+ method: 'POST',
+ body,
+ headers: {
+ 'Content-Type': 'text/plain'
+ }
+ })
+}
+```
+
+### With bare-fs
+
+```js
+const fs = require('bare-fs')
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+
+// Read text file
+function readTextFile(path) {
+ const buffer = fs.readFileSync(path)
+ const decoder = new TextDecoder()
+ return decoder.decode(buffer)
+}
+
+// Write text file
+function writeTextFile(path, text) {
+ const encoder = new TextEncoder()
+ const data = encoder.encode(text)
+ fs.writeFileSync(path, Buffer.from(data))
+}
+```
+
+## Best Practices
+
+### Reuse Encoder/Decoder Instances
+
+```js
+const { TextEncoder, TextDecoder } = require('bare-encoding')
+
+// Good: Reuse instances
+const encoder = new TextEncoder()
+const decoder = new TextDecoder()
+
+for (const text of messages) {
+ const bytes = encoder.encode(text) // Fast, reused instance
+}
+
+// Less optimal: Create new instances
+for (const text of messages) {
+ const bytes = new TextEncoder().encode(text) // Slower, creates objects
+}
+```
+
+### Handle Encoding Errors
+
+```js
+const { TextDecoder } = require('bare-encoding')
+
+// Strict mode: throws on invalid data
+const strict = new TextDecoder('utf-8', { fatal: true })
+
+try {
+ const text = strict.decode(invalidData)
+} catch (err) {
+ console.error('Invalid UTF-8 data:', err)
+}
+
+// Lenient mode: replaces invalid sequences
+const lenient = new TextDecoder('utf-8', { fatal: false })
+const text = lenient.decode(invalidData) // Uses replacement character
+```
+
+### Streaming Large Files
+
+```js
+const { TextDecoder } = require('bare-encoding')
+const fs = require('bare-fs')
+
+// Process large files in chunks
+function* readTextChunks(path, chunkSize = 64 * 1024) {
+ const decoder = new TextDecoder('utf-8', { stream: true })
+ const fd = fs.openSync(path, 'r')
+ const buffer = Buffer.alloc(chunkSize)
+
+ try {
+ while (true) {
+ const bytesRead = fs.readSync(fd, buffer, 0, chunkSize, null)
+ if (bytesRead === 0) break
+
+ const chunk = buffer.slice(0, bytesRead)
+ const text = decoder.decode(chunk, { stream: true })
+ yield text
+ }
+
+ // Finalize
+ yield decoder.decode()
+ } finally {
+ fs.closeSync(fd)
+ }
+}
+
+// Usage
+for (const chunk of readTextChunks('/tmp/bigfile.txt')) {
+ processChunk(chunk)
+}
+```
+
+## License
+
+Apache-2.0
+
+---
+**Module Type**: Runtime/Standard | **Ecosystem Role**: Core API | **Dependencies**: None (built-in standards)
diff --git a/modules/bare-env.md b/modules/bare-env.md
new file mode 100644
index 0000000..48b82d3
--- /dev/null
+++ b/modules/bare-env.md
@@ -0,0 +1,538 @@
+# bare-env - Environment Variables for Bare
+
+## Overview
+
+bare-env provides environment variable support for the Bare runtime, allowing JavaScript applications to access and manage process environment variables in a way that's compatible with both Bare and Node.js environments.
+
+### Key Features
+
+- **Standard interface**: Works like Node.js `process.env`
+- **Cross-platform**: Consistent behavior across operating systems
+- **Bare optimized**: Designed for lightweight Bare runtime
+- **Mutable**: Read and modify environment variables
+- **Object-like API**: Familiar key-value access patterns
+
+### Use Cases
+
+- **Configuration**: Load settings from environment variables
+- **Feature flags**: Enable/disable features via env vars
+- **Secrets management**: Access API keys and credentials
+- **Path management**: Work with PATH and other system variables
+- **Debugging**: Enable debug modes and logging levels
+
+## Installation
+
+```bash
+npm install bare-env
+```
+
+## Quick Start
+
+### Basic Usage
+
+```js
+const env = require('bare-env')
+
+// Read environment variables
+console.log(env.PATH)
+console.log(env.HOME)
+console.log(env.NODE_ENV)
+
+// Check if variable exists
+if (env.API_KEY) {
+ console.log('API key is set')
+}
+```
+
+### Setting Variables
+
+```js
+const env = require('bare-env')
+
+// Set new variables
+env.DEBUG = 'true'
+env.MY_APP_CONFIG = '/etc/myapp'
+
+// Variables are now available
+console.log(env.DEBUG) // 'true'
+```
+
+### Type Conversion
+
+```js
+const env = require('bare-env')
+
+// Environment variables are always strings
+const port = parseInt(env.PORT, 10) || 3000
+const debug = env.DEBUG === 'true'
+const features = env.FEATURES ? env.FEATURES.split(',') : []
+
+console.log({ port, debug, features })
+```
+
+## API Reference
+
+### Module Interface
+
+The bare-env module exports an object that behaves like `process.env`.
+
+#### Property Access
+
+```js
+const env = require('bare-env')
+
+// Get variable
+const value = env.VARIABLE_NAME
+
+// Set variable
+env.VARIABLE_NAME = 'value'
+
+// Check existence
+const exists = 'VARIABLE_NAME' in env
+
+// Delete variable
+delete env.VARIABLE_NAME
+```
+
+### Common Environment Variables
+
+| Variable | Description | Example |
+|----------|-------------|---------|
+| `PATH` | Executable search path | `/usr/local/bin:/usr/bin` |
+| `HOME` | User home directory | `/home/user` |
+| `USER` | Current username | `john` |
+| `PWD` | Current working directory | `/home/user/project` |
+| `NODE_ENV` | Application environment | `production`, `development` |
+
+## Complete Examples
+
+### Example 1: Configuration Loader
+
+```js
+const env = require('bare-env')
+
+class Config {
+ constructor() {
+ this.values = {}
+ this.load()
+ }
+
+ load() {
+ // Required variables
+ this.require('APP_NAME')
+ this.require('APP_VERSION')
+
+ // Optional variables with defaults
+ this.values.port = this.getInt('PORT', 3000)
+ this.values.host = env.HOST || '0.0.0.0'
+ this.values.debug = this.getBool('DEBUG', false)
+ this.values.logLevel = env.LOG_LEVEL || 'info'
+
+ // Array from comma-separated string
+ this.values.corsOrigins = this.getArray('CORS_ORIGINS', [])
+
+ // JSON configuration
+ this.values.features = this.getJson('FEATURES', {})
+ }
+
+ require(name) {
+ if (!env[name]) {
+ throw new Error(`Required environment variable ${name} is not set`)
+ }
+ this.values[name.toLowerCase()] = env[name]
+ }
+
+ get(name, defaultValue = undefined) {
+ return env[name] !== undefined ? env[name] : defaultValue
+ }
+
+ getInt(name, defaultValue = 0) {
+ const value = env[name]
+ if (value === undefined) return defaultValue
+ const parsed = parseInt(value, 10)
+ if (isNaN(parsed)) {
+ throw new Error(`Environment variable ${name} must be a valid integer`)
+ }
+ return parsed
+ }
+
+ getBool(name, defaultValue = false) {
+ const value = env[name]
+ if (value === undefined) return defaultValue
+ return value.toLowerCase() === 'true' || value === '1'
+ }
+
+ getArray(name, defaultValue = []) {
+ const value = env[name]
+ if (value === undefined) return defaultValue
+ return value.split(',').map(s => s.trim()).filter(Boolean)
+ }
+
+ getJson(name, defaultValue = null) {
+ const value = env[name]
+ if (value === undefined) return defaultValue
+ try {
+ return JSON.parse(value)
+ } catch (err) {
+ throw new Error(`Environment variable ${name} must be valid JSON: ${err.message}`)
+ }
+ }
+
+ get all() {
+ return { ...this.values }
+ }
+}
+
+// Usage
+const config = new Config()
+
+// Set env vars for demo
+env.APP_NAME = 'MyApp'
+env.APP_VERSION = '1.0.0'
+env.PORT = '8080'
+env.DEBUG = 'true'
+env.FEATURES = '{"auth": true, "cache": false}'
+
+config.load()
+console.log(config.all)
+```
+
+### Example 2: Feature Flags
+
+```js
+const env = require('bare-env')
+
+class FeatureFlags {
+ constructor() {
+ this.flags = new Map()
+ this.load()
+ }
+
+ load() {
+ // Load all FEATURE_ prefixed variables
+ for (const [key, value] of Object.entries(env)) {
+ if (key.startsWith('FEATURE_')) {
+ const flagName = key.slice(8).toLowerCase()
+ this.flags.set(flagName, value === 'true' || value === '1')
+ }
+ }
+ }
+
+ isEnabled(flag) {
+ return this.flags.get(flag) || false
+ }
+
+ enable(flag) {
+ this.flags.set(flag, true)
+ env[`FEATURE_${flag.toUpperCase()}`] = 'true'
+ }
+
+ disable(flag) {
+ this.flags.set(flag, false)
+ env[`FEATURE_${flag.toUpperCase()}`] = 'false'
+ }
+
+ toggle(flag) {
+ const current = this.isEnabled(flag)
+ if (current) {
+ this.disable(flag)
+ } else {
+ this.enable(flag)
+ }
+ return !current
+ }
+
+ list() {
+ return Object.fromEntries(this.flags)
+ }
+}
+
+// Usage
+const features = new FeatureFlags()
+
+// Set flags for demo
+env.FEATURE_NEW_UI = 'true'
+env.FEATURE_BETA_API = 'false'
+env.FEATURE_ANALYTICS = 'true'
+
+features.load()
+
+console.log('New UI enabled:', features.isEnabled('new_ui'))
+console.log('All flags:', features.list())
+
+features.enable('dark_mode')
+console.log('Dark mode:', features.isEnabled('dark_mode'))
+```
+
+### Example 3: Secret Manager
+
+```js
+const env = require('bare-env')
+
+class SecretManager {
+ constructor() {
+ this.secrets = new Map()
+ this.prefix = 'SECRET_'
+ }
+
+ load() {
+ for (const [key, value] of Object.entries(env)) {
+ if (key.startsWith(this.prefix)) {
+ const name = key.slice(this.prefix.length)
+ this.secrets.set(name, value)
+ }
+ }
+ }
+
+ get(name) {
+ const value = this.secrets.get(name)
+ if (!value) {
+ throw new Error(`Secret ${name} not found`)
+ }
+ return value
+ }
+
+ getOrNull(name) {
+ return this.secrets.get(name) || null
+ }
+
+ set(name, value) {
+ this.secrets.set(name, value)
+ env[`${this.prefix}${name}`] = value
+ }
+
+ has(name) {
+ return this.secrets.has(name)
+ }
+
+ require(...names) {
+ for (const name of names) {
+ if (!this.has(name)) {
+ throw new Error(`Required secret ${name} is not set`)
+ }
+ }
+ }
+
+ mask(name) {
+ const value = this.getOrNull(name)
+ if (!value) return null
+ if (value.length <= 8) return '****'
+ return value.slice(0, 4) + '****' + value.slice(-4)
+ }
+
+ listNames() {
+ return Array.from(this.secrets.keys())
+ }
+}
+
+// Usage
+const secrets = new SecretManager()
+
+// Set secrets for demo
+env.SECRET_API_KEY = 'sk-1234567890abcdef'
+env.SECRET_DATABASE_URL = 'postgres://user:pass@localhost/db'
+env.SECRET_JWT_SECRET = 'my-super-secret-jwt-key'
+
+secrets.load()
+
+console.log('API Key:', secrets.mask('API_KEY'))
+console.log('Available secrets:', secrets.listNames())
+
+try {
+ secrets.require('API_KEY', 'DATABASE_URL')
+ console.log('All required secrets present')
+} catch (err) {
+ console.error(err.message)
+}
+```
+
+### Example 4: Path Utilities
+
+```js
+const env = require('bare-env')
+const path = require('bare-path')
+
+class PathManager {
+ constructor() {
+ this.pathSeparator = process.platform === 'win32' ? ';' : ':'
+ }
+
+ getPath() {
+ return (env.PATH || '').split(this.pathSeparator).filter(Boolean)
+ }
+
+ addToPath(newPath, prepend = true) {
+ const paths = this.getPath()
+
+ // Remove if already exists
+ const index = paths.indexOf(newPath)
+ if (index > -1) {
+ paths.splice(index, 1)
+ }
+
+ // Add to beginning or end
+ if (prepend) {
+ paths.unshift(newPath)
+ } else {
+ paths.push(newPath)
+ }
+
+ env.PATH = paths.join(this.pathSeparator)
+ }
+
+ removeFromPath(targetPath) {
+ const paths = this.getPath().filter(p => p !== targetPath)
+ env.PATH = paths.join(this.pathSeparator)
+ }
+
+ findInPath(command) {
+ const paths = this.getPath()
+ const extensions = process.platform === 'win32'
+ ? (env.PATHEXT || '.EXE').split(';')
+ : ['']
+
+ for (const dir of paths) {
+ for (const ext of extensions) {
+ const fullPath = path.join(dir, command + ext.toLowerCase())
+ try {
+ const fs = require('bare-fs')
+ fs.accessSync(fullPath, fs.constants.X_OK)
+ return fullPath
+ } catch {
+ continue
+ }
+ }
+ }
+
+ return null
+ }
+
+ getHome() {
+ return env.HOME || env.USERPROFILE || '/tmp'
+ }
+
+ expandPath(filepath) {
+ if (filepath.startsWith('~/')) {
+ return path.join(this.getHome(), filepath.slice(2))
+ }
+ return filepath
+ }
+}
+
+// Usage
+const paths = new PathManager()
+
+console.log('Current PATH entries:', paths.getPath().length)
+console.log('Home directory:', paths.getHome())
+console.log('Expanded path:', paths.expandPath('~/documents'))
+
+paths.addToPath('/usr/local/bin')
+console.log('Added to PATH:', paths.getPath()[0])
+```
+
+## Integration with Other Modules
+
+### With bare-fetch
+
+```js
+const fetch = require('bare-fetch')
+const env = require('bare-env')
+
+async function apiRequest(endpoint, options = {}) {
+ const baseUrl = env.API_BASE_URL || 'https://api.example.com'
+ const apiKey = env.API_KEY
+
+ const response = await fetch(`${baseUrl}${endpoint}`, {
+ ...options,
+ headers: {
+ 'Authorization': `Bearer ${apiKey}`,
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+ })
+
+ return response
+}
+```
+
+### With bare-fs
+
+```js
+const fs = require('bare-fs')
+const env = require('bare-env')
+
+function getDataDir() {
+ const home = env.HOME || '/tmp'
+ const dataDir = env.XDG_DATA_HOME || `${home}/.local/share`
+ return dataDir
+}
+
+function ensureDataDir() {
+ const dir = getDataDir()
+ if (!fs.existsSync(dir)) {
+ fs.mkdirSync(dir, { recursive: true })
+ }
+ return dir
+}
+```
+
+## Best Practices
+
+### Validate Required Variables
+
+```js
+const env = require('bare-env')
+
+function validateEnv() {
+ const required = ['DATABASE_URL', 'JWT_SECRET', 'API_KEY']
+ const missing = required.filter(key => !env[key])
+
+ if (missing.length > 0) {
+ console.error('Missing required environment variables:', missing.join(', '))
+ process.exit(1)
+ }
+}
+
+// Run at startup
+validateEnv()
+```
+
+### Use Strong Typing
+
+```js
+const env = require('bare-env')
+
+const config = {
+ port: parseInt(env.PORT, 10) || 3000,
+ debug: env.DEBUG === 'true',
+ workers: parseInt(env.WORKERS, 10) || require('bare-os').availableParallelism(),
+ timeout: parseInt(env.TIMEOUT, 10) || 30000
+}
+```
+
+### Security Considerations
+
+```js
+const env = require('bare-env')
+
+// Never log secrets
+function safeLogConfig() {
+ const safeEnv = { ...env }
+
+ // Mask sensitive values
+ for (const key of Object.keys(safeEnv)) {
+ if (key.includes('SECRET') || key.includes('KEY') || key.includes('PASSWORD')) {
+ safeEnv[key] = '***'
+ }
+ }
+
+ console.log('Environment:', safeEnv)
+}
+```
+
+## License
+
+Apache-2.0
+
+---
+**Module Type**: Runtime/Standard | **Ecosystem Role**: Core API | **Dependencies**: None
diff --git a/modules/bare-events.md b/modules/bare-events.md
index 266ea95..b899cb8 100644
--- a/modules/bare-events.md
+++ b/modules/bare-events.md
@@ -1,26 +1,640 @@
-# bare-events v2.8.2 - EventEmitter
+# bare-events - Event Emitters for Bare
## Overview
-**Stable** WHATWG/Node EventEmitter. on/emit/once/off. AbortSignal support.
+bare-events provides EventEmitter functionality for the Bare runtime, implementing the standard Node.js EventEmitter API. It enables publish-subscribe patterns, allowing objects to emit named events and listeners to respond asynchronously.
+
+### Key Features
+
+- **Node.js compatible**: Drop-in replacement for Node.js events module
+- **Standard API**: `.on()`, `.emit()`, `.once()`, `.off()`, etc.
+- **Error handling**: Special handling for 'error' events
+- **Memory leak detection**: Warnings for too many listeners
+- **Performance optimized**: Efficient event dispatch
+- **AbortSignal support**: Integration with cancellation signals
+
+### Use Cases
+
+- **Asynchronous communication**: Decoupled component interactions
+- **State changes**: Notify listeners of data updates
+- **Progress tracking**: Emit progress during long operations
+- **Plugin systems**: Allow extensions to hook into events
+- **Real-time updates**: Stream data to multiple consumers
+
+## Installation
+
+```bash
+npm install bare-events
+```
+
+## Quick Start
+
+### Basic Usage
```js
const EventEmitter = require('bare-events')
-const ee = new EventEmitter()
-ee.on('event', data => console.log(data))
-ee.emit('event', 'hello')
+const emitter = new EventEmitter()
-ee.prependListener('pre', () => {}) // Order
-ee.off('event', handler)
+// Listen for events
+emitter.on('hello', (data) => {
+ console.log('Received:', data)
+})
+
+// Emit events
+emitter.emit('hello', 'world')
+// Output: Received: world
```
-**Global**: ./global patches global.EventTarget?
+### Once Listeners
-**Async**: await ee.once('ready')
+```js
+const EventEmitter = require('bare-events')
-**Deps**: None core, opt bare-abort-controller.
+const emitter = new EventEmitter()
-**Use**: TCP servers, drive watches, P2P signals.
+// Listen only once
+emitter.once('ready', () => {
+ console.log('Ready! (only fires once)')
+})
-**Source**: github/holepunchto/bare-events
+emitter.emit('ready') // Fires
+emitter.emit('ready') // Ignored
+```
+
+### Async/Await with Once
+
+```js
+const EventEmitter = require('bare-events')
+
+const emitter = new EventEmitter()
+
+// Wait for event with async/await
+async function waitForReady() {
+ await emitter.once('ready')
+ console.log('Now ready!')
+}
+
+waitForReady()
+setTimeout(() => emitter.emit('ready'), 1000)
+```
+
+### Removing Listeners
+
+```js
+const EventEmitter = require('bare-events')
+
+const emitter = new EventEmitter()
+
+function handler(data) {
+ console.log(data)
+}
+
+emitter.on('message', handler)
+emitter.emit('message', 'hello') // Fires
+
+// Remove listener
+emitter.off('message', handler)
+// or: emitter.removeListener('message', handler)
+emitter.emit('message', 'world') // Ignored
+```
+
+## API Reference
+
+### EventEmitter
+
+Main class for event handling.
+
+#### `new EventEmitter([options])`
+
+Create a new EventEmitter instance.
+
+**Parameters:**
+- `options` (object, optional):
+ - `captureRejections` (boolean): Capture promise rejections (default: false)
+
+#### `emitter.on(eventName, listener)`
+
+Add a listener for an event.
+
+**Parameters:**
+- `eventName` (string | symbol): Event name
+- `listener` (function): Callback function
+
+**Returns:** EventEmitter (for chaining)
+
+#### `emitter.once(eventName, listener)`
+
+Add a one-time listener.
+
+**Parameters:**
+- `eventName` (string | symbol): Event name
+- `listener` (function): Callback function
+
+**Returns:** EventEmitter (for chaining)
+
+#### `emitter.off(eventName, listener)` / `emitter.removeListener(eventName, listener)`
+
+Remove a specific listener.
+
+**Parameters:**
+- `eventName` (string | symbol): Event name
+- `listener` (function): Listener to remove
+
+**Returns:** EventEmitter (for chaining)
+
+#### `emitter.removeAllListeners([eventName])`
+
+Remove all listeners, or all listeners for a specific event.
+
+**Parameters:**
+- `eventName` (string | symbol, optional): Specific event to clear
+
+**Returns:** EventEmitter (for chaining)
+
+#### `emitter.emit(eventName[, ...args])`
+
+Emit an event with arguments.
+
+**Parameters:**
+- `eventName` (string | symbol): Event to emit
+- `...args`: Arguments passed to listeners
+
+**Returns:** boolean - Whether any listeners were called
+
+#### `emitter.listenerCount(eventName)`
+
+Get the number of listeners for an event.
+
+**Parameters:**
+- `eventName` (string | symbol): Event name
+
+**Returns:** number - Count of listeners
+
+#### `emitter.eventNames()`
+
+Get an array of all event names with listeners.
+
+**Returns:** Array
+
+#### `emitter.prependListener(eventName, listener)`
+
+Add listener to the beginning of the listeners array.
+
+#### `emitter.prependOnceListener(eventName, listener)`
+
+Add one-time listener to the beginning.
+
+### Class Properties
+
+#### `EventEmitter.defaultMaxListeners`
+
+Default maximum number of listeners per event before warnings. Default: 10.
+
+#### `emitter.setMaxListeners(n)`
+
+Set the maximum listeners for this instance.
+
+#### `emitter.getMaxListeners()`
+
+Get the current maximum listeners setting.
+
+## Complete Examples
+
+### Example 1: Data Store with Events
+
+```js
+const EventEmitter = require('bare-events')
+
+class ObservableStore extends EventEmitter {
+ constructor() {
+ super()
+ this.data = new Map()
+ }
+
+ set(key, value) {
+ const oldValue = this.data.get(key)
+ this.data.set(key, value)
+
+ this.emit('change', { key, oldValue, newValue: value })
+ this.emit(`change:${key}`, { oldValue, newValue: value })
+
+ if (oldValue === undefined) {
+ this.emit('add', { key, value })
+ } else {
+ this.emit('update', { key, oldValue, newValue: value })
+ }
+ }
+
+ get(key) {
+ return this.data.get(key)
+ }
+
+ delete(key) {
+ const value = this.data.get(key)
+ if (this.data.delete(key)) {
+ this.emit('delete', { key, value })
+ this.emit('change', { key, oldValue: value, newValue: undefined })
+ return true
+ }
+ return false
+ }
+
+ has(key) {
+ return this.data.has(key)
+ }
+
+ clear() {
+ const keys = Array.from(this.data.keys())
+ this.data.clear()
+ this.emit('clear', { keys })
+ }
+
+ keys() {
+ return Array.from(this.data.keys())
+ }
+
+ values() {
+ return Array.from(this.data.values())
+ }
+
+ entries() {
+ return Array.from(this.data.entries())
+ }
+}
+
+// Usage
+const store = new ObservableStore()
+
+store.on('add', ({ key, value }) => {
+ console.log(`Added: ${key} = ${value}`)
+})
+
+store.on('update', ({ key, oldValue, newValue }) => {
+ console.log(`Updated: ${key} from ${oldValue} to ${newValue}`)
+})
+
+store.on('change:user', ({ newValue }) => {
+ console.log(`User changed to: ${newValue}`)
+})
+
+store.set('user', 'alice') // Triggers 'add' and 'change'
+store.set('user', 'bob') // Triggers 'update' and 'change:user'
+store.set('role', 'admin') // Triggers 'add'
+```
+
+### Example 2: Job Queue
+
+```js
+const EventEmitter = require('bare-events')
+
+class JobQueue extends EventEmitter {
+ constructor(concurrency = 3) {
+ super()
+ this.concurrency = concurrency
+ this.queue = []
+ this.running = new Set()
+ this.processed = 0
+ this.failed = 0
+ this.lastId = 0
+ }
+
+ add(job, priority = 0) {
+ const jobWrapper = {
+ id: ++this.lastId,
+ job,
+ priority,
+ added: Date.now()
+ }
+
+ // Insert by priority (higher first)
+ const index = this.queue.findIndex(j => j.priority < priority)
+ if (index === -1) {
+ this.queue.push(jobWrapper)
+ } else {
+ this.queue.splice(index, 0, jobWrapper)
+ }
+
+ this.emit('job:added', jobWrapper)
+ this.process()
+
+ return jobWrapper.id
+ }
+
+ async process() {
+ if (this.running.size >= this.concurrency || this.queue.length === 0) {
+ return
+ }
+
+ const jobWrapper = this.queue.shift()
+ this.running.add(jobWrapper.id)
+
+ this.emit('job:started', jobWrapper)
+
+ try {
+ const result = await Promise.resolve(jobWrapper.job())
+ this.processed++
+ this.emit('job:completed', jobWrapper, result)
+ } catch (err) {
+ this.failed++
+ this.emit('job:failed', jobWrapper, err)
+ } finally {
+ this.running.delete(jobWrapper.id)
+ this.process()
+ }
+
+ if (this.queue.length === 0 && this.running.size === 0) {
+ this.emit('drain')
+ }
+ }
+
+ get stats() {
+ return {
+ pending: this.queue.length,
+ running: this.running.size,
+ processed: this.processed,
+ failed: this.failed
+ }
+ }
+
+ clear() {
+ this.queue = []
+ this.emit('cleared')
+ }
+}
+
+// Usage
+const queue = new JobQueue(2)
+
+queue.on('job:added', (job) => {
+ console.log(`Job ${job.id} added with priority ${job.priority}`)
+})
+
+queue.on('job:completed', (job, result) => {
+ console.log(`Job ${job.id} completed:`, result)
+})
+
+queue.on('drain', () => {
+ console.log('All jobs completed!')
+})
+
+// Add some jobs
+queue.add(() => Promise.resolve('data-1'), 5)
+queue.add(() => Promise.resolve('data-2'), 1)
+queue.add(() => Promise.resolve('data-3'), 10)
+```
+
+### Example 3: Connection Manager
+
+```js
+const EventEmitter = require('bare-events')
+
+class ConnectionManager extends EventEmitter {
+ constructor(options = {}) {
+ super()
+ this.connections = new Map()
+ this.maxConnections = options.maxConnections || 100
+ this.reconnectDelay = options.reconnectDelay || 5000
+ this.attempts = new Map()
+ }
+
+ add(id, connection) {
+ if (this.connections.size >= this.maxConnections) {
+ this.emit('error', new Error('Max connections reached'))
+ return false
+ }
+
+ this.connections.set(id, connection)
+ this.attempts.set(id, 0)
+
+ connection.on('close', () => {
+ this.handleDisconnect(id)
+ })
+
+ connection.on('error', (err) => {
+ this.emit('connection:error', id, err)
+ })
+
+ this.emit('connection', id, connection)
+ return true
+ }
+
+ remove(id) {
+ const connection = this.connections.get(id)
+ if (connection) {
+ connection.close()
+ this.connections.delete(id)
+ this.attempts.delete(id)
+ this.emit('disconnection', id)
+ return true
+ }
+ return false
+ }
+
+ handleDisconnect(id) {
+ this.connections.delete(id)
+ this.emit('disconnection', id)
+
+ const attempts = this.attempts.get(id) || 0
+ if (attempts < 3) {
+ this.attempts.set(id, attempts + 1)
+ this.emit('reconnecting', id, attempts + 1)
+
+ setTimeout(() => {
+ this.emit('reconnect', id)
+ }, this.reconnectDelay * (attempts + 1))
+ } else {
+ this.attempts.delete(id)
+ this.emit('reconnect:failed', id)
+ }
+ }
+
+ broadcast(event, data) {
+ for (const [id, connection] of this.connections) {
+ try {
+ connection.send(event, data)
+ } catch (err) {
+ this.emit('broadcast:error', id, err)
+ }
+ }
+ }
+
+ get(id) {
+ return this.connections.get(id)
+ }
+
+ has(id) {
+ return this.connections.has(id)
+ }
+
+ get count() {
+ return this.connections.size
+ }
+
+ get ids() {
+ return Array.from(this.connections.keys())
+ }
+
+ closeAll() {
+ for (const [id, connection] of this.connections) {
+ connection.close()
+ }
+ this.connections.clear()
+ this.attempts.clear()
+ this.emit('close:all')
+ }
+}
+
+// Usage
+const manager = new ConnectionManager({ maxConnections: 50 })
+
+manager.on('connection', (id, conn) => {
+ console.log(`Client ${id} connected`)
+})
+
+manager.on('disconnection', (id) => {
+ console.log(`Client ${id} disconnected`)
+})
+
+manager.on('reconnecting', (id, attempt) => {
+ console.log(`Reconnecting ${id}, attempt ${attempt}`)
+})
+```
+
+## Best Practices
+
+### Memory Management
+
+```js
+const EventEmitter = require('bare-events')
+
+class SafeEmitter extends EventEmitter {
+ constructor() {
+ super()
+ // Limit listeners to prevent memory leaks
+ this.setMaxListeners(20)
+ }
+
+ dispose() {
+ // Always clean up listeners
+ this.removeAllListeners()
+ }
+}
+
+// Usage with cleanup
+const emitter = new SafeEmitter()
+
+function onData(data) {
+ console.log(data)
+}
+
+emitter.on('data', onData)
+
+// Later, when done
+emitter.off('data', onData)
+// Or
+emitter.dispose()
+```
+
+### Error Handling
+
+```js
+const EventEmitter = require('bare-events')
+
+const emitter = new EventEmitter()
+
+// Always handle error events
+emitter.on('error', (err) => {
+ console.error('Emitter error:', err)
+})
+
+// Or use captureRejections
+const safeEmitter = new EventEmitter({ captureRejections: true })
+
+safeEmitter.on('async', async (data) => {
+ // If this throws, it will emit 'error'
+ await processAsync(data)
+})
+```
+
+### Event Naming
+
+```js
+const EventEmitter = require('bare-events')
+
+class GoodNaming extends EventEmitter {
+ // Use namespacing for related events
+ start() {
+ this.emit('process:start')
+ // ... do work
+ this.emit('process:progress', 50)
+ // ... more work
+ this.emit('process:complete')
+ }
+
+ // Use past tense for completed actions
+ save(data) {
+ this.emit('saving', data) // About to save
+ // ... save
+ this.emit('saved', data) // Saved successfully
+ }
+}
+```
+
+## Integration with Other Modules
+
+### With bare-stream
+
+```js
+const EventEmitter = require('bare-events')
+const { Readable } = require('bare-stream')
+
+class EventStream extends Readable {
+ constructor(emitter, event) {
+ super()
+ this.emitter = emitter
+ this.event = event
+
+ emitter.on(event, (data) => {
+ this.push(data)
+ })
+
+ emitter.once('end', () => {
+ this.push(null)
+ })
+ }
+
+ _read() {
+ // Data pushed from event handler
+ }
+}
+```
+
+### With AbortSignal
+
+```js
+const EventEmitter = require('bare-events')
+const AbortController = require('bare-abort-controller')
+
+const controller = new AbortController()
+const signal = controller.signal
+
+const emitter = new EventEmitter()
+
+// Listen until aborted
+emitter.on('data', handler)
+
+signal.addEventListener('abort', () => {
+ emitter.off('data', handler)
+})
+
+// Later
+controller.abort()
+```
+
+## License
+
+Apache-2.0
+
+---
+**Module Type**: Runtime/Standard | **Ecosystem Role**: Core API | **Dependencies**: None
diff --git a/modules/bare-fetch.md b/modules/bare-fetch.md
new file mode 100644
index 0000000..d174467
--- /dev/null
+++ b/modules/bare-fetch.md
@@ -0,0 +1,721 @@
+# bare-fetch - HTTP Client for Bare
+
+## Overview
+
+bare-fetch provides a WHATWG-compliant Fetch API implementation for the Bare runtime. It enables HTTP/HTTPS requests with a modern Promise-based interface, supporting streaming responses, custom headers, and various authentication methods.
+
+### Key Features
+
+- **WHATWG compliant**: Standard fetch() API as in browsers
+- **Promise-based**: Modern async/await support
+- **Streaming**: Access response body as a stream
+- **Flexible**: Custom headers, methods, and body types
+- **Redirects**: Automatic redirect following with tracking
+- **Bare optimized**: Native integration with Bare runtime
+
+### Use Cases
+
+- **API clients**: Communicate with REST and GraphQL APIs
+- **Data fetching**: Download files and resources
+- **Webhooks**: Send and receive HTTP callbacks
+- **Service mesh**: Inter-service communication
+- **Proxying**: Forward requests to other services
+
+## Installation
+
+```bash
+npm install bare-fetch
+```
+
+## Quick Start
+
+### Basic GET Request
+
+```js
+const fetch = require('bare-fetch')
+
+const response = await fetch('https://api.example.com/data')
+const data = await response.json()
+console.log(data)
+```
+
+### POST with JSON Body
+
+```js
+const fetch = require('bare-fetch')
+
+const response = await fetch('https://api.example.com/users', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ name: 'John Doe',
+ email: 'john@example.com'
+ })
+})
+
+const user = await response.json()
+```
+
+### Error Handling
+
+```js
+const fetch = require('bare-fetch')
+
+try {
+ const response = await fetch('https://api.example.com/data')
+
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`)
+ }
+
+ const data = await response.json()
+ console.log(data)
+} catch (err) {
+ console.error('Request failed:', err.message)
+}
+```
+
+## API Reference
+
+### fetch(url[, options])
+
+Perform an HTTP request.
+
+**Parameters:**
+- `url` (string | URL): Request URL
+- `options` (object, optional):
+ - `method` (string): HTTP method (default: 'GET')
+ - `headers` (object | Headers): Request headers
+ - `body` (string | Buffer | Uint8Array | ReadableStream): Request body
+ - `redirect` (string): 'follow', 'error', or 'manual' (default: 'follow')
+
+**Returns:** Promise
+
+### Response Object
+
+#### Properties
+
+- `status` (number): HTTP status code (e.g., 200, 404)
+- `statusText` (string): HTTP status text (e.g., 'OK', 'Not Found')
+- `ok` (boolean): True if status is 200-299
+- `redirected` (boolean): Whether request was redirected
+- `headers` (Headers): Response headers
+- `body` (ReadableStream | null): Response body stream
+- `bodyUsed` (boolean): Whether body has been consumed
+
+#### Methods
+
+##### `response.text()`
+
+Read response as UTF-8 text.
+
+**Returns:** Promise
+
+##### `response.json()`
+
+Parse response as JSON.
+
+**Returns:** Promise