@naarang/ccc 2.0.0-alpha.4 → 2.0.0-alpha.6

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.
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Build script for creating cross-platform binaries with embedded version
3
+ * and native library support (bun-pty)
3
4
  */
4
5
 
5
6
  import { $ } from 'bun';
6
- import { readFileSync, mkdirSync, existsSync } from 'fs';
7
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
7
8
  import { join } from 'path';
8
9
 
9
10
  // Read version from package.json
@@ -18,41 +19,296 @@ if (!existsSync(binariesDir)) {
18
19
  mkdirSync(binariesDir, { recursive: true });
19
20
  }
20
21
 
21
- // Define targets
22
+ // Define targets with their native library paths
22
23
  const targets = [
23
- { name: 'linux-x64', target: 'bun-linux-x64', outfile: 'ccc-linux-x64' },
24
- { name: 'linux-arm64', target: 'bun-linux-arm64', outfile: 'ccc-linux-arm64' },
25
- { name: 'darwin-x64', target: 'bun-darwin-x64', outfile: 'ccc-darwin-x64' },
26
- { name: 'darwin-arm64', target: 'bun-darwin-arm64', outfile: 'ccc-darwin-arm64' },
27
- { name: 'windows-x64', target: 'bun-windows-x64', outfile: 'ccc-windows-x64.exe' },
24
+ {
25
+ name: 'linux-x64',
26
+ target: 'bun-linux-x64',
27
+ outfile: 'ccc-linux-x64',
28
+ ptyLib: 'librust_pty.so',
29
+ },
30
+ {
31
+ name: 'linux-arm64',
32
+ target: 'bun-linux-arm64',
33
+ outfile: 'ccc-linux-arm64',
34
+ ptyLib: 'librust_pty_arm64.so',
35
+ },
36
+ {
37
+ name: 'darwin-x64',
38
+ target: 'bun-darwin-x64',
39
+ outfile: 'ccc-darwin-x64',
40
+ ptyLib: 'librust_pty.dylib',
41
+ },
42
+ {
43
+ name: 'darwin-arm64',
44
+ target: 'bun-darwin-arm64',
45
+ outfile: 'ccc-darwin-arm64',
46
+ ptyLib: 'librust_pty_arm64.dylib',
47
+ },
48
+ {
49
+ name: 'windows-x64',
50
+ target: 'bun-windows-x64',
51
+ outfile: 'ccc-windows-x64.exe',
52
+ ptyLib: 'rust_pty.dll',
53
+ },
28
54
  ];
29
55
 
30
56
  // Parse command line arguments
31
57
  const args = process.argv.slice(2);
32
- const targetArg = args.find(arg => !arg.startsWith('-'));
33
- const selectedTargets = targetArg
34
- ? targets.filter(t => t.name === targetArg)
35
- : targets;
58
+ const targetArg = args.find((arg) => !arg.startsWith('-'));
59
+ const selectedTargets = targetArg ? targets.filter((t) => t.name === targetArg) : targets;
36
60
 
37
61
  if (targetArg && selectedTargets.length === 0) {
38
62
  console.error(`Unknown target: ${targetArg}`);
39
- console.error(`Available targets: ${targets.map(t => t.name).join(', ')}`);
63
+ console.error(`Available targets: ${targets.map((t) => t.name).join(', ')}`);
40
64
  process.exit(1);
41
65
  }
42
66
 
67
+ // Path to the generated loader file
68
+ const loaderDir = join(import.meta.dir, '..', 'src', 'lib');
69
+ const loaderPath = join(loaderDir, 'bun-pty-loader.generated.ts');
70
+
71
+ // Ensure the lib directory exists
72
+ if (!existsSync(loaderDir)) {
73
+ mkdirSync(loaderDir, { recursive: true });
74
+ }
75
+
76
+ /**
77
+ * Generate a platform-specific bun-pty loader that embeds the native library
78
+ * This inlines the bun-pty implementation to ensure the library is extracted
79
+ * before dlopen is called (bun-pty calls dlopen at module load time)
80
+ */
81
+ function generatePtyLoader(ptyLib: string): void {
82
+ const loaderContent = `/**
83
+ * Auto-generated bun-pty implementation with embedded native library
84
+ * DO NOT EDIT - This file is generated by build-binaries.ts
85
+ *
86
+ * This is a copy of bun-pty's implementation that uses an embedded native library.
87
+ * We can't just set BUN_PTY_LIB and import bun-pty because bun-pty calls dlopen
88
+ * at module load time, before our env var setup code runs.
89
+ */
90
+
91
+ import { dlopen, FFIType, ptr } from 'bun:ffi';
92
+ import { Buffer } from 'buffer';
93
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
94
+ import { join } from 'path';
95
+ import { tmpdir } from 'os';
96
+
97
+ // Embed the native library file - Bun will include this in the binary
98
+ // @ts-ignore - Bun's file embedding syntax
99
+ import embeddedLibPath from '../../node_modules/bun-pty/rust-pty/target/release/${ptyLib}' with { type: 'file' };
100
+
101
+ // Extract embedded library to temp directory
102
+ const libName = '${ptyLib}';
103
+ const tempDir = join(tmpdir(), 'ccc-pty-lib');
104
+ const extractedLibPath = join(tempDir, libName);
105
+
106
+ if (!existsSync(extractedLibPath)) {
107
+ if (!existsSync(tempDir)) {
108
+ mkdirSync(tempDir, { recursive: true });
109
+ }
110
+ const libData = readFileSync(embeddedLibPath);
111
+ writeFileSync(extractedLibPath, libData);
112
+ }
113
+
114
+ // Load the native library
115
+ const lib = dlopen(extractedLibPath, {
116
+ bun_pty_spawn: {
117
+ args: [FFIType.cstring, FFIType.cstring, FFIType.cstring, FFIType.i32, FFIType.i32],
118
+ returns: FFIType.i32,
119
+ },
120
+ bun_pty_write: {
121
+ args: [FFIType.i32, FFIType.pointer, FFIType.i32],
122
+ returns: FFIType.i32,
123
+ },
124
+ bun_pty_read: {
125
+ args: [FFIType.i32, FFIType.pointer, FFIType.i32],
126
+ returns: FFIType.i32,
127
+ },
128
+ bun_pty_resize: {
129
+ args: [FFIType.i32, FFIType.i32, FFIType.i32],
130
+ returns: FFIType.i32,
131
+ },
132
+ bun_pty_kill: { args: [FFIType.i32], returns: FFIType.i32 },
133
+ bun_pty_get_pid: { args: [FFIType.i32], returns: FFIType.i32 },
134
+ bun_pty_get_exit_code: { args: [FFIType.i32], returns: FFIType.i32 },
135
+ bun_pty_close: { args: [FFIType.i32], returns: FFIType.void },
136
+ });
137
+
138
+ // EventEmitter for PTY events
139
+ class EventEmitter<T> {
140
+ private listeners: ((data: T) => void)[] = [];
141
+
142
+ event = (listener: (data: T) => void) => {
143
+ this.listeners.push(listener);
144
+ return {
145
+ dispose: () => {
146
+ const i = this.listeners.indexOf(listener);
147
+ if (i !== -1) this.listeners.splice(i, 1);
148
+ },
149
+ };
150
+ };
151
+
152
+ fire(data: T) {
153
+ for (const listener of this.listeners) {
154
+ listener(data);
155
+ }
156
+ }
157
+ }
158
+
159
+ // Shell quote helper
160
+ function shQuote(s: string): string {
161
+ if (s.length === 0) return "''";
162
+ return \`'\${s.replace(/'/g, \`'\\\\''\\'\`)}'\`;
163
+ }
164
+
165
+ const DEFAULT_COLS = 80;
166
+ const DEFAULT_ROWS = 24;
167
+ const DEFAULT_FILE = process.platform === 'win32' ? 'powershell.exe' : 'sh';
168
+
169
+ export interface IPtyOptions {
170
+ name?: string;
171
+ cols?: number;
172
+ rows?: number;
173
+ cwd?: string;
174
+ env?: Record<string, string>;
175
+ }
176
+
177
+ export interface IPty {
178
+ pid: number;
179
+ cols: number;
180
+ rows: number;
181
+ process: string;
182
+ onData: (listener: (data: string) => void) => { dispose: () => void };
183
+ onExit: (listener: (data: { exitCode: number; signal?: string }) => void) => { dispose: () => void };
184
+ write(data: string): void;
185
+ resize(cols: number, rows: number): void;
186
+ kill(signal?: string): void;
187
+ }
188
+
189
+ export class Terminal implements IPty {
190
+ private handle = -1;
191
+ private _pid = -1;
192
+ private _cols = DEFAULT_COLS;
193
+ private _rows = DEFAULT_ROWS;
194
+ private _readLoop = false;
195
+ private _closing = false;
196
+ private _onData = new EventEmitter<string>();
197
+ private _onExit = new EventEmitter<{ exitCode: number; signal?: string }>();
198
+
199
+ constructor(file = DEFAULT_FILE, args: string[] = [], opts: IPtyOptions = {}) {
200
+ this._cols = opts.cols ?? DEFAULT_COLS;
201
+ this._rows = opts.rows ?? DEFAULT_ROWS;
202
+ const cwd = opts.cwd ?? process.cwd();
203
+ const cmdline = [file, ...args.map(shQuote)].join(' ');
204
+ let envStr = '';
205
+ if (opts.env) {
206
+ const envPairs = Object.entries(opts.env).map(([k, v]) => \`\${k}=\${v}\`);
207
+ envStr = envPairs.join('\\x00') + '\\x00';
208
+ }
209
+
210
+ this.handle = lib.symbols.bun_pty_spawn(
211
+ Buffer.from(\`\${cmdline}\\x00\`, 'utf8'),
212
+ Buffer.from(\`\${cwd}\\x00\`, 'utf8'),
213
+ Buffer.from(\`\${envStr}\\x00\`, 'utf8'),
214
+ this._cols,
215
+ this._rows
216
+ );
217
+
218
+ if (this.handle < 0) throw new Error('PTY spawn failed');
219
+ this._pid = lib.symbols.bun_pty_get_pid(this.handle);
220
+ this._startReadLoop();
221
+ }
222
+
223
+ get pid() { return this._pid; }
224
+ get cols() { return this._cols; }
225
+ get rows() { return this._rows; }
226
+ get process() { return 'shell'; }
227
+ get onData() { return this._onData.event; }
228
+ get onExit() { return this._onExit.event; }
229
+
230
+ write(data: string) {
231
+ if (this._closing) return;
232
+ const buf = Buffer.from(data, 'utf8');
233
+ lib.symbols.bun_pty_write(this.handle, ptr(buf), buf.length);
234
+ }
235
+
236
+ resize(cols: number, rows: number) {
237
+ if (this._closing) return;
238
+ this._cols = cols;
239
+ this._rows = rows;
240
+ lib.symbols.bun_pty_resize(this.handle, cols, rows);
241
+ }
242
+
243
+ kill(signal = 'SIGTERM') {
244
+ if (this._closing) return;
245
+ this._closing = true;
246
+ lib.symbols.bun_pty_kill(this.handle);
247
+ lib.symbols.bun_pty_close(this.handle);
248
+ this._onExit.fire({ exitCode: 0, signal });
249
+ }
250
+
251
+ private async _startReadLoop() {
252
+ if (this._readLoop) return;
253
+ this._readLoop = true;
254
+ const buf = Buffer.allocUnsafe(4096);
255
+
256
+ while (this._readLoop && !this._closing) {
257
+ const n = lib.symbols.bun_pty_read(this.handle, ptr(buf), buf.length);
258
+ if (n > 0) {
259
+ this._onData.fire(buf.subarray(0, n).toString('utf8'));
260
+ } else if (n === -2) {
261
+ const exitCode = lib.symbols.bun_pty_get_exit_code(this.handle);
262
+ this._onExit.fire({ exitCode });
263
+ break;
264
+ } else if (n < 0) {
265
+ break;
266
+ } else {
267
+ await new Promise((r) => setTimeout(r, 8));
268
+ }
269
+ }
270
+ }
271
+ }
272
+
273
+ export function spawn(file: string, args: string[], options: IPtyOptions): IPty {
274
+ return new Terminal(file, args, options);
275
+ }
276
+ `;
277
+
278
+ writeFileSync(loaderPath, loaderContent);
279
+ console.log(` Generated bun-pty loader for ${ptyLib}`);
280
+ }
281
+
282
+ /**
283
+ * Clean up the generated loader file
284
+ */
285
+ function cleanupLoader(): void {
286
+ if (existsSync(loaderPath)) {
287
+ unlinkSync(loaderPath);
288
+ }
289
+ }
290
+
43
291
  // Build each target
44
- for (const { name, target, outfile } of selectedTargets) {
292
+ for (const { name, target, outfile, ptyLib } of selectedTargets) {
45
293
  console.log(`\nBuilding ${name}...`);
46
294
 
47
295
  const outfilePath = join(binariesDir, outfile);
48
296
 
49
297
  try {
50
- await $`bun build --compile --minify --bytecode --target=${target} --external bun-pty --external @ngrok/ngrok --external expo-server-sdk --define BUILD_VERSION='"${VERSION}"' src/index.ts --outfile ${outfilePath}`;
298
+ // Generate platform-specific bun-pty loader
299
+ generatePtyLoader(ptyLib);
300
+
301
+ // Build the binary (bun-pty is now bundled via the generated loader)
302
+ await $`bun build --compile --minify --bytecode --target=${target} --external @ngrok/ngrok --external expo-server-sdk --define BUILD_VERSION='"${VERSION}"' src/index.ts --outfile ${outfilePath}`;
51
303
  console.log(` ✓ Built ${outfile}`);
52
304
  } catch (error) {
53
305
  console.error(` ✗ Failed to build ${name}:`, error);
306
+ cleanupLoader();
54
307
  process.exit(1);
55
308
  }
56
309
  }
57
310
 
311
+ // Clean up generated files
312
+ cleanupLoader();
313
+
58
314
  console.log('\nBuild complete!');
@@ -1,84 +1,84 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Postinstall script (CommonJS version for npm compatibility)
4
- *
5
- * This script checks if bun-pty is working correctly.
6
- * bun-pty is a Bun-native PTY implementation that doesn't require node-gyp.
7
- */
8
-
9
- const { existsSync } = require('fs');
10
- const { join } = require('path');
11
- const { spawn } = require('child_process');
12
-
13
- const ROOT_PATH = join(__dirname, '..');
14
-
15
- /**
16
- * Check if Bun is available
17
- */
18
- function checkBun() {
19
- return new Promise((resolve) => {
20
- const result = spawn('bun', ['--version'], { stdio: 'pipe', shell: true });
21
- result.on('close', (code) => resolve(code === 0));
22
- result.on('error', () => resolve(false));
23
- });
24
- }
25
-
26
- /**
27
- * Check if bun-pty works (requires Bun runtime)
28
- */
29
- async function checkBunPty() {
30
- const hasBun = await checkBun();
31
- if (!hasBun) {
32
- console.log('[postinstall] Bun not found, skipping bun-pty check');
33
- console.log('[postinstall] Install Bun for full functionality: https://bun.sh');
34
- return false;
35
- }
36
-
37
- return new Promise((resolve) => {
38
- // Run a simple Bun script to test bun-pty
39
- const testScript = `
40
- try {
41
- const { spawn } = require('bun-pty');
42
- const shell = process.platform === 'win32' ? 'cmd.exe' : 'sh';
43
- const pty = spawn(shell, [], { cols: 80, rows: 24 });
44
- pty.kill();
45
- console.log('bun-pty is working correctly');
46
- process.exit(0);
47
- } catch (e) {
48
- console.error('bun-pty check failed:', e.message);
49
- process.exit(1);
50
- }
51
- `;
52
-
53
- const testProcess = spawn('bun', ['-e', testScript], {
54
- cwd: ROOT_PATH,
55
- stdio: 'inherit',
56
- shell: true,
57
- });
58
-
59
- testProcess.on('close', (code) => resolve(code === 0));
60
- testProcess.on('error', () => resolve(false));
61
- });
62
- }
63
-
64
- async function main() {
65
- console.log('[postinstall] Code Chat Connect v2 - Post-installation check\n');
66
-
67
- // Check bun-pty
68
- const ptyWorks = await checkBunPty();
69
-
70
- if (ptyWorks) {
71
- console.log('\n[postinstall] All checks passed!');
72
- } else {
73
- console.log('\n[postinstall] Terminal functionality may be limited.');
74
- console.log('[postinstall] Ensure Bun is installed: https://bun.sh');
75
- }
76
-
77
- console.log('\n[postinstall] Run "ccc" to start the server.\n');
78
- }
79
-
80
- main().catch((err) => {
81
- console.error('[postinstall] Error:', err.message);
82
- // Don't fail the install on postinstall errors
83
- process.exit(0);
84
- });
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Postinstall script (CommonJS version for npm compatibility)
4
+ *
5
+ * This script checks if bun-pty is working correctly.
6
+ * bun-pty is a Bun-native PTY implementation that doesn't require node-gyp.
7
+ */
8
+
9
+ const { existsSync } = require('fs');
10
+ const { join } = require('path');
11
+ const { spawn } = require('child_process');
12
+
13
+ const ROOT_PATH = join(__dirname, '..');
14
+
15
+ /**
16
+ * Check if Bun is available
17
+ */
18
+ function checkBun() {
19
+ return new Promise((resolve) => {
20
+ const result = spawn('bun', ['--version'], { stdio: 'pipe', shell: true });
21
+ result.on('close', (code) => resolve(code === 0));
22
+ result.on('error', () => resolve(false));
23
+ });
24
+ }
25
+
26
+ /**
27
+ * Check if bun-pty works (requires Bun runtime)
28
+ */
29
+ async function checkBunPty() {
30
+ const hasBun = await checkBun();
31
+ if (!hasBun) {
32
+ console.log('[postinstall] Bun not found, skipping bun-pty check');
33
+ console.log('[postinstall] Install Bun for full functionality: https://bun.sh');
34
+ return false;
35
+ }
36
+
37
+ return new Promise((resolve) => {
38
+ // Run a simple Bun script to test bun-pty
39
+ const testScript = `
40
+ try {
41
+ const { spawn } = require('bun-pty');
42
+ const shell = process.platform === 'win32' ? 'cmd.exe' : 'sh';
43
+ const pty = spawn(shell, [], { cols: 80, rows: 24 });
44
+ pty.kill();
45
+ console.log('bun-pty is working correctly');
46
+ process.exit(0);
47
+ } catch (e) {
48
+ console.error('bun-pty check failed:', e.message);
49
+ process.exit(1);
50
+ }
51
+ `;
52
+
53
+ const testProcess = spawn('bun', ['-e', testScript], {
54
+ cwd: ROOT_PATH,
55
+ stdio: 'inherit',
56
+ shell: true,
57
+ });
58
+
59
+ testProcess.on('close', (code) => resolve(code === 0));
60
+ testProcess.on('error', () => resolve(false));
61
+ });
62
+ }
63
+
64
+ async function main() {
65
+ console.log('[postinstall] Code Chat Connect v2 - Post-installation check\n');
66
+
67
+ // Check bun-pty
68
+ const ptyWorks = await checkBunPty();
69
+
70
+ if (ptyWorks) {
71
+ console.log('\n[postinstall] All checks passed!');
72
+ } else {
73
+ console.log('\n[postinstall] Terminal functionality may be limited.');
74
+ console.log('[postinstall] Ensure Bun is installed: https://bun.sh');
75
+ }
76
+
77
+ console.log('\n[postinstall] Run "ccc" to start the server.\n');
78
+ }
79
+
80
+ main().catch((err) => {
81
+ console.error('[postinstall] Error:', err.message);
82
+ // Don't fail the install on postinstall errors
83
+ process.exit(0);
84
+ });
package/package.json CHANGED
@@ -1,79 +1,79 @@
1
- {
2
- "name": "@naarang/ccc",
3
- "version": "2.0.0-alpha.4",
4
- "description": "Code Chat Connect - Control Claude Code from your mobile device",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "ccc": "bin/ccc.cjs"
9
- },
10
- "scripts": {
11
- "dev": "bun src/index.ts",
12
- "build": "bun scripts/build-dist.ts",
13
- "build:compile": "bun scripts/build-binaries.ts",
14
- "build:linux-x64": "bun scripts/build-binaries.ts linux-x64",
15
- "build:linux-arm64": "bun scripts/build-binaries.ts linux-arm64",
16
- "build:darwin-x64": "bun scripts/build-binaries.ts darwin-x64",
17
- "build:darwin-arm64": "bun scripts/build-binaries.ts darwin-arm64",
18
- "build:windows-x64": "bun scripts/build-binaries.ts windows-x64",
19
- "build:all": "bun scripts/build-binaries.ts",
20
- "clean": "rm -rf dist binaries",
21
- "type-check": "tsc --noEmit",
22
- "setup": "bun install",
23
- "test:tools": "bun run scripts/test-claude-tools.ts",
24
- "prepublishOnly": "bun run build",
25
- "postinstall": "node scripts/postinstall.cjs || true"
26
- },
27
- "keywords": [
28
- "ccc",
29
- "ccc-ui",
30
- "claude",
31
- "claude-code",
32
- "mqtt",
33
- "chat",
34
- "mobile",
35
- "ai",
36
- "assistant",
37
- "cli",
38
- "bun"
39
- ],
40
- "author": "Vishal",
41
- "license": "UNLICENSED",
42
- "private": false,
43
- "publishConfig": {
44
- "access": "public"
45
- },
46
- "files": [
47
- "dist",
48
- "bin",
49
- "scripts",
50
- "README.md",
51
- "LICENSE"
52
- ],
53
- "preferGlobal": true,
54
- "engines": {
55
- "bun": ">=1.0.0"
56
- },
57
- "dependencies": {
58
- "@ngrok/ngrok": "^1.5.2",
59
- "@seriousme/opifex": "^1.11.2",
60
- "@types/bun": "^1.3.2",
61
- "@types/qrcode-terminal": "^0.12.2",
62
- "@types/ws": "^8.18.1",
63
- "@xterm/addon-fit": "^0.10.0",
64
- "@xterm/xterm": "^5.5.0",
65
- "aedes": "^0.51.3",
66
- "aedes-server-factory": "^0.2.1",
67
- "bonjour-service": "^1.3.0",
68
- "bun-pty": "^0.4.2",
69
- "expo-server-sdk": "^4.0.0",
70
- "figlet": "^1.9.3",
71
- "mqtt": "^5.14.1",
72
- "node-gyp": "11.4.2",
73
- "qrcode-terminal": "^0.12.0",
74
- "ws": "^8.18.3"
75
- },
76
- "devDependencies": {
77
- "typescript": "^5"
78
- }
79
- }
1
+ {
2
+ "name": "@naarang/ccc",
3
+ "version": "2.0.0-alpha.6",
4
+ "description": "Code Chat Connect - Control Claude Code from your mobile device",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "ccc": "bin/ccc.cjs"
9
+ },
10
+ "scripts": {
11
+ "dev": "bun src/index.ts",
12
+ "build": "bun scripts/build-dist.ts",
13
+ "build:compile": "bun scripts/build-binaries.ts",
14
+ "build:linux-x64": "bun scripts/build-binaries.ts linux-x64",
15
+ "build:linux-arm64": "bun scripts/build-binaries.ts linux-arm64",
16
+ "build:darwin-x64": "bun scripts/build-binaries.ts darwin-x64",
17
+ "build:darwin-arm64": "bun scripts/build-binaries.ts darwin-arm64",
18
+ "build:windows-x64": "bun scripts/build-binaries.ts windows-x64",
19
+ "build:all": "bun scripts/build-binaries.ts",
20
+ "clean": "rm -rf dist binaries",
21
+ "type-check": "tsc --noEmit",
22
+ "setup": "bun install",
23
+ "test:tools": "bun run scripts/test-claude-tools.ts",
24
+ "prepublishOnly": "bun run build",
25
+ "postinstall": "node scripts/postinstall.cjs || true"
26
+ },
27
+ "keywords": [
28
+ "ccc",
29
+ "ccc-ui",
30
+ "claude",
31
+ "claude-code",
32
+ "mqtt",
33
+ "chat",
34
+ "mobile",
35
+ "ai",
36
+ "assistant",
37
+ "cli",
38
+ "bun"
39
+ ],
40
+ "author": "Vishal",
41
+ "license": "UNLICENSED",
42
+ "private": false,
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "bin",
49
+ "scripts",
50
+ "README.md",
51
+ "LICENSE"
52
+ ],
53
+ "preferGlobal": true,
54
+ "engines": {
55
+ "bun": ">=1.0.0"
56
+ },
57
+ "dependencies": {
58
+ "@ngrok/ngrok": "^1.5.2",
59
+ "@seriousme/opifex": "^1.11.2",
60
+ "@types/bun": "^1.3.2",
61
+ "@types/qrcode-terminal": "^0.12.2",
62
+ "@types/ws": "^8.18.1",
63
+ "@xterm/addon-fit": "^0.10.0",
64
+ "@xterm/xterm": "^5.5.0",
65
+ "aedes": "^0.51.3",
66
+ "aedes-server-factory": "^0.2.1",
67
+ "bonjour-service": "^1.3.0",
68
+ "bun-pty": "^0.4.2",
69
+ "expo-server-sdk": "^4.0.0",
70
+ "figlet": "^1.9.3",
71
+ "mqtt": "^5.14.1",
72
+ "node-gyp": "11.4.2",
73
+ "qrcode-terminal": "^0.12.0",
74
+ "ws": "^8.18.3"
75
+ },
76
+ "devDependencies": {
77
+ "typescript": "^5"
78
+ }
79
+ }