A unified output-control system for the @orkestrel line — one
environment-agnostic engine composing five concerns over a shared substrate:
a style engine (Styler + ANSIRenderer, style as data), structured
logging (Logger, LoggerManager), narrative reporting (Reporter),
console & stream capture (Capture, ProcessCapture), and live
animations (Spinner, Progress). Built to sit beside @orkestrel/emitter
(observable lifecycle), reusing it as it takes shape.
npm install @orkestrel/console- Node.js >= 24
- Core is ESM; the
./serversubpath ships dual ESM+CJS builds;./browseris ESM-only
The same code retargets to any environment by swapping the sink:
import { createLogger, createReporter, createSpinner } from '@src/core'
const logger = createLogger({ name: 'http', level: 'info' }) // ANSI to the console by default
logger.info('request', { method: 'GET', path: '/' }) // a styled, leveled line + an `entry` event
logger.emitter.on('entry', (record) => archive(record)) // the transport seam — file / JSON / remote
const reporter = createReporter()
reporter.section('Build')
reporter.step('bundling', { index: 2, total: 5 }) // [2/5] bundling
reporter.status('success', 'built in 1.2s') // ✔ built in 1.2s
const spinner = createSpinner({ message: 'deploying' })
spinner.start() // a self-driving glyph cycle, `\r`-redrawn by an overwrite-capable sink
spinner.success('deployed') // ✔ deployed — the timer cleared, the line committedStyle is data — a Style is a frozen record rendered through a swappable
RendererInterface (ANSIRenderer by default):
import { createStyler } from '@src/core'
const styler = createStyler()
console.log(styler.red.bold('hi')) // renders through the injected rendererTake control of console.* on the read side with Capture:
import { createCapture } from '@src/core'
const capture = createCapture({ mirror: true })
capture.start()
console.log('hello')
capture.messages() // [{ level: 'log', text: 'hello', time: ... }]
capture.stop()On the server, ProcessCapture takes over the whole process output surface
(direct process.stdout/stderr writes, not just console.*):
import { createProcessCapture } from '@src/server'
const capture = createProcessCapture({ levels: ['stderr'], mirror: true })
capture.start()See guides/src/console.md for the full documented surface — styling, logging, reporting, capture, and animations.
Published as three environment-scoped entry points per the exports field
in package.json: . (the shared, environment-agnostic core engine, the
default ANSI renderer, and the console sink), ./server (adds the server
sink and ProcessCapture), and ./browser (adds the browser sink
translating ANSI to console.log('%c…', css)). Core and ./server ship
dual ESM+CJS builds; ./browser is ESM-only.