devink
v2.0.3
Published
Terminal logging done right — structured, beautiful, and zero dependencies. A complete Node.js logging system with child loggers, HTTP middleware, and file rotation.
Maintainers
Keywords
Readme
devink
Terminal logging done right — structured, beautiful, and zero dependencies.
Why devink?
Most terminal libraries give you colors. devink gives you a complete logging system — child loggers, HTTP middleware, file rotation, field redaction, performance timers, and structured JSON output — all in a single package with zero dependencies.
Whether you are building a CLI tool, an Express API, or a production microservice, devink handles the entire logging pipeline so you don't have to glue five packages together.
Highlights
- Expressive, developer-friendly API
- Zero dependencies — nothing extra in
node_modules - Child loggers with scoped namespaces
- HTTP middleware for Express, Fastify, Hono, and Koa
- File transport with automatic size-based rotation
- Structured JSON mode for Datadog, ELK, and log aggregators
- Performance timers built into the logger
- Log sampling and rate limiting for high-throughput apps
- Sensitive field redaction (passwords, tokens, secrets)
- Pretty error formatting with colored stack traces
- Boxed output for startup banners and critical alerts
- Log grouping for multi-step operations
- Full ANSI, 256-color, and Truecolor (16 million colors) support
- Auto-detects
TTY,FORCE_COLOR,NO_COLOR, andCIenvironments - Native TypeScript with full type definitions
Install
npm install devinkyarn add devinkpnpm add devinkRequirements: Node.js 18 or later. Works with both ESM and CommonJS.
Usage
import { createLogger } from 'devink';
const logger = createLogger({ timestamps: true, level: 'info' });
logger.info('Server started on port 3000');
logger.success('Database connected');
logger.warn('Rate limit approaching');
logger.error(new Error('Connection timeout'));Define your own scoped loggers:
const dbLogger = logger.child({ namespace: 'db' });
const authLogger = logger.child({ namespace: 'auth' });
dbLogger.info('Query executed in 12ms');
// [14:30:00] [db] ℹ info Query executed in 12ms
authLogger.warn('Token expires in 5 minutes');
// [14:30:00] [auth] ⚠ warn Token expires in 5 minutesSwitch to JSON for production:
const logger = createLogger({ mode: 'json', level: 'trace' });
logger.info('Processing payment', { userId: 123, amount: 49.99 });
// {"level":"info","time":"2026-03-03T00:00:00.000Z","message":["Processing payment",{"userId":123,"amount":49.99}]}API
createLogger(options?)
Returns a new Logger instance. All options are optional.
| Option | Type | Default | Description |
| ------------ | ------------------------ | -------------------- | ---------------------------------------------------------------------- |
| level | string | 'trace' | Minimum log level: trace, debug, info, warn, error, fatal. |
| mode | 'text' \| 'json' | 'text' | Text mode for the terminal, JSON mode for log aggregators. |
| colors | boolean | true | ANSI colors. Auto-disabled when the terminal doesn't support it. |
| timestamps | boolean | false | Prepend [HH:MM:SS] to text output. |
| theme | Partial<Theme> | modernTheme | Customize prefix icons and colors for each log level. |
| transports | Transport[] | [ConsoleTransport] | Output destinations — console, file, or custom. |
| namespace | string | '' | Prefix prepended to all log lines. |
| redact | string[] | [] | Field names to mask with [REDACTED]. |
| sampling | Record<string, number> | {} | Sampling rates (0–1) for rate-limiting high-frequency events. |
Log Levels
Every logger instance exposes these methods, ordered by severity:
logger.trace('...'); // fine-grained debugging
logger.debug('...'); // development diagnostics
logger.info('...'); // general information
logger.success('...'); // operation completed
logger.warn('...'); // something unexpected
logger.error('...'); // failure
logger.fatal('...'); // unrecoverablelogger.child(bindings)
Create a scoped child logger that inherits the parent configuration:
const requestLogger = logger.child({ namespace: 'api', requestId: 'abc-123' });
requestLogger.info('Request received');
// JSON: {"level":"info","namespace":"api","requestId":"abc-123","message":"Request received"}logger.group(label) / logger.groupEnd()
Visually group related log lines with indentation:
logger.group('Database Migration');
logger.info('Running migration 001_create_users...');
logger.info('Running migration 002_add_indexes...');
logger.success('All migrations complete');
logger.groupEnd();[14:30:00] ▸ Database Migration
[14:30:00] ℹ info Running migration 001_create_users...
[14:30:01] ℹ info Running migration 002_add_indexes...
[14:30:01] ✔ success All migrations completelogger.time(label) / logger.timeEnd(label)
Measure execution time for any operation:
logger.time('database-query');
await db.query('SELECT * FROM users');
logger.timeEnd('database-query');
// ℹ info database-query: 243mslogger.box(title, message)
Draw a Unicode box around important messages:
logger.box(
'System Ready',
'All microservices have booted successfully.\nListening on http://localhost:8080',
);HTTP Middleware
Drop-in request logging for any Node.js framework:
import { createLogger, httpMiddleware } from 'devink';
import express from 'express';
const logger = createLogger({ timestamps: true });
const app = express();
app.use(httpMiddleware(logger));
// [14:30:05] ℹ info GET /api/users 200 12ms
// [14:30:06] ⚠ warn POST /api/login 401 8ms
// [14:30:07] ✖ error GET /api/crash 500 3msWorks with Express, Fastify, Hono, Koa, and any framework using the standard (req, res, next) pattern. Status codes above 400 automatically escalate to warn, and above 500 to error.
File Transport
Write logs to files with automatic rotation and retention:
import { createLogger, FileTransport } from 'devink';
const logger = createLogger({
transports: [
new FileTransport({
path: './logs/app.log',
maxSize: '10mb',
maxFiles: 5,
rotate: true,
}),
],
});
logger.info('This goes to a file with automatic rotation');When app.log exceeds 10 MB, it rotates to app.log.1, app.log.2, and so on, keeping at most 5 rotated files. Writes are async and non-blocking.
Field Redaction
Automatically mask sensitive data before it reaches any transport:
const logger = createLogger({
redact: ['password', 'token', 'authorization', 'ssn'],
});
logger.info('User login', { user: 'harry', password: 's3cret!', token: 'eyJhbG...' });
// ℹ info User login { user: 'harry', password: '[REDACTED]', token: '[REDACTED]' }Redaction works recursively on nested objects and in both text and JSON modes.
Log Sampling
In high-throughput production environments, log only a fraction of repetitive events:
const logger = createLogger({
sampling: {
'db.query': 0.1, // log 10% of database queries
'cache.hit': 0.01, // log 1% of cache hits
},
});Error Formatting
Pass an Error object and devink renders a readable, colored stack trace:
try {
throw new Error('Database connection failed');
} catch (err) {
logger.error('Fatal error during startup', err);
}- Error name and message in bold red
- Your source files highlighted with colored file paths and line numbers
node_modulesand Node.js internal frames dimmed so your code stands out
Custom Transports
Route logs anywhere by implementing the Transport interface:
import { createLogger, Transport, TransportContext } from 'devink';
class WebhookTransport implements Transport {
write(ctx: TransportContext) {
fetch('https://hooks.example.com/logs', {
method: 'POST',
body: JSON.stringify({ level: ctx.level, message: ctx.raw }),
});
}
}
const logger = createLogger({
transports: [new WebhookTransport()],
});The TransportContext object provides level, levelValue, message, formatted, raw, timestamp, namespace, and optional meta.
Themes
devink ships with three built-in themes designed for accessibility and developer comfort:
| Theme | Style |
| ----------------------- | ---------------------------------------------------------------------------------------- |
| modernTheme (default) | Soft hex colors (#10b981, #f43f5e, #38bdf8) with dimmed text to reduce eye strain. |
| classicTheme | Standard ANSI colors — Red, Green, Yellow, Cyan. |
| minimalTheme | Prefix icons only, no label text. |
import { createLogger, classicTheme } from 'devink';
const logger = createLogger({ theme: classicTheme });ANSI Utilities
Build your own CLI tools with devink's built-in ANSI module — no extra package needed:
import { ansi } from 'devink';
console.log(ansi.rgb(255, 100, 50, 'True RGB text!'));
console.log(ansi.hex('#34d399', 'Hex coded text!'));
console.log(ansi.color256(128, '256 color support!'));
console.log(ansi.bold(ansi.cyan('Bold and cyan!')));Supported Styles
Modifiers: bold, dim, italic, underline, inverse, reset
Colors: black, red, green, yellow, blue, magenta, cyan, white, gray
Background colors: bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite
Advanced: rgb(r, g, b, text), bgRgb(r, g, b, text), hex(color, text), bgHex(color, text), color256(code, text), bgColor256(code, text)
Utilities: stripAnsi(text), isColorSupported
FAQ
Why use devink instead of chalk?
Chalk is a string styling library — it colors text and that's it. devink is a complete terminal logging system. You get structured output, log levels, child loggers, HTTP middleware, file rotation, field redaction, performance timers, and JSON mode, all with zero dependencies. If you need more than colors, devink replaces an entire stack of packages with a single import.
Why not use winston or pino?
Winston and Pino are excellent loggers with large ecosystems. devink is built for developers who want a fast, zero-dependency alternative that works out of the box without plugins or configuration files. If you need deep ecosystem integrations, those are great choices. If you want something that just works with beautiful defaults, pick devink.
Is it fast enough for production?
Yes. devink uses direct ANSI escape codes, async file writes, and sampling support to minimize overhead. There are no runtime dependencies, no external I/O unless you configure a file or custom transport, and log sampling lets you throttle high-frequency events in hot paths.
Does it work on Windows?
Yes. devink auto-detects terminal capabilities. For the best experience on Windows, use Windows Terminal which supports Truecolor and Unicode out of the box.
Built with care by Harry Mate. If you find devink useful, a Star on GitHub goes a long way.
License
MIT © harrymate22
