TTY vs Non-TTY Execution Modes in abx-dl: Output Behavior Explained

abx-dl detects terminal interactivity via sys.stdout.isatty() and automatically switches between a rich interactive dashboard for humans and machine-readable JSONL streams for automation pipelines.

The archivebox/abx-dl repository implements a dual-mode output system that adapts to its execution environment. When running in an interactive terminal, the tool provides visual feedback through progress bars and summary tables. In non-interactive environments, it streams structured data suitable for piping into other tools.

How abx-dl Detects TTY Mode

The core detection logic relies on Python’s sys.stdout.isatty() method. In abx_dl/executor.py, the download() function evaluates this boolean to determine whether stdout is connected to an interactive terminal.

This single check controls multiple downstream behaviors, including UI rendering and output destination selection. The flag propagates through the execution chain, ultimately determining whether results are written silently to files or echoed to standard output.

TTY Mode: Interactive Dashboard

When isatty() returns True, abx-dl activates its full human-facing interface implemented in abx_dl/cli.py (lines 87-126).

Visual Progress Indicators

The tool renders Rich library components including spinners, progress bars, and formatted summary tables. Users see real-time plugin execution status and dependency warnings styled with colors and formatting.

Silent File-Only Output

Despite the visual verbosity, TTY mode suppresses JSONL output to stdout. In abx_dl/executor.py (lines 400-405), the write_jsonl() helper receives also_print=False, ensuring results are appended only to index.jsonl without cluttering the terminal.

Styled Warning Messages

Dependency warnings and background-hook failures are displayed as formatted console messages when is_tty is true. According to the source code in abx_dl/executor.py (lines 426-432 and 281-287), these messages use Rich styling for immediate visual attention.

Non-TTY Mode: JSONL Stream for Pipelines

When stdout is not a TTY—such as when piping to jq or running in CI environments—the tool switches to machine-readable output.

Streaming JSON Lines to stdout

In abx_dl/executor.py, the also_print parameter is set to True when is_tty is false. This triggers the printing logic in abx_dl/models.py (lines 93-100), where each result record is serialized and written to stdout immediately upon completion.

No Interactive UI Overhead

The Rich progress components are completely bypassed. Instead of visual feedback, the generator consumes data silently while emitting parseable JSON Lines. This design enables Unix pipeline patterns:

abx-dl https://example.com | jq '.status'

Key Implementation Details

Three primary files manage the dual-mode behavior:

File Function TTY Behavior Non-TTY Behavior
abx_dl/executor.py download() also_print=False also_print=True
abx_dl/cli.py Main command block Rich UI rendered (lines 87-126) UI skipped
abx_dl/models.py write_jsonl() File write only File + stdout print

The also_print flag is the critical switch. When True, the function in abx_dl/models.py (lines 93-100) executes print(json_line, flush=True) after writing to the index file.

Practical Examples

Running in an Interactive Terminal (TTY)

$ abx-dl https://example.com

Output features:

  • Animated progress spinner
  • Plugin status table
  • Final summary screen
  • Results stored in index.jsonl (not visible on screen)

Running in a Pipeline (Non-TTY)

$ abx-dl https://example.com | jq -s '.'

Output features:

  • Raw JSON Lines streamed to stdout
  • No progress indicators or colors
  • Each archive result immediately parseable

Example output line:

{"type":"ArchiveResult","plugin":"wget","status":"succeeded","output_files":["wget/wget.html"]}

Capturing Output While Preserving Warnings

Even in non-TTY mode, warnings write to stderr separately from the JSONL stdout stream, allowing proper log separation:

$ abx-dl https://example.com 2>warnings.log | jq '.'

Summary

  • abx-dl uses sys.stdout.isatty() to detect terminal interactivity at runtime in abx_dl/executor.py.
  • TTY mode activates Rich UI components in abx_dl/cli.py while suppressing JSONL stdout output via also_print=False in abx_dl/executor.py (lines 400-405).
  • Non-TTY mode streams machine-readable JSON Lines to stdout through the write_jsonl() helper in abx_dl/models.py (lines 93-100), enabling pipeline integration.
  • Warning messages adapt to the mode: styled in TTY, plain text to stderr in non-TTY.
  • Background hook finalization respects the same flag (lines 281-287 in abx_dl/executor.py), ensuring consistent output behavior throughout the execution lifecycle.

Frequently Asked Questions

How does abx-dl detect whether it is running in a TTY?

The tool calls sys.stdout.isatty() in the download() function within abx_dl/executor.py. This standard Python method returns True when the output stream is connected to an interactive terminal and False when redirected to a pipe or file.

Why do I see JSON Lines when piping abx-dl but not when running it normally?

In TTY mode, abx-dl sets also_print=False when calling write_jsonl() (lines 400-405 in abx_dl/executor.py), directing output only to index.jsonl. In non-TTY mode, also_print=True triggers the print statement in abx_dl/models.py (lines 93-100), emitting each record to stdout for pipeline consumption.

Can I force JSONL output even when running in a terminal?

While the primary logic hinges on isatty(), you can effectively force non-TTY behavior by redirecting stdout through a pipe externally (e.g., abx-dl URL | cat). The detection is automatic based on file descriptor properties; there is no separate configuration flag required.

Does non-TTY mode disable warning messages entirely?

No. Warnings and dependency messages are always written to stderr. In TTY mode, they receive Rich formatting and styling (lines 426-432 in abx_dl/executor.py). In non-TTY mode, the same messages appear as plain text in the error stream, ensuring visibility without corrupting the JSONL data stream on stdout.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →