@dmsdc-ai/aigentry-telepty 0.1.6 → 0.1.7

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 CHANGED
@@ -55,3 +55,14 @@ npm run test:watch
55
55
  ```
56
56
 
57
57
  The automated suite covers config generation, daemon HTTP APIs, WebSocket attach/output flow, bus events, session deletion regressions, and CLI smoke tests against a real daemon process.
58
+
59
+ ## Skill Installation
60
+
61
+ The package installer opens the telepty skill TUI automatically when you run it in a terminal.
62
+
63
+ To reopen it later, run `telepty` and choose `Install telepty skills`.
64
+
65
+ The TUI lets you choose:
66
+ - which packaged skills to install
67
+ - which target clients to install into (`Claude Code`, `Codex`, `Gemini`)
68
+ - whether each target uses a global path, the current project path, or a custom path
package/cli.js CHANGED
@@ -9,6 +9,7 @@ const prompts = require('prompts');
9
9
  const updateNotifier = require('update-notifier');
10
10
  const pkg = require('./package.json');
11
11
  const { getConfig } = require('./auth');
12
+ const { runInteractiveSkillInstaller } = require('./skill-installer');
12
13
  const args = process.argv.slice(2);
13
14
 
14
15
  // Check for updates unless explicitly disabled for tests/CI.
@@ -152,6 +153,7 @@ async function manageInteractive() {
152
153
  { title: 'šŸ”Œ Allow inject (Run CLI with inject)', value: 'allow' },
153
154
  { title: 'šŸ’¬ Send message to a room (Inject command)', value: 'inject' },
154
155
  { title: 'šŸ“‹ View all open rooms (List sessions)', value: 'list' },
156
+ { title: '🧠 Install telepty skills', value: 'install-skills' },
155
157
  { title: 'šŸ”„ Update telepty to latest version', value: 'update' },
156
158
  { title: 'āŒ Exit', value: 'exit' }
157
159
  ]
@@ -189,6 +191,15 @@ async function manageInteractive() {
189
191
  continue;
190
192
  }
191
193
 
194
+ if (response.action === 'install-skills') {
195
+ try {
196
+ await runInteractiveSkillInstaller({ packageRoot: __dirname, cwd: process.cwd() });
197
+ } catch (e) {
198
+ console.error(`\nāŒ ${e.message}\n`);
199
+ }
200
+ continue;
201
+ }
202
+
192
203
  if (response.action === 'list') {
193
204
  console.log('\n');
194
205
  const sessions = await discoverSessions();
package/install.js CHANGED
@@ -4,6 +4,7 @@ const { execSync, spawn } = require('child_process');
4
4
  const os = require('os');
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
+ const { runInteractiveSkillInstaller } = require('./skill-installer');
7
8
 
8
9
  console.log("šŸš€ Installing @dmsdc-ai/aigentry-telepty...");
9
10
 
@@ -16,38 +17,69 @@ function run(cmd) {
16
17
  }
17
18
  }
18
19
 
19
- // 1. Install globally via npm
20
- console.log("šŸ“¦ Installing package globally...");
21
- run("npm install -g @dmsdc-ai/aigentry-telepty");
20
+ function resolveInstalledPackageRoot() {
21
+ try {
22
+ const globalRoot = execSync('npm root -g', { encoding: 'utf8' }).trim();
23
+ return path.join(globalRoot, '@dmsdc-ai', 'aigentry-telepty');
24
+ } catch (e) {
25
+ return __dirname;
26
+ }
27
+ }
28
+
29
+ async function installSkills() {
30
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
31
+ console.log('ā­ļø Skipping interactive skill installation (no TTY).');
32
+ console.log(' Run `telepty` later and choose "Install telepty skills".');
33
+ return;
34
+ }
35
+
36
+ console.log('\nšŸ“‹ Telepty skill installation');
22
37
 
23
- // 2. Find executable
24
- let teleptyPath = '';
25
- try {
26
- teleptyPath = execSync(os.platform() === 'win32' ? 'where telepty' : 'which telepty', { encoding: 'utf8' }).split('\n')[0].trim();
27
- } catch (e) {
28
- teleptyPath = 'telepty'; // fallback
38
+ try {
39
+ await runInteractiveSkillInstaller({
40
+ packageRoot: resolveInstalledPackageRoot(),
41
+ cwd: process.cwd()
42
+ });
43
+ } catch (e) {
44
+ console.warn('āš ļø Could not install telepty skills:', e.message);
45
+ }
29
46
  }
30
47
 
31
- // 3. Setup OS-specific autostart or background daemon
32
- const platform = os.platform();
33
-
34
- if (platform === 'win32') {
35
- console.log("āš™ļø Setting up Windows background process...");
36
- // Launch daemon in background detaching from current console
37
- const subprocess = spawn(teleptyPath, ['daemon'], {
38
- detached: true,
39
- stdio: 'ignore',
40
- windowsHide: true
41
- });
42
- subprocess.unref();
43
- console.log("āœ… Windows daemon started in background.");
44
-
45
- } else if (platform === 'darwin') {
46
- console.log("āš™ļø Setting up macOS launchd service...");
47
- const plistPath = path.join(os.homedir(), 'Library', 'LaunchAgents', 'com.aigentry.telepty.plist');
48
- fs.mkdirSync(path.dirname(plistPath), { recursive: true });
49
-
50
- const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
48
+ (async () => {
49
+ // 1. Install globally via npm
50
+ console.log("šŸ“¦ Installing package globally...");
51
+ run("npm install -g @dmsdc-ai/aigentry-telepty");
52
+
53
+ // 2. Install telepty skills for supported clients
54
+ await installSkills();
55
+
56
+ // 3. Find executable
57
+ let teleptyPath = '';
58
+ try {
59
+ teleptyPath = execSync(os.platform() === 'win32' ? 'where telepty' : 'which telepty', { encoding: 'utf8' }).split('\n')[0].trim();
60
+ } catch (e) {
61
+ teleptyPath = 'telepty'; // fallback
62
+ }
63
+
64
+ // 4. Setup OS-specific autostart or background daemon
65
+ const platform = os.platform();
66
+
67
+ if (platform === 'win32') {
68
+ console.log("āš™ļø Setting up Windows background process...");
69
+ const subprocess = spawn(teleptyPath, ['daemon'], {
70
+ detached: true,
71
+ stdio: 'ignore',
72
+ windowsHide: true
73
+ });
74
+ subprocess.unref();
75
+ console.log("āœ… Windows daemon started in background.");
76
+
77
+ } else if (platform === 'darwin') {
78
+ console.log("āš™ļø Setting up macOS launchd service...");
79
+ const plistPath = path.join(os.homedir(), 'Library', 'LaunchAgents', 'com.aigentry.telepty.plist');
80
+ fs.mkdirSync(path.dirname(plistPath), { recursive: true });
81
+
82
+ const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
51
83
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
52
84
  <plist version="1.0">
53
85
  <dict>
@@ -64,20 +96,19 @@ if (platform === 'win32') {
64
96
  <true/>
65
97
  </dict>
66
98
  </plist>`;
67
-
68
- fs.writeFileSync(plistPath, plistContent);
69
- try { execSync(`launchctl unload "${plistPath}" 2>/dev/null`); } catch(e){}
70
- run(`launchctl load "${plistPath}"`);
71
- console.log("āœ… macOS LaunchAgent installed and started.");
72
-
73
- } else {
74
- // Linux
75
- try {
76
- // Check if systemd is available and running as root/sudo
77
- execSync('systemctl --version', { stdio: 'ignore' });
78
- if (process.getuid && process.getuid() === 0) {
79
- console.log("āš™ļø Setting up systemd service for Linux...");
80
- const serviceContent = `[Unit]
99
+
100
+ fs.writeFileSync(plistPath, plistContent);
101
+ try { execSync(`launchctl unload "${plistPath}" 2>/dev/null`); } catch(e){}
102
+ run(`launchctl load "${plistPath}"`);
103
+ console.log("āœ… macOS LaunchAgent installed and started.");
104
+
105
+ } else {
106
+ // Linux
107
+ try {
108
+ execSync('systemctl --version', { stdio: 'ignore' });
109
+ if (process.getuid && process.getuid() === 0) {
110
+ console.log("āš™ļø Setting up systemd service for Linux...");
111
+ const serviceContent = `[Unit]
81
112
  Description=Telepty Daemon
82
113
  After=network.target
83
114
 
@@ -90,25 +121,26 @@ Environment=NODE_ENV=production
90
121
 
91
122
  [Install]
92
123
  WantedBy=multi-user.target`;
93
-
94
- fs.writeFileSync('/etc/systemd/system/telepty.service', serviceContent);
95
- run('systemctl daemon-reload');
96
- run('systemctl enable telepty');
97
- run('systemctl start telepty');
98
- console.log("āœ… Systemd service installed and started.");
99
- process.exit(0);
100
- }
101
- } catch(e) {}
102
-
103
- // Fallback for Linux without systemd or non-root
104
- console.log("āš ļø Skipping systemd (no root or no systemd). Starting in background...");
105
- const subprocess = spawn(teleptyPath, ['daemon'], {
106
- detached: true,
107
- stdio: 'ignore'
108
- });
109
- subprocess.unref();
110
- console.log("āœ… Linux daemon started in background using nohup equivalent.");
111
- }
112
124
 
113
- console.log("\nšŸŽ‰ Installation complete! Telepty daemon is running.");
114
- console.log("šŸ‘‰ Try running: telepty attach\n");
125
+ fs.writeFileSync('/etc/systemd/system/telepty.service', serviceContent);
126
+ run('systemctl daemon-reload');
127
+ run('systemctl enable telepty');
128
+ run('systemctl start telepty');
129
+ console.log("āœ… Systemd service installed and started.");
130
+ process.exit(0);
131
+ }
132
+ } catch(e) {}
133
+
134
+ // Fallback for Linux without systemd or non-root
135
+ console.log("āš ļø Skipping systemd (no root or no systemd). Starting in background...");
136
+ const subprocess = spawn(teleptyPath, ['daemon'], {
137
+ detached: true,
138
+ stdio: 'ignore'
139
+ });
140
+ subprocess.unref();
141
+ console.log("āœ… Linux daemon started in background using nohup equivalent.");
142
+ }
143
+
144
+ console.log("\nšŸŽ‰ Installation complete! Telepty daemon is running.");
145
+ console.log("šŸ‘‰ Try running: telepty attach\n");
146
+ })();
package/install.ps1 CHANGED
@@ -31,3 +31,4 @@ Write-Host "Success: Windows daemon started in background." -ForegroundColor Gre
31
31
 
32
32
  Write-Host "`nInstallation complete! Telepty daemon is running." -ForegroundColor Cyan
33
33
  Write-Host "Next step: Try running: telepty attach" -ForegroundColor Yellow
34
+ Write-Host "Optional: Run telepty and choose 'Install telepty skills' to add skills for Claude Code, Codex, or Gemini" -ForegroundColor Yellow
package/install.sh CHANGED
@@ -116,3 +116,4 @@ fi
116
116
  echo ""
117
117
  echo "šŸŽ‰ Installation complete! Telepty daemon is running in the background."
118
118
  echo "šŸ‘‰ Try running: telepty attach"
119
+ echo "šŸ‘‰ Optional: run telepty and choose 'Install telepty skills' to add skills for Claude Code, Codex, or Gemini"
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-telepty",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "main": "daemon.js",
5
5
  "bin": {
6
6
  "telepty": "cli.js",
7
7
  "telepty-install": "install.js"
8
8
  },
9
9
  "scripts": {
10
- "test": "node --test test/auth.test.js test/daemon.test.js test/cli.test.js",
11
- "test:watch": "node --test --watch test/auth.test.js test/daemon.test.js test/cli.test.js",
12
- "test:ci": "node --test --test-reporter=spec test/auth.test.js test/daemon.test.js test/cli.test.js"
10
+ "test": "node --test test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js",
11
+ "test:watch": "node --test --watch test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js",
12
+ "test:ci": "node --test --test-reporter=spec test/auth.test.js test/daemon.test.js test/cli.test.js test/skill-installer.test.js"
13
13
  },
14
14
  "keywords": [],
15
15
  "author": "",
@@ -0,0 +1,269 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+ const prompts = require('prompts');
7
+
8
+ const TARGET_CLIENTS = {
9
+ claude: {
10
+ label: 'Claude Code',
11
+ globalDir: () => path.join(os.homedir(), '.claude', 'skills'),
12
+ projectDir: (cwd) => path.join(cwd, '.claude', 'skills'),
13
+ defaultScope: 'global'
14
+ },
15
+ codex: {
16
+ label: 'Codex',
17
+ globalDir: () => path.join(os.homedir(), '.codex', 'skills'),
18
+ projectDir: (cwd) => path.join(cwd, '.codex', 'skills'),
19
+ defaultScope: 'global'
20
+ },
21
+ gemini: {
22
+ label: 'Gemini',
23
+ globalDir: () => path.join(os.homedir(), '.gemini', 'skills'),
24
+ projectDir: (cwd) => path.join(cwd, '.gemini', 'skills'),
25
+ defaultScope: 'project'
26
+ }
27
+ };
28
+
29
+ function resolveSkillsSourceRoot(packageRoot = __dirname) {
30
+ return path.join(packageRoot, 'skills');
31
+ }
32
+
33
+ function listPackagedSkills(packageRoot = __dirname) {
34
+ const sourceRoot = resolveSkillsSourceRoot(packageRoot);
35
+ if (!fs.existsSync(sourceRoot)) {
36
+ return [];
37
+ }
38
+
39
+ return fs.readdirSync(sourceRoot)
40
+ .filter((name) => {
41
+ const skillDir = path.join(sourceRoot, name);
42
+ return fs.statSync(skillDir).isDirectory() && fs.existsSync(path.join(skillDir, 'SKILL.md'));
43
+ })
44
+ .sort()
45
+ .map((name) => ({
46
+ name,
47
+ sourceDir: path.join(sourceRoot, name)
48
+ }));
49
+ }
50
+
51
+ function resolveTargetDirectory(targetClient, scope, cwd, customPath) {
52
+ const client = TARGET_CLIENTS[targetClient];
53
+ if (!client) {
54
+ throw new Error(`Unsupported target client: ${targetClient}`);
55
+ }
56
+
57
+ if (scope === 'custom') {
58
+ if (!customPath) {
59
+ throw new Error(`Missing custom path for ${targetClient}`);
60
+ }
61
+ return path.resolve(customPath);
62
+ }
63
+
64
+ if (scope === 'project') {
65
+ return client.projectDir(cwd);
66
+ }
67
+
68
+ return client.globalDir();
69
+ }
70
+
71
+ function ensureDirectory(dirPath) {
72
+ fs.mkdirSync(dirPath, { recursive: true });
73
+ }
74
+
75
+ function copySkillDirectory(sourceDir, destDir, overwrite = false) {
76
+ if (fs.existsSync(destDir)) {
77
+ if (!overwrite) {
78
+ return 'exists';
79
+ }
80
+ fs.rmSync(destDir, { recursive: true, force: true });
81
+ }
82
+
83
+ ensureDirectory(path.dirname(destDir));
84
+ fs.cpSync(sourceDir, destDir, { recursive: true });
85
+ return 'installed';
86
+ }
87
+
88
+ async function promptForOverwrite(promptImpl, targetLabel, destDir) {
89
+ const response = await promptImpl({
90
+ type: 'select',
91
+ name: 'action',
92
+ message: `${targetLabel} already has ${path.basename(destDir)}. What should happen?`,
93
+ choices: [
94
+ { title: 'Overwrite existing copy', value: 'overwrite' },
95
+ { title: 'Skip this target', value: 'skip' },
96
+ { title: 'Cancel installation', value: 'cancel' }
97
+ ],
98
+ initial: 1
99
+ });
100
+
101
+ return response.action;
102
+ }
103
+
104
+ async function installSkillsWithPlan(plan, options = {}) {
105
+ const promptImpl = options.promptImpl || prompts;
106
+ const results = [];
107
+
108
+ for (const item of plan) {
109
+ const skillName = item.skill.name;
110
+ const destDir = path.join(item.destRoot, skillName);
111
+ let overwrite = false;
112
+
113
+ if (fs.existsSync(destDir)) {
114
+ const action = await promptForOverwrite(promptImpl, item.targetLabel, destDir);
115
+ if (!action || action === 'cancel') {
116
+ throw new Error('Installation cancelled.');
117
+ }
118
+ if (action === 'skip') {
119
+ results.push({ ...item, destDir, status: 'skipped' });
120
+ continue;
121
+ }
122
+ overwrite = true;
123
+ }
124
+
125
+ copySkillDirectory(item.skill.sourceDir, destDir, overwrite);
126
+ results.push({ ...item, destDir, status: overwrite ? 'overwritten' : 'installed' });
127
+ }
128
+
129
+ return results;
130
+ }
131
+
132
+ async function runInteractiveSkillInstaller(options = {}) {
133
+ const promptImpl = options.promptImpl || prompts;
134
+ const packageRoot = options.packageRoot || __dirname;
135
+ const cwd = options.cwd || process.cwd();
136
+ const packagedSkills = listPackagedSkills(packageRoot);
137
+
138
+ if (packagedSkills.length === 0) {
139
+ console.log('No packaged skills were found.');
140
+ return [];
141
+ }
142
+
143
+ let selectedSkills = packagedSkills;
144
+ if (packagedSkills.length > 1) {
145
+ const selectedSkillsAnswer = await promptImpl({
146
+ type: 'multiselect',
147
+ name: 'skills',
148
+ message: 'Select skills to install',
149
+ choices: packagedSkills.map((skill) => ({
150
+ title: skill.name,
151
+ value: skill.name
152
+ })),
153
+ min: 1
154
+ });
155
+
156
+ if (!selectedSkillsAnswer.skills || selectedSkillsAnswer.skills.length === 0) {
157
+ console.log('Skipped skill installation.');
158
+ return [];
159
+ }
160
+
161
+ selectedSkills = packagedSkills.filter((skill) => selectedSkillsAnswer.skills.includes(skill.name));
162
+ } else {
163
+ console.log(`Installing packaged skill: ${packagedSkills[0].name}`);
164
+ }
165
+
166
+ const selectedClientsAnswer = await promptImpl({
167
+ type: 'multiselect',
168
+ name: 'clients',
169
+ message: 'Select target clients',
170
+ choices: Object.entries(TARGET_CLIENTS).map(([key, value]) => ({
171
+ title: value.label,
172
+ value: key
173
+ })),
174
+ min: 1
175
+ });
176
+
177
+ if (!selectedClientsAnswer.clients || selectedClientsAnswer.clients.length === 0) {
178
+ console.log('Skipped skill installation.');
179
+ return [];
180
+ }
181
+
182
+ const destinationSelections = {};
183
+ for (const clientKey of selectedClientsAnswer.clients) {
184
+ const client = TARGET_CLIENTS[clientKey];
185
+ const scopeAnswer = await promptImpl([
186
+ {
187
+ type: 'select',
188
+ name: 'scope',
189
+ message: `Install ${client.label} skills where?`,
190
+ choices: [
191
+ {
192
+ title: `Global (${client.globalDir()})`,
193
+ value: 'global'
194
+ },
195
+ {
196
+ title: `Current Project (${client.projectDir(cwd)})`,
197
+ value: 'project'
198
+ },
199
+ {
200
+ title: 'Custom Path',
201
+ value: 'custom'
202
+ }
203
+ ],
204
+ initial: client.defaultScope === 'project' ? 1 : 0
205
+ },
206
+ {
207
+ type: (prev) => prev === 'custom' ? 'text' : null,
208
+ name: 'customPath',
209
+ message: `Custom ${client.label} skills path:`,
210
+ initial: client.projectDir(cwd),
211
+ validate: (value) => value ? true : 'Required'
212
+ }
213
+ ]);
214
+
215
+ if (!scopeAnswer.scope) {
216
+ console.log('Skipped skill installation.');
217
+ return [];
218
+ }
219
+
220
+ destinationSelections[clientKey] = {
221
+ scope: scopeAnswer.scope,
222
+ customPath: scopeAnswer.customPath || null
223
+ };
224
+ }
225
+
226
+ const plan = [];
227
+
228
+ for (const clientKey of selectedClientsAnswer.clients) {
229
+ const client = TARGET_CLIENTS[clientKey];
230
+ const selection = destinationSelections[clientKey];
231
+ const destRoot = resolveTargetDirectory(clientKey, selection.scope, cwd, selection.customPath);
232
+
233
+ for (const skill of selectedSkills) {
234
+ plan.push({
235
+ targetClient: clientKey,
236
+ targetLabel: client.label,
237
+ scope: selection.scope,
238
+ destRoot,
239
+ skill
240
+ });
241
+ }
242
+ }
243
+
244
+ console.log('\nInstalling telepty skills:');
245
+ for (const item of plan) {
246
+ console.log(` - ${item.skill.name} -> ${item.targetLabel} (${item.scope})`);
247
+ console.log(` ${item.destRoot}`);
248
+ }
249
+
250
+ const results = await installSkillsWithPlan(plan, { promptImpl });
251
+
252
+ console.log('\nSkill installation results:');
253
+ for (const item of results) {
254
+ const label = item.status === 'skipped' ? 'Skipped' : 'Installed';
255
+ console.log(` ${label}: ${item.skill.name} -> ${item.targetLabel}`);
256
+ console.log(` ${item.destDir}`);
257
+ }
258
+
259
+ return results;
260
+ }
261
+
262
+ module.exports = {
263
+ TARGET_CLIENTS,
264
+ copySkillDirectory,
265
+ installSkillsWithPlan,
266
+ listPackagedSkills,
267
+ resolveTargetDirectory,
268
+ runInteractiveSkillInstaller
269
+ };
@@ -0,0 +1,86 @@
1
+ # telepty
2
+
3
+ Use `telepty` to inspect active sessions, check the current telepty session ID, attach to sessions, inject commands, listen to the event bus, rename sessions, and update the daemon.
4
+
5
+ ## When To Use
6
+
7
+ Use this skill when the user asks to:
8
+ - Check whether the current shell is running inside a telepty session
9
+ - List or inspect telepty sessions
10
+ - Attach to a telepty session
11
+ - Inject a prompt or command into another telepty session
12
+ - Listen to telepty bus events or publish a JSON payload
13
+ - Rename a session
14
+ - Update telepty
15
+
16
+ ## Commands
17
+
18
+ 1. Check the current telepty session:
19
+
20
+ ```bash
21
+ echo "$TELEPTY_SESSION_ID"
22
+ ```
23
+
24
+ 2. List sessions:
25
+
26
+ ```bash
27
+ telepty list
28
+ ```
29
+
30
+ 3. Attach to a session:
31
+
32
+ ```bash
33
+ telepty attach <session_id>
34
+ ```
35
+
36
+ 4. Inject a prompt or command:
37
+
38
+ ```bash
39
+ telepty inject <session_id> "<prompt text>"
40
+ ```
41
+
42
+ 5. Inject into multiple sessions:
43
+
44
+ ```bash
45
+ telepty multicast <id1,id2,...> "<prompt text>"
46
+ ```
47
+
48
+ 6. Broadcast to all sessions:
49
+
50
+ ```bash
51
+ telepty broadcast "<prompt text>"
52
+ ```
53
+
54
+ 7. Rename a session:
55
+
56
+ ```bash
57
+ telepty rename <old_id> <new_id>
58
+ ```
59
+
60
+ 8. Listen to the event bus:
61
+
62
+ ```bash
63
+ telepty listen
64
+ ```
65
+
66
+ 9. Publish a JSON payload to the bus:
67
+
68
+ ```bash
69
+ TOKEN=$(grep authToken ~/.telepty/config.json | cut -d '"' -f 4)
70
+ curl -s -X POST http://127.0.0.1:3848/api/bus/publish \
71
+ -H "Content-Type: application/json" \
72
+ -H "x-telepty-token: $TOKEN" \
73
+ -d '{"type":"bg_message","payload":"..."}'
74
+ ```
75
+
76
+ 10. Update telepty:
77
+
78
+ ```bash
79
+ telepty update
80
+ ```
81
+
82
+ ## Notes
83
+
84
+ - `TELEPTY_SESSION_ID` is only set inside telepty-managed sessions.
85
+ - Use `telepty inject` when the target session should receive the command immediately.
86
+ - Use the JSON bus when the payload should be delivered without interrupting the target shell.
@@ -1 +0,0 @@
1
- {"topic": "Brainstorming and critiquing the 3 communication modes in telepty (Prompt Injection, Visual Log, Background JSON). What crucial interaction pattern between human users and AI agents is missing from this list? Consider synchronous vs asynchronous, blocking vs non-blocking, and explicit handshakes.", "speakers": ["claude", "codex", "gemini"], "role_preset": "brainstorm"}
@@ -1 +0,0 @@
1
- {"topic": "Re-evaluate the telepty architecture based on the user`s strict boundaries: 1. A session equals a physical, visible terminal window. If the window closes, the session MUST die. No zombies. 2. Background persistence is NOT telepty`s job (users can use tmux if they want, but telepty doesn`t manage it). 3. Unexpected disconnects (network drop, sleep) are treated as session death, and recovery is handled via a higher-level `Handoff` of context to a new session, NOT by keeping zombie processes alive. Double-check this philosophy for flaws, focusing on how AI agents will communicate (Pub/Sub) within this strict ephemeral foreground model.", "speakers": ["claude", "codex", "gemini"], "role_preset": "review"}
@@ -1 +0,0 @@
1
- {"topic": "Final architectural verification of the Telepty Boundary Model. The user asserts a hard line on responsibility: 1. If a session/process dies, context is lost. That is the CLI/Terminal`s problem, not telepty`s. 2. If a Pub message is sent to a dead Sub, it is lost. Telepty just drops it or relies on Ack. If the sub reconnects in time, it gets it; if not, drop it. 3. If Wi-Fi drops, CLI dies, agent dies, scripts die. Telepty does not care about split-brain or script recovery. Is this stateless, hyper-minimalist `dumb pipe` philosophy technically viable for our goals?", "speakers": ["claude", "gemini", "codex"], "role_preset": "consensus"}