Skip to content

CLI: JSON stream output truncated when process exits quickly (stdout buffer not flushed) #29866

@zoutaojlq

Description

@zoutaojlq

Description

When using opencode run <task> --format json and redirecting the output to a file or piping it to another command, the final JSON events (typically text or step_finish) are frequently missing. The output often stops after the initial step_start event.

Steps to Reproduce:

  1. Run a simple task with JSON output redirected to a file:
    opencode run "Please reply Hello" --format json > output.jsonl
    cat output.jsonl
  2. Observe that the file often contains only the {"type":"step_start", ...} line, missing the subsequent {"type":"text", ...} and {"type":"step_finish", ...} events.
  3. Compare with piping to jq:
    opencode run "Please reply Hello" --format json | jq .
    While more stable, this also occasionally fails to show the final events if the process exits too quickly.

Expected Behavior:
All JSON Lines events, including the final text response and step_finish marker, should be consistently written to stdout and successfully captured by redirection or pipes.

Actual Behavior:
The stdout buffer appears to not be fully flushed before the opencode process terminates. This is a classic race condition where the process exits before the OS writes the remaining buffered data to the file or pipe.

Environment:

  • OS: macOS 15.7.4
  • Node.js Version: [Insert your Node version, e.g., v22.x]
  • OpenCode Version: [Insert your opencode version, e.g., run opencode --version]

Suggested Fix:
Ensure that the CLI explicitly waits for process.stdout to drain before exiting. In Node.js, this can be achieved by:

process.stdout.write(lastChunk);
process.stdout.on('drain', () => {
    process.exit(0);
});
// Or ensure all streams are properly ended and drained in the shutdown logic.

Workaround for Users:
Currently, the most reliable way to capture full output in scripts is to implement a retry mechanism with content validation:

#!/bin/bash
for i in {1..3}; do
    opencode run "$TASK" --format json | tee output.jsonl > /dev/null
    if grep -q '"type":"text"' output.jsonl; then
        exit 0
    fi
done
echo "Failed to capture complete output after retries."
exit 1

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions