archiver

Use the Archiver library for streaming archive packaging in Node.js. Supports creating ZIP/TAR archives, appending content from streams, strings, buffers, file paths, directories, and glob patterns, as well as registering custom formats.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "archiver" with this command: npx skills add openlark/archiver

Archiver — Streaming Archive Packaging

A Node.js streaming archive library that supports ZIP and TAR, capable of appending content from multiple data sources.

Use Cases

Use when users need to compress and package, create zip/tar archives, package directories, or programmatically generate compressed files.

Trigger Words

Compress, package, archive, zip, tar, archive, archiver.

Installation

npm install archiver

Quick Start: ZIP Packaging

const fs = require('fs');
const archiver = require('archiver');

const output = fs.createWriteStream('output.zip');
const archive = archiver('zip', { zlib: { level: 9 } });

output.on('close', () => {
  console.log(`${archive.pointer()} bytes written`);
});

archive.on('error', (err) => { throw err; });

archive.pipe(output);

// Append — multiple data sources
archive.append(fs.createReadStream('file.txt'), { name: 'file.txt' });  // Stream
archive.append('string content', { name: 'readme.txt' });               // String
archive.append(Buffer.from('data'), { name: 'data.bin' });              // Buffer
archive.file('local-file.txt', { name: 'renamed.txt' });                // Local file
archive.directory('src/', 'src');                                        // Directory → subdirectory in archive
archive.directory('dist/', false);                                       // Directory contents → archive root
archive.glob('*.js', { cwd: __dirname });                                // Glob match

archive.finalize();

Data Source Overview

MethodData Sourcename Parameter
archive.append(stream, { name })ReadStreamRequired
archive.append(string, { name })StringRequired
archive.append(buffer, { name })BufferRequired
archive.file(path, { name })File pathOptional, can rename
archive.directory(path, dest)Directoryfalse = contents to root; string = subdirectory name
archive.glob(pattern, { cwd })Glob matchAuto-uses matched filenames

TAR Packaging

const archive = archiver('tar', {
  gzip: true,
  gzipOptions: { level: 6 }
});

TAR-specific options:

OptionDescriptionDefault
gzipEnable gzip compressionfalse
gzipOptions.levelCompression level 0-96

Events

archive.on('warning', (err) => {
  if (err.code === 'ENOENT') console.warn('File not found:', err);
  else throw err;
});

archive.on('error', (err) => { throw err; });

// Events on the piped destination stream (from Node.js Stream API)
output.on('close', () => { /* File descriptor closed */ });
output.on('end', () => { /* Data drained */ });
output.on('finish', () => { /* All data written */ });
  • warning — Non-fatal errors (e.g., file not found, stat failure, etc.); ENOENT can be ignored, others should be thrown
  • error — Fatal errors; must be handled
  • close (output) — Emitted after the file descriptor is closed; archive.pointer() can be used to get the total byte count at this point
  • end (output) — Data drained; emitted regardless of the data source
  • progress — Progress tracking, see below

Progress Tracking

archive.on('progress', (progress) => {
  console.log(`${progress.entries.processed} / ${progress.entries.total} entries`);
  console.log(`${progress.fs.processedBytes} / ${progress.fs.totalBytes} bytes`);
});

progress object structure:

{
  entries: { total: number, processed: number },
  fs: { totalBytes: number, processedBytes: number }
}

Common Patterns

Pattern 1: Responsive Archiving — HTTP Streaming Output

app.get('/download', (req, res) => {
  res.attachment('archive.zip');
  const archive = archiver('zip', { zlib: { level: 1 } }); // Low compression = faster

  archive.on('error', (err) => { res.status(500).end(); });

  archive.pipe(res);
  archive.directory('user-files/', false);
  archive.finalize();
});

Pattern 2: Conditional Append — On-Demand Packaging

const archive = archiver('zip');

// Dynamically append based on conditions
if (includeSource) {
  archive.directory('src/', 'source');
}
if (includeDocs) {
  archive.glob('docs/**/*.md', { cwd: __dirname });
}

archive.finalize();

Pattern 3: In-Memory Archiving — No File Output

const { Writable } = require('stream');

const chunks = [];
const memoryStream = new Writable({
  write(chunk, enc, cb) { chunks.push(chunk); cb(); }
});

const archive = archiver('zip');
archive.pipe(memoryStream);

archive.append('hello', { name: 'hello.txt' });
archive.finalize();

memoryStream.on('finish', () => {
  const buffer = Buffer.concat(chunks);
  console.log(`Archive in memory: ${buffer.length} bytes`);
  // Can be used for uploading, sending, etc.
});

Pattern 4: Batch Packaging — Multiple Archives in Series

async function createBatchedArchives(fileGroups, outputDir) {
  for (const [i, files] of fileGroups.entries()) {
    await new Promise((resolve, reject) => {
      const output = fs.createWriteStream(`${outputDir}/batch-${i}.zip`);
      const archive = archiver('zip');

      archive.on('error', reject);
      output.on('close', resolve);

      archive.pipe(output);
      files.forEach(f => archive.file(f, { name: path.basename(f) }));
      archive.finalize();
    });
    console.log(`Batch ${i} complete`);
  }
}

Custom Format Registration

archiver.registerFormat('myformat', module);
const archive = archiver('myformat');

Check if a format is registered:

if (archiver.isRegisteredFormat('zip')) {
  // ZIP is available
}

Symlink Handling

archive.symlink('target', { name: 'link-name' });

Common Options Reference — archiver(format, options)

const archive = archiver('zip', {
  zlib: { level: 9 },          // Compression level 0-9
  comment: 'my comment',       // ZIP comment
  forceLocalTime: true,        // Use local time instead of UTC
  forceZip64: false,           // Whether to force Zip64
  namePrependSlash: false,     // Prepend / to filenames
  statConcurrency: 4           // Stat concurrency
});

For the full API reference, see references/api-reference.md.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Publish Ascii Excalidraw

Convert ASCII art diagrams to hand-drawn Excalidraw JSON files. Analyzes structure first, then generates incrementally module-by-module.

Registry SourceRecently Updated
General

Clawhub Publish

融资诊断、资本情商指导、进度指引的AI融资顾问。用于评估融资准备度、提升Capital EQ、跟踪进度。当用户说'我要融资''看看准备好了吗'时调用。触发:融资、诊断、资本情商、Capital EQ、进度、TS、条款。

Registry SourceRecently Updated
General

Lvmh Louis Vuitton

Louis Vuitton, LVMH’s flagship brand, excels in luxury leather goods with over €22B revenue, strict distribution control, iconic monogram, and creative colla...

Registry SourceRecently Updated
General

La Quinta

美国中档连锁酒店品牌,提供免费早餐和宠物友好服务,属于温德姆酒店集团,覆盖约900家门店。

Registry SourceRecently Updated