{"id":51122468,"url":"https://github.com/myrialabs/zipkit","last_synced_at":"2026-06-25T04:00:36.413Z","repository":{"id":366095878,"uuid":"1273941395","full_name":"myrialabs/zipkit","owner":"myrialabs","description":"Overkill compression for Node, Bun \u0026 the browser with a typed API and CLI over a single Wasm engine","archived":false,"fork":false,"pushed_at":"2026-06-20T07:53:13.000Z","size":654,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-20T09:14:37.758Z","etag":null,"topics":["brotli","browser","bun","bzip2","compression","deflate","gzip","lz4","lzma","nodejs","snappy","typescript","wasm","zip","zstd"],"latest_commit_sha":null,"homepage":"https://zipkit.myrialabs.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/myrialabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-19T03:07:11.000Z","updated_at":"2026-06-20T07:53:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/myrialabs/zipkit","commit_stats":null,"previous_names":["myrialabs/zipkit"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/myrialabs/zipkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/myrialabs%2Fzipkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/myrialabs%2Fzipkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/myrialabs%2Fzipkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/myrialabs%2Fzipkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/myrialabs","download_url":"https://codeload.github.com/myrialabs/zipkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/myrialabs%2Fzipkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34758776,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-25T02:00:05.521Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["brotli","browser","bun","bzip2","compression","deflate","gzip","lz4","lzma","nodejs","snappy","typescript","wasm","zip","zstd"],"created_at":"2026-06-25T04:00:35.083Z","updated_at":"2026-06-25T04:00:36.405Z","avatar_url":"https://github.com/myrialabs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://zipkit.myrialabs.dev/favicon.svg\" alt=\"ZipKit\" width=\"72\" height=\"72\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eZipKit\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eOverkill compression for Node, Bun \u0026amp; the browser.\u003c/strong\u003e\u003cbr /\u003e\n  gzip · deflate · zlib · zstd · lz4 · snappy · brotli · lzma · bzip2 · ZIP —\n  one tiny, typed API over a single Wasm engine.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://demo.zipkit.myrialabs.dev/\"\u003eDemo\u003c/a\u003e ·\n  \u003ca href=\"https://zipkit.myrialabs.dev/\"\u003eWebsite\u003c/a\u003e ·\n  \u003ca href=\"https://www.npmjs.com/package/zipkit\"\u003enpm\u003c/a\u003e ·\n  \u003ca href=\"./docs/api.md\"\u003eAPI reference\u003c/a\u003e ·\n  \u003ca href=\"./docs/cli.md\"\u003eCLI reference\u003c/a\u003e ·\n  \u003ca href=\"./examples/README.md\"\u003eExamples\u003c/a\u003e ·\n  \u003ca href=\"https://github.com/myrialabs/zipkit/issues\"\u003eIssues\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/zipkit\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/zipkit\" alt=\"npm version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-blue.svg\" alt=\"License: MIT\" /\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/runtime-Node%2018%2B%20%7C%20Bun%20%7C%20Browser-black\" alt=\"Node 18+, Bun and Browser\" /\u003e\n\u003c/p\u003e\n\n---\n\nZipKit compiles best-in-class C compression libraries (libdeflate, zstd, lz4,\nbrotli, snappy, LZMA, bzip2) into one WebAssembly engine, then wraps them in a\nsmall TypeScript API. The default path is adaptive: native speed where the runtime\nwins, the portable engine where it wins, and libdeflate density when ratio matters.\n\n```ts\nimport { gzip, gunzip, zstd, unzstd, zip, unzip, compress, decompress } from 'zipkit';\n\nconst gz = await gzip(bytes);              // balanced default\nconst back = await gunzip(gz);\n\nconst fast = await zstd(bytes, { mode: 'speed' });\nconst exact = await unzstd(fast);\n\nconst archive = await zip([{ name: 'data.bin', data: bytes }]);\nconst files = await unzip(archive);\n\nconst small = await compress(bytes, 'zstd', { mode: 'ratio' });\nconst orig = await decompress(small);      // auto-detects the format\n```\n\n```sh\nzipkit compress data.json --codec zstd     # CLI\nzipkit zip site.zip index.html app.js --method zstd\n```\n\n## Why ZipKit\n\n- **One simple API, every codec** — named imports (`gzip`, `zstd`, `zip`) when you\n  know what you want, or `compress()` / `decompress()` for generic dispatch.\n- **One clear option** — `mode: 'speed' | 'balanced' | 'ratio'`. No tuning maze;\n  `level` is still available when you need exact control.\n- **Adaptive performance** — ZipKit chooses native Bun zlib/zstd where it wins,\n  the Wasm engine where it wins, and libdeflate for density.\n- **Denser gzip when you ask for ratio** — `mode: 'ratio'` uses libdeflate for\n  gzip/deflate/zlib and beats runtime zlib output size on every benchmark dataset.\n- **Runs everywhere** — Node 18+, Bun, and the browser, from the same import. No\n  Bun required; native APIs are accelerators only when present.\n- **More than fflate** — feature parity with fflate plus zstd/brotli/lzma/bzip2,\n  ZIP-with-zstd, native `TransformStream`s, and lossless image (QOI) and video\n  (frame-delta) codecs.\n- **Typed \u0026 documented** — TypeScript-first, JSDoc on every export, tree-shakeable\n  named imports, `sideEffects: false`.\n\n## Install\n\n```sh\nbun add zipkit          # or: npm i zipkit / pnpm add zipkit\nbun add -g zipkit       # CLI\n```\n\n## Quick start\n\n| Task | API |\n| --- | --- |\n| Compress | `await zstd(bytes)` |\n| Decompress | `await unzstd(bytes)` |\n| Generic + auto-detect | `await compress(bytes, 'gzip')` · `await decompress(bytes)` |\n| Just the smallest | `await pack(bytes)` · `await unpack(packed)` |\n| Prefer speed | `await gzip(bytes, { mode: 'speed' })` |\n| Prefer ratio | `await zstd(bytes, { mode: 'ratio' })` |\n| ZIP archive | `await zip([{ name, data }])` · `await unzip(archive)` |\n| Stream | `readable.pipeThrough(compressionStream('gzip'))` |\n\n\u003e **Auto-detect scope.** `decompress()` recognizes only the self-describing\n\u003e formats — **gzip, zlib, zstd** (and it flags ZIP archives, pointing you to\n\u003e `unzip`). For headerless or ZipKit-framed codecs (brotli, snappy, lz4, lzma,\n\u003e bzip2) name the codec: `decompressWith(bytes, 'brotli')`.\n\n### The two API styles\n\n**Named functions** (async, tree-shakeable) — the default. Each lazily loads the\nshared engine the first time it's called.\n\n```ts\nimport { brotli, unbrotli } from 'zipkit';\nconst c = await brotli(bytes, { mode: 'ratio' });\n```\n\n**The `ZipKit` class** (synchronous) — load the engine once, then call\nsynchronously. It accepts the same `mode` option as the async helpers while still\nsupporting the old numeric level argument (`zk.gzip(bytes, 6)`).\n\n```ts\nimport { ZipKit } from 'zipkit';\nconst zk = await ZipKit.load();\nconst gz = zk.gzip(bytes, { mode: 'speed' }); // sync\nconst smallest = zk.pack(bytes); // tries brotli/lzma/bzip2/zstd-max, keeps the smallest\n```\n\n## Performance\n\nBun 1.3.14, every codec against its best competitor. Reproduce with\n`bun run bench.ts`; the full tables (three datasets + parallel + ZIP archive vs\nJSZip/fflate) live in [bench-results.md](./bench-results.md). All roundtrips are\nbyte-identical.\n\nRepresentative — **E-commerce API**, ~97 KB JSON (throughput, higher is faster):\n\n| Codec | Implementation | Ratio | Compress | Decompress |\n|-------|----------------|------:|---------:|-----------:|\n| **gzip** | | | | |\n| | ZipKit | 5.1% | 391 MB/s | 2.4 GB/s |\n| | ZipKit (ratio) | 4.9% | 51 MB/s | 2.4 GB/s |\n| | fflate | 5.9% | 54 MB/s | 121 MB/s |\n| | Bun.gzipSync | 5.1% | 395 MB/s | 2.6 GB/s |\n| **deflate** | | | | |\n| | ZipKit | 5.1% | 409 MB/s | 2.5 GB/s |\n| | ZipKit (ratio) | 4.9% | 53 MB/s | 2.5 GB/s |\n| | fflate | 5.9% | 66 MB/s | 118 MB/s |\n| | Bun.deflateSync | 5.1% | 408 MB/s | 2.9 GB/s |\n| **zlib** | | | | |\n| | ZipKit | 6.0% | 262 MB/s | 1.2 GB/s |\n| | ZipKit (ratio) | 4.9% | 53 MB/s | 2.0 GB/s |\n| | fflate | 5.9% | 67 MB/s | 117 MB/s |\n| **zstd** | | | | |\n| | ZipKit | 5.6% | 1.6 GB/s | 3.5 GB/s |\n| | ZipKit (ratio) | 3.9% | 2 MB/s | 4.7 GB/s |\n| | zstd-wasm | 5.6% | 354 MB/s | 970 MB/s |\n| | Bun.zstdCompressSync | 5.6% | 1.9 GB/s | 3.5 GB/s |\n| **lz4** | | | | |\n| | ZipKit | 12.9% | 1022 MB/s | 2.1 GB/s |\n| | lz4js | 12.5% | 402 MB/s | 492 MB/s |\n| **snappy** | | | | |\n| | ZipKit | 13.5% | 575 MB/s | 1.5 GB/s |\n| | snappyjs | 13.5% | 357 MB/s | 440 MB/s |\n| **brotli** | | | | |\n| | ZipKit | 4.1% | 108 MB/s | 969 MB/s |\n| | ZipKit (ratio) | 3.4% | 613.1 KB/s | 1.8 GB/s |\n| | brotli-wasm | 4.1% | 43 MB/s | 600 MB/s |\n| **lzma** | | | | |\n| | ZipKit | 3.8% | 18 MB/s | 395 MB/s |\n| **bzip2** | | | | |\n| | ZipKit | 3.4% | 17 MB/s | 83 MB/s |\n\nWhat the full run adds beyond this table:\n\n- **Against portable JS** (fflate, pako, zstd-wasm, brotli-wasm), ZipKit\n  compresses several× faster at an equal-or-better ratio across all datasets.\n- **`mode: 'ratio'`** trades speed for size: libdeflate gzip/deflate is denser\n  than native zlib, and brotli/lzma/bzip2 reach the smallest output (~3.3–3.8% on JSON).\n- **Parallel** (8 cores, 34 MB logs) is the multi-core path native libs lack:\n  `compressParallel` gzip runs **5.1× faster** than `Bun.gzipSync`, same output size.\n- **ZIP archives** fan entry compression across the pool: a 20-file, 8 MB archive\n  packs **8.5× faster** than `fflate` and **7.5× faster** than JSZip, 10% smaller.\n\n## Streaming\n\nWeb-standard `TransformStream`s for every codec. gzip / zlib / deflate are backed by\nthe platform's native `CompressionStream` (true incremental streaming); the rest\nbuffer and compress on flush.\n\n```ts\nimport { compressionStream } from 'zipkit/streams';\n\nawait fetch(url)\n  .then((r) =\u003e r.body!)\n  .then((body) =\u003e body.pipeThrough(compressionStream('gzip')).pipeTo(dest));\n```\n\n## ZIP archives\n\n```ts\nimport { zip, unzip } from 'zipkit';\n\nconst archive = await zip([\n  { name: 'index.html', data: html },\n  { name: 'app.js', data: js, method: 'zstd' },     // denser, ZipKit-aware peers\n  { name: 'logo.png', data: png, method: 'store', unixPermissions: 0o644 }\n]);\n\nconst files = await unzip(archive, { filter: (e) =\u003e e.name.endsWith('.js') });\n```\n\n`store` and `deflate` entries interoperate with every standard ZIP tool; `zstd`\nentries (method 93) are much denser between ZipKit-aware peers. ZIP64 kicks in\nautomatically beyond 4 GB / 65 535 entries.\n\n## HTTP middleware\n\n`Accept-Encoding`-negotiating compression for Elysia, Express, and Hono\n(brotli → zstd → gzip → deflate).\n\n```ts\nimport { Elysia } from 'elysia';\nimport { elysia as compression } from 'zipkit/middleware';\n\nnew Elysia()\n  .onAfterHandle(compression())\n  .get('/', () =\u003e ({ rows: Array.from({ length: 200 }, (_, i) =\u003e ({ i })) }))\n  .listen(3000);\n```\n\n```ts\nimport express from 'express';\nimport { express as compression } from 'zipkit/middleware';\n\nconst app = express();\napp.use(compression());\napp.get('/', (_req, res) =\u003e res.json({ rows: Array.from({ length: 200 }, (_, i) =\u003e ({ i })) }));\napp.listen(3000);\n```\n\n```ts\nimport { Hono } from 'hono';\nimport { hono as compression } from 'zipkit/middleware';\n\nconst app = new Hono();\napp.use('*', compression());\n```\n\n## Browser\n\nThe engine loads its `.wasm` via `import.meta.url`, which Vite, webpack 5, esbuild,\nand Rollup resolve as an asset out of the box. See [docs/browser.md](./docs/browser.md).\n\nThe combined engine is ~1.4 MB of `.wasm` (every codec in one module), loaded\nonce and cached. Keep it off your initial bundle with a dynamic import\n(`const { gzip } = await import('zipkit')`), or skip the engine entirely for\ngzip/zlib/deflate by using [`zipkit/streams`](./docs/streaming.md), which run on\nthe browser's native `CompressionStream`. Per-codec Wasm splitting is on the\nroadmap.\n\n## Documentation\n\n- [API reference](./docs/api.md) — every export, option, and method.\n- [CLI reference](./docs/cli.md) — every command and flag.\n- [Algorithms](./docs/algorithms.md) — which codec to use, with benchmark tables.\n- [Streaming](./docs/streaming.md) · [ZIP](./docs/zip.md) · [Browser](./docs/browser.md)\n- [Examples](./examples/README.md) — runnable scenarios.\n\n## Support\n\nIf ZipKit is useful to you, consider supporting its development:\n\n| Method | Address / Link |\n|--------|----------------|\n| Bitcoin (BTC) | `bc1qd9fyx4r84cce2a9hkjksetah802knadw5msls3` |\n| Solana (SOL) | `Ev3P4KLF1PNC5C9rZYP8M3DdssyBQAQAiNJkvNmPQPVs` |\n| Ethereum (ERC-20) | `0x61D826e5b666AA5345302EEEd485Acca39b1AFCF` |\n| USDT (TRC-20) | `TLH49i3EoVKhFyLb6u2JUXZWScK7uzksdC` |\n| Saweria | [saweria.co/myrialabs](https://saweria.co/myrialabs) |\n\n## License\n\nMIT — see [LICENSE](LICENSE). Bundles several open-source C libraries; see\n[their licenses](./docs/algorithms.md#third-party-licenses).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmyrialabs%2Fzipkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmyrialabs%2Fzipkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmyrialabs%2Fzipkit/lists"}