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

@ceschiatti/redistail

v0.0.20

Published

CLI tool for monitoring Redis streams and PubSub

Downloads

205

Readme

Redistail

A real-time Redis message monitoring CLI, similar to tail -f for log files. Supports both Pub/Sub channels and Redis Streams with automatic reconnection, multi-day stream traversal, and colored output.

| Feature | Description | | :--- | :--- | | Pub/Sub monitoring | Subscribe to any channel and display messages as they arrive | | Stream monitoring | Continuous polling via blocking XREAD with entry ID continuity | | Multi-day streams | Automatically traverse daily-partitioned streams (Cedro protocol) | | Date filtering | Retrieve historical messages with --from and transition to real-time | | Colored output | ANSI color-coded timestamps, channels, fields, and errors | | JSON pretty-print | Automatic detection and formatting of JSON payloads | | Cross-platform | Pre-compiled binaries for Linux, macOS, and Windows via Bun | | Effect-TS native | Built entirely with Effect services, layers, and structured errors |


Table of Contents

Installation

Global Installation

# Using pnpm (recommended)
pnpm add -g @ceschiatti/redistail

# Using npm
npm install -g @ceschiatti/redistail

# Using bun
bun add -g @ceschiatti/redistail

Local Installation

pnpm add @ceschiatti/redistail

# Run locally
npx redistail --help

Binary Distribution

The npm package ships only the JS bundle (~2 MB). On postinstall, a platform-specific compiled binary is downloaded from GitHub Releases. If the download fails (no network, no release for the platform), the launcher falls back to node dist/redistail.js automatically.

To skip binary download: REDISTAIL_SKIP_BINARY_DOWNLOAD=1 pnpm add -g @ceschiatti/redistail

Verify Installation

redistail --version
redistail --help

Quick Start

# Monitor a Pub/Sub channel
redistail pubsub my-channel

# Monitor a Redis Stream
redistail stream my-stream

# Historical messages + real-time transition
redistail stream my-stream --from "2026-01-09T10:00:00Z"

# Custom Redis connection
REDIS_HOST=redis.example.com redistail pubsub notifications

Architecture

CLI args + env vars
        |
        v
  CLIConfigService          (parses args, loads env config, shows help/version)
        |
        v
  RedistailConfig           (immutable config: redis + display + monitoring)
   /       |        \
  v        v         v
DisplayService  PubSubMonitorService  StreamMonitorService
(formatting)    (channel monitoring)  (stream monitoring)
   |               |                      |
   |               v                      v
   |          RedisPubSub            RedisStream
   |          (effect-redis)         (effect-redis)
   |               \                    /
   |                v                  v
   |            RedisConnectionOptions
   |                      |
   v                      v
stdout/stderr        Redis Server

Connection Optimization

The CLI creates only the Redis connections needed for the selected mode:

| Mode | Redis Connections | Layer Used | | :--- | :--- | :--- | | pubsub | 2 (publish + subscribe) | PubSubAppLive | | stream | 2 (producer + consumer) | StreamAppLive | | --help / --version | 0 | CLIConfigServiceLive | | Invalid args | 0 | CLIConfigServiceLive |


CLI Reference

Syntax

redistail <CONNECTION_TYPE> <TOPIC_NAME> [OPTIONS]

Arguments

| Argument | Values | Description | | :--- | :--- | :--- | | CONNECTION_TYPE | pubsub, stream | Type of Redis connection | | TOPIC_NAME | any string | Channel name (Pub/Sub) or stream key (Streams) |

Options

| Option | Description | | :--- | :--- | | -h, --help | Show help message with all options and environment variables | | -v, --version | Show version, build hash, compile date, Effect and effect-redis versions | | --from <date> | (Stream only) Retrieve historical messages from a date, then transition to real-time |

Version Output

redistail 0.0.17
Build: 4cc301e
Compiled: 2026-01-19T10:37:28.864Z (UTC)
Effect: 3.19.16
effect-redis: 0.0.32

Monitoring Modes

Pub/Sub Monitoring

redistail pubsub channel-name
  • Subscribes to the specified channel via RedisPubSub.subscribe()
  • Displays messages as they are published
  • Shows timestamp, channel name, and message content
  • Automatic reconnection with exponential backoff (up to maxReconnectAttempts)
  • Continues running until interrupted (Ctrl+C)

Stream Monitoring

redistail stream stream-name
  • Reads from the stream starting from the latest entry ($)
  • Uses blocking XREAD to wait for new entries
  • Shows timestamp, entry ID, and all message fields
  • Maintains entry ID continuity across reconnections

Stream with Date Filter

redistail stream stream-name --from "2026-01-09T10:00:00Z"
  1. Retrieves all historical messages from the date onwards via XRANGE
  2. Displays them in chronological order
  3. Seamlessly transitions to real-time monitoring from the last seen entry ID
  4. No messages are lost during the transition

Supported date formats:

| Format | Example | | :--- | :--- | | Keywords | today, yesterday | | ISO 8601 | 2026-01-09T10:00:00Z, 2026-01-09 | | RFC 2822 | Fri, 09 Jan 2026 10:00:00 GMT | | Simple | Jan 9 2026, 2026/01/09 |

Edge cases:

  • Future date: Warning logged, monitoring starts from latest entry
  • Old date: All available messages are retrieved
  • Empty stream: Proceeds directly to real-time mode
  • Invalid format: Clear error with supported format examples

Multi-day Stream Monitoring

For daily-partitioned streams (common in the Cedro protocol), provide a partial stream name (3 colon-separated fields) with --from:

redistail stream stream:raw:WING26 --from yesterday

Stream name formats:

  • Partial (3 fields): stream:<type>:<ticker> (e.g., stream:raw:WING26)
  • Full (6 fields): stream:<type>:<ticker>:<year>:<month>:<day>

How it works:

  1. Generates date range from --from date to today
  2. Constructs full stream names for each day (e.g., stream:raw:WING26:2026:01:16)
  3. Sequentially reads all historical messages from each day's stream
  4. On the final day (today), transitions to real-time monitoring
  5. Missing or empty streams are skipped with a warning
📅 Multi-day mode: stream:raw:WING26 from 2026-01-16T00:00:00.000Z
⏳ Iterating through daily streams, then transitioning to real-time...
📆 Processing stream: stream:raw:WING26:2026:01:16
📆 Processing stream: stream:raw:WING26:2026:01:17
📆 Processing stream: stream:raw:WING26:2026:01:18 (switching to real-time)

Configuration

All configuration is loaded from environment variables via Effect.Config with validation and defaults.

Environment Variables

Redis Connection

| Variable | Default | Description | | :--- | :--- | :--- | | REDIS_HOST | 127.0.0.1 | Redis server hostname | | REDIS_PORT | 6379 | Redis server port (1–65535) | | REDIS_URL | — | Complete Redis URL (overrides host/port) | | REDIS_TIMEOUT | 5000 | Connection timeout in milliseconds | | REDIS_RETRY_ATTEMPTS | 3 | Number of connection retry attempts | | REDIS_RETRY_DELAY | 1000 | Delay between retries in milliseconds |

Display

| Variable | Default | Description | | :--- | :--- | :--- | | REDISTAIL_COLORS | true | Enable ANSI colored output | | REDISTAIL_TIMESTAMPS | true | Show timestamps in output | | REDISTAIL_PRETTY_JSON | true | Pretty-print JSON content |

Monitoring

| Variable | Default | Description | | :--- | :--- | :--- | | REDISTAIL_BLOCK_TIMEOUT | 5000 | Stream blocking timeout in milliseconds | | REDISTAIL_MAX_RECONNECT_ATTEMPTS | 5 | Maximum reconnection attempts |

Configuration Examples

# Production
REDIS_URL=redis://user:[email protected]:6380 \
REDISTAIL_COLORS=false \
redistail stream orders

# Development
REDIS_HOST=localhost REDISTAIL_PRETTY_JSON=true redistail pubsub app-logs

# CI/CD (minimal output)
REDISTAIL_COLORS=false REDISTAIL_TIMESTAMPS=false redistail stream events

Services & Layers

Redistail is built as a set of Effect-TS services composed via layers.

Service Catalog

| Service | Tag | Purpose | | :--- | :--- | :--- | | CLIConfigService | 'CLIConfigService' | Argument parsing, env config loading, help/version display | | DisplayService | '@redistail/DisplayService' | Message formatting, color output, stdout/stderr separation | | PubSubMonitorService | 'PubSubMonitorService' | Pub/Sub channel monitoring with reconnection | | StreamMonitorService | 'StreamMonitorService' | Stream monitoring, date filtering, multi-day traversal | | SignalHandlerService | 'SignalHandlerService' | SIGINT/SIGTERM handling, graceful shutdown | | DateFilterService | 'DateFilterService' | Date parsing and Redis stream ID conversion |

Layer Composition

// Full application layer (all services)
import { AppLive } from './layers.js';

// Mode-specific layers (optimized connection count)
import { PubSubAppLive, StreamAppLive } from './layers.js';

// Testing layers
import { createTestAppLayer, createMockAppLayer } from './layers.js';

Layer Dependency Chain

CLIConfigServiceLive (no deps)
        |
        v
RedistailConfigLive (depends on CLIConfigService)
   /         \
  v           v
RedisConnectionLive    DisplayServiceLive
  |
  v
RedisPubSubLive / RedisStreamLive
  |
  v
PubSubMonitorServiceLive / StreamMonitorServiceLive

Error Model

Every operation fails with RedistailError, a discriminated union of three tagged error types. All extend Data.TaggedError for pattern matching with Effect.catchTag.

class CLIError extends Data.TaggedError('CLIError')<{
  readonly reason: 'InvalidArguments' | 'MissingArguments'
    | 'UnknownCommand' | 'InvalidDateFormat';
  readonly message: string;
  readonly context?: string;
}> {}

class ConfigError extends Data.TaggedError('ConfigError')<{
  readonly reason: 'InvalidEnvironment' | 'ConnectionFailed'
    | 'ValidationFailed';
  readonly message: string;
  readonly cause?: unknown;
  readonly context?: string;
}> {}

class MonitoringError extends Data.TaggedError('MonitoringError')<{
  readonly reason: 'ConnectionLost' | 'SubscriptionFailed'
    | 'StreamReadFailed';
  readonly message: string;
  readonly retryable: boolean;
  readonly cause?: unknown;
}> {}

type RedistailError = CLIError | ConfigError | MonitoringError;

| Error | Tag | When | | :--- | :--- | :--- | | CLIError | 'CLIError' | Invalid arguments, missing arguments, bad date format | | ConfigError | 'ConfigError' | Invalid environment variables, connection failures | | MonitoringError | 'MonitoringError' | Connection lost, subscription failed, stream read failed |

Error Helper Functions

| Helper | Creates | Retryable | | :--- | :--- | :--- | | createInvalidArgumentError(msg) | CLIError (InvalidArguments) | — | | createMissingArgumentError(msg) | CLIError (MissingArguments) | — | | createDateFilterError(msg) | CLIError (InvalidDateFormat) | — | | createEnvironmentError(msg) | ConfigError (InvalidEnvironment) | — | | createConnectionError(msg) | ConfigError (ConnectionFailed) | — | | createConnectionLostError(msg) | MonitoringError (ConnectionLost) | Yes | | createSubscriptionFailedError(msg) | MonitoringError (SubscriptionFailed) | Configurable | | createStreamReadFailedError(msg) | MonitoringError (StreamReadFailed) | Configurable |


Types Reference

CLI Configuration

interface CLIConfig {
  readonly connectionType: 'pubsub' | 'stream';
  readonly topicName: string;
  readonly help?: boolean;
  readonly version?: boolean;
  readonly fromDate?: Date;
}

Application Configuration

interface RedistailConfig {
  readonly redis: {
    readonly host: string;
    readonly port: number;
    readonly url?: string;
    readonly timeout: number;
    readonly retryAttempts: number;
    readonly retryDelay: number;
  };
  readonly display: {
    readonly colors: boolean;
    readonly timestamps: boolean;
    readonly prettyJson: boolean;
  };
  readonly monitoring: {
    readonly blockTimeout: number;
    readonly maxReconnectAttempts: number;
  };
}

Message Types

interface PubSubMessage {
  readonly timestamp: Date;
  readonly channel: string;
  readonly content: string;
}

interface StreamMessage {
  readonly timestamp: Date;
  readonly streamKey: string;
  readonly entryId: string;
  readonly fields: Record<string, string>;
}

Stream Name Utilities

| Function | Signature | Description | | :--- | :--- | :--- | | isPartialStreamName | (name: string) => boolean | Check if name has 3 colon-separated fields | | isFullStreamName | (name: string) => boolean | Check if name has 6 colon-separated fields | | constructDailyStreamName | (partial: string, date: Date) => string | Build full name from partial + date | | generateDateRange | (from: Date, to: Date) => Date[] | Generate inclusive date array | | generateDailyStreamNames | (partial: string, from: Date, to: Date) => string[] | Generate all daily stream names |


Build System

The build process is handled by build-cli.js and produces both ESM modules and cross-platform compiled binaries.

Build Command

pnpm build    # or: node build-cli.js

Build Steps

  1. Version injection: Reads src/version.ts template, replaces placeholders with git commit hash, package version, and ISO timestamp, writes src/version-generated.ts
  2. ESM bundle: bun build produces dist/redistail.js (Node.js target, ESM)
  3. Cross-platform binaries: Compiled via bun build --compile for 5 targets
  4. Launcher: Copies redistail-launcher.js to dist/

Build Targets

| Platform | Architecture | Output | | :--- | :--- | :--- | | Windows | x64 | redistail-win-x64.exe | | Linux | x64 | redistail-linux-x64 | | Linux | ARM64 | redistail-linux-arm64 | | macOS | x64 | redistail-osx-x64 | | macOS | ARM64 | redistail-osx-arm64 |

Distribution Model

Binaries are excluded from the npm package (via .npmignore) to keep the tarball under ~2 MB. Instead, binaries are distributed through GitHub Releases:

  1. npm package ships: dist/redistail.js + dist/redistail-launcher.js + scripts/postinstall.js
  2. postinstall runs scripts/postinstall.js, which downloads the platform-specific binary from https://github.com/6qat/monorepo/releases/download/redistail-v{version}/{binary}
  3. Launcher (redistail-launcher.js) checks for the binary; if absent, falls back to node dist/redistail.js

Releasing Binaries

After pnpm build, upload the 5 binaries from dist/ to a GitHub Release tagged redistail-v{version}:

gh release create redistail-v0.0.18 \
  dist/redistail-linux-x64 \
  dist/redistail-linux-arm64 \
  dist/redistail-osx-x64 \
  dist/redistail-osx-arm64 \
  dist/redistail-win-x64.exe \
  --title "redistail v0.0.18" \
  --notes "Pre-compiled binaries for redistail v0.0.18"

Output Format

Pub/Sub Messages

TIMESTAMP [CHANNEL] MESSAGE_CONTENT
2026-01-09 15:30:45.123 [notifications] User alice logged in

Stream Messages

TIMESTAMP [STREAM_KEY:ENTRY_ID] FIELD1=VALUE1 FIELD2=VALUE2 ...
2026-01-09 15:31:12.345 [events:1704636672345-0] user=alice action=login

If a stream entry has a single data or message field, the field name is omitted and the value is displayed directly (unwrapped payload).

Color Coding

| Color | Element | | :--- | :--- | | Gray (\x1b[90m) | Timestamps | | Cyan (\x1b[36m) | Pub/Sub channel names | | Magenta (\x1b[35m) | Stream names and entry IDs | | Yellow (\x1b[33m) | Field names in streams | | White (\x1b[37m) | Message content and field values | | Red (\x1b[31m) | Error messages |

Binary Content Safety

Non-printable characters are automatically escaped as \xHH. Content with more than 10% non-printable characters is treated as binary and fully escaped.


Examples

Basic Pub/Sub

redistail pubsub notifications
2026-01-09 15:30:45.123 [notifications] Welcome to the system!
2026-01-09 15:30:47.456 [notifications] New user registered

Multi-day Data Recovery

redistail stream stream:raw:WING26 --from "2026-01-16"

JSON Pretty-Printing

Input message: {"user":"alice","action":"login"}

2026-01-09 15:31:12.345 [api-events] {
  "user": "alice",
  "action": "login"
}

Pipe to File

REDISTAIL_COLORS=false redistail stream events >> /var/log/redis-events.log

Multiple Instances

redistail pubsub critical-alerts &
redistail stream user-events &
redistail pubsub app-logs &

Bash Monitoring Script

#!/bin/bash
CHANNELS=("user-events" "system-logs" "error-alerts")
PIDS=()

for channel in "${CHANNELS[@]}"; do
  redistail pubsub "$channel" > "/var/log/redis-$channel.log" &
  PIDS+=($!)
done

trap 'kill "${PIDS[@]}"; exit' INT TERM
wait

Troubleshooting

Connection Refused

❌ Error: Connection failed to redis://localhost:6379
  1. Verify Redis is running: redis-cli ping
  2. Check host/port: REDIS_HOST=localhost REDIS_PORT=6379 redistail --help
  3. Test directly: redis-cli -h localhost -p 6379 ping

No Messages Appearing

  1. Publish a test message: redis-cli publish test-channel "hello"
  2. Add a stream entry: redis-cli xadd test-stream * msg hello
  3. Verify topic name matches exactly
  4. Check stream length: redis-cli xlen stream-name

Authentication Failed

Include credentials in URL: REDIS_URL=redis://user:pass@host:port

Intermittent Disconnections

  1. Increase retries: REDISTAIL_MAX_RECONNECT_ATTEMPTS=10
  2. Adjust delay: REDIS_RETRY_DELAY=2000
  3. Check network stability and Redis server logs

Colors Not Displaying

  1. Set explicitly: REDISTAIL_COLORS=true
  2. Piping disables colors — use REDISTAIL_COLORS=true to force
  3. Check terminal: echo $TERM

Date Filter Errors

# Invalid format
$ redistail stream events --from "invalid"
❌ CLI Error: Invalid date format: "invalid". Supported formats: ...

# --from with pubsub
$ redistail pubsub channel --from "2026-01-09"
❌ CLI Error: The --from option is only available for stream mode

# Missing value
$ redistail stream events --from
❌ CLI Error: The --from option requires a date argument

Debugging

# Test Redis connectivity
redis-cli -h $REDIS_HOST -p $REDIS_PORT ping

# Monitor all Redis commands
redis-cli monitor

# Test pub/sub manually
redis-cli subscribe test-channel
# In another terminal:
redis-cli publish test-channel "hello"

Peer Dependencies

| Package | Version | | :--- | :--- | | effect | (provided via workspace catalog) | | effect-redis | workspace:* | | @effect/experimental | (provided via workspace catalog) | | @effect/platform-bun | (provided via workspace catalog) |