@miphamai/cli 0.5.7 → 0.5.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miphamai/cli",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "description": "Mipham Code — Multi-model open-core intelligent coding terminal by MiphamAI",
5
5
  "keywords": [
6
6
  "ai",
@@ -66,6 +66,19 @@ export class SkillsLoader {
66
66
  return this.skills.has(name)
67
67
  }
68
68
 
69
+ countByType(): { standard: number; mipham: number; total: number } {
70
+ const all = this.list()
71
+ return {
72
+ standard: all.filter((s) => s.type === 'standard').length,
73
+ mipham: all.filter((s) => s.type === 'mipham').length,
74
+ total: all.length,
75
+ }
76
+ }
77
+
78
+ getNamesByType(type: 'standard' | 'mipham'): string[] {
79
+ return this.listByType(type).map((s) => s.name)
80
+ }
81
+
69
82
  private loadDirectory(dir: string, type: 'standard' | 'mipham'): void {
70
83
  try {
71
84
  const entries = readdirSync(dir)
package/src/ui/app.tsx CHANGED
@@ -423,7 +423,7 @@ export function App({
423
423
  </Text>
424
424
  <Text dimColor> · ⏵⏵ accept edits on</Text>
425
425
  <Text dimColor> (Shift+Tab to cycle)</Text>
426
- <Text dimColor> · Ctrl+P pick · /help · Esc cancel</Text>
426
+ <Text dimColor> · Ctrl+P pick · /help /commands · Esc cancel</Text>
427
427
  <Text dimColor> · ← agents</Text>
428
428
  </Box>
429
429
  </Box>
@@ -49,107 +49,123 @@ type CommandHandler = (
49
49
  // Session & Identity
50
50
  // ═══════════════════════════════════════════════════════════════
51
51
 
52
- const helpCmd: CommandHandler = (_ctx) => ({
53
- content: stripIndent`
54
- Mipham Code v${PACKAGE_VERSION} — Commands
55
-
56
- ── Session ──────────────────────────
57
- /help Show this help
58
- /version Show version info
59
- /clear Clear conversation
60
- /compact Compact context window
61
- /context Show context stats
62
- /status Session and system status
63
- /cost Token usage estimate
64
- /usage Detailed usage dashboard
65
- /rename <name> Rename current session
66
- /goal <text> Set session goal
67
- /recap Summarize session so far
68
- /export Export conversation to file
69
- /doctor System diagnostics
70
- /resume List saved sessions
71
- /branch <name> Fork conversation
72
-
73
- ── History ─────────────────────────
74
- /rewind Undo last AI turn
75
- /undo Same as /rewind
76
- /copy [N] Copy last response to clipboard
77
- /focus Toggle focus view (last exchange only)
78
-
79
- ── Model & Provider ────────────────
80
- /pick Open model picker (or Ctrl+P)
81
- /model Show current model
82
- /models List all available models
83
- /provider Show current provider
84
- /providers List configured providers
85
- /switch <p> <m> Switch provider and model
86
- /config View configuration
87
- /fast [on|off] Toggle fast mode
88
- /effort <lvl> Set reasoning effort (low|medium|high|xhigh|max)
89
- /theme [dark|light|auto] Set terminal theme
90
-
91
- ── Tools & Skills ──────────────────
92
- /tools List available tools (16 total)
93
- /skills List loaded skills (14 built-in)
94
- /reload-skills Reload all skills
95
- /mcp MCP server status
96
-
97
- ── Workflow ────────────────────────
98
- /plan Enter plan mode (read-only)
99
- /no-plan Exit plan mode
100
- /tdd TDD mode [stub]
101
- /todos Task management
102
- /tasks Background tasks
103
- /review Code review workflow
104
- /pr-comments PR review summary
105
- /diff Show git diff
106
- /workflows List workflow scripts
107
- /loop <int> <p> Run prompt on interval
108
- /schedule View scheduled tasks [stub]
109
-
110
- ── Project ─────────────────────────
111
- /init Initialize .mipham config
112
- /setup Guided project setup wizard
113
- /permissions Show permission settings
114
- /add-dir <dir> Add workspace directory
115
- /security Security review checklist
116
- /audit Same as /security
117
-
118
- ── Environment ─────────────────────
119
- /upgrade Show upgrade instructions
120
- /release-notes View version changelog
121
- /ide IDE integration guide
122
- /terminal-setup Shell & terminal config
123
- /memory Manage AI memories
124
-
125
- ── Account ─────────────────────────
126
- /login Show API key status
127
- /logout Clear credentials guide
128
- /feedback Send feedback
129
-
130
- ── Agents ──────────────────────────
131
- /agents Agent view dashboard
132
- /bg <prompt> Run a background agent task
133
-
134
- Type /exit or Esc to quit.
135
- `,
136
- })
52
+ const helpCmd: CommandHandler = (ctx) => {
53
+ const skillCount = ctx.skillsLoader?.list().length ?? 14
54
+ const toolsCount = ctx.engine.getTools().size
55
+ const cmdCount = getCommandNames().length
137
56
 
138
- const versionCmd: CommandHandler = (ctx) => ({
139
- content: stripIndent`
140
- Mipham Code v${ctx.version}
57
+ return {
58
+ content: stripIndent`
59
+ Mipham Code v${PACKAGE_VERSION} — Commands
60
+
61
+ ── Session ──────────────────────────
62
+ /help Show this help
63
+ /commands List all ${cmdCount} commands
64
+ /version Show version info
65
+ /clear Clear conversation
66
+ /compact Compact context window
67
+ /context Show context stats
68
+ /status Session and system status
69
+ /cost Token usage estimate
70
+ /usage Detailed usage dashboard
71
+ /rename <name> Rename current session
72
+ /goal <text> Set session goal
73
+ /recap Summarize session so far
74
+ /export Export conversation to file
75
+ /doctor System diagnostics
76
+ /resume List saved sessions
77
+ /branch <name> Fork conversation
78
+
79
+ ── History ─────────────────────────
80
+ /rewind Undo last AI turn
81
+ /undo Same as /rewind
82
+ /copy [N] Copy last response to clipboard
83
+ /focus Toggle focus view (last exchange only)
84
+
85
+ ── Model & Provider ────────────────
86
+ /pick Open model picker (or Ctrl+P)
87
+ /model Show current model
88
+ /models List all available models
89
+ /provider Show current provider
90
+ /providers List configured providers
91
+ /switch <p> <m> Switch provider and model
92
+ /config View configuration
93
+ /fast [on|off] Toggle fast mode
94
+ /effort <lvl> Set reasoning effort (low|medium|high|xhigh|max)
95
+ /theme [dark|light|auto] Set terminal theme
96
+
97
+ ── Tools & Skills ──────────────────
98
+ /tools List available tools (${toolsCount} total)
99
+ /skills List loaded skills (${skillCount} built-in)
100
+ /reload-skills Reload all skills
101
+ /commands List all slash commands
102
+ /mcp MCP server status
103
+
104
+ ── Workflow ────────────────────────
105
+ /plan Enter plan mode (read-only)
106
+ /no-plan Exit plan mode
107
+ /tdd TDD mode [stub]
108
+ /todos Task management
109
+ /tasks Background tasks
110
+ /review Code review workflow
111
+ /pr-comments PR review summary
112
+ /diff Show git diff
113
+ /workflows List workflow scripts
114
+ /loop <int> <p> Run prompt on interval
115
+ /schedule View scheduled tasks [stub]
116
+
117
+ ── Project ─────────────────────────
118
+ /init Initialize .mipham config
119
+ /setup Guided project setup wizard
120
+ /permissions Show permission settings
121
+ /add-dir <dir> Add workspace directory
122
+ /security Security review checklist
123
+ /audit Same as /security
124
+
125
+ ── Environment ─────────────────────
126
+ /upgrade Show upgrade instructions
127
+ /release-notes View version changelog
128
+ /ide IDE integration guide
129
+ /terminal-setup Shell & terminal config
130
+ /memory Manage AI memories
131
+
132
+ ── Account ─────────────────────────
133
+ /login Show API key status
134
+ /logout Clear credentials guide
135
+ /feedback Send feedback
136
+
137
+ ── Agents ──────────────────────────
138
+ /agents Agent view dashboard
139
+ /bg <prompt> Run a background agent task
140
+
141
+ Type /exit or Esc to quit.
142
+ `,
143
+ }
144
+ }
141
145
 
142
- Runtime: Bun ${typeof Bun !== 'undefined' ? Bun.version : '(Node.js)'}
143
- Platform: ${process.platform} ${process.arch}
144
- Node: ${process.version}
145
- CWD: ${process.cwd()}
146
+ const versionCmd: CommandHandler = (ctx) => {
147
+ const skillCounts = ctx.skillsLoader?.countByType()
148
+ const skillsLine = skillCounts
149
+ ? `Skills: ${skillCounts.total} built-in (${skillCounts.standard} standard + ${skillCounts.mipham} mipham)`
150
+ : `Skills: (loader unavailable)`
151
+ const toolsCount = ctx.engine.getTools().size
146
152
 
147
- Provider: ${ctx.providerId} / ${ctx.modelId}
148
- Tools: 16 built-in
149
- Skills: 14 built-in (12 standard + 2 mipham)
150
- License: Apache 2.0
151
- `,
152
- })
153
+ return {
154
+ content: stripIndent`
155
+ Mipham Code v${ctx.version}
156
+
157
+ Runtime: Bun ${typeof Bun !== 'undefined' ? Bun.version : '(Node.js)'}
158
+ Platform: ${process.platform} ${process.arch}
159
+ Node: ${process.version}
160
+ CWD: ${process.cwd()}
161
+
162
+ Provider: ${ctx.providerId} / ${ctx.modelId}
163
+ Tools: ${toolsCount} built-in
164
+ ${skillsLine}
165
+ License: Apache 2.0
166
+ `,
167
+ }
168
+ }
153
169
 
154
170
  const clearCmd: CommandHandler = (ctx) => {
155
171
  ctx.engine.getContext().clear()
@@ -317,29 +333,25 @@ const toolsCmd: CommandHandler = (ctx) => {
317
333
  return { content: `Available tools (${tools.size}):\n\n${sections.join('\n\n')}` }
318
334
  }
319
335
 
320
- const skillsCmd: CommandHandler = (_ctx) => ({
321
- content: stripIndent`
322
- ── Standard Skills (12) ──
323
- code-review Code review automation (v2.0)
324
- compassionate-communication Warm, respectful, user-centered interaction
325
- doc-generator Generate technical docs from code
326
- github-ops GitHub PR/issues/releases management
327
- memory Persistent memory read/write
328
- mipham-code-setup Mipham Code install & config guide
329
- security-review Security audit (OWASP, secrets, supply chain)
330
- self-review Self-review diff for bugs and cleanup
331
- superpower Skill discovery and usage guide
332
- tdd Test-Driven Development workflow
333
- web-search Web search for current information
334
- code-review (classic) Legacy code review
335
-
336
- ── Mipham Exclusive (2) ──
337
- om-security Security analysis (injection, PII, adversarial)
338
- om-model-optimize Model optimization (context, caching, tokens)
339
-
340
- 14 skills loaded. Use Skill tool to invoke.
341
- `,
342
- })
336
+ const skillsCmd: CommandHandler = (ctx) => {
337
+ if (!ctx.skillsLoader) {
338
+ return { content: 'SkillsLoader not available.' }
339
+ }
340
+ const counts = ctx.skillsLoader.countByType()
341
+ const standard = ctx.skillsLoader.listByType('standard')
342
+ const mipham = ctx.skillsLoader.listByType('mipham')
343
+
344
+ const lines: string[] = [
345
+ `── Standard Skills (${counts.standard}) ──`,
346
+ ...standard.map((s) => ` ${s.name.padEnd(28)} ${s.description}`),
347
+ '',
348
+ `── Mipham Exclusive (${counts.mipham}) ──`,
349
+ ...mipham.map((s) => ` ${s.name.padEnd(20)} ${s.description}`),
350
+ '',
351
+ `${counts.total} skills loaded. Use Skill tool to invoke.`,
352
+ ]
353
+ return { content: lines.join('\n') }
354
+ }
343
355
 
344
356
  // ═══════════════════════════════════════════════════════════════
345
357
  // Workflow
@@ -1500,16 +1512,19 @@ async function setupStep3(ctx: CommandContext): Promise<CommandResult> {
1500
1512
  return { content: lines.join('\n') }
1501
1513
  }
1502
1514
 
1503
- async function setupStep4(_ctx: CommandContext): Promise<CommandResult> {
1515
+ async function setupStep4(ctx: CommandContext): Promise<CommandResult> {
1516
+ const counts = ctx.skillsLoader?.countByType() ?? { standard: 0, mipham: 0, total: 0 }
1517
+ const standardNames = ctx.skillsLoader?.getNamesByType('standard') ?? []
1518
+ const miphamNames = ctx.skillsLoader?.getNamesByType('mipham') ?? []
1519
+
1504
1520
  return {
1505
1521
  content: `── Step 4: Install Skills ──
1506
1522
 
1507
1523
  Skills extend Mipham Code with specialized capabilities.
1508
1524
 
1509
- Built-in skills (11 total):
1510
- Standard (9): code-review, compassionate-communication, doc-generator,
1511
- github-ops, memory, self-review, superpower, tdd, web-search
1512
- Mipham (2): om-model-optimize, om-security
1525
+ Built-in skills (${counts.total} total):
1526
+ Standard (${counts.standard}): ${standardNames.join(', ')}
1527
+ Mipham (${counts.mipham}): ${miphamNames.join(', ')}
1513
1528
 
1514
1529
  Community skills:
1515
1530
  Coming soon — the Mipham Code skills marketplace will let you
@@ -2273,6 +2288,114 @@ const artifactBaseCmd: CommandHandler = (ctx, args) => {
2273
2288
  // Remaining low-priority stubs (backend not yet available)
2274
2289
  // ═══════════════════════════════════════════════════════════════
2275
2290
 
2291
+ // ═══════════════════════════════════════════════════════════════
2292
+ // Commands — list all registered slash commands
2293
+ // ═══════════════════════════════════════════════════════════════
2294
+
2295
+ const commandsListCmd: CommandHandler = () => {
2296
+ const names = getCommandNames()
2297
+ const categories: Record<string, string[]> = {
2298
+ 'Session & Identity': [],
2299
+ History: [],
2300
+ 'Model & Provider': [],
2301
+ 'Tools & Skills': [],
2302
+ Workflow: [],
2303
+ Project: [],
2304
+ Environment: [],
2305
+ Account: [],
2306
+ Agents: [],
2307
+ Artifacts: [],
2308
+ Other: [],
2309
+ }
2310
+
2311
+ const catMap: Record<string, string> = {
2312
+ '/help': 'Session & Identity',
2313
+ '/version': 'Session & Identity',
2314
+ '/clear': 'Session & Identity',
2315
+ '/exit': 'Session & Identity',
2316
+ '/quit': 'Session & Identity',
2317
+ '/compact': 'Session & Identity',
2318
+ '/context': 'Session & Identity',
2319
+ '/status': 'Session & Identity',
2320
+ '/cost': 'Session & Identity',
2321
+ '/usage': 'Session & Identity',
2322
+ '/rename': 'Session & Identity',
2323
+ '/goal': 'Session & Identity',
2324
+ '/recap': 'Session & Identity',
2325
+ '/export': 'Session & Identity',
2326
+ '/doctor': 'Session & Identity',
2327
+ '/resume': 'Session & Identity',
2328
+ '/branch': 'Session & Identity',
2329
+ '/rewind': 'History',
2330
+ '/undo': 'History',
2331
+ '/copy': 'History',
2332
+ '/focus': 'History',
2333
+ '/pick': 'Model & Provider',
2334
+ '/model': 'Model & Provider',
2335
+ '/models': 'Model & Provider',
2336
+ '/provider': 'Model & Provider',
2337
+ '/providers': 'Model & Provider',
2338
+ '/switch': 'Model & Provider',
2339
+ '/config': 'Model & Provider',
2340
+ '/fast': 'Model & Provider',
2341
+ '/effort': 'Model & Provider',
2342
+ '/theme': 'Model & Provider',
2343
+ '/upgrade': 'Model & Provider',
2344
+ '/tools': 'Tools & Skills',
2345
+ '/skills': 'Tools & Skills',
2346
+ '/reload-skills': 'Tools & Skills',
2347
+ '/mcp': 'Tools & Skills',
2348
+ '/commands': 'Tools & Skills',
2349
+ '/plan': 'Workflow',
2350
+ '/no-plan': 'Workflow',
2351
+ '/tdd': 'Workflow',
2352
+ '/todos': 'Workflow',
2353
+ '/tasks': 'Workflow',
2354
+ '/review': 'Workflow',
2355
+ '/pr-comments': 'Workflow',
2356
+ '/diff': 'Workflow',
2357
+ '/workflows': 'Workflow',
2358
+ '/loop': 'Workflow',
2359
+ '/init': 'Project',
2360
+ '/setup': 'Project',
2361
+ '/permissions': 'Project',
2362
+ '/add-dir': 'Project',
2363
+ '/security': 'Project',
2364
+ '/audit': 'Project',
2365
+ '/ide': 'Environment',
2366
+ '/terminal-setup': 'Environment',
2367
+ '/memory': 'Environment',
2368
+ '/release-notes': 'Environment',
2369
+ '/login': 'Account',
2370
+ '/logout': 'Account',
2371
+ '/feedback': 'Account',
2372
+ '/agents': 'Agents',
2373
+ '/bg': 'Agents',
2374
+ '/artifact': 'Artifacts',
2375
+ '/schedule': 'Other',
2376
+ }
2377
+
2378
+ for (const name of names) {
2379
+ const cat = catMap[name] ?? 'Other'
2380
+ categories[cat]?.push(name)
2381
+ }
2382
+
2383
+ const lines: string[] = [`── All Slash Commands (${names.length}) ──`, '']
2384
+
2385
+ for (const [cat, cmds] of Object.entries(categories)) {
2386
+ if (cmds.length === 0) continue
2387
+ lines.push(`── ${cat} (${cmds.length}) ──`)
2388
+ for (const c of cmds) {
2389
+ lines.push(` ${c}`)
2390
+ }
2391
+ lines.push('')
2392
+ }
2393
+
2394
+ lines.push('Type /help for details, or /<command> to run.')
2395
+
2396
+ return { content: lines.join('\n') }
2397
+ }
2398
+
2276
2399
  // ═══════════════════════════════════════════════════════════════
2277
2400
  // Command Registry
2278
2401
  // ═══════════════════════════════════════════════════════════════
@@ -2314,6 +2437,7 @@ registry.set('/effort', effortCmd)
2314
2437
  registry.set('/tools', toolsCmd)
2315
2438
  registry.set('/skills', skillsCmd)
2316
2439
  registry.set('/reload-skills', reloadSkillsCmd)
2440
+ registry.set('/commands', commandsListCmd)
2317
2441
 
2318
2442
  // Workflow
2319
2443
  registry.set('/plan', planCmd)
@@ -2375,6 +2499,85 @@ export function getCommandNames(): string[] {
2375
2499
  return Array.from(registry.keys()).sort()
2376
2500
  }
2377
2501
 
2502
+ export interface CommandEntry {
2503
+ name: string
2504
+ description: string
2505
+ }
2506
+
2507
+ const COMMAND_DESCRIPTIONS: Record<string, string> = {
2508
+ '/help': 'Show help',
2509
+ '/commands': 'List all slash commands',
2510
+ '/version': 'Show version info',
2511
+ '/clear': 'Clear conversation',
2512
+ '/exit': 'Exit Mipham Code',
2513
+ '/quit': 'Exit Mipham Code',
2514
+ '/compact': 'Compact context window',
2515
+ '/context': 'Show context stats',
2516
+ '/status': 'Session and system status',
2517
+ '/cost': 'Token usage estimate',
2518
+ '/usage': 'Detailed usage dashboard',
2519
+ '/rename': 'Rename current session',
2520
+ '/goal': 'Set session goal',
2521
+ '/recap': 'Summarize session so far',
2522
+ '/export': 'Export conversation to file',
2523
+ '/doctor': 'System diagnostics',
2524
+ '/resume': 'List saved sessions',
2525
+ '/branch': 'Fork conversation',
2526
+ '/rewind': 'Undo last AI turn',
2527
+ '/undo': 'Same as /rewind',
2528
+ '/copy': 'Copy last response to clipboard',
2529
+ '/focus': 'Toggle focus view',
2530
+ '/pick': 'Open model picker',
2531
+ '/model': 'Show current model',
2532
+ '/models': 'List all available models',
2533
+ '/provider': 'Show current provider',
2534
+ '/providers': 'List configured providers',
2535
+ '/switch': 'Switch provider and model',
2536
+ '/config': 'View configuration',
2537
+ '/fast': 'Toggle fast mode',
2538
+ '/effort': 'Set reasoning effort',
2539
+ '/theme': 'Set terminal theme',
2540
+ '/tools': 'List available tools',
2541
+ '/skills': 'List loaded skills',
2542
+ '/reload-skills': 'Reload all skills',
2543
+ '/mcp': 'MCP server status',
2544
+ '/plan': 'Enter plan mode',
2545
+ '/no-plan': 'Exit plan mode',
2546
+ '/tdd': 'TDD mode',
2547
+ '/todos': 'Task management',
2548
+ '/tasks': 'Background tasks',
2549
+ '/review': 'Code review workflow',
2550
+ '/pr-comments': 'PR review summary',
2551
+ '/diff': 'Show git diff',
2552
+ '/workflows': 'List workflow scripts',
2553
+ '/loop': 'Run prompt on interval',
2554
+ '/init': 'Initialize .mipham config',
2555
+ '/setup': 'Guided project setup wizard',
2556
+ '/permissions': 'Show permission settings',
2557
+ '/add-dir': 'Add workspace directory',
2558
+ '/security': 'Security review checklist',
2559
+ '/audit': 'Same as /security',
2560
+ '/ide': 'IDE integration guide',
2561
+ '/terminal-setup': 'Shell & terminal config',
2562
+ '/memory': 'Manage AI memories',
2563
+ '/release-notes': 'View version changelog',
2564
+ '/upgrade': 'Show upgrade instructions',
2565
+ '/login': 'Show API key status',
2566
+ '/logout': 'Clear credentials guide',
2567
+ '/feedback': 'Send feedback',
2568
+ '/agents': 'Agent view dashboard',
2569
+ '/bg': 'Run a background agent task',
2570
+ '/artifact': 'Manage artifacts',
2571
+ '/schedule': 'View scheduled tasks',
2572
+ }
2573
+
2574
+ export function getCommandList(): CommandEntry[] {
2575
+ return getCommandNames().map((name) => ({
2576
+ name,
2577
+ description: COMMAND_DESCRIPTIONS[name] ?? '',
2578
+ }))
2579
+ }
2580
+
2378
2581
  export function looksLikeSlashCommand(input: string): boolean {
2379
2582
  return input.trim().startsWith('/')
2380
2583
  }
package/src/ui/input.tsx CHANGED
@@ -1,7 +1,8 @@
1
- import React, { useState, useEffect, useRef } from 'react'
1
+ import React, { useState, useEffect, useRef, useMemo } from 'react'
2
2
  import { Box, Text, useInput } from 'ink'
3
3
  import TextInput from 'ink-text-input'
4
4
  import { VimMotionEngine, type VimMode } from './vim-motions.js'
5
+ import { getCommandList, type CommandEntry } from './commands.js'
5
6
 
6
7
  interface InputBarProps {
7
8
  onSubmit: (input: string) => void
@@ -111,6 +112,15 @@ export function InputBar({ onSubmit, isLoading }: InputBarProps) {
111
112
  const [completionVerb, setCompletionVerb] = useState<string | null>(null)
112
113
  const prevLoading = useRef(isLoading)
113
114
 
115
+ // ── Slash command hints ──
116
+ const allCommands = useMemo(() => getCommandList(), [])
117
+ const slashHints = useMemo(() => {
118
+ if (!value.startsWith('/')) return []
119
+ const filter = value.slice(1).toLowerCase()
120
+ if (!filter) return allCommands.slice(0, 12) // show first 12 when just "/"
121
+ return allCommands.filter((c) => c.name.toLowerCase().includes(filter)).slice(0, 8)
122
+ }, [value, allCommands])
123
+
114
124
  // Rotate gerunds while loading
115
125
  useEffect(() => {
116
126
  if (!isLoading) return
@@ -249,32 +259,54 @@ export function InputBar({ onSubmit, isLoading }: InputBarProps) {
249
259
  }
250
260
 
251
261
  return (
252
- <Box marginTop={1}>
253
- <Box marginRight={1}>
254
- <Text color={vimMode === 'normal' ? 'magenta' : isLoading ? 'yellow' : 'cyan'}>
255
- {vimMode === 'normal' ? ':' : '>'}
256
- </Text>
262
+ <Box flexDirection="column" marginTop={1}>
263
+ <Box>
264
+ <Box marginRight={1}>
265
+ <Text color={vimMode === 'normal' ? 'magenta' : isLoading ? 'yellow' : 'cyan'}>
266
+ {vimMode === 'normal' ? ':' : '>'}
267
+ </Text>
268
+ </Box>
269
+ <TextInput
270
+ value={value}
271
+ onChange={(val) => {
272
+ // Block text changes during search mode — keys go to search query
273
+ if (searchMode) return
274
+ setValue(val)
275
+ }}
276
+ onSubmit={handleSubmit}
277
+ placeholder={
278
+ searchMode
279
+ ? `/${searchQuery}`
280
+ : vimMode === 'normal'
281
+ ? '[NORMAL] h/j/k/l w/b 0/$ dd yy p u / (Esc to insert)'
282
+ : isLoading
283
+ ? `${verb}...`
284
+ : completionVerb
285
+ ? completionVerb
286
+ : 'Type a message (Esc to cancel)...'
287
+ }
288
+ />
257
289
  </Box>
258
- <TextInput
259
- value={value}
260
- onChange={(val) => {
261
- // Block text changes during search mode — keys go to search query
262
- if (searchMode) return
263
- setValue(val)
264
- }}
265
- onSubmit={handleSubmit}
266
- placeholder={
267
- searchMode
268
- ? `/${searchQuery}`
269
- : vimMode === 'normal'
270
- ? '[NORMAL] h/j/k/l w/b 0/$ dd yy p u / (Esc to insert)'
271
- : isLoading
272
- ? `${verb}...`
273
- : completionVerb
274
- ? completionVerb
275
- : 'Type a message (Esc to cancel)...'
276
- }
277
- />
290
+ {/* Slash command hints — shown when typing / in INSERT mode */}
291
+ {slashHints.length > 0 && vimMode === 'insert' && (
292
+ <Box marginTop={1} flexDirection="row" gap={1}>
293
+ <Text dimColor>Commands: </Text>
294
+ {slashHints.map((cmd, i) => (
295
+ <Text key={cmd.name} color="cyan">
296
+ {i > 0 ? ' ' : ''}
297
+ {cmd.name}
298
+ </Text>
299
+ ))}
300
+ <Text dimColor>
301
+ {' '}
302
+ (
303
+ {slashHints.length === allCommands.length
304
+ ? 'all'
305
+ : `${slashHints.length} of ${allCommands.length}`}
306
+ )
307
+ </Text>
308
+ </Box>
309
+ )}
278
310
  </Box>
279
311
  )
280
312
  }