npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tabrider

v1.0.0

Published

A powerful Chrome extension automation engine with Playwright-style API for browser automation

Readme

Tabrider

A powerful automation engine for Chrome extensions with Playwright-style API.

Features

  • Tab Management - Create, close, and switch between browser tabs
  • DOM Interactions - Click, fill, wait for elements with CSS selectors and XPath support
  • Form Automation - Fill entire forms with a single call
  • Job Management - Track automation progress with jobs
  • State Persistence - Automatically persist state to Chrome storage
  • Logging - Built-in logging system
  • Rust-style Results - Explicit error handling with Result<T> type

Installation

npm install tabrider

Usage

Basic Usage

import { AutomationEngine } from 'tabrider';

// Create and initialize the engine
const engine = new AutomationEngine();
await engine.init();

// Create a new page
const pageResult = await engine.createPage('https://example.com');
if (pageResult.is_err()) {
  console.error('Failed to create page:', pageResult.error);
  return;
}
const pageId = pageResult.unwrap();

// Fill a form field
await engine.fill(pageId, '#email', '[email protected]');

// Click a button
const clickResult = await engine.click(pageId, 'button[type="submit"]');
if (clickResult.is_ok()) {
  console.log('Button clicked successfully!');
}

// Wait for an element
const waitResult = await engine.waitFor(pageId, '.success-message', 5000);
if (waitResult.is_ok()) {
  console.log('Success message appeared!');
}

// Close the page when done
await engine.closePage(pageId);

Using the Singleton Instance

import { Engine } from 'tabrider';

await Engine.init();
const page = await Engine.createPage('https://example.com');

Selector Support

The engine supports both CSS selectors and XPath:

// CSS Selectors
await engine.click(pageId, '#submit-button');
await engine.click(pageId, '.form-control');
await engine.click(pageId, 'button[type="submit"]');

// XPath
await engine.click(pageId, '//button[text()="Submit"]');
await engine.click(pageId, '//input[@name="email"]');
await engine.click(pageId, '(//div[@class="item"])[1]');

Form Automation

// Fill multiple fields at once
await engine.fillForm(pageId, {
  '#firstName': 'John',
  '#lastName': 'Doe',
  '#email': '[email protected]',
  '#phone': '555-1234',
});

Scraping Data

// Scrape single elements
const title = await engine.getText(pageId, 'h1');

// Scrape multiple elements (prefix with [all])
const data = await engine.scrapeData(pageId, {
  title: 'h1',
  description: '.description',
  items: '[all].list-item', // Returns array of texts
});

Job Management

await engine.startJob('Apply to Jobs', async () => {
  // Your automation steps here
  engine.updateJobProgress(25);
  await engine.fill(pageId, '#name', 'John');

  engine.updateJobProgress(50);
  await engine.click(pageId, '#submit');

  engine.updateJobProgress(100);
  return { applied: true };
});

Human-like Delays

// Wait for random time (3-8 seconds by default)
await engine.randomWait();

// Custom range
await engine.randomWait(1, 3); // 1-3 seconds

Automation Sessions

// Start session (highlights all tabs under automation)
await engine.startAutomationSession();

// Your automation code...

// End session (removes highlights)
await engine.endAutomationSession();

API Reference

AutomationEngine

Initialization

  • init() - Initialize the engine (required before use)
  • isInitialized() - Check if engine is initialized
  • getContext() - Get current context (background/content/popup)

Page Management

  • createPage(url?) - Create a new tab
  • closePage(pageId) - Close a tab
  • switchToPage(pageId) - Switch to a tab
  • getPages() - Get all managed pages
  • getActivePage() - Get the active page
  • closeAllPages() - Close all managed pages

DOM Interactions

  • click(pageId, selector) - Click an element
  • fill(pageId, selector, value) - Fill an input field
  • selectOption(pageId, selector, value) - Select dropdown option
  • waitFor(pageId, selector, timeout?) - Wait for element
  • getText(pageId, selector) - Get element text
  • getAllTexts(pageId, selector) - Get text from multiple elements
  • goto(pageId, url) - Navigate to URL
  • uploadFile(pageId, selector, filePath) - Upload a file

High-Level Automation

  • fillForm(pageId, formData) - Fill multiple form fields
  • clickAndWait(pageId, clickSelector, waitSelector) - Click and wait
  • scrapeData(pageId, selectors) - Scrape multiple data points
  • evaluate(pageId, fn, ...args) - Execute JavaScript in page

Timing

  • wait(ms) - Wait for milliseconds
  • waitSeconds(seconds) - Wait for seconds
  • randomWait(min?, max?) - Wait random time

Job Management

  • startJob(name, steps) - Start a named job
  • updateJobProgress(progress) - Update job progress
  • getJobs() - Get all jobs
  • getCurrentJob() - Get current job

State & Settings

  • getState() - Get current state
  • onStateChange(callback) - Subscribe to state changes
  • getLogs() - Get all logs
  • clearLogs() - Clear logs
  • getSettings() - Get settings
  • updateSettings(updates) - Update settings

Utilities

import {
  clickAndCheckNavigation,
  withRetry,
  waitForCondition,
  getEngine
} from 'tabrider';

// Try multiple selectors until one works
await clickAndCheckNavigation(engine, pageId, [
  '#submit',
  '.submit-btn',
  '//button[text()="Submit"]'
]);

// Retry with exponential backoff
await withRetry(() => engine.click(pageId, '#flaky-button'), 3, 1000);

// Wait for custom condition
await waitForCondition(async () => {
  const text = await engine.getText(pageId, '#status');
  return text === 'Ready';
});

Chrome Extension Setup

Add these permissions to your manifest.json:

{
  "permissions": [
    "activeTab",
    "storage",
    "tabs",
    "scripting"
  ],
  "host_permissions": [
    "*://*/*"
  ]
}

License

MIT