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 +63 -0
- package/package.json +38 -0
- package/src/cli.js +20 -0
- package/src/index.js +39 -0
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;
|