Mischief

43 / Code

Terminal Output

Streaming command output with stderr called out, an exit code, and scroll that follows without trapping you.

pnpm install mischief-ui
Running

Installation

Copy the source into your project, or keep it behind a package.

npx shadcn@latest add Tinkerers-Labs/mischief-ui/terminal-output
import { TerminalOutput } from "mischief-ui/terminal-output"
Also installs
  • lucide-react

Or paste it in yourself. The source imports the shared cn helper from @/lib/utils, so point that at your own copy.

registry/default/terminal-output/terminal-output.tsx
"use client" import * as React from "react"import { ChevronRight, Loader2 } from "lucide-react" import { cn } from "@/lib/utils" export type TerminalStream = "stdout" | "stderr" export type TerminalLine = {  text: string  stream?: TerminalStream} 

Usage

export function Install() {
  return (
    <TerminalOutput
      command="pnpm install"
      output={lines}
      running={pending}
      exitCode={code}
    />
  )
}

Streaming output

Append to the array as lines arrive and the log grows. Keep running true until the command settles, then pass its exit code -- that is what turns the running indicator into a result.

const [lines, setLines] = useState<TerminalLine[]>([])
const [exitCode, setExitCode] = useState<number>()

for await (const chunk of process.stdout) {
  setLines((current) => [...current, { text: chunk }])
}

Send stderr through with stream set, rather than merging both into one string, so failures stay distinguishable after the fact.

Following, and when it stops

The log sticks to the newest line while it is already at the bottom. The moment the reader scrolls up it stops following, and it resumes when they come back within a couple of dozen pixels of the end. Reading back through output is therefore never interrupted by more of it arriving.

ANSI escape sequences are stripped rather than rendered, so colour codes from a shell do not appear as noise. Colour is not reconstructed: stderr is distinguished, and nothing else is.

API

outputstring | (TerminalLine | string)[]A plain string is split on newlines as stdout.
commandstringThe command that produced the output, shown above it.
cwdstringWorking directory, shown beside the command on wider screens.
runningbooleanShows the running indicator and marks the log busy.
exitCodenumberShown once settled. Anything other than zero reads as a failure.
maxHeightnumber | stringHeight before the log scrolls. Defaults to "18rem".
followbooleanKeeps the newest line in view. Defaults to true.

TerminalLine

textstringOne line, without its ending. ANSI escapes are stripped.
stream"stdout" | "stderr"Which stream it came from. Defaults to "stdout".

Accessibility

Output is a log region marked busy while the command runs, so assistive technology reads new lines without the page stealing focus. stderr is distinguished by a data attribute as well as colour. Following is abandoned the moment the reader scrolls up and resumes when they return to the bottom, so reading back is never interrupted. ANSI escape sequences are stripped rather than rendered.