Generated banner for Transformers JS
Generated logo for Transformers JS

Transformers JS

Hugging FaceOfficialCreated by huggingfaceDistributed by Hugging Face

  • Skill
  • Tool integration
  • Data and AI
  • Apache-2.0
  • No issues found

From the author

Use Transformers.js to run state-of-the-art machine learning models directly in JavaScript/TypeScript. Supports NLP (text classification, translation, summarization), computer vision (image classification, object detection), audio (speech recognition, audio classification), and multimodal tasks. Works in browsers and server-side runtimes (Node.js, Bun, Deno) with WebGPU/WASM using pre-trained models from Hugging Face Hub.
— the description by huggingface

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

Transformers.js is a library that enables the execution of machine learning models within JavaScript and TypeScript environments, including web browsers and server-side runtimes like Node.js, Bun, and Deno. It leverages WebGPU and WASM to run models locally, eliminating the need for a dedicated Python backend. The library provides a pipeline API for common tasks such as NLP, computer vision, audio processing, and multimodal applications, with support for models hosted on the Hugging Face Hub.

What it does

  • Provides a pipeline API for common machine learning tasks
  • Supports NLP, computer vision, audio, and multimodal model execution
  • Enables local model inference in browsers and server-side runtimes
  • Integrates with the Hugging Face Hub for model discovery and loading
  • Offers configuration for caching, quantization, and device selection
  • Includes tools for standalone tokenization and tensor manipulation

When to use it

  • When you need to run ML models client-side in a browser
  • When you want to avoid maintaining a separate Python backend for ML
  • When building applications in Node.js, Bun, or Deno that require AI capabilities
  • When you need to perform text, image, or audio analysis locally

Advantages

  • Runs directly in JavaScript/TypeScript environments
  • Supports both browser and server-side execution
  • Reduces infrastructure requirements by removing the need for a Python server
  • Provides flexible caching options for different environments
  • Allows for model quantization to manage memory and storage

Usage examples

“How do I run a sentiment analysis model in my browser?”
Use the pipeline API: const pipe = await pipeline('sentiment-analysis'); const result = await pipe('I love transformers!');
“How can I load a specific model from Hugging Face?”
Pass the model ID as the second argument to the pipeline: const pipe = await pipeline('sentiment-analysis', 'Xenova/bert-base-multilingual-uncased-sentiment');
“How do I enable GPU acceleration for my model?”
Set the device option in the pipeline: const pipe = await pipeline('task', 'model-id', { device: 'webgpu' });
“How do I free up memory after using a model?”
Call the dispose method on the pipeline instance: await pipe.dispose();

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/huggingface/transformers-js/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip transformers-js.zip -d .agents/skills

Documentation by huggingface

Transformers.js - Machine Learning for JavaScript

Transformers.js enables running state-of-the-art machine learning models directly in JavaScript across browsers and server-side runtimes (Node.js, Bun, Deno), with no Python server required.

When to Use This Skill

Use this skill when you need to:

  • Run ML models for text analysis, generation, or translation in JavaScript

  • Perform image classification, object detection, or segmentation

  • Implement speech recognition or audio processing

  • Build multimodal AI applications (text-to-image, image-to-text, etc.)

  • Run models client-side in the browser without a backend

Installation

NPM Installation
npm install @huggingface/transformers
Browser Usage (CDN)
<script type="module">
  import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers';
</script>

Core Concepts

1. Pipeline API

The pipeline API is the easiest way to use models. It groups together preprocessing, model inference, and postprocessing:

import { pipeline } from '@huggingface/transformers';

// Create a pipeline for a specific task
const pipe = await pipeline('sentiment-analysis');

// Use the pipeline
const result = await pipe('I love transformers!');
// Output: [{ label: 'POSITIVE', score: 0.999817686 }]

// IMPORTANT: Always dispose when done to free memory
await pipe.dispose();

⚠️ Memory Management: All pipelines must be disposed with pipe.dispose() when finished to prevent memory leaks. See examples in Code Examples for cleanup patterns across different environments.

2. Model Selection

You can specify a custom model as the second argument:

const pipe = await pipeline(
  'sentiment-analysis',
  'Xenova/bert-base-multilingual-uncased-sentiment'
);

Finding Models:

Browse available Transformers.js models on Hugging Face Hub:

Tip: Filter by task type, sort by trending/downloads, and check model cards for performance metrics and usage examples.

3. Device Selection

Choose where to run the model:

// Run on CPU (default for WASM)
const pipe = await pipeline('sentiment-analysis', 'model-id');

// Run on GPU (WebGPU)
const pipe = await pipeline('sentiment-analysis', 'model-id', {
  device: 'webgpu',
});
4. Quantization Options

Control model precision vs. performance:

// Use quantized model (faster, smaller)
const pipe = await pipeline('sentiment-analysis', 'model-id', {
  dtype: 'q4',  // Options: 'fp32', 'fp16', 'q8', 'q4'
});

Supported Tasks

Note: All examples below show basic usage.

Natural Language Processing
Text Classification
const classifier = await pipeline('text-classification');
const result = await classifier('This movie was amazing!');
Named Entity Recognition (NER)
const ner = await pipeline('token-classification');
const entities = await ner('My name is John and I live in New York.');
Question Answering
const qa = await pipeline('question-answering');
const answer = await qa({
  question: 'What is the capital of France?',
  context: 'Paris is the capital and largest city of France.'
});
Text Generation
const generator = await pipeline('text-generation', 'onnx-community/gemma-3-270m-it-ONNX');
const text = await generator('Once upon a time', {
  max_new_tokens: 100,
  temperature: 0.7
});

For streaming and chat: See Text Generation Guide for:

  • Streaming token-by-token output with TextStreamer

  • Chat/conversation format with system/user/assistant roles

  • Generation parameters (temperature, top_k, top_p)

  • Browser and Node.js examples

  • React components and API endpoints

Translation
const translator = await pipeline('translation', 'Xenova/nllb-200-distilled-600M');
const output = await translator('Hello, how are you?', {
  src_lang: 'eng_Latn',
  tgt_lang: 'fra_Latn'
});
Summarization
const summarizer = await pipeline('summarization');
const summary = await summarizer(longText, {
  max_length: 100,
  min_length: 30
});
Zero-Shot Classification
const classifier = await pipeline('zero-shot-classification');
const result = await classifier('This is a story about sports.', ['politics', 'sports', 'technology']);
Computer Vision
Image Classification
const classifier = await pipeline('image-classification');
const result = await classifier('https://example.com/image.jpg');
// Or with local file
const result = await classifier(imageUrl);
Object Detection
const detector = await pipeline('object-detection');
const objects = await detector('https://example.com/image.jpg');
// Returns: [{ label: 'person', score: 0.95, box: { xmin, ymin, xmax, ymax } }, ...]
Image Segmentation
const segmenter = await pipeline('image-segmentation');
const segments = await segmenter('https://example.com/image.jpg');
Depth Estimation
const depthEstimator = await pipeline('depth-estimation');
const depth = await depthEstimator('https://example.com/image.jpg');
Zero-Shot Image Classification
const classifier = await pipeline('zero-shot-image-classification');
const result = await classifier('image.jpg', ['cat', 'dog', 'bird']);
Audio Processing
Automatic Speech Recognition
const transcriber = await pipeline('automatic-speech-recognition');
const result = await transcriber('audio.wav');
// Returns: { text: 'transcribed text here' }
Audio Classification
const classifier = await pipeline('audio-classification');
const result = await classifier('audio.wav');
Text-to-Speech
const synthesizer = await pipeline('text-to-speech', 'Xenova/speecht5_tts');
const audio = await synthesizer('Hello, this is a test.', {
  speaker_embeddings: speakerEmbeddings
});
Multimodal
Image-to-Text (Image Captioning)
const captioner = await pipeline('image-to-text');
const caption = await captioner('image.jpg');
Document Question Answering
const docQA = await pipeline('document-question-answering');
const answer = await docQA('document-image.jpg', 'What is the total amount?');
Zero-Shot Object Detection
const detector = await pipeline('zero-shot-object-detection');
const objects = await detector('image.jpg', ['person', 'car', 'tree']);
Feature Extraction (Embeddings)
const extractor = await pipeline('feature-extraction');
const embeddings = await extractor('This is a sentence to embed.');
// Returns: tensor of shape [1, sequence_length, hidden_size]

// For sentence embeddings (mean pooling)
const extractor = await pipeline('feature-extraction', 'onnx-community/all-MiniLM-L6-v2-ONNX');
const embeddings = await extractor('Text to embed', { pooling: 'mean', normalize: true });

Finding and Choosing Models

Browsing the Hugging Face Hub

Discover compatible Transformers.js models on Hugging Face Hub:

Base URL (all models):

https://huggingface.co/models?library=transformers.js&sort=trending

Filter by task using the pipeline_tag parameter:

TaskURL
Text Generationhttps://huggingface.co/models?pipeline_tag=text-generation&library=transformers.js&sort=trending
Text Classificationhttps://huggingface.co/models?pipeline_tag=text-classification&library=transformers.js&sort=trending
Translationhttps://huggingface.co/models?pipeline_tag=translation&library=transformers.js&sort=trending
Summarizationhttps://huggingface.co/models?pipeline_tag=summarization&library=transformers.js&sort=trending
Question Answeringhttps://huggingface.co/models?pipeline_tag=question-answering&library=transformers.js&sort=trending
Image Classificationhttps://huggingface.co/models?pipeline_tag=image-classification&library=transformers.js&sort=trending
Object Detectionhttps://huggingface.co/models?pipeline_tag=object-detection&library=transformers.js&sort=trending
Image Segmentationhttps://huggingface.co/models?pipeline_tag=image-segmentation&library=transformers.js&sort=trending
Speech Recognitionhttps://huggingface.co/models?pipeline_tag=automatic-speech-recognition&library=transformers.js&sort=trending
Audio Classificationhttps://huggingface.co/models?pipeline_tag=audio-classification&library=transformers.js&sort=trending
Image-to-Texthttps://huggingface.co/models?pipeline_tag=image-to-text&library=transformers.js&sort=trending
Feature Extractionhttps://huggingface.co/models?pipeline_tag=feature-extraction&library=transformers.js&sort=trending
Zero-Shot Classificationhttps://huggingface.co/models?pipeline_tag=zero-shot-classification&library=transformers.js&sort=trending

Sort options:

  • &sort=trending - Most popular recently

  • &sort=downloads - Most downloaded overall

  • &sort=likes - Most liked by community

  • &sort=modified - Recently updated

Choosing the Right Model

Consider these factors when selecting a model:

1. Model Size

  • Small (< 100MB): Fast, suitable for browsers, limited accuracy

  • Medium (100MB - 500MB): Balanced performance, good for most use cases

  • Large (> 500MB): High accuracy, slower, better for Node.js or powerful devices

2. Quantization Models are often available in different quantization levels:

  • fp32 - Full precision (largest, most accurate)

  • fp16 - Half precision (smaller, still accurate)

  • q8 - 8-bit quantized (much smaller, slight accuracy loss)

  • q4 - 4-bit quantized (smallest, noticeable accuracy loss)

3. Task Compatibility Check the model card for:

  • Supported tasks (some models support multiple tasks)

  • Input/output formats

  • Language support (multilingual vs. English-only)

  • License restrictions

4. Performance Metrics Model cards typically show:

  • Accuracy scores

  • Benchmark results

  • Inference speed

  • Memory requirements

Example: Finding a Text Generation Model
// 1. Visit: https://huggingface.co/models?pipeline_tag=text-generation&library=transformers.js&sort=trending

// 2. Browse and select a model (e.g., onnx-community/gemma-3-270m-it-ONNX)

// 3. Check model card for:
//    - Model size: ~270M parameters
//    - Quantization: q4 available
//    - Language: English
//    - Use case: Instruction-following chat

// 4. Use the model:
import { pipeline } from '@huggingface/transformers';

const generator = await pipeline(
  'text-generation',
  'onnx-community/gemma-3-270m-it-ONNX',
  { dtype: 'q4' } // Use quantized version for faster inference
);

const output = await generator('Explain quantum computing in simple terms.', {
  max_new_tokens: 100
});

await generator.dispose();
Tips for Model Selection
  1. Start Small: Test with a smaller model first, then upgrade if needed

  2. Check ONNX Support: Ensure the model has ONNX files (look for onnx folder in model repo)

  3. Read Model Cards: Model cards contain usage examples, limitations, and benchmarks

  4. Test Locally: Benchmark inference speed and memory usage in your environment

  5. Filter by Library: Use library=transformers.js to find compatible models: https://huggingface.co/models?library=transformers.js

  6. Version Pin: Use specific git commits in production for stability:

    const pipe = await pipeline('task', 'model-id', { revision: 'abc123' });

Advanced Configuration

Environment Configuration (env)

The env object provides comprehensive control over Transformers.js execution, caching, and model loading.

Quick Overview:

import { env, LogLevel } from '@huggingface/transformers';

// View version
console.log(env.version); // e.g., '4.x'

// Common settings
env.allowRemoteModels = true;  // Load from Hugging Face Hub
env.allowLocalModels = false;  // Load from file system
env.localModelPath = '/models/'; // Local model directory
env.useFSCache = true;         // Cache models on disk (Node.js)
env.useBrowserCache = true;    // Cache models in browser
env.cacheDir = './.cache';     // Cache directory location
// Optional: override logging level (default is LogLevel.WARNING)
env.logLevel = LogLevel.INFO;

// Optional: custom fetch for auth headers, retries, abort signals, etc.
env.fetch = (url, options) =>
  fetch(url, {
    ...options,
    headers: {
      ...options?.headers,
      Authorization: `Bearer ${HF_TOKEN}`,
    },
  });

Configuration Patterns:

// Development: Fast iteration with remote models
env.allowRemoteModels = true;
env.useFSCache = true;

// Production: Local models only
env.allowRemoteModels = false;
env.allowLocalModels = true;
env.localModelPath = '/app/models/';

// Custom CDN
env.remoteHost = 'https://cdn.example.com/models';

// Disable caching (testing)
env.useFSCache = false;
env.useBrowserCache = false;

For complete documentation on all configuration options, caching strategies, cache management, pre-downloading models, and more, see:

→ Configuration Reference

ModelRegistry (v4)

ModelRegistry gives you visibility and control over model assets before loading a pipeline. Use it to estimate download size, check cache status, inspect available dtypes, and clear cached artifacts for a specific task/model/options tuple.

import { ModelRegistry } from '@huggingface/transformers';

const task = 'feature-extraction';
const modelId = 'onnx-community/all-MiniLM-L6-v2-ONNX';
const modelOptions = { dtype: 'fp32' };

// List required files for this pipeline
const files = await ModelRegistry.get_pipeline_files(task, modelId, modelOptions);

// Check if assets are already cached
const cached = await ModelRegistry.is_pipeline_cached(task, modelId, modelOptions);

// Inspect precision formats available for this model
const dtypes = await ModelRegistry.get_available_dtypes(modelId);

console.log({ files: files.length, cached, dtypes });

For production patterns and full API coverage, see ModelRegistry Reference.

Standalone Tokenization (@huggingface/tokenizers)

For tokenization-only workflows, use @huggingface/tokenizers. It is a separate lightweight package useful when you need fast tokenization/encoding without loading full model inference pipelines.

npm install @huggingface/tokenizers
import { Tokenizer } from '@huggingface/tokenizers';
Working with Tensors
import { AutoTokenizer, AutoModel } from '@huggingface/transformers';

// Load tokenizer and model separately for more control
const tokenizer = await AutoTokenizer.from_pretrained('bert-base-uncased');
const model = await AutoModel.from_pretrained('bert-base-uncased');

// Tokenize input
const inputs = await tokenizer('Hello world!');

// Run model
const outputs = await model(inputs);
Batch Processing
const classifier = await pipeline('sentiment-analysis');

// Process multiple texts
const results = await classifier([
  'I love this!',
  'This is terrible.',
  'It was okay.'
]);

Runtime-Specific Considerations

WebGPU Usage

WebGPU provides GPU acceleration in browsers and server-side runtimes (when supported):

const pipe = await pipeline('text-generation', 'onnx-community/gemma-3-270m-it-ONNX', {
  device: 'webgpu',
  dtype: 'fp32'
});

Note: Use webgpu when available and fall back to WASM/CPU when not supported in the current runtime.

WASM Performance

WASM is the most compatible execution backend across runtimes:

// Optimized for browsers with quantization
const pipe = await pipeline('sentiment-analysis', 'model-id', {
  dtype: 'q8'  // or 'q4' for even smaller size
});
Progress Tracking & Loading Indicators

Models can be large (ranging from a few MB to several GB) and consist of multiple files. Track download progress by passing a callback to the pipeline() function:

import { pipeline } from '@huggingface/transformers';

// Track progress for each file
const fileProgress = {};

function onProgress(info) {
  if (info.status === 'progress_total') {
    console.log(`Total: ${info.progress.toFixed(1)}%`);
    return;
  }

  console.log(`${info.status}: ${info.file ?? ''}`);
  
  if (info.status === 'progress') {
    fileProgress[info.file] = info.progress;
    console.log(`${info.file}: ${info.progress.toFixed(1)}%`);
  }
  
  if (info.status === 'done') {
    console.log(`✓ ${info.file} complete`);
  }
}

// Pass callback to pipeline
const classifier = await pipeline('sentiment-analysis', null, {
  progress_callback: onProgress
});

Progress Info Properties:

interface ProgressInfo {
  status: 'initiate' | 'download' | 'progress' | 'progress_total' | 'done' | 'ready';
  name: string;      // Model id or path
  file?: string;     // File being processed (per-file events)
  progress?: number; // Percentage (0-100, for 'progress' and 'progress_total')
  loaded?: number;   // Bytes downloaded (only for 'progress' status)
  total?: number;    // Total bytes (only for 'progress' status)
}

For complete examples including browser UIs, React components, CLI progress bars, and retry logic, see:

→ Pipeline Options - Progress Callback

Error Handling

try {
  const pipe = await pipeline('sentiment-analysis', 'model-id');
  const result = await pipe('text to analyze');
} catch (error) {
  if (error.message.includes('fetch')) {
    console.error('Model download failed. Check internet connection.');
  } else if (error.message.includes('ONNX')) {
    console.error('Model execution failed. Check model compatibility.');
  } else {
    console.error('Unknown error:', error);
  }
}

Performance Tips

  1. Reuse Pipelines: Create pipeline once, reuse for multiple inferences

  2. Use Quantization: Start with q8 or q4 for faster inference

  3. Batch Processing: Process multiple inputs together when possible

  4. Cache Models: Models are cached automatically (see Caching Reference for details on browser Cache API, Node.js filesystem cache, and custom implementations)

  5. WebGPU for Large Models: Use WebGPU for models that benefit from GPU acceleration

  6. Prune Context: For text generation, limit max_new_tokens to avoid memory issues

  7. Clean Up Resources: Call pipe.dispose() when done to free memory

Memory Management

IMPORTANT: Always call pipe.dispose() when finished to prevent memory leaks.

const pipe = await pipeline('sentiment-analysis');
const result = await pipe('Great product!');
await pipe.dispose();  // ✓ Free memory (100MB - several GB per model)

When to dispose:

  • Application shutdown or component unmount

  • Before loading a different model

  • After batch processing in long-running apps

Models consume significant memory and hold GPU/CPU resources. Disposal is critical for browser memory limits and server stability.

For detailed patterns (React cleanup, servers, browser), see Code Examples

Troubleshooting

Model Not Found
  • Verify model exists on Hugging Face Hub

  • Check model name spelling

  • Ensure model has ONNX files (look for onnx folder in model repo)

Memory Issues
  • Use smaller models or quantized versions (dtype: 'q4')

  • Reduce batch size

  • Limit sequence length with max_length

WebGPU Errors
  • Check browser compatibility (Chrome 113+, Edge 113+)

  • Try dtype: 'fp16' if fp32 fails

  • Fall back to WASM if WebGPU unavailable

Reference Documentation

This Skill
Official Transformers.js

Best Practices

  1. Always Dispose Pipelines: Call pipe.dispose() when done - critical for preventing memory leaks

  2. Start with Pipelines: Use the pipeline API unless you need fine-grained control

  3. Test Locally First: Test models with small inputs before deploying

  4. Monitor Model Sizes: Be aware of model download sizes for web applications

  5. Handle Loading States: Show progress indicators for better UX

  6. Version Pin: Pin specific model versions for production stability

  7. Error Boundaries: Always wrap pipeline calls in try-catch blocks

  8. Progressive Enhancement: Provide fallbacks for unsupported browsers

  9. Reuse Models: Load once, use many times - don't recreate pipelines unnecessarily

  10. Graceful Shutdown: Dispose models on SIGTERM/SIGINT in servers

Quick Reference: Task IDs

TaskTask ID
Text classificationtext-classification or sentiment-analysis
Token classificationtoken-classification or ner
Question answeringquestion-answering
Fill maskfill-mask
Summarizationsummarization
Translationtranslation
Text generationtext-generation
Text-to-text generationtext2text-generation
Zero-shot classificationzero-shot-classification
Image classificationimage-classification
Image segmentationimage-segmentation
Object detectionobject-detection
Depth estimationdepth-estimation
Image-to-imageimage-to-image
Zero-shot image classificationzero-shot-image-classification
Zero-shot object detectionzero-shot-object-detection
Automatic speech recognitionautomatic-speech-recognition
Audio classificationaudio-classification
Text-to-speechtext-to-speech or text-to-audio
Image-to-textimage-to-text
Document question answeringdocument-question-answering
Feature extractionfeature-extraction
Sentence similaritysentence-similarity

This skill enables you to integrate state-of-the-art machine learning capabilities directly into JavaScript applications without requiring separate ML servers or Python environments.

Files

references/EXAMPLES.md

Transformers.js Code Examples

Working examples showing how to use Transformers.js across different runtimes and frameworks.

All examples use the same task and model for consistency:

  • Task: feature-extraction

  • Model: onnx-community/all-MiniLM-L6-v2-ONNX

Table of Contents

  1. Browser (Vanilla JS)

  2. Node.js

  3. React

  4. Express API

Browser (Vanilla JS)

Basic Usage
<!DOCTYPE html>
<html>
<head>
  <title>Feature Extraction</title>
</head>
<body>
  <h1>Text Embedding Generator</h1>
  <textarea id="input" placeholder="Enter text to embed..."></textarea>
  <button onclick="generateEmbedding()">Generate Embedding</button>
  <div id="result"></div>
  <div id="loading" style="display:none;">Loading model...</div>

  <script type="module">
    import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@4';
    
    let extractor;
    
    // Initialize model on page load
    document.getElementById('loading').style.display = 'block';
    extractor = await pipeline(
      'feature-extraction',
      'onnx-community/all-MiniLM-L6-v2-ONNX'
    );
    document.getElementById('loading').style.display = 'none';
    
    window.generateEmbedding = async function() {
      const text = document.getElementById('input').value;
      const output = await extractor(text, { pooling: 'mean', normalize: true });
      
      document.getElementById('result').innerHTML = `
        <h3>Embedding Generated:</h3>
        <p>Dimensions: ${output.data.length}</p>
        <p>First 5 values: ${Array.from(output.data).slice(0, 5).join(', ')}</p>
      `;
    };
    
    // Cleanup on page unload
    window.addEventListener('beforeunload', () => {
      if (extractor) extractor.dispose();
    });
  </script>
</body>
</html>
With Progress Tracking
<!DOCTYPE html>
<html>
<head>
  <title>Feature Extraction with Progress</title>
  <style>
    .file-progress {
      margin: 10px 0;
    }
    .file-name {
      font-size: 12px;
      margin-bottom: 5px;
    }
    .progress-bar {
      width: 100%;
      height: 20px;
      background: #f0f0f0;
      border-radius: 5px;
      overflow: hidden;
    }
    .progress-fill {
      height: 100%;
      background: #4CAF50;
      transition: width 0.3s;
    }
  </style>
</head>
<body>
  <h1>Text Embedding Generator</h1>
  <div id="loading">
    <p id="status">Loading model...</p>
    <div id="progress-container"></div>
  </div>
  <div id="app" style="display:none;">
    <textarea id="input" placeholder="Enter text..."></textarea>
    <button onclick="generateEmbedding()">Generate</button>
    <div id="result"></div>
  </div>

  <script type="module">
    import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@4';
    
    let extractor;
    const fileProgressBars = {};
    const progressContainer = document.getElementById('progress-container');
    
    extractor = await pipeline(
      'feature-extraction',
      'onnx-community/all-MiniLM-L6-v2-ONNX',
      {
        progress_callback: (info) => {
          if (info.status === 'progress_total') {
            document.getElementById('status').textContent = `Total: ${info.progress.toFixed(1)}%`;
            return;
          }

          document.getElementById('status').textContent = `${info.status}: ${info.file ?? ''}`;
          
          if (info.status === 'progress') {
            // Create progress bar for each file
            if (!fileProgressBars[info.file]) {
              const fileDiv = document.createElement('div');
              fileDiv.className = 'file-progress';
              fileDiv.innerHTML = `
                <div class="file-name">${info.file}</div>
                <div class="progress-bar">
                  <div class="progress-fill"></div>
                </div>
              `;
              progressContainer.appendChild(fileDiv);
              fileProgressBars[info.file] = fileDiv.querySelector('.progress-fill');
            }
            
            // Update progress
            fileProgressBars[info.file].style.width = `${info.progress}%`;
          }
          
          if (info.status === 'ready') {
            document.getElementById('loading').style.display = 'none';
            document.getElementById('app').style.display = 'block';
          }
        }
      }
    );
    
    window.generateEmbedding = async function() {
      const text = document.getElementById('input').value;
      const output = await extractor(text, { pooling: 'mean', normalize: true });
      
      document.getElementById('result').innerHTML = `
        <p>Embedding: ${output.data.length} dimensions</p>
      `;
    };
    
    // Cleanup on page unload
    window.addEventListener('beforeunload', () => {
      if (extractor) extractor.dispose();
    });
  </script>
</body>
</html>

Node.js

Basic Script
// embed.js
import { pipeline } from '@huggingface/transformers';

async function generateEmbedding(text) {
  const extractor = await pipeline(
    'feature-extraction',
    'onnx-community/all-MiniLM-L6-v2-ONNX'
  );
  
  const output = await extractor(text, { pooling: 'mean', normalize: true });
  
  console.log('Text:', text);
  console.log('Embedding dimensions:', output.data.length);
  console.log('First 5 values:', Array.from(output.data).slice(0, 5));
  
  await extractor.dispose();
}

generateEmbedding('Hello, world!');
Batch Processing
// batch-embed.js
import { pipeline } from '@huggingface/transformers';
import fs from 'fs/promises';

async function embedDocuments(documents) {
  const extractor = await pipeline(
    'feature-extraction',
    'onnx-community/all-MiniLM-L6-v2-ONNX'
  );
  
  console.log(`Processing ${documents.length} documents...`);
  
  const embeddings = [];
  
  for (let i = 0; i < documents.length; i++) {
    const output = await extractor(documents[i], { 
      pooling: 'mean', 
      normalize: true 
    });
    
    embeddings.push({
      text: documents[i],
      embedding: Array.from(output.data)
    });
    
    console.log(`Processed ${i + 1}/${documents.length}`);
  }
  
  await fs.writeFile(
    'embeddings.json',
    JSON.stringify(embeddings, null, 2)
  );
  
  console.log('Saved to embeddings.json');
  
  await extractor.dispose();
}

const documents = [
  'The cat sat on the mat',
  'A dog played in the park',
  'Machine learning is fascinating'
];

embedDocuments(documents);
CLI with Progress
// cli-embed.js
import { pipeline } from '@huggingface/transformers';

async function main() {
  const text = process.argv[2] || 'Hello, world!';
  
  console.log('Loading model...');
  
  const fileProgress = {};
  
  const extractor = await pipeline(
    'feature-extraction',
    'onnx-community/all-MiniLM-L6-v2-ONNX',
    {
      progress_callback: (info) => {
        if (info.status === 'progress_total') {
          process.stdout.write(`\r\x1b[KTotal: ${info.progress.toFixed(1)}%`);
          return;
        }

        if (info.status === 'progress') {
          fileProgress[info.file] = info.progress;
          
          // Show all files progress
          const progressLines = Object.entries(fileProgress)
            .map(([file, progress]) => `  ${file}: ${progress.toFixed(1)}%`)
            .join('\n');
          
          process.stdout.write(`\r\x1b[K${progressLines}`);
        }
        
        if (info.status === 'done') {
          console.log(`\n✓ ${info.file} complete`);
        }
        
        if (info.status === 'ready') {
          console.log('\nModel ready!');
        }
      }
    }
  );
  
  console.log('Generating embedding...');
  const output = await extractor(text, { pooling: 'mean', normalize: true });
  
  console.log(`\nText: "${text}"`);
  console.log(`Dimensions: ${output.data.length}`);
  console.log(`First 5 values: ${Array.from(output.data).slice(0, 5).join(', ')}`);
  
  await extractor.dispose();
}

main();

React

Basic Component
// EmbeddingGenerator.jsx
import { useState, useRef, useEffect } from 'react';
import { pipeline } from '@huggingface/transformers';

export function EmbeddingGenerator() {
  const extractorRef = useRef(null);
  const [text, setText] = useState('');
  const [embedding, setEmbedding] = useState(null);
  const [loading, setLoading] = useState(false);

  const generate = async () => {
    if (!text) return;
    
    setLoading(true);
    
    // Load model on first generate
    if (!extractorRef.current) {
      extractorRef.current = await pipeline(
        'feature-extraction',
        'onnx-community/all-MiniLM-L6-v2-ONNX'
      );
    }
    
    const output = await extractorRef.current(text, { 
      pooling: 'mean', 
      normalize: true 
    });
    setEmbedding(Array.from(output.data));
    setLoading(false);
  };

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (extractorRef.current) {
        extractorRef.current.dispose();
      }
    };
  }, []);

  return (
    <div>
      <h2>Text Embedding Generator</h2>
      
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Enter text"
        disabled={loading}
      />
      
      <button onClick={generate} disabled={loading || !text}>
        {loading ? 'Processing...' : 'Generate Embedding'}
      </button>
      
      {embedding && (
        <div>
          <h3>Result:</h3>
          <p>Dimensions: {embedding.length}</p>
          <p>First 5 values: {embedding.slice(0, 5).join(', ')}</p>
        </div>
      )}
    </div>
  );
}
With Progress Tracking
// EmbeddingGeneratorWithProgress.jsx
import { useState, useRef, useEffect } from 'react';
import { pipeline } from '@huggingface/transformers';

export function EmbeddingGeneratorWithProgress() {
  const extractorRef = useRef(null);
  const [text, setText] = useState('');
  const [embedding, setEmbedding] = useState(null);
  const [fileProgress, setFileProgress] = useState({});
  const [status, setStatus] = useState('');
  const [loading, setLoading] = useState(false);

  const generate = async () => {
    if (!text) return;
    
    setLoading(true);
    
    // Load model on first generate
    if (!extractorRef.current) {
      setStatus('Loading model...');
      
      extractorRef.current = await pipeline(
        'feature-extraction',
        'onnx-community/all-MiniLM-L6-v2-ONNX',
        {
          progress_callback: (info) => {
            if (info.status === 'progress_total') {
              setStatus(`Total: ${info.progress.toFixed(1)}%`);
              return;
            }

            setStatus(`${info.status}: ${info.file ?? ''}`);
            
            if (info.status === 'progress') {
              setFileProgress(prev => ({
                ...prev,
                [info.file]: info.progress
              }));
            }
            
            if (info.status === 'ready') {
              setStatus('Model ready!');
            }
          }
        }
      );
    }
    
    setStatus('Generating embedding...');
    const output = await extractorRef.current(text, { 
      pooling: 'mean', 
      normalize: true 
    });
    setEmbedding(Array.from(output.data));
    setStatus('Complete!');
    setLoading(false);
  };

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (extractorRef.current) {
        extractorRef.current.dispose();
      }
    };
  }, []);

  return (
    <div>
      <h2>Text Embedding Generator</h2>
      
      {loading && Object.keys(fileProgress).length > 0 && (
        <div>
          <p>{status}</p>
          {Object.entries(fileProgress).map(([file, progress]) => (
            <div key={file} style={{ margin: '10px 0' }}>
              <div style={{ fontSize: '12px', marginBottom: '5px' }}>{file}</div>
              <div style={{ width: '100%', height: '20px', background: '#f0f0f0', borderRadius: '5px', overflow: 'hidden' }}>
                <div 
                  style={{ 
                    width: `${progress}%`, 
                    height: '100%', 
                    background: '#4CAF50',
                    transition: 'width 0.3s'
                  }} 
                />
              </div>
            </div>
          ))}
        </div>
      )}
      
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Enter text"
        disabled={loading}
      />
      
      <button onClick={generate} disabled={loading || !text}>
        {loading ? 'Processing...' : 'Generate Embedding'}
      </button>
      
      {embedding && (
        <div>
          <h3>Result:</h3>
          <p>Dimensions: {embedding.length}</p>
          <p>First 5 values: {embedding.slice(0, 5).join(', ')}</p>
        </div>
      )}
    </div>
  );
}

Express API

Basic API Server
// server.js
import express from 'express';
import { pipeline } from '@huggingface/transformers';

const app = express();
app.use(express.json());

// Initialize model once at startup
let extractor;
(async () => {
  console.log('Loading model...');
  extractor = await pipeline(
    'feature-extraction',
    'onnx-community/all-MiniLM-L6-v2-ONNX'
  );
  console.log('Model ready!');
})();

app.post('/embed', async (req, res) => {
  try {
    const { text } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }
    
    const output = await extractor(text, { 
      pooling: 'mean', 
      normalize: true 
    });
    
    res.json({
      text,
      embedding: Array.from(output.data),
      dimensions: output.data.length
    });
  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({ error: 'Failed to generate embedding' });
  }
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});
API with Graceful Shutdown
// server-with-shutdown.js
import express from 'express';
import { pipeline } from '@huggingface/transformers';

const app = express();
app.use(express.json());

let extractor;
let server;

async function initialize() {
  console.log('Loading model...');
  extractor = await pipeline(
    'feature-extraction',
    'onnx-community/all-MiniLM-L6-v2-ONNX'
  );
  console.log('Model ready!');
}

app.post('/embed', async (req, res) => {
  try {
    const { text } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: 'Text is required' });
    }
    
    const output = await extractor(text, { 
      pooling: 'mean', 
      normalize: true 
    });
    
    res.json({
      embedding: Array.from(output.data),
      dimensions: output.data.length
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

async function shutdown(signal) {
  console.log(`\n${signal} received. Shutting down...`);
  
  if (server) {
    server.close(() => {
      console.log('HTTP server closed');
    });
  }
  
  if (extractor) {
    console.log('Disposing model...');
    await extractor.dispose();
    console.log('Model disposed');
  }
  
  process.exit(0);
}

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));

initialize().then(() => {
  server = app.listen(3000, () => {
    console.log('Server running on http://localhost:3000');
  });
});

These examples demonstrate the same functionality across different runtimes and frameworks, making it easy to adapt to your specific use case. All examples include proper cleanup with .dispose() to free memory.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

The author says: Requires Node.js 18+ (or compatible Bun/Deno runtime) or modern browser with ES modules support. WebGPU requires runtime and hardware support; WASM is the broad fallback. Internet access is needed for downloading models from Hugging Face Hub (optional if using local models).

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
huggingface
Publisher
Hugging Face (Official)
Distributed by
Hugging Face
Source
huggingface/skills · skills/transformers-js · commit 25910b3
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by huggingface or Hugging Face.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download transformers-js.zip