overengineeringstudio / overengineeringstudio/effect-utils

@overeng/tui-react: make machine output modes safer and less surprising for CLI scripting

Open
#419 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:tui origin:agent type:feature
Dominant language
TypeScript
Stars
82
Forks
2
Avg merge
1d 8h
Merged PRs (30d)
121

Description

Context

Several CLIs built on @overeng/tui-react expose --output json|ndjson|pipe and are usable from scripts, but the current output contract is harder to consume than it needs to be.

The issue is not limited to one CLI. The same behavior shows up in multiple consumers because it comes from the shared tui-react output/runtime layer.

Current behavior

json

Final JSON output is wrapped in a Success / Failure envelope rather than emitting just the app payload.

For non-struct states this becomes:

{ "_tag": "Success", "value": { ...state } }
ndjson

Progressive JSON output emits:

  1. an initial raw state line
  2. intermediate raw state lines
  3. a final wrapped Success / Failure line

This is a valid design, but it is surprising for CLI scripting unless the contract is very explicit.

pipe

pipe is currently a final React render mode, not a strict machine-output mode. That is fine for some commands, but the name strongly suggests something script-safe and raw.

Whether it is safe for scripting depends on the command's view, which makes the contract easy to misread.

Why this is a problem

For CLI scripting, there are two separate needs:

  1. a stable machine-readable contract
  2. a human-readable final render that happens to work when piped

Right now these are too close together.

The result is:

  • JSON consumers need CLI-specific decoding knowledge
  • NDJSON consumers need to understand initial-state and final-envelope semantics
  • pipe can look machine-safe while actually rendering human framing

Relevant implementation points

Shared behavior appears to come from these places:

  • packages/@overeng/tui-react/src/effect/TuiApp.tsx
    • final JSON wrapping in Success / Failure
    • progressive NDJSON initial raw-state emission + final wrapped line
  • packages/@overeng/tui-react/src/effect/OutputMode.tsx
    • pipe defined as final React output mode
  • packages/@overeng/tui-react/src/effect/cli.tsx
    • shared outputOption / outputModeLayer used by multiple CLIs

Desired behavior

A more explicit split between human and machine output modes.

Possible directions:

  1. Keep current behavior, but document it much more explicitly.
  2. Introduce a stricter machine mode, for example raw or json-final / json-stream.
  3. Make json emit only the payload by default, and reserve envelopes for a separate mode.
  4. Make ndjson emit a documented event stream shape instead of mixing raw states with a wrapped final line.
  5. Rename or better document pipe so it is clear that it is a final visual render mode, not necessarily script-safe.

Recommendation

I think the minimum improvement should be:

  • document the exact contracts for json, ndjson, and pipe
  • clarify that pipe is a final render mode
  • add one truly machine-safe mode with a minimal predictable contract

Workaround

Consumers can use json today, but they need to know about the extra envelope shape. ndjson is also usable, but only if they explicitly handle the initial-state line and final wrapped line.


Filed by an AI assistant on behalf of @schickling

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read packages/@overeng/tui-react/src/effect/TuiApp.tsx, OutputMode.tsx, and cli.tsx to trace the shared json, ndjson, and pipe contracts used by multiple CLIs. Compare the current behavior with the listed directions and establish a documented, predictable machine-output contract while making the final render behavior of pipe explicit; the issue does not name a specific test.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.