@dmsdc-ai/aigentry-telepty 0.1.80 → 0.1.82
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 +113 -54
- package/cli.js +93 -37
- package/daemon.js +10 -8
- package/package.json +25 -4
package/README.md
CHANGED
|
@@ -1,92 +1,151 @@
|
|
|
1
|
-
#
|
|
1
|
+
# telepty
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Connect any terminal to any terminal, any machine.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
telepty is a lightweight PTY multiplexer and session bridge. It lets you spawn, attach to, and inject commands into terminal sessions — locally or across machines via Tailscale.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Built for AI CLI workflows (Claude Code, Codex, Gemini CLI), but works with any interactive terminal program.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Install
|
|
10
10
|
|
|
11
|
-
To install or update `telepty` on any machine (macOS, Linux, or Windows), just run the command for your OS. (Node.js will be automatically installed if you don't have it).
|
|
12
|
-
|
|
13
|
-
### For macOS and Linux (Ubuntu, CentOS, etc.)
|
|
14
|
-
Open your terminal and run:
|
|
15
11
|
```bash
|
|
12
|
+
# macOS / Linux
|
|
16
13
|
curl -fsSL https://raw.githubusercontent.com/dmsdc-ai/aigentry-telepty/main/install.sh | bash
|
|
17
|
-
```
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
Open PowerShell as Administrator and run:
|
|
21
|
-
```powershell
|
|
15
|
+
# Windows (PowerShell as Admin)
|
|
22
16
|
iwr -useb https://raw.githubusercontent.com/dmsdc-ai/aigentry-telepty/main/install.ps1 | iex
|
|
17
|
+
|
|
18
|
+
# Or via npm
|
|
19
|
+
npm install -g @dmsdc-ai/aigentry-telepty
|
|
23
20
|
```
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
The installer sets up telepty as a background service (`launchd` on macOS, `systemd` on Linux, detached process on Windows).
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
26
25
|
|
|
27
26
|
```bash
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
# 1. Start the daemon
|
|
28
|
+
telepty daemon
|
|
29
|
+
|
|
30
|
+
# 2. Wrap an existing CLI session for remote control
|
|
31
|
+
telepty allow --id my-session claude
|
|
32
|
+
|
|
33
|
+
# 3. List active sessions (local + Tailnet)
|
|
34
|
+
telepty list
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
# 4. Inject a prompt into a session
|
|
37
|
+
telepty inject my-session "explain this codebase"
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
# 5. Attach to a session interactively
|
|
40
|
+
telepty attach my-session
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```
|
|
42
|
+
# 6. Broadcast to all sessions
|
|
43
|
+
telepty broadcast "status report"
|
|
44
|
+
```
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
## Core Commands
|
|
47
|
+
|
|
48
|
+
| Command | Description |
|
|
49
|
+
|---------|-------------|
|
|
50
|
+
| `telepty daemon` | Start the background daemon (port 3848) |
|
|
51
|
+
| `telepty allow --id <name> <cmd>` | Wrap a CLI for inject control |
|
|
52
|
+
| `telepty spawn --id <name> <cmd>` | Spawn a new background session |
|
|
53
|
+
| `telepty list [--json]` | List sessions across all discovered hosts |
|
|
54
|
+
| `telepty attach [id[@host]]` | Attach to a session (interactive picker if no ID) |
|
|
55
|
+
| `telepty inject <id[@host]> "text"` | Inject text into a session |
|
|
56
|
+
| `telepty enter <id[@host]>` | Send Enter/Return to a session |
|
|
57
|
+
| `telepty multicast <id1,id2> "text"` | Inject into multiple sessions |
|
|
58
|
+
| `telepty broadcast "text"` | Inject into ALL sessions |
|
|
59
|
+
| `telepty rename <old> <new>` | Rename a session |
|
|
60
|
+
| `telepty read-screen <id> [--lines N]` | Read session screen buffer |
|
|
61
|
+
| `telepty reply "text"` | Reply to the last injector |
|
|
62
|
+
| `telepty monitor` | Real-time event billboard |
|
|
63
|
+
| `telepty listen` | Stream event bus as JSON |
|
|
64
|
+
| `telepty tui` | Full TUI dashboard |
|
|
65
|
+
| `telepty layout [grid\|tall\|stack]` | Arrange kitty windows |
|
|
66
|
+
| `telepty update` | Update to latest version |
|
|
67
|
+
|
|
68
|
+
## Cross-Machine Sessions
|
|
69
|
+
|
|
70
|
+
telepty auto-discovers sessions across your Tailnet. All commands (`list`, `attach`, `inject`, `rename`, `multicast`, `broadcast`) work seamlessly across machines.
|
|
71
|
+
|
|
72
|
+
When the same session ID exists on multiple hosts, disambiguate with `session_id@host`:
|
|
46
73
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
```bash
|
|
75
|
+
telepty inject my-session@macbook "hello"
|
|
76
|
+
telepty attach worker@server-01
|
|
77
|
+
```
|
|
51
78
|
|
|
52
|
-
|
|
79
|
+
## How It Works
|
|
53
80
|
|
|
54
|
-
|
|
81
|
+
```
|
|
82
|
+
CLI (telepty) ──> HTTP/WS ──> Daemon (:3848)
|
|
83
|
+
├── Session WebSocket (/api/sessions/:id)
|
|
84
|
+
├── Event Bus WebSocket (/api/bus)
|
|
85
|
+
└── REST API (/api/sessions/*)
|
|
86
|
+
```
|
|
55
87
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-H "Content-Type: application/json" \
|
|
60
|
-
-d '{"prompt": "your command here"}'
|
|
61
|
-
```
|
|
88
|
+
- **`allow`** wraps a CLI process in a PTY bridge, enabling remote inject
|
|
89
|
+
- **`inject`** delivers text via the fastest available path: kitty terminal API, WebSocket, or UDS (Unix Domain Socket for embedded integrations)
|
|
90
|
+
- **`submit`** is handled separately from text injection for reliability across all AI CLIs
|
|
62
91
|
|
|
63
|
-
|
|
92
|
+
## Inject Delivery Paths
|
|
64
93
|
|
|
65
|
-
|
|
94
|
+
| Priority | Method | When |
|
|
95
|
+
|----------|--------|------|
|
|
96
|
+
| 1 | `kitty @ send-text` | Terminal supports kitty protocol |
|
|
97
|
+
| 2 | UDS (Unix Domain Socket) | Embedded IPC sessions (e.g. aterm) |
|
|
98
|
+
| 3 | WebSocket PTY write | Wrapped sessions via allow-bridge |
|
|
99
|
+
|
|
100
|
+
## AI CLI Integration
|
|
66
101
|
|
|
67
|
-
|
|
102
|
+
telepty works as a session bridge for AI CLIs. Use `allow` to wrap any CLI:
|
|
68
103
|
|
|
69
104
|
```bash
|
|
70
|
-
|
|
105
|
+
# Claude Code
|
|
106
|
+
telepty allow --id claude-main claude
|
|
107
|
+
|
|
108
|
+
# Codex
|
|
109
|
+
telepty allow --id codex-main codex
|
|
110
|
+
|
|
111
|
+
# Gemini CLI
|
|
112
|
+
telepty allow --id gemini-main gemini
|
|
71
113
|
```
|
|
72
114
|
|
|
73
|
-
|
|
115
|
+
Then inject prompts, read output, or attach from anywhere:
|
|
74
116
|
|
|
75
117
|
```bash
|
|
76
|
-
|
|
118
|
+
telepty inject claude-main "refactor the auth module"
|
|
119
|
+
telepty read-screen claude-main --lines 50
|
|
120
|
+
telepty attach claude-main
|
|
77
121
|
```
|
|
78
122
|
|
|
79
|
-
|
|
123
|
+
## Deliberation (Multi-Session Discussion)
|
|
80
124
|
|
|
81
|
-
|
|
125
|
+
Coordinate structured discussions across multiple AI sessions:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
telepty deliberate --topic "API design for v2" --sessions claude-1,claude-2,codex-1
|
|
129
|
+
telepty deliberate status
|
|
130
|
+
telepty deliberate end <thread_id>
|
|
131
|
+
```
|
|
82
132
|
|
|
83
133
|
## Skill Installation
|
|
84
134
|
|
|
85
|
-
|
|
135
|
+
telepty ships with packaged skills for Claude Code, Codex, and Gemini CLI. Run the interactive installer:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
telepty
|
|
139
|
+
# Choose "Install telepty skills"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Testing
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm test # 70 tests (node:test)
|
|
146
|
+
npm run test:watch # Watch mode
|
|
147
|
+
```
|
|
86
148
|
|
|
87
|
-
|
|
149
|
+
## License
|
|
88
150
|
|
|
89
|
-
|
|
90
|
-
- which packaged skills to install
|
|
91
|
-
- which target clients to install into (`Claude Code`, `Codex`, `Gemini`)
|
|
92
|
-
- whether each target uses a global path, the current project path, or a custom path
|
|
151
|
+
ISC
|
package/cli.js
CHANGED
|
@@ -1819,6 +1819,39 @@ async function main() {
|
|
|
1819
1819
|
return;
|
|
1820
1820
|
}
|
|
1821
1821
|
|
|
1822
|
+
if (cmd === 'delete') {
|
|
1823
|
+
const sessionRef = args[1];
|
|
1824
|
+
if (!sessionRef) { console.error('❌ Usage: telepty delete <session-id>'); process.exit(1); }
|
|
1825
|
+
try {
|
|
1826
|
+
const target = await resolveSessionTarget(sessionRef);
|
|
1827
|
+
if (!target) { console.error(`❌ Session '${sessionRef}' not found.`); process.exit(1); }
|
|
1828
|
+
const res = await fetchWithAuth(`http://${target.host}:${PORT}/api/sessions/${encodeURIComponent(target.id)}`, { method: 'DELETE' });
|
|
1829
|
+
const data = await res.json();
|
|
1830
|
+
if (!res.ok) { console.error(`❌ Error: ${data.error}`); return; }
|
|
1831
|
+
console.log(`✅ Session '\x1b[36m${target.id}\x1b[0m' deleted.`);
|
|
1832
|
+
} catch (e) { console.error(`❌ ${e.message || 'Failed to delete session.'}`); }
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
if (cmd === 'clean') {
|
|
1837
|
+
try {
|
|
1838
|
+
const sessions = await discoverSessions({ silent: true });
|
|
1839
|
+
if (sessions.length === 0) { console.log('No sessions found.'); return; }
|
|
1840
|
+
let cleaned = 0;
|
|
1841
|
+
for (const s of sessions) {
|
|
1842
|
+
if (s.healthStatus === 'STALE' || s.healthStatus === 'DISCONNECTED') {
|
|
1843
|
+
try {
|
|
1844
|
+
const host = s.host || '127.0.0.1';
|
|
1845
|
+
const res = await fetchWithAuth(`http://${host}:${PORT}/api/sessions/${encodeURIComponent(s.id)}`, { method: 'DELETE' });
|
|
1846
|
+
if (res.ok) { console.log(` 🗑 Removed ghost: \x1b[36m${s.id}\x1b[0m (${s.healthStatus})`); cleaned++; }
|
|
1847
|
+
} catch (_) {}
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
console.log(cleaned > 0 ? `✅ Cleaned ${cleaned} ghost session(s).` : '✅ No ghost sessions found.');
|
|
1851
|
+
} catch (e) { console.error(`❌ ${e.message || 'Failed to clean sessions.'}`); }
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1822
1855
|
if (cmd === 'rename') {
|
|
1823
1856
|
const oldId = args[1]; const newId = args[2];
|
|
1824
1857
|
if (!oldId || !newId) { console.error('❌ Usage: telepty rename <old_id> <new_id>'); process.exit(1); }
|
|
@@ -2711,43 +2744,66 @@ Discuss the following topic from your project's perspective. Engage with other s
|
|
|
2711
2744
|
}
|
|
2712
2745
|
|
|
2713
2746
|
console.log(`
|
|
2714
|
-
\x1b[
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
telepty daemon Start the background daemon
|
|
2718
|
-
telepty spawn --id <id> <command> [args...] Spawn a new background
|
|
2719
|
-
telepty allow [--id <id>] [--auto-restart] <command> [args...]
|
|
2720
|
-
telepty list [--json] List
|
|
2721
|
-
telepty attach [id[@host]] Attach
|
|
2722
|
-
telepty
|
|
2723
|
-
telepty
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
telepty
|
|
2727
|
-
telepty
|
|
2728
|
-
telepty
|
|
2729
|
-
telepty
|
|
2730
|
-
telepty
|
|
2731
|
-
telepty
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
telepty
|
|
2735
|
-
telepty
|
|
2736
|
-
telepty
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2747
|
+
\x1b[1mtelepty\x1b[0m — Connect any terminal to any terminal, any machine.
|
|
2748
|
+
|
|
2749
|
+
\x1b[1mSession Management:\x1b[0m
|
|
2750
|
+
telepty daemon Start the background daemon (port 3848)
|
|
2751
|
+
telepty spawn --id <id> <command> [args...] Spawn a new background session
|
|
2752
|
+
telepty allow [--id <id>] [--auto-restart] <command> [args...] Wrap a CLI for remote control
|
|
2753
|
+
telepty list [--json] List sessions (local + Tailnet)
|
|
2754
|
+
telepty attach [id[@host]] Attach interactively (picker if no ID)
|
|
2755
|
+
telepty rename <old_id[@host]> <new_id> Rename a session
|
|
2756
|
+
telepty session info <id[@host]> [--json] Show session metadata
|
|
2757
|
+
|
|
2758
|
+
\x1b[1mInject & Communicate:\x1b[0m
|
|
2759
|
+
telepty inject [--ref [file]] [--from <id>] <id[@host]> "<prompt>" Inject text
|
|
2760
|
+
telepty enter <id[@host]> Send Enter/Return
|
|
2761
|
+
telepty reply "<text>" Reply to last injector
|
|
2762
|
+
telepty multicast <id1,id2> "<prompt>" Inject into multiple sessions
|
|
2763
|
+
telepty broadcast [--ref [file]] "<prompt>" Inject into ALL sessions
|
|
2764
|
+
telepty read-screen <id[@host]> [--lines N] Read session screen buffer
|
|
2765
|
+
|
|
2766
|
+
\x1b[1mCross-Machine:\x1b[0m
|
|
2767
|
+
telepty connect <user@host> [--name N] [--port P] SSH tunnel to remote host
|
|
2768
|
+
telepty disconnect <name> | --all Disconnect remote host
|
|
2769
|
+
telepty peers [--remove <name>] List connected peers
|
|
2770
|
+
|
|
2771
|
+
\x1b[1mMonitoring:\x1b[0m
|
|
2772
|
+
telepty tui Full TUI dashboard
|
|
2773
|
+
telepty monitor Real-time event billboard
|
|
2774
|
+
telepty listen Stream event bus as JSON
|
|
2775
|
+
|
|
2776
|
+
\x1b[1mHandoff:\x1b[0m
|
|
2777
|
+
telepty handoff list [--status=S] List handoffs
|
|
2778
|
+
telepty handoff drop [options] Create handoff from synthesis
|
|
2779
|
+
telepty handoff claim <id> [--agent=S] Claim a pending handoff
|
|
2780
|
+
telepty handoff status <id> [status] Get/update handoff status
|
|
2781
|
+
|
|
2782
|
+
\x1b[1mDeliberation:\x1b[0m
|
|
2783
|
+
telepty deliberate --topic "..." [--sessions s1,s2] Start multi-session discussion
|
|
2784
|
+
telepty deliberate status [thread_id] Show thread details
|
|
2785
|
+
telepty deliberate end <thread_id> Close a thread
|
|
2786
|
+
|
|
2787
|
+
\x1b[1mOther:\x1b[0m
|
|
2788
|
+
telepty update Update to latest version
|
|
2789
|
+
telepty layout [grid|tall|stack] Arrange terminal windows
|
|
2790
|
+
telepty status-report --phase <p> [options] Emit structured status event
|
|
2791
|
+
|
|
2792
|
+
\x1b[1mExamples:\x1b[0m
|
|
2793
|
+
\x1b[2m# Wrap Claude Code for remote control\x1b[0m
|
|
2794
|
+
telepty allow --id my-claude claude
|
|
2795
|
+
|
|
2796
|
+
\x1b[2m# Send a prompt to a session\x1b[0m
|
|
2797
|
+
telepty inject my-claude "explain the auth module"
|
|
2798
|
+
|
|
2799
|
+
\x1b[2m# Read what a session is showing\x1b[0m
|
|
2800
|
+
telepty read-screen my-claude --lines 30
|
|
2801
|
+
|
|
2802
|
+
\x1b[2m# Broadcast to all sessions\x1b[0m
|
|
2803
|
+
telepty broadcast "status report please"
|
|
2804
|
+
|
|
2805
|
+
\x1b[2m# Inject into a session on another machine\x1b[0m
|
|
2806
|
+
telepty inject my-claude@server-01 "run the tests"
|
|
2751
2807
|
`);
|
|
2752
2808
|
}
|
|
2753
2809
|
|
package/daemon.js
CHANGED
|
@@ -1478,18 +1478,20 @@ app.delete('/api/sessions/:id', (req, res) => {
|
|
|
1478
1478
|
try {
|
|
1479
1479
|
session.isClosing = true;
|
|
1480
1480
|
if (session.type === 'wrapped') {
|
|
1481
|
-
session.clients.forEach(ws => ws.close(1000, 'Session destroyed'));
|
|
1482
|
-
|
|
1483
|
-
console.log(`[KILL] Wrapped session ${id} removed`);
|
|
1484
|
-
persistSessions();
|
|
1485
|
-
} else {
|
|
1481
|
+
if (session.clients) session.clients.forEach(ws => ws.close(1000, 'Session destroyed'));
|
|
1482
|
+
} else if (session.ptyProcess) {
|
|
1486
1483
|
session.ptyProcess.kill();
|
|
1487
|
-
console.log(`[KILL] Session ${id} forcefully closed`);
|
|
1488
|
-
persistSessions();
|
|
1489
1484
|
}
|
|
1485
|
+
delete sessions[id];
|
|
1486
|
+
console.log(`[KILL] Session ${id} removed`);
|
|
1487
|
+
persistSessions();
|
|
1490
1488
|
res.json({ success: true, status: 'closing' });
|
|
1491
1489
|
} catch (err) {
|
|
1492
|
-
|
|
1490
|
+
// Even if kill fails, remove from registry
|
|
1491
|
+
delete sessions[id];
|
|
1492
|
+
persistSessions();
|
|
1493
|
+
console.log(`[KILL] Session ${id} force-removed (process cleanup error: ${err.message})`);
|
|
1494
|
+
res.json({ success: true, status: 'force-removed' });
|
|
1493
1495
|
}
|
|
1494
1496
|
});
|
|
1495
1497
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dmsdc-ai/aigentry-telepty",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.82",
|
|
4
4
|
"main": "daemon.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"aigentry-telepty": "install.js",
|
|
@@ -12,10 +12,31 @@
|
|
|
12
12
|
"test:watch": "node --test --watch test/auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/cli.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js",
|
|
13
13
|
"test:ci": "node --test --test-reporter=spec test/auth.test.js test/daemon.test.js test/daemon-singleton.test.js test/cli.test.js test/skill-installer.test.js test/interactive-terminal.test.js test/runtime-info.test.js test/session-routing.test.js"
|
|
14
14
|
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
|
|
15
|
+
"keywords": [
|
|
16
|
+
"pty",
|
|
17
|
+
"terminal",
|
|
18
|
+
"session",
|
|
19
|
+
"multiplexer",
|
|
20
|
+
"remote",
|
|
21
|
+
"inject",
|
|
22
|
+
"ai-cli",
|
|
23
|
+
"claude",
|
|
24
|
+
"codex",
|
|
25
|
+
"gemini",
|
|
26
|
+
"cross-machine",
|
|
27
|
+
"tailscale"
|
|
28
|
+
],
|
|
29
|
+
"author": "dmsdc-ai",
|
|
17
30
|
"license": "ISC",
|
|
18
|
-
"description": "",
|
|
31
|
+
"description": "Universal terminal session bridge — connect any terminal to any terminal, any machine",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/dmsdc-ai/aigentry-telepty.git"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/dmsdc-ai/aigentry-telepty#readme",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/dmsdc-ai/aigentry-telepty/issues"
|
|
39
|
+
},
|
|
19
40
|
"dependencies": {
|
|
20
41
|
"blessed": "^0.1.81",
|
|
21
42
|
"cors": "^2.8.6",
|