Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

dor send --stdin interprets backslash escapes in piped bytes

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

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
50/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
typescript
Domain
cli

Research direction

Start in dor/src/commands/send.ts at the stdin handling and text escape conversion described in the issue. Confirm the current behavior with the documented piping example, then wait for the maintainer to choose between raw stdin by default and documenting the existing behavior. Done means the chosen contract is implemented or documented, with a regression test preserving the relevant bytes.

Written by the indexing model from the issue text.

Description

dor send --stdin interprets backslash escapes in piped bytes, corrupting the documented use case

dor send --stdin reads standard input and forwards it as a text input:

if (flags.stdin === true) {
  if (!readStdin) return { ok: false, message: 'stdin is not available' };
  return { ok: true, value: [{ kind: 'text', text: await readStdin() }] };
}

(send.ts:183-186)

Text inputs then run through interpretTextEscapes unless --raw is set:

input += raw ? item.text : interpretTextEscapes(item.text);

(send.ts:227-228, converting \n \r \t \\ at send.ts:238-253)

Why this is a footgun for --stdin

The flagship stdin example in the help is:

cat script.sh | dor send surface:3 --stdin

(send.ts:115)

Bytes arriving on stdin are already literal — they are not a shell-authored string where a two-character \t stands in for a tab. Shell scripts routinely contain literal backslash sequences (printf 'a\tb', sed 's/\n/ /', grep -P '\d', Windows paths with \\). Piping such a file through --stdin silently rewrites every \n/\r/\t/\\, so the text typed into the target terminal is not the file's contents.

Repro: printf 'printf "a\\tb\\n"\n' | dor send surface:3 --stdin types a real TAB and newline into the middle of the line instead of the literal \t/\n the script source contains.

The escape interpretation is desirable for --text "echo hi\nthere" (a human types escapes on the command line), but for --stdin the input is already-real bytes.

Design question (why an issue, not a drive-by PR)

The current behavior is consistent with the documented contract — the help says "Text input interprets backslash escapes … unless --raw is set" (send.ts:97), and --stdin is documented as text input — so flipping the default is a contract change that needs a maintainer call. Options:

  1. Make --stdin raw by default — treat piped bytes as literal; keep --text interpreting escapes. Most aligned with the cat script.sh | … example. Would need an opt-in flag if anyone wants escape interpretation on stdin.
  2. Keep current behavior, document it — call out at the --stdin help that it interprets escapes and that --raw is needed for literal file contents.

I lean toward option 1, but it changes documented behavior, so I'm leaving the call to a maintainer. Happy to open the PR (including a regression test that pipes a script containing \t and asserts the bytes are preserved) once a direction is chosen.

Surfaced by the nightly code-quality survey.

Dominant language
TypeScript
Stars
5
Forks
1
Avg merge
17h 45m
Merged PRs (30d)
235

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.

More from diffplug/dormouse

All issues in diffplug/dormouse

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.