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

tachyo

v0.1.12

Published

Ultra-fast, zero-dependency state engine matching minimal libraries while providing native Undo/Redo & JSON diffing

Downloads

48

Readme

tachyo

🎯 A fully-featured, zero-dependency state engine matching the speed of minimal libraries while keeping native Undo/Redo & JSON diffing out-of-the-box.

npm version License: MIT

Enterprise-grade features at vanilla speeds. tachyo provides built-in undo/redo, change path tracking, native Chrome DevTools bridging, and extreme micro-optimizations in a single lightweight package.

🕹️ Try the Interactive Demo & DevTools Dashboard

Installation

npm install tachyo

Quick Start

import { TachyoManager } from 'tachyo';

const store = new TachyoManager({ count: 0 }, { autoSnapshot: true });

store.subscribe((state, event) => {
  console.log('Changed:', event.changePath);
});

store.setState({ count: 1 });
store.setState({ count: 2 });
store.undo(); // Back to count: 1
store.redo(); // Forward to count: 2

React Integration

import { useTachyo } from 'tachyo/react';

function Counter() {
  const { state, setState, undo, redo, canUndo, canRedo } = useTachyo(
    { count: 0 },
    { autoSnapshot: true }
  );

  return (
    <div>
      <h1>Count: {state.count}</h1>
      <button onClick={() => setState({ count: state.count + 1 })}>+</button>
      <button onClick={undo} disabled={!canUndo}>Undo</button>
      <button onClick={redo} disabled={!canRedo}>Redo</button>
    </div>
  );
}

Key Features

🎯 Built-in Undo/Redo

Automatic history management — enable autoSnapshot and every setState call is tracked.

Use cases:

  • Form editors: Users can undo accidental changes
  • Design tools: Essential for creative workflows
  • Game development: Checkpoint/rollback functionality
  • Data entry: Reduce user frustration from mistakes

🔍 Change Path Tracking

Track exactly which properties changed, where, and how. Enable enableChangePathTracking to activate.

const store = new TachyoManager(initialState, {
  enableChangePathTracking: true,
  enableStackTrace: true, // also captures caller name
});

store.subscribe((state, event) => {
  console.log('Changed paths:', event.changePath);
  // ['user', 'profile', 'email'] - nested paths tracked!

  console.log('Who changed it:', event.actionContext?.caller);
  // 'handleFormSubmit' - which function triggered it

  console.log('When:', new Date(event.actionContext?.timestamp ?? 0));
});

Benefits:

  • Faster debugging: Know exactly what changed
  • Better onboarding: New developers understand state flow
  • Easier code reviews: Reviewers see complete action history

⚡ Async Flow Debugging

Track all async operations automatically with full context.

// Register async action once
store.registerAsyncAction({
  name: 'saveDocument',
  handler: async (state, documentId) => {
    return await api.saveDocument(documentId, state.content);
  },
  onStart: (state) => ({ ...state, saving: true }),
  onSuccess: (state, result) => ({ ...state, saving: false, lastSaved: result }),
  onError: (state, error) => ({ ...state, saving: false, error: error.message }),
});

// Execute - automatically tracked!
await store.dispatchAsync('saveDocument', 'doc-123');

// Debug anytime
const active = store.getActiveAsyncActions();
// [{ name: 'saveDocument', status: 'pending', startTime: ... }]

const completed = store.getCompletedAsyncActions();
// [{ name: 'saveDocument', status: 'success', duration: 234ms }]

Benefits:

  • API debugging: Know exactly which request failed and why
  • Performance monitoring: Identify slow async operations
  • Better UX: Show accurate loading states

🛠️ Action Chain Tracking

Track complete action chains with parent-child relationships.

const store = new TachyoManager({ step: 0 }, { enableStackTrace: true });

store.setState({ step: 1 }, { action: 'loadData' });
store.setState({ step: 2 }, { action: 'validateForm' });
store.setState({ step: 3 }, { action: 'submitForm' });

const chain = store.getActionChain();
// [
//   { name: 'loadData', id: '1', ... },
//   { name: 'validateForm', id: '2', ... },
//   { name: 'submitForm', id: '3', ... }
// ]

🎨 Framework Agnostic

Works with React and vanilla JavaScript.

// React
import { useTachyo } from 'tachyo/react';

// Vanilla JS - no framework needed!
import { TachyoManager } from 'tachyo';
const store = new TachyoManager({ count: 0 });

🏎️ Blazing Fast Performance

tachyo is carefully designed and V8 micro-optimized directly at the physical JS engine allocation limits.

  • ~8.5 Million ops/sec for simple state modifications (highly conservative).
  • ~19.0 Million ops/sec for history navigation (Undo/Redo).

All heavy features (Action Tracking, Deep Object comparisons) are perfectly isolated and opt-in, so baseline performance is completely on par with the world's most minimal libraries (like Zustand and Redux).

🚀 Zero Dependencies

Lightweight with no external dependencies.

// tachyo: Zero dependencies
// - Custom EventEmitter (no 'events' package)
// - All utilities included
// - Tree-shaking friendly
// - ~7KB gzipped with ALL features

🔧 Middleware System

Flexible middleware system supports custom patterns.

// Logging middleware
const loggingMiddleware = (state, next, action) => {
  console.log(`[${action.name}]`, state);
  next(state);
};

// Validation middleware
const validationMiddleware = (state, next, action) => {
  if (isValid(state)) {
    next(state);
  } else {
    throw new Error('Invalid state!');
  }
};

// Analytics middleware
const analyticsMiddleware = (state, next, action) => {
  analytics.track(action.name, state);
  next(state);
};

// Use all together
const store = new TachyoManager(initialState, {
  middleware: [loggingMiddleware, validationMiddleware, analyticsMiddleware],
});

// Or add dynamically
store.use(customMiddleware);
store.removeMiddleware(customMiddleware);

Complete Example

import { useTachyo } from 'tachyo/react';

interface TodoState {
  todos: { id: string; text: string; completed: boolean }[];
}

function TodoApp() {
  const { state, setState, undo, redo, canUndo, canRedo } = useTachyo<TodoState>(
    { todos: [] },
    { autoSnapshot: true }
  );

  const addTodo = (text: string) => {
    setState({ todos: [...state.todos, { id: Date.now().toString(), text, completed: false }] });
  };

  const toggleTodo = (id: string) => {
    setState({ todos: state.todos.map(t => t.id === id ? { ...t, completed: !t.completed } : t) });
  };

  const clearCompleted = () => {
    setState({ todos: state.todos.filter(t => !t.completed) });
  };

  return (
    <div>
      <h1>Todo List</h1>
      <ul>
        {state.todos.map(todo => (
          <li key={todo.id}>
            <input type="checkbox" checked={todo.completed} onChange={() => toggleTodo(todo.id)} />
            {todo.text}
          </li>
        ))}
      </ul>
      <button onClick={() => addTodo('New todo')}>Add Todo</button>
      <button onClick={clearCompleted}>Clear Completed</button>
      <button onClick={undo} disabled={!canUndo}>Undo</button>
      <button onClick={redo} disabled={!canRedo}>Redo</button>
    </div>
  );
}

Vanilla Usage

import { TachyoManager } from 'tachyo';

const gameStore = new TachyoManager(
  { score: 0, level: 1, lives: 3 },
  { autoSnapshot: true, enableChangePathTracking: true }
);

// Subscribe to changes
const unsubscribe = gameStore.subscribe((state, event) => {
  console.log('Game state changed:', state);
  console.log('What changed:', event.changePath); // ['score'] or ['level']
});

// Subscribe to specific property
gameStore.subscribeToProperty('score', (newScore, oldScore) => {
  console.log(`Score: ${oldScore} -> ${newScore}`);
});

// Update state
gameStore.setState({ score: 100 });
gameStore.setState({ level: 2 });

// Undo/Redo
gameStore.undo(); // Back to level 1
gameStore.redo(); // Forward to level 2

// Cleanup
unsubscribe();
gameStore.destroy();

Using with TypeScript

import { TachyoManager } from 'tachyo';

interface ShoppingCartState {
  items: { id: string; name: string; price: number; quantity: number }[];
}

const cartStore = new TachyoManager<ShoppingCartState>({ items: [] });

const addItem = (item: { id: string; name: string; price: number }) => {
  cartStore.setState({
    items: [...cartStore.state.items, { ...item, quantity: 1 }],
  });
};

// Fully typed!
cartStore.setState({ items: [] }); // ✅
// cartStore.setState({ items: 'invalid' }); // ❌ Type error

Redux DevTools

tachyo automatically integrates with Redux DevTools Extension when available.

const editorStore = new TachyoManager({ content: '', fontSize: 16 });

editorStore.setState({ content: 'Hello World' });
editorStore.setState({ fontSize: 18 });
// Automatically appears in Redux DevTools! 🎉

Options

const store = new TachyoManager(initialState, {
  maxHistorySize: 100,            // Maximum undo/redo steps (default: 50)
  enableDeepEquality: false,      // Deep equality for change detection (default: false)
  autoSnapshot: false,            // Save history on every setState (default: false)
  enableChangePathTracking: false,// Track which properties changed (default: false)
  enableAsyncTracking: true,      // Track async operations (default: true)
  enableStackTrace: false,        // Stack traces — has performance impact (default: false)
  middleware: [],                 // Custom middleware
  equalityFn: customEqualFn,     // Custom equality function
});

Comparison with Other Libraries

| Feature | tachyo | Zustand | Zundo | Redux | |---------|-------|---------|-------|-------| | Automatic Undo/Redo | ✅ Core | ❌ | ✅* | ❌** | | Change Path Tracking | ✅ | ❌ | ❌ | ❌ | | Async Action Tracking | ✅ | ❌ | ❌ | ❌ | | Redux DevTools | ✅ | ⚠️ | ⚠️ | ✅ | | Performance (ops/sec)| ~8.5M | ~7.5M | N/A | ~8.0M | | Simple API | ✅ | ✅ | ✅ | ❌ | | Type Safety | ✅ | ✅ | ✅ | ✅ | | Zero Dependencies | ✅ | ✅ | ✅ | ❌ | | Framework Agnostic | ✅ | ✅ | ❌ | ✅ | | Bundle Size | ✅ (~7KB) | ✅ (~1KB) | ✅ (~700B) | ❌ (~15KB+) |

*Zundo requires Zustand (separate library)
**Redux requires Redux Undo (separate library)

When to Use tachyo?

✅ Perfect For:

  • Form editors - Undo/redo is essential
  • Design tools - Figma, Sketch-like applications
  • Game development - Checkpoint/rollback functionality
  • Data entry apps - Reduce user frustration
  • Complex state flows - Need to track what changed
  • Async-heavy apps - Need to debug API calls
  • Multi-framework projects - Same API everywhere

⚠️ Consider Alternatives If:

  • Ultra-minimal bundle size - Zustand is smaller (but lacks features)
  • Already using Redux - Migration might not be worth it
  • Simple state only - If you don't need undo/redo or debugging

Best Practices

  • Organize your stores: Split stores into separate slices for better maintenance
  • Use TypeScript: Full type safety out of the box
  • Enable tracking selectively: enableChangePathTracking and autoSnapshot have a small perf cost — enable only when needed
  • Use middleware: Add logging, validation, or analytics through middleware
  • Clean up: Call store.destroy() when a store is no longer needed

Examples

Documentation

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


tachyo - State management with built-in undo/redo, change tracking, and async debugging 🎯