winter-super-cli 2026.6.7 → 2026.6.9

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/src/cli/repl.js CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  renderStartupTui,
17
17
  renderStatusPanel,
18
18
  } from './tui.js';
19
+ import { terminalManager } from './terminal-manager.js';
19
20
  import { WinterInputController } from './input-controller.js';
20
21
  import { ToolExecutor } from '../tools/executor.js';
21
22
  import { SessionManager } from '../session/manager.js';
@@ -125,6 +126,8 @@ export class WinterREPL {
125
126
  this.watchers = [];
126
127
  this.startupNotices = [];
127
128
  this._fixedPanel = Boolean(process.stdout.isTTY) && process.env.WINTER_FIXED_PANEL_TUI !== '0';
129
+
130
+ terminalManager.install();
128
131
  }
129
132
 
130
133
  async initCodebaseSearch() {
@@ -654,22 +657,106 @@ export class WinterREPL {
654
657
  // Hiển thị prompt lần đầu tiên ngay khi khởi động xong.
655
658
  this.showInputPrompt();
656
659
 
657
- this.rl.on('line', (line) => {
660
+ // Paste buffer: gom nhiều dòng paste nhanh thành 1 tin nhắn
661
+ this._multilineBuffer = [];
662
+ this._pasteBuffer = [];
663
+ this._pasteTimer = null;
664
+ this._isPasteChunk = false;
665
+ this._pasteChunkTimer = null;
666
+ const PASTE_DELAY = 80;
667
+
668
+ process.stdin.on('data', (chunk) => {
669
+ // If a large chunk or chunk with newlines arrives, it's definitely a paste.
670
+ if (chunk.length > 3 || chunk.includes('\n')) {
671
+ this._isPasteChunk = true;
672
+ if (this._pasteChunkTimer) clearTimeout(this._pasteChunkTimer);
673
+ this._pasteChunkTimer = setTimeout(() => {
674
+ this._isPasteChunk = false;
675
+ }, 150);
676
+ }
677
+ });
678
+
679
+ const flushPasteBuffer = () => {
680
+ this._pasteTimer = null;
681
+ if (this._pasteBuffer.length === 0) return;
682
+
683
+ const isSingleLineInput = this._pasteBuffer.length === 1 && !this._isPasteChunk;
684
+ const isJustEmptyEnter = this._pasteBuffer.length === 1 && this._pasteBuffer[0].trim() === '';
685
+
686
+ // Normal single-line submit
687
+ if (isSingleLineInput && this._multilineBuffer.length === 0) {
688
+ const line = this._pasteBuffer[0].trim();
689
+ this._pasteBuffer = [];
690
+ if (!line) {
691
+ if (this.running && !this.readlineClosed) {
692
+ readline.moveCursor(process.stdout, 0, -1);
693
+ readline.clearLine(process.stdout, 0);
694
+ this.rl.prompt(true);
695
+ }
696
+ return;
697
+ }
698
+
699
+ // Command to enter multiline mode manually
700
+ if (line === '/multi' || line === '/m') {
701
+ this._multilineBuffer.push('');
702
+ console.log(`${colors.cyan}│ ${colors.dim}[ Đã bật chế độ gõ nhiều dòng. Nhấn Enter 2 lần (dòng trống) để gửi. ]${colors.reset}`);
703
+ if (this.running && !this.readlineClosed) this.rl.prompt(true);
704
+ return;
705
+ }
706
+
707
+ this.submitInputQueue(line);
708
+ return;
709
+ }
710
+
711
+ // We are in multiline/paste mode
712
+ this._multilineBuffer.push(...this._pasteBuffer);
713
+ this._pasteBuffer = [];
714
+
715
+ // If they pressed Enter on an empty line, submit the multiline buffer!
716
+ if (isJustEmptyEnter && this._multilineBuffer.length > 1) {
717
+ // Remove the trailing empty line
718
+ this._multilineBuffer.pop();
719
+ const combined = this._multilineBuffer.join('\n').trim();
720
+ this._multilineBuffer = [];
721
+ this._isPasteChunk = false;
722
+
723
+ if (!combined) {
724
+ if (this.running && !this.readlineClosed) {
725
+ this.closeInputBox();
726
+ this.showInputPrompt();
727
+ }
728
+ return;
729
+ }
730
+
731
+ this.submitInputQueue(combined);
732
+ return;
733
+ }
734
+
735
+ // Otherwise, we are still collecting! Wait for user to submit.
736
+ readline.clearLine(process.stdout, 0);
737
+ readline.cursorTo(process.stdout, 0);
738
+ const linesCount = this._multilineBuffer.length;
739
+ console.log(`${colors.cyan}│ ${colors.dim}[ Đang nhập nhiều dòng (${linesCount} dòng)... Nhấn Enter ở dòng trống để gửi ]${colors.reset}`);
740
+ if (this.running && !this.readlineClosed) this.rl.prompt(true);
741
+ };
742
+
743
+ this.submitInputQueue = (combined) => {
658
744
  this.inputQueue = this.inputQueue
659
745
  .then(async () => {
660
746
  this.closeInputBox();
661
- const input = line.trim();
662
- if (input) {
663
- await this.handleInput(input);
664
- } else {
665
- if (this.running && !this.readlineClosed) this.showInputPrompt();
666
- }
747
+ await this.handleInput(combined);
667
748
  })
668
749
  .catch((error) => {
669
750
  this.closeInputBox();
670
751
  console.log(`\n${colors.red}? Error: ${error.message}${colors.reset}\n`);
671
752
  if (this.running && !this.readlineClosed) this.showInputPrompt();
672
753
  });
754
+ };
755
+
756
+ this.rl.on('line', (line) => {
757
+ this._pasteBuffer.push(line);
758
+ if (this._pasteTimer) clearTimeout(this._pasteTimer);
759
+ this._pasteTimer = setTimeout(flushPasteBuffer, PASTE_DELAY);
673
760
  });
674
761
 
675
762
  this.rl.on('close', async () => {
@@ -936,9 +1023,12 @@ export class WinterREPL {
936
1023
  const preview = input.length > 40 ? input.slice(0, 37) + '...' : input;
937
1024
  console.log(`${colors.yellow}⧗${colors.reset} ${colors.bright}Queued #${pos}${colors.reset} ${colors.dim}› ${preview}${colors.reset}`);
938
1025
  this.taskQueue.push(input);
1026
+ if (!this.readlineClosed) this.showInputPrompt();
939
1027
  return;
940
1028
  }
941
- await this.processInputTask(input);
1029
+ this.processInputTask(input).catch(err => {
1030
+ console.log(colors.red + '\nLỗi xử lý hàng đợi: ' + err.message + colors.reset);
1031
+ });
942
1032
  }
943
1033
 
944
1034
  async processInputTask(input) {
@@ -952,6 +1042,12 @@ export class WinterREPL {
952
1042
  this.history = this.history.slice(-this.maxHistory);
953
1043
  }
954
1044
 
1045
+ // Echo tin nhắn user để xác nhận đã nhận
1046
+ if (!input.startsWith('/') && !input.startsWith('!')) {
1047
+ const preview = input.length > 120 ? input.slice(0, 117) + '...' : input;
1048
+ console.log(`\n${colors.bright}${colors.green}You${colors.reset} ${colors.dim}›${colors.reset} ${colors.white}${preview}${colors.reset}`);
1049
+ }
1050
+
955
1051
  if (input.startsWith('!')) {
956
1052
  const command = input.slice(1).trim();
957
1053
  if (!command) {
@@ -1030,6 +1126,7 @@ export class WinterREPL {
1030
1126
  if (this.spinner) this.spinner.stop();
1031
1127
 
1032
1128
  if (this.taskQueue.length > 0) {
1129
+ this.closeInputBox();
1033
1130
  const nextTask = this.taskQueue.shift();
1034
1131
  setTimeout(() => this.processInputTask(nextTask), 0);
1035
1132
  } else {
@@ -1748,22 +1845,27 @@ ${colors.reset}
1748
1845
  }
1749
1846
 
1750
1847
  if (chunk.content) {
1751
- if (!printed) {
1752
- if (this.spinner) this.spinner.stop();
1753
- if (!bufferToolModeContent) {
1754
- process.stdout.write(`\n${colors.white}`);
1755
- printed = true;
1756
- }
1757
- }
1758
1848
  content += chunk.content;
1759
- if (!bufferToolModeContent) {
1760
- process.stdout.write(chunk.content);
1849
+ }
1850
+
1851
+ if (this.spinner && printed === false) {
1852
+ if (toolCallParts.length > 0) {
1853
+ const lastCall = toolCallParts[toolCallParts.length - 1];
1854
+ if (lastCall.function?.name) {
1855
+ const args = lastCall.function.arguments || '';
1856
+ let summary = args.replace(/\s+/g, ' ');
1857
+ if (summary.length > 60) summary = '...' + summary.slice(-60);
1858
+ this.spinner.update(`Calling ${lastCall.function.name}... ${summary}`);
1859
+ }
1860
+ } else if (content.length > 0 && bufferToolModeContent) {
1861
+ let summary = content.replace(/\s+/g, ' ');
1862
+ if (summary.length > 60) summary = '...' + summary.slice(-60);
1863
+ this.spinner.update(`Generating... ${summary}`);
1761
1864
  }
1762
1865
  }
1763
1866
  }
1764
1867
 
1765
1868
  if (this.spinner) this.spinner.stop();
1766
- if (printed) process.stdout.write(colors.reset);
1767
1869
 
1768
1870
  const inlineToolExtraction = this.extractInlineToolCalls(content);
1769
1871
  const rawToolCalls = [
@@ -1776,7 +1878,7 @@ ${colors.reset}
1776
1878
  const toolCalls = this.normalizeToolCalls(rawToolCalls);
1777
1879
  const visibleContent = inlineToolExtraction.content || content;
1778
1880
 
1779
- if (bufferToolModeContent && toolCalls.length === 0 && visibleContent) {
1881
+ if (toolCalls.length === 0 && visibleContent) {
1780
1882
  if (options?.requireToolEvidence && this.responseNeedsToolEvidence(visibleContent)) {
1781
1883
  return {
1782
1884
  assistantMsg: { content: visibleContent },
@@ -1794,18 +1896,6 @@ ${colors.reset}
1794
1896
  };
1795
1897
  }
1796
1898
 
1797
- if (toolCalls.length === 0 && visibleContent) {
1798
- console.log(`\n${colors.dim}${this.formatAnswerFooter(startedAt, totalUsage)}${colors.reset}\n`);
1799
- return {
1800
- assistantMsg: { content: visibleContent },
1801
- toolCalls,
1802
- finalContent: visibleContent,
1803
- finishReason,
1804
- };
1805
- } else if (printed && visibleContent) {
1806
- process.stdout.write('\n');
1807
- }
1808
-
1809
1899
  return {
1810
1900
  assistantMsg: {
1811
1901
  content: visibleContent,
@@ -1974,7 +2064,6 @@ ${colors.reset}
1974
2064
  const profile = executionProfile || this.selectExecutionProfile(messages, { enableTools: false });
1975
2065
 
1976
2066
  try {
1977
- process.stdout.write(`\n${colors.white}`);
1978
2067
  let isFirst = true;
1979
2068
  for await (const chunk of this.ai.streamRequest(messages, {
1980
2069
  provider: profile.provider,
@@ -1982,16 +2071,19 @@ ${colors.reset}
1982
2071
  enableTools: false,
1983
2072
  signal: this.currentAbortController?.signal,
1984
2073
  })) {
2074
+ if (isFirst) {
2075
+ isFirst = false;
2076
+ }
1985
2077
  if (chunk.usage) this.addUsage(totalUsage, chunk.usage);
1986
2078
  if (chunk.content) {
1987
2079
  content += chunk.content;
1988
- process.stdout.write(chunk.content);
1989
2080
  }
1990
2081
  }
1991
- process.stdout.write(colors.reset);
2082
+
2083
+ if (this.spinner) this.spinner.stop();
1992
2084
 
1993
2085
  if (content) {
1994
- console.log(`\n${colors.dim}${this.formatAnswerFooter(startedAt, totalUsage)}${colors.reset}\n`);
2086
+ this.printAssistantAnswer(content, startedAt, totalUsage);
1995
2087
  return content;
1996
2088
  }
1997
2089
  } catch (error) {
@@ -9,6 +9,7 @@ export const SLASH_COMMANDS = [
9
9
  { cmd: '/session', desc: 'Session management' },
10
10
  { cmd: '/sessions', desc: 'List all sessions' },
11
11
  { cmd: '/history', desc: 'Browse recent chat and tool history', usage: '/history [count]' },
12
+ { cmd: '/tool', desc: 'Inspect recent tool calls and their raw data', usage: '/tool [index]' },
12
13
  { cmd: '/new', desc: 'Start a new conversation' },
13
14
  { cmd: '/clear', desc: 'Clear screen' },
14
15
  { cmd: '/remember', desc: 'Store in memory', usage: '/remember <text>' },
@@ -13,8 +13,14 @@ export class Spinner {
13
13
  const cyan = this.colors.cyan || '';
14
14
  const reset = this.colors.reset || '';
15
15
  const dim = this.colors.dim || '';
16
+ this.startTime = Date.now();
16
17
  this.interval = setInterval(() => {
17
- process.stdout.write(`\r\x1b[K${cyan}${this.frames[this.frameIndex]}${reset} ${dim}${this.text}${reset}`);
18
+ const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
19
+ let timeStr = '';
20
+ if (elapsed >= 5) {
21
+ timeStr = ` (still thinking... ${elapsed}s)`;
22
+ }
23
+ process.stdout.write(`\r\x1b[K${cyan}${this.frames[this.frameIndex]}${reset} ${dim}${this.text}${timeStr}${reset}`);
18
24
  this.frameIndex = (this.frameIndex + 1) % this.frames.length;
19
25
  }, 80);
20
26
  }
@@ -0,0 +1,74 @@
1
+ import readline from 'readline';
2
+
3
+ class TerminalManager {
4
+ constructor() {
5
+ this.isPromptVisible = false;
6
+ this.getLinesCountFn = null;
7
+ this.redrawFn = null;
8
+ this.onHideFn = null;
9
+ this._originalLog = console.log;
10
+ this._originalError = console.error;
11
+ this._isIntercepting = false;
12
+ }
13
+
14
+ install() {
15
+ if (this._isIntercepting) return;
16
+ this._isIntercepting = true;
17
+
18
+ console.log = (...args) => this._interceptLog(this._originalLog, args);
19
+ console.error = (...args) => this._interceptLog(this._originalError, args);
20
+ }
21
+
22
+ uninstall() {
23
+ if (!this._isIntercepting) return;
24
+ this._isIntercepting = false;
25
+ console.log = this._originalLog;
26
+ console.error = this._originalError;
27
+ }
28
+
29
+ setPromptState(isVisible, getLinesCountFn = null, redrawFn = null, onHideFn = null) {
30
+ this.isPromptVisible = isVisible;
31
+ this.getLinesCountFn = getLinesCountFn;
32
+ this.redrawFn = redrawFn;
33
+ this.onHideFn = onHideFn;
34
+ }
35
+
36
+ hidePrompt() {
37
+ if (!this.isPromptVisible || !process.stdout.isTTY) return;
38
+
39
+ // Clear the current line first (the readline prompt itself)
40
+ readline.clearLine(process.stdout, 0);
41
+ readline.cursorTo(process.stdout, 0);
42
+
43
+ // If the prompt panel has multiple lines above it, move up and clear
44
+ const linesCount = this.getLinesCountFn ? this.getLinesCountFn() : 0;
45
+ if (linesCount > 1) {
46
+ readline.moveCursor(process.stdout, 0, -(linesCount - 1));
47
+ readline.clearScreenDown(process.stdout);
48
+ }
49
+
50
+ if (this.onHideFn) {
51
+ this.onHideFn();
52
+ }
53
+ }
54
+
55
+ _interceptLog(originalFn, args) {
56
+ if (!this.isPromptVisible) {
57
+ originalFn.apply(console, args);
58
+ return;
59
+ }
60
+
61
+ // Hide prompt
62
+ this.hidePrompt();
63
+
64
+ // Print the actual log
65
+ originalFn.apply(console, args);
66
+
67
+ // Redraw prompt
68
+ if (this.redrawFn) {
69
+ this.redrawFn();
70
+ }
71
+ }
72
+ }
73
+
74
+ export const terminalManager = new TerminalManager();
@@ -70,12 +70,11 @@ export function terminalWidth(min = 72, max = 120, fallback = 88) {
70
70
 
71
71
  export function supportsUnicodeUi(env = process.env, platform = process.platform) {
72
72
  if (env.WINTER_ASCII_UI === '1' || env.WINTER_ASCII_UI === 'true') return false;
73
- if (env.WINTER_UNICODE_UI === '1' || env.WINTER_UNICODE_UI === 'true') return platform !== 'win32';
74
- if (platform !== 'win32') return true;
75
- return false;
73
+ return true;
76
74
  }
77
75
 
78
76
  export function getBoxChars() {
77
+ if (supportsUnicodeUi()) return UNICODE_BOX;
79
78
  return ASCII_BOX;
80
79
  }
81
80
 
package/src/cli/tui.js CHANGED
@@ -176,6 +176,22 @@ export function renderAssistantPanel({ content = '', footer = '', colors, title
176
176
  export function renderToolPanel({ toolName = 'Tool', summary = '', success = true, colors } = {}) {
177
177
  const c = colors || {};
178
178
  const status = success ? `${c.brightGreen}✓${c.reset}` : `${c.red}✖${c.reset}`;
179
- const plainSummary = String(summary || '').replace(/\n/g, ' ');
180
- return `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${plainSummary}${c.reset}`;
179
+
180
+ if (!summary.includes('\n')) {
181
+ return `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${summary}${c.reset}`;
182
+ }
183
+
184
+ const lines = summary.split('\n');
185
+ const firstLine = lines.shift();
186
+
187
+ const formattedRest = lines.map(line => {
188
+ if (line.startsWith('+')) return ` ${c.green}${line}${c.reset}`;
189
+ if (line.startsWith('-')) return ` ${c.red}${line}${c.reset}`;
190
+ if (line.startsWith('@@')) return ` ${c.cyan}${line}${c.reset}`;
191
+ return ` ${c.dim}${line}${c.reset}`;
192
+ }).join('\n');
193
+
194
+ let output = `${status} ${c.bright}${c.cyan}${toolName}${c.reset} ${c.dim}· ${firstLine}${c.reset}`;
195
+ if (formattedRest) output += `\n${formattedRest}`;
196
+ return output;
181
197
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ CODEBASE INDEXER ❄️
2
+ * CODEBASE INDEXER
3
3
  * Scans project files, creates chunks for embedding/search.
4
4
  * Phase 1 — Cursor-like codebase indexing.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ CODEBASE SEMANTIC SEARCH ❄️
2
+ * CODEBASE SEMANTIC SEARCH
3
3
  * Wraps CodebaseIndexer with advanced query capabilities:
4
4
  * - Natural language search
5
5
  * - Symbol/definition search
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ CODEBASE WATCHER ❄️
2
+ * CODEBASE WATCHER
3
3
  * Watches project files for changes and triggers re-indexing.
4
4
  * Uses fs.watch with debouncing.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ DESIGN COMMANDS ❄️
2
+ * DESIGN COMMANDS
3
3
  * Design system integration with brand guidelines
4
4
  */
5
5
 
@@ -163,7 +163,7 @@ export class DesignCommands {
163
163
  }
164
164
 
165
165
  console.log(`\n${'='.repeat(60)}`);
166
- console.log(`${colors.cyan}📋 ${brand} - ${fileName}${colors.reset}`);
166
+ console.log(`${colors.cyan} ${brand} - ${fileName}${colors.reset}`);
167
167
  console.log('='.repeat(60));
168
168
  console.log('');
169
169
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ INLINE COMPLETION — /complete command ❄️
2
+ * INLINE COMPLETION — /complete command
3
3
  * Provides code completion suggestions based on context.
4
4
  * Integrates the existing CompletionProvider into the REPL.
5
5
  */
@@ -76,15 +76,15 @@ export class InlineComplete {
76
76
  const width = terminalWidth(76, 116, 92);
77
77
  const body = result.completions.map((c, i) => {
78
78
  const typeIcon = c.type === 'block-close' ? '}' :
79
- c.type === 'import' ? '📦' :
79
+ c.type === 'import' ? '' :
80
80
  c.type === 'function' ? 'ƒ' :
81
81
  c.type === 'method' ? '.' :
82
82
  c.type === 'arrow-function' ? '=>' :
83
83
  c.type === 'variable' ? '✕' :
84
- c.type === 'keyword' ? '🔑' :
85
- c.type === 'export' ? '📤' :
86
- c.type === 'import-path' ? '📁' :
87
- c.type === 'cached' ? '💾' : '•';
84
+ c.type === 'keyword' ? '#' :
85
+ c.type === 'export' ? '^' :
86
+ c.type === 'import-path' ? '' :
87
+ c.type === 'cached' ? 'v' : '•';
88
88
  const confidence = (c.confidence * 100).toFixed(0);
89
89
  return ` ${colors.cyan}#${i + 1}${colors.reset} ${typeIcon} ${colors.green}${c.text}${colors.reset}` +
90
90
  `\n ${colors.dim}type: ${c.type}, confidence: ${confidence}%${colors.reset}`;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ PLUGIN MANAGER ❄️
2
+ * PLUGIN MANAGER
3
3
  * Manage Winter CLI plugins
4
4
  */
5
5
 
@@ -21,7 +21,7 @@ export class PluginManager {
21
21
  {
22
22
  name: 'winter-core',
23
23
  version: '1.0.0',
24
- icon: '❄️',
24
+ icon: '',
25
25
  description: 'Core Winter CLI functionality',
26
26
  hooks: {},
27
27
  commands: {},
@@ -30,7 +30,7 @@ export class PluginManager {
30
30
  {
31
31
  name: 'winter-design',
32
32
  version: '1.0.0',
33
- icon: '🎨',
33
+ icon: '*',
34
34
  description: 'Design system integration',
35
35
  hooks: {},
36
36
  commands: {},
@@ -39,7 +39,7 @@ export class PluginManager {
39
39
  {
40
40
  name: 'winter-coding',
41
41
  version: '1.0.0',
42
- icon: '💻',
42
+ icon: '',
43
43
  description: 'Coding assistance tools',
44
44
  hooks: {},
45
45
  commands: {},
@@ -67,7 +67,7 @@ export class PluginManager {
67
67
  plugins.push({
68
68
  name: plugin.default?.name || file.replace('.js', ''),
69
69
  version: plugin.default?.version || '1.0.0',
70
- icon: plugin.default?.icon || '🔌',
70
+ icon: plugin.default?.icon || '+',
71
71
  description: plugin.default?.description || 'Plugin',
72
72
  hooks: plugin.default?.hooks || {},
73
73
  commands: plugin.default?.commands || {},
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ SESSION MANAGER ❄️
2
+ * SESSION MANAGER
3
3
  * Handles session management with context memory,
4
4
  * plans, and project tracking.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ SKILL MANAGER ❄️
2
+ * SKILL MANAGER
3
3
  * Manage Winter CLI skills
4
4
  */
5
5
 
@@ -19,7 +19,7 @@ export class SkillManager {
19
19
  return [
20
20
  {
21
21
  name: 'coding',
22
- icon: '💻',
22
+ icon: '',
23
23
  description: 'Code analysis, generation, and review',
24
24
  prompts: [
25
25
  'Analyze this code for issues',
@@ -29,7 +29,7 @@ export class SkillManager {
29
29
  },
30
30
  {
31
31
  name: 'design',
32
- icon: '🎨',
32
+ icon: '*',
33
33
  description: 'Design system and brand guidelines',
34
34
  prompts: [
35
35
  'Apply {brand} design patterns',
@@ -39,7 +39,7 @@ export class SkillManager {
39
39
  },
40
40
  {
41
41
  name: 'debug',
42
- icon: '🔧',
42
+ icon: '$',
43
43
  description: 'Debugging and error analysis',
44
44
  prompts: [
45
45
  'Find the root cause of this error',
@@ -49,7 +49,7 @@ export class SkillManager {
49
49
  },
50
50
  {
51
51
  name: 'refactor',
52
- icon: '♻️',
52
+ icon: '',
53
53
  description: 'Code refactoring and improvements',
54
54
  prompts: [
55
55
  'Simplify this function',
@@ -69,7 +69,7 @@ export class SkillManager {
69
69
  },
70
70
  {
71
71
  name: 'security',
72
- icon: '🔒',
72
+ icon: '#',
73
73
  description: 'Security analysis and best practices',
74
74
  prompts: [
75
75
  'Find potential security vulnerabilities',
@@ -79,7 +79,7 @@ export class SkillManager {
79
79
  },
80
80
  {
81
81
  name: 'performance',
82
- icon: '',
82
+ icon: '',
83
83
  description: 'Performance optimization',
84
84
  prompts: [
85
85
  'Identify performance bottlenecks',
@@ -107,7 +107,7 @@ export class SkillManager {
107
107
  const name = file.replace('.md', '');
108
108
  skills.push({
109
109
  name,
110
- icon: '🔧',
110
+ icon: '$',
111
111
  description: this.extractDescription(content),
112
112
  isCustom: true,
113
113
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ AGENT TOOL ❄️
2
+ * AGENT TOOL
3
3
  * Full subagent orchestration tool
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ WINTER TOOL EXECUTOR ❄️
2
+ * WINTER TOOL EXECUTOR
3
3
  * Complete Claude Code / Codex compatible tool system
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ INSERT TEXT TOOL ❄️
2
+ * INSERT TEXT TOOL
3
3
  * Insert text at a specific line or position in a file
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ INTERACTIVE TOOL ❄️
2
+ * INTERACTIVE TOOL
3
3
  * Ask user questions with multi-select, single-select, and text input support.
4
4
  * Pauses execution and waits for user input.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ NOTEBOOK TOOL ❄️
2
+ * NOTEBOOK TOOL
3
3
  * Jupyter notebook read/edit support (.ipynb files)
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ SCHEDULER TOOL ❄️
2
+ * SCHEDULER TOOL
3
3
  * Schedule wakeup reminders and recurring tasks
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ STRING REPLACE ALL TOOL ❄️
2
+ * STRING REPLACE ALL TOOL
3
3
  * Batch replace all occurrences of a string in a file
4
4
  */
5
5
 
package/src/tools/todo.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ TODO TOOL ❄️
2
+ * TODO TOOL
3
3
  * Persistent todo list management
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ❄️ WEB ARCHIVE TOOL ❄️
2
+ * WEB ARCHIVE TOOL
3
3
  * Fetch archived/cached versions of web pages from Wayback Machine,
4
4
  * Google Cache, and local cache. Inspired by Claude Code's WebArchive.
5
5
  */