create-claude-workspace 1.1.130 → 1.1.132

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,13 +1,10 @@
1
1
  // ─── Terminal UI for autonomous loop ───
2
- // Two modes:
3
- // Default: beautiful colored line-by-line output (works everywhere)
4
- // Interactive (--interactive): adds input prompt + keyboard controls (needs capable terminal)
2
+ // Events push lines to a buffer. Render loop (4 fps) draws pending lines
3
+ // + status bar. No cursor tricks — just append lines and \r overwrite status.
5
4
  import { appendFileSync } from 'node:fs';
6
5
  // ─── ANSI ───
7
6
  const a = {
8
- reset: '\x1b[0m',
9
- bold: '\x1b[1m',
10
- dim: '\x1b[2m',
7
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
11
8
  fg: {
12
9
  red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
13
10
  blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', white: '\x1b[37m',
@@ -17,7 +14,7 @@ const a = {
17
14
  },
18
15
  bg: { gray: '\x1b[48;5;236m' },
19
16
  };
20
- // ─── Agent colors ───
17
+ // ─── Shared utilities ───
21
18
  const AGENT_PALETTE = [a.fg.brightCyan, a.fg.brightMagenta, a.fg.brightGreen, a.fg.brightYellow, a.fg.brightBlue, a.fg.brightRed];
22
19
  const agentColors = new Map();
23
20
  let nextColor = 0;
@@ -26,13 +23,10 @@ function agentColor(name) {
26
23
  agentColors.set(name, AGENT_PALETTE[nextColor++ % AGENT_PALETTE.length]);
27
24
  return agentColors.get(name);
28
25
  }
29
- // ─── Tool icons ───
30
26
  const ICONS = {
31
27
  Bash: '⚡', Read: '📖', Write: '✏️ ', Edit: '🔧', Glob: '🔍', Grep: '🔎',
32
- Agent: '🤖', TodoRead: '📋', TodoWrite: '📝', WebSearch: '🌐', WebFetch: '🌐',
33
- AskUserQuestion: '❓',
28
+ Agent: '🤖', TodoRead: '📋', TodoWrite: '📝', WebSearch: '🌐', WebFetch: '🌐', AskUserQuestion: '❓',
34
29
  };
35
- // ─── Helpers ───
36
30
  function ts() { return new Date().toLocaleTimeString('en-GB', { hour12: false }); }
37
31
  function strip(s) { return s.replace(/\x1b\[[0-9;]*m/g, ''); }
38
32
  function trunc(s, n) { const c = s.replace(/\n/g, ' ').trim(); return c.length > n ? c.slice(0, n) + '…' : c; }
@@ -46,6 +40,10 @@ export class TUI {
46
40
  onInput = null;
47
41
  onHotkey = null;
48
42
  paused_ = false;
43
+ // Render state
44
+ pendingLines = [];
45
+ renderTimer = null;
46
+ lastStatusLen = 0;
49
47
  // Stats
50
48
  loopStart = Date.now();
51
49
  iteration_ = 0;
@@ -57,21 +55,61 @@ export class TUI {
57
55
  tokens_ = { input: 0, output: 0 };
58
56
  iterStart_ = 0;
59
57
  agents = [];
60
- lastModel_ = '';
61
58
  inputBuf = '';
62
- ticker = null;
63
59
  constructor(logFile, interactive = false) {
64
60
  this.logFile = logFile;
65
61
  this.interactive = interactive && process.stdin.isTTY === true;
66
62
  if (this.interactive) {
67
63
  this.setupInput();
68
- this.renderStatusBar();
69
- this.printInputPrompt('');
70
- // Tick every second to update elapsed time in status bar
71
- this.ticker = setInterval(() => this.refreshStatusBar(), 1000);
64
+ // 4 fps render loop
65
+ this.renderTimer = setInterval(() => this.render(), 250);
72
66
  }
73
67
  }
74
- // ─── Input handling (interactive only) ───
68
+ // ─── Render loop ───
69
+ render() {
70
+ const out = process.stdout;
71
+ // Clear current status line
72
+ if (this.lastStatusLen > 0) {
73
+ out.write('\r\x1b[2K');
74
+ }
75
+ // Flush pending log lines
76
+ for (const line of this.pendingLines) {
77
+ out.write(line + '\n');
78
+ }
79
+ this.pendingLines = [];
80
+ // Draw status bar (single line, no \n — stays overwritable)
81
+ const status = this.buildStatus();
82
+ out.write(status);
83
+ this.lastStatusLen = strip(status).length;
84
+ }
85
+ buildStatus() {
86
+ const elapsed = fmtDur(Date.now() - this.loopStart);
87
+ const iterTime = this.iterStart_ ? fmtDur(Date.now() - this.iterStart_) : '—';
88
+ const pct = this.maxIter > 0 ? Math.round((this.iteration_ / this.maxIter) * 100) : 0;
89
+ const tok = fmtTok(this.tokens_.input + this.tokens_.output);
90
+ const parts = [
91
+ `${a.fg.white}${elapsed}`,
92
+ `Iter ${this.iteration_}/${this.maxIter} ${bar(pct, 8)}`,
93
+ `${iterTime}`,
94
+ `${a.fg.cyan}${this.tools}${a.reset} tools`,
95
+ `${a.fg.yellow}${tok}${a.reset} tok`,
96
+ ];
97
+ if (this.agents.length > 0) {
98
+ const cur = this.agents[this.agents.length - 1];
99
+ parts.push(`${agentColor(cur)}${cur}${a.reset}`);
100
+ }
101
+ if (this.taskName_)
102
+ parts.push(`${a.fg.cyan}${trunc(this.taskName_, 20)}${a.reset}`);
103
+ if (this.paused_)
104
+ parts.push(`${a.fg.yellow}⏸ PAUSED${a.reset}`);
105
+ const info = parts.join(`${a.fg.gray} │ ${a.reset}`);
106
+ const input = this.inputBuf ? ` ${a.fg.gray}›${a.reset} ${this.inputBuf}` : '';
107
+ const cols = process.stdout.columns || 120;
108
+ const line = ` ${info}${input} `;
109
+ const pad = Math.max(0, cols - strip(line).length);
110
+ return `\r${a.bg.gray}${line}${' '.repeat(pad)}${a.reset}`;
111
+ }
112
+ // ─── Input ───
75
113
  setupInput() {
76
114
  if (!process.stdin.isTTY)
77
115
  return;
@@ -82,8 +120,8 @@ export class TUI {
82
120
  if (key === '\x03') {
83
121
  this.onHotkey?.('quit');
84
122
  return;
85
- } // Ctrl+C
86
- if (key === '\x1a') { // Ctrl+Z
123
+ }
124
+ if (key === '\x1a') {
87
125
  this.paused_ = !this.paused_;
88
126
  this.onHotkey?.(this.paused_ ? 'pause' : 'resume');
89
127
  return;
@@ -91,59 +129,42 @@ export class TUI {
91
129
  if (key === '\x13') {
92
130
  this.onHotkey?.('stop');
93
131
  return;
94
- } // Ctrl+S
132
+ }
95
133
  if (key === '\r' || key === '\n') {
96
- if (this.inputBuf.trim()) {
134
+ if (this.inputBuf.trim())
97
135
  this.onInput?.(this.inputBuf.trim());
98
- }
99
136
  this.inputBuf = '';
100
- this.printInputPrompt(this.inputBuf);
101
137
  return;
102
138
  }
103
139
  if (key === '\x7f' || key === '\b') {
104
140
  this.inputBuf = this.inputBuf.slice(0, -1);
105
- this.printInputPrompt(this.inputBuf);
106
141
  return;
107
142
  }
108
143
  if (key.length === 1 && key >= ' ') {
109
144
  this.inputBuf += key;
110
- this.printInputPrompt(this.inputBuf);
111
145
  }
112
146
  });
113
147
  }
114
- printInputPrompt(buf) {
115
- const prompt = `${a.fg.gray} › ${a.fg.white}${buf}${a.reset}`;
116
- process.stdout.write(`\r\x1b[2K${prompt}`);
117
- }
118
148
  destroy() {
119
- if (this.ticker) {
120
- clearInterval(this.ticker);
121
- this.ticker = null;
149
+ if (this.renderTimer) {
150
+ clearInterval(this.renderTimer);
151
+ this.renderTimer = null;
122
152
  }
123
- if (this.interactive && process.stdin.isTTY) {
124
- process.stdin.setRawMode(false);
153
+ if (this.interactive) {
154
+ // Final flush
155
+ this.render();
125
156
  process.stdout.write('\n');
157
+ if (process.stdin.isTTY)
158
+ process.stdin.setRawMode(false);
126
159
  }
127
160
  }
128
- refreshStatusBar() {
129
- // Overwrite status bar + input in place (no new log line)
130
- process.stdout.write('\x1b[2K\r'); // clear input line
131
- process.stdout.write('\x1b[A\x1b[2K\r'); // move up, clear status line
132
- this.renderStatusBar();
133
- this.printInputPrompt(this.inputBuf);
134
- }
135
161
  setInputHandler(handler) { this.onInput = handler; }
136
162
  setHotkeyHandler(handler) { this.onHotkey = handler; }
137
163
  isPaused() { return this.paused_; }
138
- // ─── Output ───
139
- out(formatted, raw) {
164
+ // ─── Output (buffered) ───
165
+ push(formatted, raw) {
140
166
  if (this.interactive) {
141
- // Move up 2 lines (status + input), clear them, print log, redraw
142
- process.stdout.write('\x1b[2K\r'); // clear input line
143
- process.stdout.write('\x1b[A\x1b[2K\r'); // move up, clear status line
144
- console.log(formatted);
145
- this.renderStatusBar();
146
- this.printInputPrompt(this.inputBuf);
167
+ this.pendingLines.push(formatted);
147
168
  }
148
169
  else {
149
170
  console.log(formatted);
@@ -156,16 +177,6 @@ export class TUI {
156
177
  catch { /* */ }
157
178
  }
158
179
  }
159
- renderStatusBar() {
160
- const elapsed = this.loopStart ? fmtDur(Date.now() - this.loopStart) : '—';
161
- const iterElapsed = this.iterStart_ ? fmtDur(Date.now() - this.iterStart_) : '—';
162
- const pct = this.maxIter > 0 ? Math.round((this.iteration_ / this.maxIter) * 100) : 0;
163
- const tok = fmtTok(this.tokens_.input + this.tokens_.output);
164
- const taskInfo = this.taskName_ ? ` │ ${a.fg.cyan}${trunc(this.taskName_, 30)}${a.reset}` : '';
165
- const pauseLabel = this.paused_ ? ` │ ${a.fg.yellow}⏸ PAUSED${a.reset}` : '';
166
- const line = ` ${a.fg.gray}${elapsed}${a.reset} │ Iter ${this.iteration_}/${this.maxIter} ${bar(pct, 10)} │ ${iterElapsed} │ ${a.fg.cyan}${this.tools}${a.reset} tools │ ${a.fg.yellow}${tok}${a.reset} tok${taskInfo}${pauseLabel}`;
167
- process.stdout.write(`${a.bg.gray}${line}${' '.repeat(Math.max(0, (process.stdout.columns || 80) - strip(line).length))}${a.reset}\n`);
168
- }
169
180
  fileOnly(msg) {
170
181
  if (this.logFile) {
171
182
  try {
@@ -174,21 +185,37 @@ export class TUI {
174
185
  catch { /* */ }
175
186
  }
176
187
  }
177
- // ─── Public methods ───
188
+ // ─── Agent prefix ───
189
+ agentPrefix() {
190
+ if (this.agents.length === 0)
191
+ return '';
192
+ const cur = this.agents[this.agents.length - 1];
193
+ const col = agentColor(cur);
194
+ const short = cur.length > 14 ? cur.slice(0, 14) : cur;
195
+ return `${col}${short}${a.reset} `;
196
+ }
197
+ indent() {
198
+ const prefix = this.agentPrefix();
199
+ if (this.agents.length <= 1)
200
+ return ` ${prefix}`;
201
+ const pipes = this.agents.slice(0, -1).map(n => `${agentColor(n)}│${a.reset}`).join('');
202
+ return ` ${pipes} ${prefix}`;
203
+ }
204
+ // ─── Public API ───
178
205
  banner() {
179
- this.out('');
180
- this.out(` ${a.fg.cyan}${a.bold}╔══════════════════════════════════════════════╗${a.reset}`);
181
- this.out(` ${a.fg.cyan}${a.bold}║ ${a.fg.white}Claude Starter Kit — Autonomous Loop${a.fg.cyan} ║${a.reset}`);
182
- this.out(` ${a.fg.cyan}${a.bold}╚══════════════════════════════════════════════╝${a.reset}`);
206
+ this.push('');
207
+ this.push(` ${a.fg.cyan}${a.bold}╔══════════════════════════════════════════════╗${a.reset}`);
208
+ this.push(` ${a.fg.cyan}${a.bold}║ ${a.fg.white}Claude Starter Kit — Autonomous Loop${a.fg.cyan} ║${a.reset}`);
209
+ this.push(` ${a.fg.cyan}${a.bold}╚══════════════════════════════════════════════╝${a.reset}`);
183
210
  if (this.interactive) {
184
- this.out(` ${a.fg.gray} Ctrl+Z pause/resume │ Ctrl+S stop │ Ctrl+C quit${a.reset}`);
211
+ this.push(` ${a.fg.gray} Ctrl+Z pause │ Ctrl+S stop │ Ctrl+C quit │ Type to send input${a.reset}`);
185
212
  }
186
- this.out('');
213
+ this.push('');
187
214
  }
188
- info(msg) { this.out(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.blue}ℹ${a.reset} ${msg}`); }
189
- warn(msg) { this.out(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.yellow}⚠${a.reset} ${a.fg.yellow}${msg}${a.reset}`); }
190
- error(msg) { this.out(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.red}✗${a.reset} ${a.fg.red}${msg}${a.reset}`); }
191
- success(msg) { this.out(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.green}✓${a.reset} ${a.fg.green}${msg}${a.reset}`); }
215
+ info(msg) { this.push(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.blue}ℹ${a.reset} ${msg}`); }
216
+ warn(msg) { this.push(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.yellow}⚠${a.reset} ${a.fg.yellow}${msg}${a.reset}`); }
217
+ error(msg) { this.push(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.red}✗${a.reset} ${a.fg.red}${msg}${a.reset}`); }
218
+ success(msg) { this.push(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.green}✓${a.reset} ${a.fg.green}${msg}${a.reset}`); }
192
219
  setIteration(i, max) {
193
220
  this.iteration_ = i;
194
221
  this.maxIter = max;
@@ -198,13 +225,13 @@ export class TUI {
198
225
  this.agents = [];
199
226
  const pct = Math.round((i / max) * 100);
200
227
  const elapsed = fmtDur(Date.now() - this.loopStart);
201
- this.out('');
202
- this.out(` ${a.bold}${a.fg.white}━━━ Iteration ${i}/${max} ${bar(pct, 20)} ${pct}% ${a.fg.gray}│ ${elapsed} elapsed${a.fg.white} ━━━${a.reset}`);
228
+ this.push('');
229
+ this.push(` ${a.bold}${a.fg.white}━━━ Iteration ${i}/${max} ${bar(pct, 20)} ${pct}% ${a.fg.gray}│ ${elapsed} elapsed${a.fg.white} ━━━${a.reset}`);
203
230
  if (this.taskName_) {
204
231
  const tPct = this.tasksTotal_ > 0 ? Math.round((this.tasksDone_ / this.tasksTotal_) * 100) : 0;
205
- this.out(` ${a.fg.cyan}📋 ${this.taskName_}${a.reset} ${a.fg.gray}(${this.tasksDone_}/${this.tasksTotal_} tasks ${bar(tPct, 10)} ${tPct}%)${a.reset}`);
232
+ this.push(` ${a.fg.cyan}📋 ${this.taskName_}${a.reset} ${a.fg.gray}(${this.tasksDone_}/${this.tasksTotal_} tasks ${bar(tPct, 10)} ${tPct}%)${a.reset}`);
206
233
  }
207
- this.out('');
234
+ this.push('');
208
235
  }
209
236
  setTask(name, done, total) {
210
237
  this.taskName_ = name;
@@ -215,8 +242,8 @@ export class TUI {
215
242
  const iterElapsed = fmtDur(Date.now() - this.iterStart_);
216
243
  const totalElapsed = fmtDur(Date.now() - this.loopStart);
217
244
  const tok = fmtTok(this.tokens_.input + this.tokens_.output);
218
- this.out('');
219
- this.out(` ${a.fg.gray}━━━━ ${iterElapsed} (iter) │ ${totalElapsed} (total) │ ${this.tools} tools │ ${tok} tokens ━━━━${a.reset}`);
245
+ this.push('');
246
+ this.push(` ${a.fg.gray}━━━━ ${iterElapsed} (iter) │ ${totalElapsed} (total) │ ${this.tools} tools │ ${tok} tokens ━━━━${a.reset}`);
220
247
  }
221
248
  // ─── SDK message handler ───
222
249
  handleMessage(message) {
@@ -243,14 +270,9 @@ export class TUI {
243
270
  this.tokens_.input += msg.message.usage.input_tokens || 0;
244
271
  this.tokens_.output += msg.message.usage.output_tokens || 0;
245
272
  }
246
- // Show model from message if available
247
- const model = msg.message?.model;
248
- if (model && !this.lastModel_) {
249
- this.lastModel_ = model;
250
- }
251
273
  for (const block of content) {
252
274
  if (block.type === 'text' && block.text?.trim()) {
253
- this.out(`${this.indent()}${a.fg.white}${trunc(block.text, 300)}${a.reset}`, `TEXT: ${trunc(block.text, 300)}`);
275
+ this.push(`${this.indent()}${a.fg.white}${trunc(block.text, 300)}${a.reset}`, `TEXT: ${trunc(block.text, 300)}`);
254
276
  }
255
277
  if (block.type === 'tool_use')
256
278
  this.onToolUse(block);
@@ -263,14 +285,13 @@ export class TUI {
263
285
  const input = block.input || {};
264
286
  const pre = this.indent();
265
287
  const time = `${a.fg.gray}${ts()}${a.reset}`;
266
- // Agent delegation
267
288
  if (name === 'Agent') {
268
289
  const type = input.subagent_type || input.type || 'agent';
269
290
  const model = input.model ? ` ${a.fg.gray}(${input.model})${a.reset}` : '';
270
291
  const desc = trunc(input.description || input.prompt || '', 50);
271
292
  const col = agentColor(type);
272
293
  this.agents.push(type);
273
- this.out(`${pre}${time} ${icon} ${col}${a.bold}${type}${a.reset}${model} ${a.fg.gray}${desc}${a.reset}`, `AGENT: ${type} ${input.model || ''} — ${desc}`);
294
+ this.push(`${pre}${time} ${icon} ${col}${a.bold}${type}${a.reset}${model} ${a.fg.gray}${desc}${a.reset}`, `AGENT: ${type} ${input.model || ''} — ${desc}`);
274
295
  return;
275
296
  }
276
297
  let detail;
@@ -293,7 +314,7 @@ export class TUI {
293
314
  break;
294
315
  default: detail = `${a.fg.gray}${trunc(JSON.stringify(input), 60)}${a.reset}`;
295
316
  }
296
- this.out(`${pre}${time} ${icon} ${a.bold}${name}${a.reset} ${detail}`, `TOOL: ${name} ${JSON.stringify(input).slice(0, 200)}`);
317
+ this.push(`${pre}${time} ${icon} ${a.bold}${name}${a.reset} ${detail}`, `TOOL: ${name} ${JSON.stringify(input).slice(0, 200)}`);
297
318
  }
298
319
  onToolResult(msg) {
299
320
  const content = msg.message?.content;
@@ -307,52 +328,53 @@ export class TUI {
307
328
  continue;
308
329
  const pre = this.indent();
309
330
  if (block.is_error) {
310
- this.out(`${pre} ${a.fg.red}✗ ${trunc(output, 100)}${a.reset}`, `ERROR: ${trunc(output, 100)}`);
331
+ this.push(`${pre} ${a.fg.red}✗ ${trunc(output, 100)}${a.reset}`, `ERROR: ${trunc(output, 100)}`);
311
332
  }
312
333
  else if (output.length < 150) {
313
- this.out(`${pre} ${a.fg.green}✓${a.reset} ${a.fg.gray}${trunc(output, 100)}${a.reset}`, `OK: ${trunc(output, 100)}`);
334
+ this.push(`${pre} ${a.fg.green}✓${a.reset} ${a.fg.gray}${trunc(output, 100)}${a.reset}`, `OK: ${trunc(output, 100)}`);
314
335
  }
315
336
  else {
316
337
  const n = output.split('\n').length;
317
- this.out(`${pre} ${a.fg.green}✓${a.reset} ${a.fg.gray}${n} lines${a.reset}`, `OK: (${n} lines)`);
338
+ this.push(`${pre} ${a.fg.green}✓${a.reset} ${a.fg.gray}${n} lines${a.reset}`, `OK: (${n} lines)`);
318
339
  }
319
340
  }
320
341
  }
321
342
  onSystem(msg) {
322
- // Init message — show model, agents, version
323
343
  if (msg.subtype === 'init') {
324
- const model = msg.model || 'unknown';
325
- const agents = msg.agents?.length ? msg.agents.join(', ') : 'none';
344
+ const model = msg.model || '?';
326
345
  const ver = msg.claude_code_version || '';
327
- this.out(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.cyan}⚙${a.reset} Claude Code ${ver} │ Model: ${a.bold}${model}${a.reset} Agents: ${a.fg.cyan}${agents}${a.reset}`);
328
- if (msg.tools?.length) {
329
- this.out(` ${a.fg.gray} Tools: ${msg.tools.join(', ')}${a.reset}`);
346
+ const agentList = msg.agents?.join(', ') || 'none';
347
+ this.push(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.cyan}⚙${a.reset} Claude Code ${ver} │ Model: ${a.bold}${model}${a.reset} │ Agents: ${a.fg.cyan}${agentList}${a.reset}`);
348
+ // Set top-level agent name from permissionMode or first agent
349
+ if (this.agents.length === 0 && msg.agents?.length) {
350
+ const topAgent = msg.agents[0];
351
+ this.agents.push(topAgent);
352
+ this.push(` ${a.fg.gray}${ts()}${a.reset} 🤖 ${agentColor(topAgent)}${a.bold}${topAgent}${a.reset} ${a.fg.gray}(${model})${a.reset}`, `AGENT_START: ${topAgent} (${model})`);
330
353
  }
331
354
  return;
332
355
  }
333
356
  if (msg.subtype === 'task_started') {
334
357
  const desc = msg.description || '';
335
- const taskType = msg.task_type || '';
336
358
  const col = agentColor(desc);
337
359
  this.agents.push(desc);
338
- this.out(` ${a.fg.gray}${ts()}${a.reset} 🤖 ${col}${a.bold}${desc}${a.reset}${taskType ? ` ${a.fg.gray}(${taskType})${a.reset}` : ''}`, `AGENT_START: ${desc} ${taskType}`);
360
+ this.push(` ${a.fg.gray}${ts()}${a.reset} 🤖 ${col}${a.bold}${desc}${a.reset}`, `AGENT_START: ${desc}`);
339
361
  return;
340
362
  }
341
363
  if (msg.subtype === 'task_notification') {
342
364
  const status = msg.status || '';
365
+ const name = this.agents.length > 0 ? this.agents.pop() : 'agent';
366
+ const col = agentColor(name);
343
367
  const icon = status === 'completed' ? `${a.fg.green}✓` : `${a.fg.red}✗`;
344
- const summary = msg.summary ? ` ${a.fg.gray}${trunc(msg.summary, 80)}${a.reset}` : '';
345
- if (this.agents.length > 0)
346
- this.agents.pop();
347
- this.out(` ${a.fg.gray}${ts()}${a.reset} ${icon}${a.reset} Agent ${status}${summary}`, `AGENT_END: ${status} ${msg.summary || ''}`);
368
+ const summary = msg.summary ? ` ${a.fg.gray}${trunc(msg.summary, 60)}${a.reset}` : '';
369
+ this.push(` ${a.fg.gray}${ts()}${a.reset} ${icon}${a.reset} ${col}${name}${a.reset} ${status}${summary}`, `AGENT_END: ${name} ${status}`);
348
370
  return;
349
371
  }
350
372
  if (msg.subtype === 'task_progress' && msg.description) {
351
- this.out(`${this.indent()} ${a.dim}${trunc(msg.description, 70)}${a.reset}`, `PROGRESS: ${msg.description}`);
373
+ this.push(`${this.indent()} ${a.dim}${trunc(msg.description, 70)}${a.reset}`, `PROGRESS: ${msg.description}`);
352
374
  return;
353
375
  }
354
376
  if (msg.subtype === 'api_retry') {
355
- this.out(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.yellow}↻${a.reset} ${a.fg.yellow}API retry ${msg.attempt}/${msg.max_retries} (${msg.error || 'unknown'})${a.reset}`);
377
+ this.push(` ${a.fg.gray}${ts()}${a.reset} ${a.fg.yellow}↻${a.reset} ${a.fg.yellow}API retry ${msg.attempt}/${msg.max_retries} (${msg.error || ''})${a.reset}`);
356
378
  return;
357
379
  }
358
380
  }
@@ -360,12 +382,6 @@ export class TUI {
360
382
  if (msg.session_id)
361
383
  this.fileOnly(`SESSION: ${msg.session_id}`);
362
384
  }
363
- // ─── Indent ───
364
- indent() {
365
- if (this.agents.length === 0)
366
- return ' ';
367
- return ' ' + this.agents.map(n => `${agentColor(n)}│${a.reset} `).join('');
368
- }
369
385
  resetAgentStack() { this.agents = []; }
370
386
  getSessionId(msg) { return msg.session_id ?? null; }
371
387
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-workspace",
3
- "version": "1.1.130",
3
+ "version": "1.1.132",
4
4
  "author": "",
5
5
  "repository": {
6
6
  "type": "git",