osc-progress
v0.2.0
Published
Tiny TypeScript helper for OSC 9;4 terminal progress sequences.
Downloads
1,067
Maintainers
Readme
⏳ osc-progress — Tiny lib for OSC 9;4 terminal progress.
Tiny TypeScript helper for OSC 9;4 terminal progress sequences (used by terminals like Ghostty / WezTerm / Windows Terminal).
Install
pnpm add osc-progressUsage
import process from 'node:process'
import { startOscProgress } from 'osc-progress'
const stop = startOscProgress({
label: 'Fetching',
write: (chunk) => process.stderr.write(chunk),
env: process.env,
isTty: process.stderr.isTTY,
})
// ...do work...
stop()Indeterminate (spinner-like) mode:
import { startOscProgress } from 'osc-progress'
const stop = startOscProgress({ label: 'Waiting', indeterminate: true })
// ...
stop()Strip OSC progress from stored logs:
import { sanitizeOscProgress } from 'osc-progress'
const clean = sanitizeOscProgress(text, /*keepOsc*/ process.stdout.isTTY)API
supportsOscProgress(env?, isTty?, options?)
Returns true when emitting OSC 9;4 progress makes sense.
Heuristics:
- requires a TTY
- enables for
TERM_PROGRAM=ghostty*,TERM_PROGRAM=wezterm*, orWT_SESSION(Windows Terminal)
Optional overrides:
options.disabled/options.forceoptions.disableEnvVar/options.forceEnvVar(expects= "1")
startOscProgress(options?)
Starts a best-effort progress indicator and returns stop(): void.
Notes:
labelis appended as extra payload; not part of the canonical OSC 9;4 spec (many terminals ignore it, some show it).- default is a timer-driven
0% → 99%progression (never completes by itself). terminatordefaults tost(ESC \\);belis also supported.
createOscProgressController(options?)
Returns a small stateful controller:
setIndeterminate(label)setPercent(label, percent)clear()
Use this when you already have real progress (bytes/total, seconds/total) and want determinate terminal progress instead of the timer-based ramp.
Notes:
- returns no-op methods when
supportsOscProgress(...)is false percentis rounded and clamped to0..100clear()uses the last label (or the initialoptions.labelif nothing was set yet)
import process from 'node:process'
import { createOscProgressController } from 'osc-progress'
const osc = createOscProgressController({
env: process.env,
isTty: process.stderr.isTTY,
write: (chunk) => process.stderr.write(chunk),
})
osc.setIndeterminate('Connecting')
osc.setPercent('Downloading', 12)
osc.setPercent('Downloading', 67)
osc.clear()sanitizeOscProgress(text, keepOsc)
Removes OSC 9;4 progress sequences (terminated by BEL, ST (ESC \\), or 0x9c).
Semantics / portability
OSC 9;4 is widely implemented, but state 4 is ambiguous across terminals (some treat it as paused, some as warning).
This library exposes the raw numeric state and does not try to reinterpret it.
