shellx-ai 1.0.12 → 1.1.1

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +666 -0
  3. package/dist/automation/element-finder.d.ts +189 -0
  4. package/dist/automation/element-finder.js +322 -0
  5. package/dist/automation/element-finder.js.map +1 -0
  6. package/dist/automation/ui-action-handler.d.ts +330 -0
  7. package/dist/automation/ui-action-handler.js +873 -0
  8. package/dist/automation/ui-action-handler.js.map +1 -0
  9. package/dist/cbor-compat.d.ts +27 -0
  10. package/dist/cbor-compat.js +111 -0
  11. package/dist/cbor-compat.js.map +1 -0
  12. package/dist/domain-manager.d.ts +80 -0
  13. package/dist/domain-manager.js +161 -0
  14. package/dist/domain-manager.js.map +1 -0
  15. package/dist/error-handler.d.ts +87 -0
  16. package/dist/error-handler.js +151 -0
  17. package/dist/error-handler.js.map +1 -0
  18. package/dist/errors.d.ts +114 -0
  19. package/dist/errors.js +139 -0
  20. package/dist/errors.js.map +1 -0
  21. package/dist/index.d.ts +163 -54
  22. package/dist/index.js +678 -481
  23. package/dist/index.js.map +1 -0
  24. package/dist/logger.d.ts +81 -0
  25. package/dist/logger.js +128 -0
  26. package/dist/logger.js.map +1 -0
  27. package/dist/protocol.d.ts +147 -31
  28. package/dist/protocol.js +2 -2
  29. package/dist/protocol.js.map +1 -0
  30. package/dist/shell/output-buffer.d.ts +152 -0
  31. package/dist/shell/output-buffer.js +176 -0
  32. package/dist/shell/output-buffer.js.map +1 -0
  33. package/dist/shell/shell-command-executor.d.ts +182 -0
  34. package/dist/shell/shell-command-executor.js +404 -0
  35. package/dist/shell/shell-command-executor.js.map +1 -0
  36. package/dist/shellx.d.ts +681 -178
  37. package/dist/shellx.js +762 -1159
  38. package/dist/shellx.js.map +1 -0
  39. package/dist/types.d.ts +132 -57
  40. package/dist/types.js +4 -4
  41. package/dist/types.js.map +1 -0
  42. package/dist/utils/retry-helper.d.ts +73 -0
  43. package/dist/utils/retry-helper.js +95 -0
  44. package/dist/utils/retry-helper.js.map +1 -0
  45. package/dist/utils.d.ts +3 -3
  46. package/dist/utils.js +20 -23
  47. package/dist/utils.js.map +1 -0
  48. package/package.json +95 -62
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 10cl <notice@toscl.com>
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,666 @@
1
+ # ShellX AI
2
+
3
+ <div align="center">
4
+
5
+ **TypeScript library for Android device automation via WebSocket**
6
+
7
+ [![npm version](https://badge.fury.io/js/shellx-ai.svg)](https://www.npmjs.org/package/shellx-ai)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ [![Node.js Version](https://img.shields.io/node/v/shellx-ai.svg)](https://nodejs.org)
10
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.8-blue.svg)](https://www.typescriptlang.org/)
11
+
12
+ [Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-examples)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ ## Summary
19
+
20
+ ShellX AI is a TypeScript library that enables programmatic control of Android devices through a WebSocket connection. It provides a simple, type-safe API for:
21
+
22
+ - **UI Automation** - Click, input, swipe, press keys, wait for elements
23
+ - **Element Finding** - Find UI elements by text, ID, class, or coordinates
24
+ - **Shell Commands** - Execute shell commands and get output
25
+ - **Device Info** - Get screen info, app info, screenshots
26
+ - **Batch Operations** - Execute multiple actions in sequence
27
+
28
+ ---
29
+
30
+ ## Features
31
+
32
+ - 🎯 **Simple API** - Intuitive methods for common automation tasks
33
+ - 🔄 **Auto Retry** - Built-in retry logic for robust operations
34
+ - 📝 **Type-Safe** - Full TypeScript support with comprehensive types
35
+ - 🌍 **Cross-Platform** - Works in Node.js and browser environments
36
+ - 📸 **Screenshots** - Capture screenshots with customizable options
37
+ - 🔧 **Shell Commands** - Execute commands with real-time output
38
+ - 🛠️ **Batch Actions** - Chain multiple operations together
39
+
40
+ ---
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ npm install shellx-ai
46
+ ```
47
+
48
+ ### Requirements
49
+
50
+ - Node.js >= 14.0.0
51
+ - TypeScript >= 4.0.0 (recommended)
52
+ - Android device connected to ShellX service
53
+
54
+ ### Optional Dependencies
55
+
56
+ For Node.js environment, install ws:
57
+
58
+ ```bash
59
+ npm install ws # Optional, for Node.js WebSocket support
60
+ ```
61
+
62
+ For browser environments, no additional dependencies needed.
63
+
64
+ ---
65
+
66
+ ## Quick Start
67
+
68
+ ### 1. Basic Example
69
+
70
+ ```typescript
71
+ import { ShellX } from 'shellx-ai';
72
+
73
+ // Create ShellX instance
74
+ const shellx = new ShellX({
75
+ deviceId: 'your-device-id' // Replace with your device ID
76
+ });
77
+
78
+ // Wait for connection
79
+ await shellx.ready();
80
+
81
+ // Click element by text
82
+ await shellx.click('Settings');
83
+
84
+ // Get screen info
85
+ const screen = await shellx.getScreenInfo();
86
+ console.log(`Screen: ${screen.width}x${screen.height}`);
87
+
88
+ // Execute shell command
89
+ const result = await shellx.command('getprop ro.build.version.release');
90
+ console.log('Android version:', result.output);
91
+ ```
92
+
93
+ ### 2. Using Environment Variables
94
+
95
+ Create a `.env` file:
96
+
97
+ ```env
98
+ DEVICE_ID=your-device-id
99
+ ```
100
+
101
+ Then use it in your code:
102
+
103
+ ```typescript
104
+ import { ShellX } from 'shellx-ai';
105
+ import dotenv from 'dotenv';
106
+
107
+ dotenv.config();
108
+
109
+ const shellx = new ShellX({
110
+ deviceId: process.env.DEVICE_ID
111
+ });
112
+
113
+ await shellx.ready();
114
+ // Start automating...
115
+ ```
116
+
117
+ ### 3. With Connection Events
118
+
119
+ ```typescript
120
+ const shellx = new ShellX({
121
+ deviceId: 'your-device-id',
122
+ onOpen: () => console.log('✅ Connected'),
123
+ onClose: () => console.log('❌ Disconnected'),
124
+ onError: (error) => console.error('⚠️ Error:', error)
125
+ });
126
+
127
+ await shellx.ready();
128
+ ```
129
+
130
+ ---
131
+
132
+ ## API Reference
133
+
134
+ ### ShellX Class
135
+
136
+ The main class for Android automation.
137
+
138
+ #### Constructor
139
+
140
+ ```typescript
141
+ new ShellX(options: ShellXOptions)
142
+ ```
143
+
144
+ **Options:**
145
+
146
+ | Parameter | Type | Required | Default | Description |
147
+ |-----------|------|----------|---------|-------------|
148
+ | `deviceId` | `string` | Yes | - | Device ID (UUID or identifier) |
149
+ | `timeout` | `number` | No | `5000` | Connection timeout in ms |
150
+ | `reconnect` | `boolean` | No | `true` | Enable auto-reconnect |
151
+ | `reconnectMaxAttempts` | `number` | No | `5` | Max reconnect attempts |
152
+ | `logLevel` | `LogLevel` | No | `INFO` | Log level (0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) |
153
+ | `onOpen` | `() => void` | No | - | Callback when connection opens |
154
+ | `onClose` | `() => void` | No | - | Callback when connection closes |
155
+ | `onError` | `(error?) => void` | No | - | Callback on error |
156
+ | `onMessage` | `(msg) => void` | No | - | Callback on message |
157
+
158
+ #### Methods
159
+
160
+ ##### Connection
161
+
162
+ | Method | Description | Returns |
163
+ |--------|-------------|---------|
164
+ | `ready()` | Wait for connection to be ready | `Promise<void>` |
165
+ | `getClient()` | Get underlying ConnectionClient | `ConnectionClient` |
166
+
167
+ ##### UI Actions
168
+
169
+ | Method | Description | Example |
170
+ |--------|-------------|---------|
171
+ | `click(selector)` | Click element | `await shellx.click('Submit')` |
172
+ | `input(data)` | Input text | `await shellx.input({ text: 'Hello' })` |
173
+ | `swipe(data)` | Swipe gesture | `await shellx.swipe({ fromX: 500, fromY: 1000, toX: 500, toY: 500 })` |
174
+ | `press(key)` | Press key | `await shellx.press('BACK')` |
175
+ | `wait(selector)` | Wait for element | `await shellx.wait('Loading')` |
176
+ | `find(selector)` | Find elements | `await shellx.find('Button', { multiple: true })` |
177
+
178
+ ##### Device Operations
179
+
180
+ | Method | Description | Example |
181
+ |--------|-------------|---------|
182
+ | `command(cmd)` | Execute shell command | `await shellx.command('ls -la')` |
183
+ | `getScreenInfo()` | Get screen info | `await shellx.getScreenInfo()` |
184
+ | `takeScreenshot()` | Take screenshot | `await shellx.takeScreenshot({ format: 'png' })` |
185
+ | `getAppInfo(pkg)` | Get app info | `await shellx.getAppInfo('com.example.app')` |
186
+ | `getAppList()` | Get app list | `await shellx.getAppList()` |
187
+ | `clipboard(data)` | Clipboard operations | `await shellx.clipboard({ text: 'Hello' })` |
188
+
189
+ ##### Advanced
190
+
191
+ | Method | Description | Example |
192
+ |--------|-------------|---------|
193
+ | `executeActions(actions)` | Execute multiple actions | `await shellx.executeActions([{ text: 'OK' }, { cmd: 'ls' }])` |
194
+ | `sendRawMessage(msg)` | Send raw WebSocket message | `await shellx.sendRawMessage({ screenInfo: {} })` |
195
+
196
+ ---
197
+
198
+ ## Type Definitions
199
+
200
+ ### Click
201
+
202
+ Click on an element by text, ID, or coordinates.
203
+
204
+ **Simplified form (click by text):**
205
+ ```typescript
206
+ await shellx.click('Submit');
207
+ await shellx.click('Submit', { clickType: 'long' });
208
+ ```
209
+
210
+ **Full form:**
211
+ ```typescript
212
+ await shellx.click({
213
+ text: 'Submit', // Click by text
214
+ elementId: 'btn123', // Or by element ID
215
+ resourceId: 'submit_btn', // Or by resource ID
216
+ x: 500, // Or by coordinates
217
+ y: 1000,
218
+ clickType: 'single', // 'single' | 'double' | 'long' | 'normal'
219
+ timeout: 5000
220
+ });
221
+ ```
222
+
223
+ ### Input
224
+
225
+ Input text into a field.
226
+
227
+ ```typescript
228
+ await shellx.input({
229
+ elementId: 'field123',
230
+ text: 'Hello World',
231
+ clear: true, // Clear field before input
232
+ hideKeyboard: true // Hide keyboard after input
233
+ });
234
+ ```
235
+
236
+ ### Swipe
237
+
238
+ Perform swipe gesture.
239
+
240
+ ```typescript
241
+ await shellx.swipe({
242
+ fromX: 500,
243
+ fromY: 1000,
244
+ toX: 500,
245
+ toY: 500,
246
+ duration: 800 // Duration in ms
247
+ });
248
+ ```
249
+
250
+ ### Press
251
+
252
+ Press hardware key.
253
+
254
+ **Simplified:**
255
+ ```typescript
256
+ await shellx.press('BACK');
257
+ await shellx.press('HOME');
258
+ await shellx.press('MENU', { longPress: true });
259
+ ```
260
+
261
+ **Full:**
262
+ ```typescript
263
+ await shellx.press({
264
+ key: 'BACK',
265
+ longPress: false
266
+ });
267
+ ```
268
+
269
+ ### Wait
270
+
271
+ Wait for an element condition.
272
+
273
+ **Simplified:**
274
+ ```typescript
275
+ await shellx.wait('Submit');
276
+ await shellx.wait('Loading', { timeout: 10000 });
277
+ ```
278
+
279
+ **Full:**
280
+ ```typescript
281
+ await shellx.wait({
282
+ text: 'Submit',
283
+ condition: 'visible', // 'visible' | 'gone' | 'enabled'
284
+ timeout: 5000
285
+ });
286
+ ```
287
+
288
+ ### Find
289
+
290
+ Find UI elements.
291
+
292
+ **Simplified:**
293
+ ```typescript
294
+ const result = await shellx.find('Button');
295
+ const all = await shellx.find('Button', { multiple: true, maxResults: 10 });
296
+ ```
297
+
298
+ **Full:**
299
+ ```typescript
300
+ const result = await shellx.find({
301
+ text: 'Submit',
302
+ multiple: false,
303
+ maxResults: 100,
304
+ pressClick: true // Auto-click after find
305
+ });
306
+ ```
307
+
308
+ ### Command
309
+
310
+ Execute shell command.
311
+
312
+ **Simplified:**
313
+ ```typescript
314
+ const result = await shellx.command('ls -la');
315
+ const result = await shellx.command('ls -la', { timeout: 5000 });
316
+ ```
317
+
318
+ **Full:**
319
+ ```typescript
320
+ const result = await shellx.command({
321
+ cmd: 'ls -la',
322
+ timeout: 10000,
323
+ wait: 1000 // Wait after command
324
+ });
325
+ ```
326
+
327
+ ### Screenshot
328
+
329
+ Take screenshot.
330
+
331
+ ```typescript
332
+ const screenshot = await shellx.takeScreenshot({
333
+ format: 'png', // 'png' | 'jpeg'
334
+ quality: 100, // 0-100 for JPEG
335
+ saveToFile: true
336
+ });
337
+ ```
338
+
339
+ ### Clipboard
340
+
341
+ Clipboard operations.
342
+
343
+ ```typescript
344
+ // Get clipboard
345
+ const result = await shellx.clipboard({ get: true });
346
+
347
+ // Set clipboard
348
+ await shellx.clipboard({ text: 'Hello' });
349
+
350
+ // Paste clipboard
351
+ await shellx.clipboard({ paste: true });
352
+ ```
353
+
354
+ ### ExecuteActions (Batch)
355
+
356
+ Execute multiple actions in sequence.
357
+
358
+ ```typescript
359
+ const result = await shellx.executeActions([
360
+ { text: 'Settings' }, // Click
361
+ { cmd: 'ls -la' }, // Command
362
+ { fromX: 500, fromY: 1000, toX: 500, toY: 500 }, // Swipe
363
+ { key: 'BACK' } // Press
364
+ ]);
365
+
366
+ console.log(`Success: ${result.successCount}/${result.results.length}`);
367
+ ```
368
+
369
+ ---
370
+
371
+ ## Complete Working Example
372
+
373
+ Here's a complete example that you can run directly:
374
+
375
+ ```typescript
376
+ // File: example.ts
377
+ import { ShellX } from 'shellx-ai';
378
+
379
+ async function main() {
380
+ // 1. Create ShellX instance
381
+ const shellx = new ShellX({
382
+ deviceId: process.env.DEVICE_ID || 'your-device-id',
383
+ onOpen: () => console.log('✅ Connected!')
384
+ });
385
+
386
+ try {
387
+ // 2. Wait for connection
388
+ await shellx.ready();
389
+ console.log('📱 Connected to device');
390
+
391
+ // 3. Get screen info
392
+ const screen = await shellx.getScreenInfo();
393
+ console.log(`Screen: ${screen.width}x${screen.height}`);
394
+
395
+ // 4. Click element
396
+ await shellx.click('Settings');
397
+ console.log('✅ Clicked Settings');
398
+
399
+ // 5. Press back
400
+ await shellx.press('BACK');
401
+ console.log('✅ Pressed BACK');
402
+
403
+ // 6. Execute command
404
+ const result = await shellx.command('getprop ro.build.version.release');
405
+ console.log(`Android: ${result.output.trim()}`);
406
+
407
+ // 7. Take screenshot
408
+ const screenshot = await shellx.takeScreenshot({ format: 'png' });
409
+ console.log(`Screenshot: ${screenshot.imagePath}`);
410
+
411
+ // 8. Batch operations
412
+ const batch = await shellx.executeActions([
413
+ { text: 'Settings' },
414
+ { cmd: 'wm size' }
415
+ ]);
416
+ console.log(`Batch: ${batch.successCount}/${batch.results.length} successful`);
417
+
418
+ console.log('🎉 All operations completed!');
419
+ } catch (error) {
420
+ console.error('❌ Error:', error);
421
+ }
422
+ }
423
+
424
+ main();
425
+ ```
426
+
427
+ Compile and run:
428
+
429
+ ```bash
430
+ # Install dependencies
431
+ npm install shellx-ai dotenv
432
+
433
+ # Create .env file
434
+ echo "DEVICE_ID=your-device-id" > .env
435
+
436
+ # Run with tsx
437
+ npx tsx example.ts
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Response Types
443
+
444
+ All operations return a result object with the following structure:
445
+
446
+ ```typescript
447
+ interface Result {
448
+ success: boolean; // Operation success status
449
+ error?: string; // Error message if failed
450
+ duration: number; // Operation duration in ms
451
+ timestamp: number; // Operation timestamp
452
+ // ... additional fields specific to each operation
453
+ }
454
+ ```
455
+
456
+ ### CommandResult
457
+
458
+ ```typescript
459
+ {
460
+ success: boolean;
461
+ output: string; // Command output
462
+ error?: string;
463
+ exitCode?: number;
464
+ duration: number;
465
+ cmd: string;
466
+ timestamp: number;
467
+ }
468
+ ```
469
+
470
+ ### FindResult
471
+
472
+ ```typescript
473
+ {
474
+ success: boolean;
475
+ found: boolean;
476
+ count: number; // Number of elements found
477
+ elements: Array<{
478
+ id: string;
479
+ text: string;
480
+ class: string;
481
+ left: number;
482
+ top: number;
483
+ right: number;
484
+ bottom: number;
485
+ visible: boolean;
486
+ clickable: boolean;
487
+ }>;
488
+ duration: number;
489
+ timestamp: number;
490
+ }
491
+ ```
492
+
493
+ ### ScreenInfoResult
494
+
495
+ ```typescript
496
+ {
497
+ success: boolean;
498
+ width: number;
499
+ height: number;
500
+ density: number;
501
+ screenOn: boolean;
502
+ screenUnlocked: boolean;
503
+ foregroundApp?: string;
504
+ foregroundActivity?: string;
505
+ model?: string;
506
+ androidVersion?: string;
507
+ manufacturer?: string;
508
+ duration: number;
509
+ timestamp: number;
510
+ }
511
+ ```
512
+
513
+ ---
514
+
515
+ ## Logging
516
+
517
+ Control logging level:
518
+
519
+ ```typescript
520
+ const shellx = new ShellX({
521
+ deviceId: 'your-device-id',
522
+ logLevel: 3 // 0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG
523
+ });
524
+
525
+ // Or at runtime
526
+ shellx.setLogLevel(4); // Enable debug logging
527
+ shellx.enableDebugLogging(); // Shortcut
528
+ shellx.disableLogging(); // Disable all logging
529
+ ```
530
+
531
+ ---
532
+
533
+ ## Error Handling
534
+
535
+ ```typescript
536
+ try {
537
+ await shellx.click('Settings');
538
+ } catch (error) {
539
+ if (error instanceof Error) {
540
+ console.error('Click failed:', error.message);
541
+ }
542
+ }
543
+
544
+ // Or check result
545
+ const result = await shellx.click('Settings');
546
+ if (!result.success) {
547
+ console.error('Failed:', result.error);
548
+ }
549
+ ```
550
+
551
+ ---
552
+
553
+ ## Advanced Usage
554
+
555
+ ### Wait for Multiple Elements
556
+
557
+ ```typescript
558
+ const result = await shellx.waitAnyElement([
559
+ { text: 'OK' },
560
+ { text: 'Confirm' },
561
+ { text: 'Submit' }
562
+ ], 10000);
563
+ ```
564
+
565
+ ### Scroll to Find Element
566
+
567
+ ```typescript
568
+ const element = await shellx.scrollToFindElement(
569
+ { text: 'Target Item' },
570
+ 5, // max scroll attempts
571
+ 'down' // direction
572
+ );
573
+ ```
574
+
575
+ ### Find with Retry
576
+
577
+ ```typescript
578
+ const element = await shellx.findElementWithRetry(
579
+ { text: 'Submit', visible: true },
580
+ 3, // max retries
581
+ 1000 // retry delay
582
+ );
583
+ ```
584
+
585
+ ---
586
+
587
+ ## Platform Support
588
+
589
+ ### Node.js
590
+
591
+ ```bash
592
+ npm install shellx-ai ws
593
+ ```
594
+
595
+ ```typescript
596
+ import { ShellX } from 'shellx-ai';
597
+ const shellx = new ShellX({ deviceId: 'device-id' });
598
+ ```
599
+
600
+ ### Browser
601
+
602
+ ```bash
603
+ npm install shellx-ai
604
+ ```
605
+
606
+ ```typescript
607
+ import { ShellX } from 'shellx-ai';
608
+ const shellx = new ShellX({ deviceId: 'device-id' });
609
+ ```
610
+
611
+ ---
612
+
613
+ ## Troubleshooting
614
+
615
+ ### Connection Issues
616
+
617
+ ```typescript
618
+ const shellx = new ShellX({
619
+ deviceId: 'your-device-id',
620
+ timeout: 10000, // Increase timeout
621
+ reconnect: true, // Enable auto-reconnect
622
+ reconnectMaxAttempts: 10, // More attempts
623
+ onError: (error) => console.error('Connection error:', error)
624
+ });
625
+ ```
626
+
627
+ ### Element Not Found
628
+
629
+ ```typescript
630
+ // Wait for element first
631
+ await shellx.wait('Submit', { timeout: 10000 });
632
+
633
+ // Then click
634
+ await shellx.click('Submit');
635
+ ```
636
+
637
+ ### Command Timeout
638
+
639
+ ```typescript
640
+ const result = await shellx.command({
641
+ cmd: 'long-running-command',
642
+ timeout: 30000 // 30 seconds
643
+ });
644
+ ```
645
+
646
+ ---
647
+
648
+ ## See Also
649
+
650
+ - [API-GUIDE.md](./API-GUIDE.md) - Detailed API guide
651
+ - [API-QUICK-REFERENCE.md](./API-QUICK-REFERENCE.md) - Quick reference
652
+ - [example/](./example/) - Complete working examples
653
+
654
+ ---
655
+
656
+ ## License
657
+
658
+ MIT License - see [LICENSE](LICENSE) file.
659
+
660
+ ---
661
+
662
+ ## Support
663
+
664
+ - 📚 [Documentation](https://github.com/10cl/shellx)
665
+ - 🐛 [Issues](https://github.com/10cl/shellx/issues)
666
+ - 💬 [Discussions](https://github.com/10cl/shellx/discussions)