@leverageaiapps/gogogo 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LeverageAI Apps
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # GoGoGo
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@leverageaiapps/gogogo.svg)](https://www.npmjs.com/package/@leverageaiapps/gogogo)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ CLI tool to forward terminal sessions to your mobile device via Cloudflare Tunnel. **Code anywhere from your pocket.**
7
+
8
+ <p align="center">
9
+ <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="Node.js">
10
+ <img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-blue" alt="Platform">
11
+ </p>
12
+
13
+ ## Features
14
+
15
+ - **Instant Setup** - One command to start forwarding your terminal
16
+ - **Mobile Access** - Access your terminal from any device with a browser
17
+ - **Secure** - Cryptographic token auth with httpOnly cookies
18
+ - **No Port Forwarding** - Uses Cloudflare Quick Tunnel (no account needed)
19
+ - **Real-time** - WebSocket-based communication for instant feedback
20
+ - **PTY Support** - Full terminal emulation with node-pty
21
+ - **Image Paste** - Paste images from clipboard to upload file paths
22
+
23
+ ## Prerequisites
24
+
25
+ ### Install cloudflared
26
+
27
+ GoGoGo requires `cloudflared` to create secure tunnels:
28
+
29
+ **macOS:**
30
+ ```bash
31
+ brew install cloudflared
32
+ ```
33
+
34
+ **Ubuntu/Debian:**
35
+ ```bash
36
+ sudo mkdir -p --mode=0755 /usr/share/keyrings
37
+ curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
38
+ echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
39
+ sudo apt-get update && sudo apt-get install cloudflared
40
+ ```
41
+
42
+ **Arch Linux:**
43
+ ```bash
44
+ sudo pacman -S cloudflared
45
+ ```
46
+
47
+ For other systems, see the [official installation guide](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/).
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ npm install -g @leverageaiapps/gogogo
53
+ ```
54
+
55
+ **Verify Installation:**
56
+ ```bash
57
+ gogogo --version
58
+ ```
59
+
60
+ ## Quick Start
61
+
62
+ ```bash
63
+ # Start a terminal session
64
+ gogogo start
65
+
66
+ # Start with a specific command
67
+ gogogo start claude
68
+ gogogo start python
69
+ gogogo start vim
70
+ ```
71
+
72
+ A QR code will appear - scan it with your phone to access your terminal. Authentication is automatic via a secure token embedded in the URL.
73
+
74
+ ## Usage
75
+
76
+ ### Basic Commands
77
+
78
+ ```bash
79
+ # Start a terminal session (opens your default shell)
80
+ gogogo start
81
+
82
+ # Start with a machine name
83
+ gogogo start --name "My Laptop"
84
+
85
+ # Start a specific command
86
+ gogogo start claude
87
+ gogogo start "claude --dangerously-skip-permissions"
88
+ ```
89
+
90
+ ### Options
91
+
92
+ | Option | Short | Description |
93
+ |--------|-------|-------------|
94
+ | `--name <name>` | `-n` | Set a custom machine name (default: hostname) |
95
+ | `--version` | `-V` | Show version number |
96
+ | `--help` | `-h` | Show help |
97
+
98
+ ## How It Works
99
+
100
+ 1. Run `gogogo start [command]` in your terminal
101
+ 2. GoGoGo starts a local web server and creates a Cloudflare tunnel
102
+ 3. A QR code appears with your unique, authenticated URL
103
+ 4. Scan the QR code with your phone
104
+ 5. Your terminal is now accessible from your mobile device!
105
+
106
+ ### Exiting
107
+
108
+ To exit GoGoGo, you can:
109
+ - Type `exit` in the terminal (or the command to exit your current program)
110
+ - Press `Ctrl+C` in the terminal where you ran `gogogo start`
111
+ - Close the terminal window
112
+
113
+ When you see **"Terminal session ended."**, the session has been successfully closed.
114
+
115
+ ## Security
116
+
117
+ - **Token Authentication** - Each session gets a unique 128-bit cryptographic token
118
+ - **httpOnly Cookies** - Token is stored as a secure, httpOnly cookie after first visit
119
+ - **WebSocket Auth** - WebSocket connections are verified via cookie
120
+ - **Connection Limits** - Max 10 concurrent WebSocket connections
121
+ - **Rate Limiting** - Message rate limiting per connection
122
+ - **Security Headers** - CSP, HSTS, X-Frame-Options, and more
123
+
124
+ ## Troubleshooting
125
+
126
+ ### Error: posix_spawnp failed
127
+
128
+ Fix permissions on the node-pty spawn-helper:
129
+
130
+ ```bash
131
+ # macOS ARM (M1/M2/M3)
132
+ chmod +x node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper
133
+
134
+ # macOS Intel
135
+ chmod +x node_modules/node-pty/prebuilds/darwin-x64/spawn-helper
136
+
137
+ # Linux x64
138
+ chmod +x node_modules/node-pty/prebuilds/linux-x64/spawn-helper
139
+ ```
140
+
141
+ ### cloudflared not found
142
+
143
+ Install cloudflared following the [Prerequisites](#prerequisites) section, then verify:
144
+
145
+ ```bash
146
+ cloudflared --version
147
+ ```
148
+
149
+ ## Contributing
150
+
151
+ Contributions are welcome! Please feel free to submit a Pull Request.
152
+
153
+ 1. Fork the repository
154
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
155
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
156
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
157
+ 5. Open a Pull Request
158
+
159
+ ## License
160
+
161
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
162
+
163
+ ## Acknowledgments
164
+
165
+ - [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/) for secure tunneling
166
+ - [node-pty](https://github.com/microsoft/node-pty) for PTY support
167
+ - [xterm.js](https://xtermjs.org/) for terminal emulation in the browser
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Start Cloudflare Quick Tunnel
3
+ * Returns the generated tunnel URL
4
+ */
5
+ export declare function startTunnel(localPort?: number): Promise<string>;
6
+ export declare function stopTunnel(): void;
7
+ /** Register a callback for when the tunnel crashes unexpectedly */
8
+ export declare function onTunnelCrash(callback: (code: number | null) => void): void;
9
+ //# sourceMappingURL=cloudflare-tunnel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-tunnel.d.ts","sourceRoot":"","sources":["../src/cloudflare-tunnel.ts"],"names":[],"mappings":"AAqFA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAcrE;AAsED,wBAAgB,UAAU,IAAI,IAAI,CAQjC;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAE3E"}
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.startTunnel = startTunnel;
37
+ exports.stopTunnel = stopTunnel;
38
+ exports.onTunnelCrash = onTunnelCrash;
39
+ const child_process_1 = require("child_process");
40
+ const fs = __importStar(require("fs"));
41
+ const os = __importStar(require("os"));
42
+ let tunnelProcess = null;
43
+ let tunnelUrl = null;
44
+ let crashCallbacks = [];
45
+ let intentionalStop = false;
46
+ /**
47
+ * Get platform-specific installation instructions for cloudflared
48
+ */
49
+ function getInstallationInstructions() {
50
+ const platform = os.platform();
51
+ switch (platform) {
52
+ case 'darwin': // macOS
53
+ return `cloudflared is required for gogogo to work. Please install it using Homebrew:
54
+
55
+ brew install cloudflared
56
+
57
+ Alternatively, you can download it from: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/`;
58
+ case 'linux':
59
+ // Detect Linux distribution
60
+ let distroInstructions = '';
61
+ try {
62
+ // Check for common package managers
63
+ if (fs.existsSync('/usr/bin/apt') || fs.existsSync('/usr/bin/apt-get')) {
64
+ // Debian/Ubuntu
65
+ distroInstructions = ` # Add Cloudflare GPG key
66
+ sudo mkdir -p --mode=0755 /usr/share/keyrings
67
+ curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
68
+
69
+ # Add Cloudflare repository
70
+ echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
71
+
72
+ # Install cloudflared
73
+ sudo apt-get update && sudo apt-get install cloudflared`;
74
+ }
75
+ else if (fs.existsSync('/usr/bin/yum')) {
76
+ // CentOS/RHEL
77
+ distroInstructions = ` # Add Cloudflare repository
78
+ curl -fsSl https://pkg.cloudflare.com/cloudflared.repo | sudo tee /etc/yum.repos.d/cloudflared.repo
79
+
80
+ # Install cloudflared
81
+ sudo yum update && sudo yum install cloudflared`;
82
+ }
83
+ else if (fs.existsSync('/usr/bin/dnf')) {
84
+ // Fedora
85
+ distroInstructions = ` # Add Cloudflare repository
86
+ sudo dnf config-manager --add-repo https://pkg.cloudflare.com/cloudflared.repo
87
+
88
+ # Install cloudflared
89
+ sudo dnf install cloudflared`;
90
+ }
91
+ else if (fs.existsSync('/usr/bin/pacman')) {
92
+ // Arch Linux
93
+ distroInstructions = ` # Install from community repository
94
+ sudo pacman -S cloudflared`;
95
+ }
96
+ else {
97
+ // Generic Linux
98
+ distroInstructions = ` # Download and install manually
99
+ curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
100
+ chmod +x cloudflared
101
+ sudo mv cloudflared /usr/local/bin/`;
102
+ }
103
+ }
104
+ catch (error) {
105
+ // Fallback to generic instructions
106
+ distroInstructions = ` # Download and install manually
107
+ curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
108
+ chmod +x cloudflared
109
+ sudo mv cloudflared /usr/local/bin/`;
110
+ }
111
+ return `cloudflared is required for gogogo to work. Please install it:
112
+
113
+ ${distroInstructions}
114
+
115
+ For other distributions, see: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/`;
116
+ default:
117
+ return `cloudflared is required for gogogo to work. Please install it from:
118
+ https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/`;
119
+ }
120
+ }
121
+ /**
122
+ * Start Cloudflare Quick Tunnel
123
+ * Returns the generated tunnel URL
124
+ */
125
+ function startTunnel(localPort = 4020) {
126
+ return new Promise((resolve, reject) => {
127
+ // Check if cloudflared is installed
128
+ const which = (0, child_process_1.spawn)('which', ['cloudflared']);
129
+ which.on('close', (code) => {
130
+ if (code !== 0) {
131
+ reject(new Error(getInstallationInstructions()));
132
+ return;
133
+ }
134
+ startTunnelProcess(localPort, resolve, reject);
135
+ });
136
+ });
137
+ }
138
+ function startTunnelProcess(localPort, resolve, reject) {
139
+ // Inherit process.env (proxy vars already cleaned by session.ts)
140
+ const env = { ...process.env };
141
+ // Use --url for quick tunnel (no account needed)
142
+ // Bypass proxy to avoid TLS handshake issues
143
+ tunnelProcess = (0, child_process_1.spawn)('cloudflared', ['tunnel', '--url', `http://localhost:${localPort}`], {
144
+ stdio: ['ignore', 'pipe', 'pipe'],
145
+ env: env,
146
+ });
147
+ let urlFound = false;
148
+ const timeout = setTimeout(() => {
149
+ if (!urlFound) {
150
+ reject(new Error('Timeout waiting for tunnel URL'));
151
+ stopTunnel();
152
+ }
153
+ }, 30000); // 30 second timeout
154
+ // cloudflared outputs the URL to stderr
155
+ tunnelProcess.stderr?.on('data', (data) => {
156
+ const output = data.toString();
157
+ const urlMatch = output.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
158
+ if (urlMatch && !urlFound) {
159
+ urlFound = true;
160
+ clearTimeout(timeout);
161
+ tunnelUrl = urlMatch[0];
162
+ resolve(tunnelUrl);
163
+ }
164
+ });
165
+ tunnelProcess.stdout?.on('data', (data) => {
166
+ const output = data.toString();
167
+ const urlMatch = output.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
168
+ if (urlMatch && !urlFound) {
169
+ urlFound = true;
170
+ clearTimeout(timeout);
171
+ tunnelUrl = urlMatch[0];
172
+ resolve(tunnelUrl);
173
+ }
174
+ });
175
+ tunnelProcess.on('error', (err) => {
176
+ clearTimeout(timeout);
177
+ console.error(' [Tunnel] Failed to start:', err);
178
+ reject(err);
179
+ });
180
+ tunnelProcess.on('close', (code) => {
181
+ if (!urlFound) {
182
+ clearTimeout(timeout);
183
+ reject(new Error(`cloudflared exited with code ${code}`));
184
+ }
185
+ else if (!intentionalStop) {
186
+ // Tunnel crashed after URL was found — notify listeners
187
+ for (const cb of crashCallbacks) {
188
+ cb(code);
189
+ }
190
+ }
191
+ tunnelProcess = null;
192
+ tunnelUrl = null;
193
+ intentionalStop = false;
194
+ });
195
+ }
196
+ function stopTunnel() {
197
+ if (tunnelProcess) {
198
+ intentionalStop = true;
199
+ tunnelProcess.kill('SIGTERM');
200
+ tunnelProcess = null;
201
+ tunnelUrl = null;
202
+ }
203
+ crashCallbacks = [];
204
+ }
205
+ /** Register a callback for when the tunnel crashes unexpectedly */
206
+ function onTunnelCrash(callback) {
207
+ crashCallbacks.push(callback);
208
+ }
209
+ //# sourceMappingURL=cloudflare-tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-tunnel.js","sourceRoot":"","sources":["../src/cloudflare-tunnel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const commander_1 = require("commander");
38
+ const session_1 = require("./session");
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ // Read version from package.json
42
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
43
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
44
+ const version = packageJson.version;
45
+ const program = new commander_1.Command();
46
+ program
47
+ .name('gogogo')
48
+ .description('gogogo - Forward your terminal to your mobile device')
49
+ .version(version);
50
+ program
51
+ .command('start')
52
+ .description('Start a new gogogo session')
53
+ .argument('[command...]', 'Command to run (default: none, opens terminal only)')
54
+ .option('-n, --name <name>', 'Machine name to display', process.env.HOSTNAME || 'My Computer')
55
+ .action(async (command, options) => {
56
+ console.log('');
57
+ console.log(' 🚀 gogogo - Coding anywhere in your pocket');
58
+ console.log('');
59
+ await (0, session_1.startSession)(options.name, command);
60
+ });
61
+ program.parse();
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,uCAAyC;AACzC,uCAAyB;AACzB,2CAA6B;AAE7B,iCAAiC;AACjC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AACnE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1E,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,sDAAsD,CAAC;KACnE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,OAAO;KACF,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,4BAA4B,CAAC;KACzC,QAAQ,CAAC,cAAc,EAAE,qDAAqD,CAAC;KAC/E,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;KAC7F,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC/B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,IAAA,sBAAY,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEP,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/dist/pty.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import * as pty from 'node-pty';
2
+ export interface PTYOptions {
3
+ cols?: number;
4
+ rows?: number;
5
+ command?: string;
6
+ args?: string[];
7
+ cwd?: string;
8
+ }
9
+ export declare function getLocalSize(): {
10
+ cols: number;
11
+ rows: number;
12
+ };
13
+ export declare function spawnPTY(options?: PTYOptions): pty.IPty;
14
+ export declare function writeToPTY(data: string): void;
15
+ export declare function resizePTY(cols: number, rows: number): void;
16
+ export declare function killPTY(): void;
17
+ export declare function onPTYData(callback: (data: string) => void): void;
18
+ export declare function onPTYExit(callback: (code: number) => void): void;
19
+ export declare function onLocalTerminalResize(callback: () => void): void;
20
+ /** Clear all registered callbacks (for cleanup/testing) */
21
+ export declare function clearCallbacks(): void;
22
+ //# sourceMappingURL=pty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty.d.ts","sourceRoot":"","sources":["../src/pty.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,MAAM,WAAW,UAAU;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD,wBAAgB,YAAY,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAE7D;AAED,wBAAgB,QAAQ,CAAC,OAAO,GAAE,UAAe,GAAG,GAAG,CAAC,IAAI,CA6E3D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI7C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI1D;AAED,wBAAgB,OAAO,IAAI,IAAI,CAqB9B;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAEhE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAEhE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAEhE;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,IAAI,IAAI,CAIrC"}