Skip to content

cli: piped stdout truncated at 64 KiB (breaks Homebrew fish completions) #55525

Open

Description

@samandmoore

👋 Hi! Thanks for opencode. I've been looving this tool. I'm a fish user and I'm running into a small issue.

Summary

opencode --completions fish truncates its output at exactly 65,536 bytes when stdout is a pipe. Homebrew generates completions through a pipe, so the fish completion file it ships ends mid-line. Every completion attempt then throws a fish parse error.

Environment

  • opencode version: 2.0.25
  • OS: macOS (Darwin 25.6.0, arm64)
  • Terminal: kitty
  • Shell: fish
  • Install/channel: Homebrew (opencode formula), latest
  • Active plugins: none

Reproduction

opencode --completions fish > out.fish; wc -c < out.fish   # 67907
opencode --completions fish | wc -c                        # 65536
opencode --completions fish | cat >/dev/null; echo $?      # 0 (silent)

Via Homebrew (generate_completions_from_executable(bin/"opencode", "--completions")):

  1. brew install opencode
  2. In fish, type opencode m

Expected Behavior

Piped output is identical to file output, and completions work.

Actual Behavior

❯ opencode m/opt/homebrew/share/fish/vendor_completions.d/opencode.fish (line 354): Unexpected end of string, quotes are not balanced
complete -c opencode -n '__f

The installed file is exactly 65,536 bytes and stops mid-line, without the ###-end-opencode-completions-### marker.

Additional Context

🤖 AI-assisted

Activity

  1. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for the clear report, @samandmoore! I reproduced this on 2.0.25 (on Linux, so it isn't macOS-specific), and it still happens on the latest dev (13afea6a1) run from source.

    • opencode --completions fish > file writes the complete script (67,907 bytes on 2.0.25), ending with ###-end-opencode-completions-###.
    • opencode --completions fish | wc -c and opencode --completions fish | (sleep 1; wc -c) both print exactly 65,536. The output stops mid-line, has no end marker, and the exit code is 0.

    The script below compares the file output with the piped output.

    Your workaround is the right one for now: redirect to a file instead of piping, e.g. opencode --completions fish > ~/.config/fish/completions/opencode.fish.

    Related: #52925 is the same problem in opencode api get. Its open fix, #52955, only changes the api get command, so it won't cover --completions on its own.

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Reproduces anomalyco/opencode#55525: `opencode --completions fish` is truncated
    # at 65536 bytes when stdout is a pipe, but complete when redirected to a file.
    # Usage: ./repro.sh                      (uses `opencode` from PATH)
    #        OC_DEV=/path/to/checkout ./repro.sh   (runs the CLI from source)
    set -u
    oc() {
      if [ -n "${OC_DEV:-}" ]; then
        bun --conditions=browser \
          --preload="$OC_DEV/packages/tui/node_modules/@opentui/solid/scripts/preload.js" \
          "$OC_DEV/packages/cli/src/index.ts" "$@"
      else
        opencode "$@"
      fi
    }
    tmp=$(mktemp -d)
    echo "version: $(oc --version)"
    oc --completions fish > "$tmp/file.fish"
    file_bytes=$(wc -c < "$tmp/file.fish")
    pipe_bytes=$(oc --completions fish | cat | wc -c)
    slow_bytes=$(oc --completions fish | (sleep 1; wc -c))
    echo "redirect to file: $file_bytes bytes"
    echo "pipe:             $pipe_bytes bytes"
    echo "slow pipe:        $slow_bytes bytes"
    oc --completions fish | cat > "$tmp/pipe.fish"
    if grep -q '###-end-opencode-completions-###' "$tmp/pipe.fish"; then
      echo "piped output has end marker"
    else
      echo "piped output is MISSING the end marker (truncated)"
    fi
    if [ "$file_bytes" = "$pipe_bytes" ] && [ "$file_bytes" = "$slow_bytes" ]; then
      echo "OK: outputs match"; exit 0
    else
      echo "BUG: piped output truncated"; exit 1
    fi

    Run it: bash repro.sh

  2. Velmet44 commented on Oct 15, 2026

    @Velmet44
    Contributor

    Update from my side: I could not reproduce this on current v2 (source build, Bun 1.4.2, Windows). --completions fish is ~68.5 KB here and arrives byte-identical via pipe vs redirect, end marker included - above the old 64 KiB ceiling. A synthetic 5 MB write plus immediate process.exit(0) also arrives fully intact, so the exit path drains correctly on this runtime. (Side note: my first pipe-vs-file comparison looked truncated only because PowerShell's redirect writes UTF-16.) The 2.0.25 truncation looks runtime-version-specific rather than an opencode bug, so no code change from me. Reporter: does this still happen for you on latest?

  3. bercedev commented on Oct 15, 2026

    @bercedev
    Contributor

    Checked on Linux with the 2.0.29 release binary, and I can't reproduce it there: opencode --completions fish > file, opencode --completions fish | wc -c and opencode --completions fish | (sleep 1; wc -c) all give 69,533 bytes, and the piped output ends with ###-end-opencode-completions-###. So on this build the pipe isn't cut at 64 KiB any more, which matches what @Velmet44 saw on a source build.

  4. neoscaler commented on Oct 22, 2026

    @neoscaler

    Additional data point: this still reproduces on opencode 2.0.32 on Linux (NixOS), installed from nixpkgs.

    $ opencode --version
    2.0.32
    $ opencode --completions fish | wc -c
    65536
    $ opencode --completions fish > /tmp/opencode.fish; wc -c < /tmp/opencode.fish
    69533
    $ opencode --completions fish | tail -c 15 | xxd
    00000000: 7361 626c 6520 7265 6d6f 7465 270a 63    sable remote'.c

    So the piped output is still cut at exactly 65,536 bytes on this build, while the redirect writes the full 69,533 bytes including ###-end-opencode-completions-###.

    The interesting part is the packaging impact: Nix builds the completion files at derivation build time, capturing stdout through a pipe. The shipped share/fish/vendor_completions.d/opencode.fish therefore contains the truncated script and ends with a bare c (no trailing newline, no end marker). Every fish user on NixOS gets this as soon as fish autoloads the completion script:

    fish: Unknown command: c
    /nix/store/...-opencode-2.0.32/share/fish/vendor_completions.d/opencode.fish (line 355):
    c
    ^
    from sourcing file /nix/store/...-opencode-2.0.32/share/fish/vendor_completions.d/opencode.fish
    

    Reproducible with complete -C 'opencode ' in fish 4.9.3.

    Since the truncation happens at build time, the workaround of regenerating into ~/.config/fish/completions/opencode.fish via redirect works (fish sources the user completion file instead of the vendor one), but the packaged file stays broken for everyone else until this is fixed at the stdout/exit level.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions