How Wigolo's CLI Shell Mode Supports NDJSON Piping for Data Processing

Wigolo's interactive shell enables newline-delimited JSON (NDJSON) output via the global --json flag or the .json meta-command, routing machine-readable data to stdout and human-facing messages to stderr for reliable pipeline integration.

Wigolo (KnockOutEZ/wigolo) provides an interactive shell environment designed to operate as both a user-friendly REPL and a machine-readable data processor. By implementing NDJSON piping support, the tool separates presentation from data, allowing seamless integration with stream processors such as jq, grep, and custom scripts without console noise contaminating the JSON stream.

Flag Detection and Shell Initialization

The NDJSON pipeline support begins at the CLI entry point. In src/cli/shell.ts, the argument parser checks for the global --json flag and sets a jsonMode boolean when present [[src/cli/shell.ts#L21-L24]]. The runShell function forwards this flag to the REPL initializer startShell [[src/cli/shell.ts#L95-L99]], ensuring the mode persists throughout the session.

The parser configuration in src/repl/parser.ts (via booleanFlagsFor) ensures --json is treated as a valueless boolean, preventing the flag from accidentally consuming subsequent arguments.

Dual-Stream Architecture for Clean Pipelines

Inside the REPL implementation (src/repl/shell.ts), the architecture follows a strict separation contract documented in the source comments: “Result/data → stdout; everything human‑facing → stderr. This keeps NDJSON stdout parseable (one JSON doc per line, zero human text interleaved)” [[src/repl/shell.ts#L41-L45]].

This design produces two distinct output channels:

  • stdout contains only compact JSON objects when NDJSON mode is active, with exactly one line per command result.
  • stderr carries prompts, error messages, help text, and diagnostic output.

Because stderr handles all interactive elements, downstream tools reading from stdout receive valid NDJSON without filtering noise.

Result Serialization and Formatting

When the shell executes a command, the emitResult helper determines the output format based on the current mode. If NDJSON output is requested, it calls formatJsonLine [[src/repl/shell.ts#L124-L125]], which resides in src/repl/formatters.ts.

The formatJsonLine function serializes data using JSON.stringify(data) without additional formatting, guaranteeing single-line output compatible with NDJSON specifications [[src/repl/formatters.ts#L15-L22]]. This ensures that complex objects containing nested data never introduce internal newlines that would break the line-delimited stream contract.

Runtime Toggling with the .json Command

The REPL supports dynamic mode switching through the .json on|off meta-command [[src/repl/shell.ts#L92-L103]]. This allows users to begin an interactive session in human-readable mode, switch to NDJSON for specific data extraction operations, then return to formatted output without restarting the shell.

Practical Usage Examples

Launch the shell in human-friendly mode for exploration:

wigolo shell

Enable NDJSON piping for automated processing with jq:

wigolo shell --json <<EOF | jq -r '.url'
search "open source licenses"
fetch https://github.com/KnockOutEZ/wigolo
EOF

Toggle NDJSON mode during an existing session:

wigolo> .json on
wigolo> fetch https://example.com
{"url":"https://example.com","markdown":"...","cached":false}
wigolo> .json off
wigolo> fetch https://example.com
Fetch: https://example.com
  # Example Title

  ... (formatted preview)

Summary

  • Wigolo's src/cli/shell.ts parses the --json flag to initialize NDJSON mode at startup and passes it to the REPL initializer.
  • The REPL in src/repl/shell.ts maintains separate stdout (data) and stderr (human interface) streams to ensure parseable output.
  • The formatJsonLine function in src/repl/formatters.ts generates compact single-line JSON using JSON.stringify(data) for NDJSON compatibility.
  • Users can toggle NDJSON output at runtime using the .json on and .json off meta-commands.
  • This architecture enables reliable piping to tools like jq without console noise contamination.

Frequently Asked Questions

How do I enable NDJSON output in Wigolo's shell?

You can enable NDJSON piping by launching the shell with the --json flag: wigolo shell --json. Alternatively, start the shell normally and execute .json on at the REPL prompt to switch modes dynamically without restarting.

Why does Wigolo send human-readable output to stderr instead of stdout?

According to the source code in src/repl/shell.ts, the design intentionally routes all human-facing content (prompts, help text, diagnostics) to stderr while reserving stdout for pure NDJSON data. This separation prevents interactive elements from corrupting JSON streams when piping to other tools.

What function ensures JSON output stays on a single line for NDJSON compatibility?

The formatJsonLine function in src/repl/formatters.ts handles serialization by calling JSON.stringify(data) without beautification, ensuring no internal newlines break the NDJSON format where each line must contain exactly one JSON document.

Can I switch between human-readable and NDJSON modes without restarting the shell?

Yes. The REPL supports the .json on|off command (implemented in src/repl/shell.ts lines 92-103) to toggle NDJSON output at runtime. This allows you to switch to machine-readable format for specific commands, then return to human-friendly display for interactive exploration.

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 →