is-tty 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # is-tty
2
+
3
+ > CLI tool and API to detect whether the current environment is interactive (TTY).
4
+
5
+ Useful for determining if your script can safely prompt users for input, or if it should fall back to non-interactive mode (e.g., in CI environments).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # With bun
11
+ bun add -d is-tty
12
+
13
+ # With npm
14
+ npm install -D is-tty
15
+
16
+ # Global install for CLI usage
17
+ npm install -g is-tty
18
+ ```
19
+
20
+ ## CLI Usage
21
+
22
+ ```bash
23
+ # Exit code 0 if interactive, 1 if non-interactive
24
+ if is-tty; then
25
+ echo "✅ Interactive terminal"
26
+ else
27
+ echo "❌ Non-interactive (e.g., CI, pipe, dumb terminal)"
28
+ fi
29
+
30
+ # Use it in package.json scripts
31
+ {
32
+ "scripts": {
33
+ "postinstall": "is-tty && npx @lvxiaohui/ai-rule || echo 'Skipping in non-interactive env'"
34
+ }
35
+ }
36
+ ```
37
+
38
+ ## API Usage
39
+
40
+ ```javascript
41
+ const isTTY = require('is-tty');
42
+
43
+ if (isTTY()) {
44
+ console.log('✅ Interactive terminal');
45
+ // Prompt user for input, run interactive commands, etc.
46
+ } else {
47
+ console.log('❌ Non-interactive environment');
48
+ // Fallback to silent/default mode
49
+ }
50
+ ```
51
+
52
+ ## Detection Logic
53
+
54
+ | Condition | Interactive? |
55
+ | :--- | :---: |
56
+ | `process.stdout.isTTY === true` | ✅ |
57
+ | `CI=true` or `CI=1` | ❌ |
58
+ | `TERM=dumb` | ❌ |
59
+ | Otherwise | ✅ |
60
+
61
+ ## License
62
+
63
+ MIT
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "is-tty",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool to detect whether the current environment is interactive (TTY).",
5
+ "bin": {
6
+ "is-tty": "./src/cli.js"
7
+ },
8
+ "main": "./src/index.js",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./src/index.js",
12
+ "require": "./src/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "test": "bun test",
17
+ "prepublishOnly": "bun test"
18
+ },
19
+ "keywords": [
20
+ "tty",
21
+ "interactive",
22
+ "cli",
23
+ "terminal",
24
+ "stdout",
25
+ "isatty",
26
+ "ci"
27
+ ],
28
+ "author": "rainmanhhh",
29
+ "license": "MIT",
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "files": [
34
+ "src/",
35
+ "README.md",
36
+ "LICENSE"
37
+ ]
38
+ }
package/src/cli.js ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+
3
+ const isTTY = require('./index.js');
4
+
5
+ const interactive = isTTY();
6
+
7
+ if (process.argv.includes('--json') || process.argv.includes('-j')) {
8
+ process.stdout.write(JSON.stringify({ interactive }) + '\n');
9
+ } else if (process.argv.includes('--verbose') || process.argv.includes('-v')) {
10
+ process.stdout.write(
11
+ `stdout.isTTY: ${process.stdout.isTTY}\n` +
12
+ `stdin.isTTY: ${process.stdin.isTTY}\n` +
13
+ `stderr.isTTY: ${process.stderr.isTTY}\n` +
14
+ `CI: ${JSON.stringify(process.env.CI)}\n` +
15
+ `TERM: ${JSON.stringify(process.env.TERM)}\n` +
16
+ `interactive: ${interactive}\n`
17
+ );
18
+ }
19
+
20
+ process.exit(interactive ? 0 : 1);
package/src/index.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Check if the current environment is interactive (TTY).
3
+ *
4
+ * Detection logic:
5
+ * - `process.stdout.isTTY` is `true` — interactive
6
+ * - `CI` env var is set to a truthy value — non-interactive (e.g., GitHub Actions, GitLab CI)
7
+ * - `TERM` env var is `dumb` — non-interactive
8
+ * - Otherwise — interactive
9
+ *
10
+ * @returns {boolean} `true` if the environment is interactive, `false` otherwise.
11
+ */
12
+ function isTTY() {
13
+ // Direct TTY check on stdout (most reliable)
14
+ if (process.stdout.isTTY) {
15
+ return true;
16
+ }
17
+
18
+ // CI environments are non-interactive by definition
19
+ const ci = process.env.CI;
20
+ if (ci !== undefined && ci !== '' && ci !== '0' && ci !== 'false') {
21
+ return false;
22
+ }
23
+
24
+ // Dumb terminals (e.g., Emacs, some CI runners) are non-interactive
25
+ if (process.env.TERM === 'dumb') {
26
+ return false;
27
+ }
28
+
29
+ // Fallback: if neither CI nor dumb terminal, check stdin/stderr
30
+ if (process.stdin.isTTY || process.stderr.isTTY) {
31
+ return true;
32
+ }
33
+
34
+ // If all streams are non-TTY and no explicit CI/TERM signal, assume non-interactive
35
+ return false;
36
+ }
37
+
38
+ module.exports = isTTY;
39
+ module.exports.default = isTTY;