How to do it in Node.js or TypeScript
UPDATE: I made a package in a minute
I see people commenting on how to do this for other languages ββin Eliot Sykes' answer, but the JavaScript solution is a bit long, so I will make a separate answer.
I'm not sure if O_NOCTTY is O_NOCTTY , but it does not seem to affect anything. I do not really understand what a control terminal is. Description of GNU documents . I think this means that with O_NOCTTY enabled O_NOCTTY you cannot send CTRL+C process (if it does not already have a control terminal). In this case, I will leave it turned on so that you do not control the spawned processes. I think that the process of the main node should already have a control terminal.
I adapted the answer from this GitHub question
I do not see any documents on how to use the tty.ReadStream constructor, so I made some trial and error / delved into the source code of Node.js.
You should use Object.defineProperty because the internal device of Node.js also uses it and does not define a setter. An alternative is to do process.stdin.fd = fd , but I get duplicate output in this way.
Anyway, I wanted to use this with Husky.js , and it seems to be working so far. I should probably turn this into an npm package when I have time.
Node.js
#!/usr/bin/env node const fs = require('fs'); const tty = require('tty'); if (!process.stdin.isTTY) { const { O_RDONLY, O_NOCTTY } = fs.constants; let fd; try { fd = fs.openSync('/dev/tty', O_RDONLY + O_NOCTTY); } catch (error) { console.error('Please push your code in a terminal.'); process.exit(1); } const stdin = new tty.ReadStream(fd); Object.defineProperty(process, 'stdin', { configurable: true, enumerable: true, get: () => stdin, }); } ...Do your stuff... process.stdin.destroy(); process.exit(0);
Typescript:
#!/usr/bin/env ts-node import fs from 'fs'; import tty from 'tty'; if (!process.stdin.isTTY) { const { O_RDONLY, O_NOCTTY } = fs.constants; let fd; try { fd = fs.openSync('/dev/tty', O_RDONLY + O_NOCTTY); } catch (error) { console.error('Please push your code in a terminal.'); process.exit(1); } // @ts-ignore: 'ReadStream' in @types/node incorrectly expects an object. // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/37174 const stdin = new tty.ReadStream(fd); Object.defineProperty(process, 'stdin', { configurable: true, enumerable: true, get: () => stdin, }); } ...Do your stuff... process.stdin.destroy(); process.exit(0);