@austinthesing/magic-shell 0.2.25 → 0.2.27

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
@@ -145,22 +145,17 @@ Launch with `mshell` for a full interactive experience.
145
145
 
146
146
  ### Keyboard Shortcuts
147
147
 
148
- All shortcuts use the `Ctrl+X` chord (press Ctrl+X, then the key):
148
+ Magic Shell follows OpenCode-style TUI shortcuts where they map cleanly:
149
149
 
150
150
  | Shortcut | Action |
151
151
  | ---------- | ---------------------- |
152
- | `Ctrl+X P` | Open command palette |
152
+ | `Ctrl+P` | Open Commands |
153
153
  | `Ctrl+X M` | Change model |
154
- | `Ctrl+X S` | Switch provider |
155
- | `Ctrl+X D` | Toggle dry-run mode |
156
154
  | `Ctrl+X T` | Change theme |
157
- | `Ctrl+X R` | Toggle project context |
158
- | `Ctrl+X H` | Show history |
159
- | `Ctrl+X C` | Show config |
160
- | `Ctrl+X L` | Clear output |
161
- | `Ctrl+X ?` | Show help |
162
155
  | `Ctrl+X Q` | Exit |
163
- | `Ctrl+C` | Exit / Cancel |
156
+ | `Ctrl+T` | Cycle thinking level |
157
+ | `Ctrl+C` | Exit / Cancel active UI |
158
+ | `Ctrl+D` | Exit |
164
159
  | `Esc` | Close dialogs |
165
160
 
166
161
  ### Direct Commands in TUI
package/dist/cli.js CHANGED
@@ -77094,9 +77094,11 @@ function createMainUI() {
77094
77094
  keyBindings: [
77095
77095
  { name: "return", action: "submit" },
77096
77096
  { name: "linefeed", action: "submit" },
77097
- { name: "return", shift: true, action: "submit" },
77098
- { name: "linefeed", shift: true, action: "submit" },
77099
- { name: "return", meta: true, action: "submit" }
77097
+ { name: "return", shift: true, action: "newline" },
77098
+ { name: "linefeed", shift: true, action: "newline" },
77099
+ { name: "return", ctrl: true, action: "newline" },
77100
+ { name: "return", meta: true, action: "newline" },
77101
+ { name: "j", ctrl: true, action: "newline" }
77100
77102
  ],
77101
77103
  onSubmit: () => {
77102
77104
  const value = inputField.editBuffer.getText();
@@ -77134,7 +77136,7 @@ function getHelpBarContent() {
77134
77136
  if (awaitingConfirmation) {
77135
77137
  return t`${fg(theme.colors.warning)(">>> Cmd+Enter or Enter to execute <<<")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.error)("Esc")}${fg(theme.colors.textMuted)(" Cancel")} ${fg(theme.colors.primary)("e")}${fg(theme.colors.textMuted)(" Edit")} ${fg(theme.colors.primary)("c")}${fg(theme.colors.textMuted)(" Copy")}`;
77136
77138
  }
77137
- return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+K")}${fg(theme.colors.textMuted)(" Think")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
77139
+ return t`${fg(theme.colors.primary)("Ctrl+P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+T")}${fg(theme.colors.textMuted)(" Think")} ${fg(theme.colors.primary)("Ctrl+C")}${fg(theme.colors.textMuted)(" Exit")} ${fg(theme.colors.primary)("Esc")}${fg(theme.colors.textMuted)(" Cancel")}`;
77138
77140
  }
77139
77141
  function getInputHintContent() {
77140
77142
  const theme = getTheme();
@@ -77143,7 +77145,7 @@ function getInputHintContent() {
77143
77145
  function getWelcomeMessage() {
77144
77146
  const providerName = getProviderDisplayName(config2.provider);
77145
77147
  return `Ready. Using ${providerName}.
77146
- Type what you want to do, or press Ctrl+X P for command palette.`;
77148
+ Type what you want to do, or press Ctrl+P for Commands.`;
77147
77149
  }
77148
77150
  function addSystemMessage(content) {
77149
77151
  const msg = {
@@ -77577,11 +77579,17 @@ async function handleSpecialCommand(input) {
77577
77579
  showHelp();
77578
77580
  break;
77579
77581
  case "model":
77582
+ case "models":
77580
77583
  showModelSelector();
77581
77584
  break;
77582
77585
  case "provider":
77586
+ case "providers":
77583
77587
  await switchProvider();
77584
77588
  break;
77589
+ case "theme":
77590
+ case "themes":
77591
+ showThemeSelector();
77592
+ break;
77585
77593
  case "dry":
77586
77594
  dryRunMode = !dryRunMode;
77587
77595
  statusBarText.content = getStatusBarContent();
@@ -77600,6 +77608,10 @@ async function handleSpecialCommand(input) {
77600
77608
  case "clear":
77601
77609
  clearChat();
77602
77610
  break;
77611
+ case "exit":
77612
+ case "quit":
77613
+ renderer.destroy();
77614
+ process.exit(0);
77603
77615
  default:
77604
77616
  if (cmd) {
77605
77617
  addUserMessage(cmd);
@@ -77615,25 +77627,25 @@ function clearChat() {
77615
77627
  addSystemMessage(getWelcomeMessage());
77616
77628
  }
77617
77629
  function showHelp() {
77618
- const helpText = `Direct Shortcuts:
77619
- Ctrl+Y Cycle safety level (strict/moderate/relaxed)
77620
- Ctrl+K Cycle thinking level (low/medium/high/off)
77621
- Ctrl+Z Exit magic-shell
77622
- Ctrl+C Cancel / Close popup
77630
+ const helpText = `Shortcuts:
77631
+ Ctrl+P Commands
77632
+ Ctrl+T Cycle thinking level (low/medium/high/off)
77633
+ Ctrl+C Exit magic-shell
77634
+ Ctrl+D Exit magic-shell
77635
+ Esc Cancel / Close popup
77636
+ Ctrl+C Close popup/cancel first when active
77623
77637
 
77624
- Chord Shortcuts (Ctrl+X then...):
77625
- P Command palette M Change model
77626
- S Switch provider D Toggle dry-run
77627
- T Change theme R Toggle repo context
77628
- H Show history L Clear chat
77629
- C Show config K Thinking level
77630
- ? This help
77638
+ OpenCode Leader (Ctrl+X then...):
77639
+ M Change model
77640
+ T Change theme
77641
+ Q Exit
77631
77642
 
77632
77643
  Commands (type ! or / followed by):
77633
- help Show this help model Change model
77634
- provider Switch provider dry Toggle dry-run
77635
- thinking Cycle thinking config Show configuration
77636
- history Show history clear Clear chat
77644
+ help Show this help models Change model
77645
+ provider Switch provider themes Change theme
77646
+ dry Toggle dry-run thinking Cycle thinking
77647
+ config Show config history Show history
77648
+ clear Clear chat exit Exit
77637
77649
 
77638
77650
  Safety Levels:
77639
77651
  - strict: Confirm ALL potentially dangerous commands
@@ -77648,9 +77660,9 @@ Thinking Levels:
77648
77660
 
77649
77661
  Tips:
77650
77662
  - Type naturally: "list all files" -> ls -la
77651
- - Use ! or / commands: !help or /help
77663
+ - Use ! or / commands: !help, /help, or /models
77652
77664
  - Reference history: "do that again", "undo"
77653
- - Enable repo context to use project scripts (Ctrl+X R)`;
77665
+ - Enable repo context from Commands to use project scripts`;
77654
77666
  addSystemMessage(helpText);
77655
77667
  }
77656
77668
  async function showConfig() {
@@ -77912,6 +77924,7 @@ function showThemeSelector() {
77912
77924
  themeSelector.focus();
77913
77925
  }
77914
77926
  var commandPalette = null;
77927
+ var commandPaletteQuery = "";
77915
77928
  var chordMode = "none";
77916
77929
  function cycleThinkingLevel() {
77917
77930
  const levels = ["low", "medium", "high", "off"];
@@ -77924,32 +77937,21 @@ function cycleThinkingLevel() {
77924
77937
  }
77925
77938
  function getCommandPaletteOptions() {
77926
77939
  return [
77927
- {
77928
- name: "Command Palette",
77929
- description: "Open this menu",
77930
- key: "p",
77931
- chord: "p",
77932
- action: () => {}
77933
- },
77934
77940
  {
77935
77941
  name: "Change Model",
77936
77942
  description: `Current: ${currentModel.name}`,
77937
- key: "m",
77943
+ shortcut: "Ctrl+X M",
77938
77944
  chord: "m",
77939
77945
  action: () => showModelSelector()
77940
77946
  },
77941
77947
  {
77942
77948
  name: "Switch Provider",
77943
77949
  description: `Current: ${getProviderDisplayName(config2.provider)}`,
77944
- key: "s",
77945
- chord: "s",
77946
77950
  action: () => switchProvider()
77947
77951
  },
77948
77952
  {
77949
77953
  name: "Toggle Dry Run",
77950
77954
  description: dryRunMode ? "Currently ON" : "Currently OFF",
77951
- key: "d",
77952
- chord: "d",
77953
77955
  action: () => {
77954
77956
  dryRunMode = !dryRunMode;
77955
77957
  statusBarText.content = getStatusBarContent();
@@ -77959,8 +77961,6 @@ function getCommandPaletteOptions() {
77959
77961
  {
77960
77962
  name: "Cycle Safety Level",
77961
77963
  description: `Current: ${config2.safetyLevel}`,
77962
- key: "y",
77963
- chord: "y",
77964
77964
  action: () => {
77965
77965
  const levels = ["moderate", "strict", "relaxed"];
77966
77966
  const currentIndex = levels.indexOf(config2.safetyLevel);
@@ -77979,15 +77979,12 @@ function getCommandPaletteOptions() {
77979
77979
  {
77980
77980
  name: "Cycle Thinking Level",
77981
77981
  description: `Current: ${config2.thinkingLevel}`,
77982
- key: "k",
77983
- chord: "k",
77982
+ shortcut: "Ctrl+T",
77984
77983
  action: () => cycleThinkingLevel()
77985
77984
  },
77986
77985
  {
77987
77986
  name: "Toggle Project Context",
77988
77987
  description: config2.repoContext ? "Currently ON (sends script names to AI)" : "Currently OFF",
77989
- key: "r",
77990
- chord: "r",
77991
77988
  action: () => {
77992
77989
  config2.repoContext = !config2.repoContext;
77993
77990
  saveConfig(config2);
@@ -77998,42 +77995,34 @@ function getCommandPaletteOptions() {
77998
77995
  {
77999
77996
  name: "Show Config",
78000
77997
  description: "View current configuration",
78001
- key: "c",
78002
- chord: "c",
78003
77998
  action: () => showConfig()
78004
77999
  },
78005
78000
  {
78006
78001
  name: "Show History",
78007
78002
  description: `${history.length} commands`,
78008
- key: "h",
78009
- chord: "h",
78010
78003
  action: () => showHistory()
78011
78004
  },
78012
78005
  {
78013
78006
  name: "Change Theme",
78014
78007
  description: `Current: ${getTheme().name}`,
78015
- key: "t",
78008
+ shortcut: "Ctrl+X T",
78016
78009
  chord: "t",
78017
78010
  action: () => showThemeSelector()
78018
78011
  },
78019
78012
  {
78020
78013
  name: "Clear Chat",
78021
78014
  description: "Clear the chat history",
78022
- key: "l",
78023
- chord: "l",
78024
78015
  action: () => clearChat()
78025
78016
  },
78026
78017
  {
78027
78018
  name: "Show Help",
78028
78019
  description: "View all commands and shortcuts",
78029
- key: "?",
78030
- chord: "?",
78031
78020
  action: () => showHelp()
78032
78021
  },
78033
78022
  {
78034
78023
  name: "Exit",
78035
78024
  description: "Close magic-shell",
78036
- key: "q",
78025
+ shortcut: "Ctrl+D / Ctrl+X Q",
78037
78026
  chord: "q",
78038
78027
  action: () => {
78039
78028
  renderer.destroy();
@@ -78046,6 +78035,7 @@ function showCommandPalette() {
78046
78035
  if (commandPalette) {
78047
78036
  return;
78048
78037
  }
78038
+ commandPaletteQuery = "";
78049
78039
  const commands = getCommandPaletteOptions();
78050
78040
  const paletteWidth = 55;
78051
78041
  const termWidth = process.stdout.columns || 80;
@@ -78061,22 +78051,17 @@ function showCommandPalette() {
78061
78051
  border: true,
78062
78052
  borderColor: "#60a5fa",
78063
78053
  borderStyle: "single",
78064
- title: "Command Palette (Ctrl+X ...)",
78054
+ title: "Commands",
78065
78055
  titleAlignment: "center",
78066
78056
  zIndex: 200,
78067
78057
  padding: 1
78068
78058
  });
78069
78059
  renderer.root.add(container);
78070
- const options = commands.map((cmd) => ({
78071
- name: cmd.chord ? `[${cmd.key}] ${cmd.name}` : `[${cmd.key}] ${cmd.name}`,
78072
- description: cmd.description,
78073
- value: cmd
78074
- }));
78075
78060
  commandPalette = new SelectRenderable(renderer, {
78076
78061
  id: "command-palette-select",
78077
78062
  width: "100%",
78078
78063
  height: Math.min(commands.length + 2, 12),
78079
- options,
78064
+ options: getCommandPaletteSelectOptions(),
78080
78065
  backgroundColor: "transparent",
78081
78066
  focusedBackgroundColor: "transparent",
78082
78067
  selectedBackgroundColor: "#334155",
@@ -78089,41 +78074,59 @@ function showCommandPalette() {
78089
78074
  });
78090
78075
  container.add(commandPalette);
78091
78076
  commandPalette.on(SelectRenderableEvents.ITEM_SELECTED, async (_2, option) => {
78077
+ if (!option.value)
78078
+ return;
78092
78079
  const cmd = option.value;
78093
78080
  closeCommandPalette();
78094
78081
  await cmd.action();
78095
78082
  });
78096
78083
  commandPalette.focus();
78097
78084
  }
78085
+ function getCommandPaletteSelectOptions() {
78086
+ const query = commandPaletteQuery.toLowerCase();
78087
+ const commands = getCommandPaletteOptions().filter((cmd) => {
78088
+ if (!query)
78089
+ return true;
78090
+ return `${cmd.name} ${cmd.description} ${cmd.shortcut ?? ""}`.toLowerCase().includes(query);
78091
+ });
78092
+ if (commands.length === 0) {
78093
+ return [{
78094
+ name: "No commands found",
78095
+ description: commandPaletteQuery,
78096
+ value: null
78097
+ }];
78098
+ }
78099
+ return commands.map((cmd) => ({
78100
+ name: cmd.name,
78101
+ description: cmd.shortcut ? `${cmd.description} · ${cmd.shortcut}` : cmd.description,
78102
+ value: cmd
78103
+ }));
78104
+ }
78105
+ function updateCommandPaletteOptions() {
78106
+ if (!commandPalette)
78107
+ return;
78108
+ commandPalette.options = getCommandPaletteSelectOptions();
78109
+ commandPalette.setSelectedIndex(0);
78110
+ }
78098
78111
  function closeCommandPalette() {
78099
78112
  if (commandPalette) {
78100
78113
  renderer.root.remove("command-palette-container");
78101
78114
  commandPalette = null;
78115
+ commandPaletteQuery = "";
78102
78116
  inputField?.focus();
78103
78117
  }
78104
78118
  }
78105
78119
  function handleKeypress(key) {
78106
78120
  const commands = getCommandPaletteOptions();
78107
- if (key.ctrl && key.name === "y") {
78108
- const levels = ["moderate", "strict", "relaxed"];
78109
- const currentIndex = levels.indexOf(config2.safetyLevel);
78110
- const nextIndex = (currentIndex + 1) % levels.length;
78111
- config2.safetyLevel = levels[nextIndex];
78112
- saveConfig(config2);
78113
- statusBarText.content = getStatusBarContent();
78114
- const descriptions = {
78115
- strict: "confirms ALL potentially dangerous commands",
78116
- moderate: "confirms high/critical severity commands",
78117
- relaxed: "only confirms critical commands"
78118
- };
78119
- addSystemMessage(`Safety level: ${config2.safetyLevel} (${descriptions[config2.safetyLevel]})`);
78121
+ if (key.ctrl && key.name === "p") {
78122
+ showCommandPalette();
78120
78123
  return;
78121
78124
  }
78122
- if (key.ctrl && key.name === "k") {
78125
+ if (key.ctrl && key.name === "t") {
78123
78126
  cycleThinkingLevel();
78124
78127
  return;
78125
78128
  }
78126
- if (key.ctrl && key.name === "z") {
78129
+ if (key.ctrl && key.name === "d") {
78127
78130
  renderer.destroy();
78128
78131
  process.exit(0);
78129
78132
  }
@@ -78136,21 +78139,21 @@ function handleKeypress(key) {
78136
78139
  const keyName2 = key.name || key.sequence;
78137
78140
  const cmd = commands.find((c) => c.chord === keyName2);
78138
78141
  if (cmd) {
78139
- if (cmd.key === "p") {
78140
- showCommandPalette();
78141
- } else {
78142
- cmd.action();
78143
- }
78142
+ cmd.action();
78144
78143
  return;
78145
78144
  }
78146
78145
  return;
78147
78146
  }
78148
78147
  if (commandPalette) {
78149
- const keyName2 = key.name || key.sequence;
78150
- const cmd = commands.find((c) => c.key === keyName2);
78151
- if (cmd) {
78152
- closeCommandPalette();
78153
- cmd.action();
78148
+ if (key.name === "backspace" || key.name === "delete") {
78149
+ commandPaletteQuery = commandPaletteQuery.slice(0, -1);
78150
+ updateCommandPaletteOptions();
78151
+ return;
78152
+ }
78153
+ const sequence = key.sequence ?? "";
78154
+ if (!key.ctrl && !key.meta && sequence.length === 1 && sequence >= " ") {
78155
+ commandPaletteQuery += sequence;
78156
+ updateCommandPaletteOptions();
78154
78157
  return;
78155
78158
  }
78156
78159
  }
@@ -78177,12 +78180,8 @@ function handleKeypress(key) {
78177
78180
  inputField.focus();
78178
78181
  return;
78179
78182
  }
78180
- if (providerSelector) {
78181
- renderer.destroy();
78182
- process.exit(0);
78183
- }
78184
- addSystemMessage("Press Ctrl+Z to exit.");
78185
- return;
78183
+ renderer.destroy();
78184
+ process.exit(0);
78186
78185
  }
78187
78186
  if (key.name === "escape") {
78188
78187
  chordMode = "none";
package/dist/tui.js CHANGED
@@ -77094,9 +77094,11 @@ function createMainUI() {
77094
77094
  keyBindings: [
77095
77095
  { name: "return", action: "submit" },
77096
77096
  { name: "linefeed", action: "submit" },
77097
- { name: "return", shift: true, action: "submit" },
77098
- { name: "linefeed", shift: true, action: "submit" },
77099
- { name: "return", meta: true, action: "submit" }
77097
+ { name: "return", shift: true, action: "newline" },
77098
+ { name: "linefeed", shift: true, action: "newline" },
77099
+ { name: "return", ctrl: true, action: "newline" },
77100
+ { name: "return", meta: true, action: "newline" },
77101
+ { name: "j", ctrl: true, action: "newline" }
77100
77102
  ],
77101
77103
  onSubmit: () => {
77102
77104
  const value = inputField.editBuffer.getText();
@@ -77134,7 +77136,7 @@ function getHelpBarContent() {
77134
77136
  if (awaitingConfirmation) {
77135
77137
  return t`${fg(theme.colors.warning)(">>> Cmd+Enter or Enter to execute <<<")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.error)("Esc")}${fg(theme.colors.textMuted)(" Cancel")} ${fg(theme.colors.primary)("e")}${fg(theme.colors.textMuted)(" Edit")} ${fg(theme.colors.primary)("c")}${fg(theme.colors.textMuted)(" Copy")}`;
77136
77138
  }
77137
- return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+K")}${fg(theme.colors.textMuted)(" Think")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
77139
+ return t`${fg(theme.colors.primary)("Ctrl+P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+T")}${fg(theme.colors.textMuted)(" Think")} ${fg(theme.colors.primary)("Ctrl+C")}${fg(theme.colors.textMuted)(" Exit")} ${fg(theme.colors.primary)("Esc")}${fg(theme.colors.textMuted)(" Cancel")}`;
77138
77140
  }
77139
77141
  function getInputHintContent() {
77140
77142
  const theme = getTheme();
@@ -77143,7 +77145,7 @@ function getInputHintContent() {
77143
77145
  function getWelcomeMessage() {
77144
77146
  const providerName = getProviderDisplayName(config2.provider);
77145
77147
  return `Ready. Using ${providerName}.
77146
- Type what you want to do, or press Ctrl+X P for command palette.`;
77148
+ Type what you want to do, or press Ctrl+P for Commands.`;
77147
77149
  }
77148
77150
  function addSystemMessage(content) {
77149
77151
  const msg = {
@@ -77577,11 +77579,17 @@ async function handleSpecialCommand(input) {
77577
77579
  showHelp();
77578
77580
  break;
77579
77581
  case "model":
77582
+ case "models":
77580
77583
  showModelSelector();
77581
77584
  break;
77582
77585
  case "provider":
77586
+ case "providers":
77583
77587
  await switchProvider();
77584
77588
  break;
77589
+ case "theme":
77590
+ case "themes":
77591
+ showThemeSelector();
77592
+ break;
77585
77593
  case "dry":
77586
77594
  dryRunMode = !dryRunMode;
77587
77595
  statusBarText.content = getStatusBarContent();
@@ -77600,6 +77608,10 @@ async function handleSpecialCommand(input) {
77600
77608
  case "clear":
77601
77609
  clearChat();
77602
77610
  break;
77611
+ case "exit":
77612
+ case "quit":
77613
+ renderer.destroy();
77614
+ process.exit(0);
77603
77615
  default:
77604
77616
  if (cmd) {
77605
77617
  addUserMessage(cmd);
@@ -77615,25 +77627,25 @@ function clearChat() {
77615
77627
  addSystemMessage(getWelcomeMessage());
77616
77628
  }
77617
77629
  function showHelp() {
77618
- const helpText = `Direct Shortcuts:
77619
- Ctrl+Y Cycle safety level (strict/moderate/relaxed)
77620
- Ctrl+K Cycle thinking level (low/medium/high/off)
77621
- Ctrl+Z Exit magic-shell
77622
- Ctrl+C Cancel / Close popup
77630
+ const helpText = `Shortcuts:
77631
+ Ctrl+P Commands
77632
+ Ctrl+T Cycle thinking level (low/medium/high/off)
77633
+ Ctrl+C Exit magic-shell
77634
+ Ctrl+D Exit magic-shell
77635
+ Esc Cancel / Close popup
77636
+ Ctrl+C Close popup/cancel first when active
77623
77637
 
77624
- Chord Shortcuts (Ctrl+X then...):
77625
- P Command palette M Change model
77626
- S Switch provider D Toggle dry-run
77627
- T Change theme R Toggle repo context
77628
- H Show history L Clear chat
77629
- C Show config K Thinking level
77630
- ? This help
77638
+ OpenCode Leader (Ctrl+X then...):
77639
+ M Change model
77640
+ T Change theme
77641
+ Q Exit
77631
77642
 
77632
77643
  Commands (type ! or / followed by):
77633
- help Show this help model Change model
77634
- provider Switch provider dry Toggle dry-run
77635
- thinking Cycle thinking config Show configuration
77636
- history Show history clear Clear chat
77644
+ help Show this help models Change model
77645
+ provider Switch provider themes Change theme
77646
+ dry Toggle dry-run thinking Cycle thinking
77647
+ config Show config history Show history
77648
+ clear Clear chat exit Exit
77637
77649
 
77638
77650
  Safety Levels:
77639
77651
  - strict: Confirm ALL potentially dangerous commands
@@ -77648,9 +77660,9 @@ Thinking Levels:
77648
77660
 
77649
77661
  Tips:
77650
77662
  - Type naturally: "list all files" -> ls -la
77651
- - Use ! or / commands: !help or /help
77663
+ - Use ! or / commands: !help, /help, or /models
77652
77664
  - Reference history: "do that again", "undo"
77653
- - Enable repo context to use project scripts (Ctrl+X R)`;
77665
+ - Enable repo context from Commands to use project scripts`;
77654
77666
  addSystemMessage(helpText);
77655
77667
  }
77656
77668
  async function showConfig() {
@@ -77912,6 +77924,7 @@ function showThemeSelector() {
77912
77924
  themeSelector.focus();
77913
77925
  }
77914
77926
  var commandPalette = null;
77927
+ var commandPaletteQuery = "";
77915
77928
  var chordMode = "none";
77916
77929
  function cycleThinkingLevel() {
77917
77930
  const levels = ["low", "medium", "high", "off"];
@@ -77924,32 +77937,21 @@ function cycleThinkingLevel() {
77924
77937
  }
77925
77938
  function getCommandPaletteOptions() {
77926
77939
  return [
77927
- {
77928
- name: "Command Palette",
77929
- description: "Open this menu",
77930
- key: "p",
77931
- chord: "p",
77932
- action: () => {}
77933
- },
77934
77940
  {
77935
77941
  name: "Change Model",
77936
77942
  description: `Current: ${currentModel.name}`,
77937
- key: "m",
77943
+ shortcut: "Ctrl+X M",
77938
77944
  chord: "m",
77939
77945
  action: () => showModelSelector()
77940
77946
  },
77941
77947
  {
77942
77948
  name: "Switch Provider",
77943
77949
  description: `Current: ${getProviderDisplayName(config2.provider)}`,
77944
- key: "s",
77945
- chord: "s",
77946
77950
  action: () => switchProvider()
77947
77951
  },
77948
77952
  {
77949
77953
  name: "Toggle Dry Run",
77950
77954
  description: dryRunMode ? "Currently ON" : "Currently OFF",
77951
- key: "d",
77952
- chord: "d",
77953
77955
  action: () => {
77954
77956
  dryRunMode = !dryRunMode;
77955
77957
  statusBarText.content = getStatusBarContent();
@@ -77959,8 +77961,6 @@ function getCommandPaletteOptions() {
77959
77961
  {
77960
77962
  name: "Cycle Safety Level",
77961
77963
  description: `Current: ${config2.safetyLevel}`,
77962
- key: "y",
77963
- chord: "y",
77964
77964
  action: () => {
77965
77965
  const levels = ["moderate", "strict", "relaxed"];
77966
77966
  const currentIndex = levels.indexOf(config2.safetyLevel);
@@ -77979,15 +77979,12 @@ function getCommandPaletteOptions() {
77979
77979
  {
77980
77980
  name: "Cycle Thinking Level",
77981
77981
  description: `Current: ${config2.thinkingLevel}`,
77982
- key: "k",
77983
- chord: "k",
77982
+ shortcut: "Ctrl+T",
77984
77983
  action: () => cycleThinkingLevel()
77985
77984
  },
77986
77985
  {
77987
77986
  name: "Toggle Project Context",
77988
77987
  description: config2.repoContext ? "Currently ON (sends script names to AI)" : "Currently OFF",
77989
- key: "r",
77990
- chord: "r",
77991
77988
  action: () => {
77992
77989
  config2.repoContext = !config2.repoContext;
77993
77990
  saveConfig(config2);
@@ -77998,42 +77995,34 @@ function getCommandPaletteOptions() {
77998
77995
  {
77999
77996
  name: "Show Config",
78000
77997
  description: "View current configuration",
78001
- key: "c",
78002
- chord: "c",
78003
77998
  action: () => showConfig()
78004
77999
  },
78005
78000
  {
78006
78001
  name: "Show History",
78007
78002
  description: `${history.length} commands`,
78008
- key: "h",
78009
- chord: "h",
78010
78003
  action: () => showHistory()
78011
78004
  },
78012
78005
  {
78013
78006
  name: "Change Theme",
78014
78007
  description: `Current: ${getTheme().name}`,
78015
- key: "t",
78008
+ shortcut: "Ctrl+X T",
78016
78009
  chord: "t",
78017
78010
  action: () => showThemeSelector()
78018
78011
  },
78019
78012
  {
78020
78013
  name: "Clear Chat",
78021
78014
  description: "Clear the chat history",
78022
- key: "l",
78023
- chord: "l",
78024
78015
  action: () => clearChat()
78025
78016
  },
78026
78017
  {
78027
78018
  name: "Show Help",
78028
78019
  description: "View all commands and shortcuts",
78029
- key: "?",
78030
- chord: "?",
78031
78020
  action: () => showHelp()
78032
78021
  },
78033
78022
  {
78034
78023
  name: "Exit",
78035
78024
  description: "Close magic-shell",
78036
- key: "q",
78025
+ shortcut: "Ctrl+D / Ctrl+X Q",
78037
78026
  chord: "q",
78038
78027
  action: () => {
78039
78028
  renderer.destroy();
@@ -78046,6 +78035,7 @@ function showCommandPalette() {
78046
78035
  if (commandPalette) {
78047
78036
  return;
78048
78037
  }
78038
+ commandPaletteQuery = "";
78049
78039
  const commands = getCommandPaletteOptions();
78050
78040
  const paletteWidth = 55;
78051
78041
  const termWidth = process.stdout.columns || 80;
@@ -78061,22 +78051,17 @@ function showCommandPalette() {
78061
78051
  border: true,
78062
78052
  borderColor: "#60a5fa",
78063
78053
  borderStyle: "single",
78064
- title: "Command Palette (Ctrl+X ...)",
78054
+ title: "Commands",
78065
78055
  titleAlignment: "center",
78066
78056
  zIndex: 200,
78067
78057
  padding: 1
78068
78058
  });
78069
78059
  renderer.root.add(container);
78070
- const options = commands.map((cmd) => ({
78071
- name: cmd.chord ? `[${cmd.key}] ${cmd.name}` : `[${cmd.key}] ${cmd.name}`,
78072
- description: cmd.description,
78073
- value: cmd
78074
- }));
78075
78060
  commandPalette = new SelectRenderable(renderer, {
78076
78061
  id: "command-palette-select",
78077
78062
  width: "100%",
78078
78063
  height: Math.min(commands.length + 2, 12),
78079
- options,
78064
+ options: getCommandPaletteSelectOptions(),
78080
78065
  backgroundColor: "transparent",
78081
78066
  focusedBackgroundColor: "transparent",
78082
78067
  selectedBackgroundColor: "#334155",
@@ -78089,41 +78074,59 @@ function showCommandPalette() {
78089
78074
  });
78090
78075
  container.add(commandPalette);
78091
78076
  commandPalette.on(SelectRenderableEvents.ITEM_SELECTED, async (_2, option) => {
78077
+ if (!option.value)
78078
+ return;
78092
78079
  const cmd = option.value;
78093
78080
  closeCommandPalette();
78094
78081
  await cmd.action();
78095
78082
  });
78096
78083
  commandPalette.focus();
78097
78084
  }
78085
+ function getCommandPaletteSelectOptions() {
78086
+ const query = commandPaletteQuery.toLowerCase();
78087
+ const commands = getCommandPaletteOptions().filter((cmd) => {
78088
+ if (!query)
78089
+ return true;
78090
+ return `${cmd.name} ${cmd.description} ${cmd.shortcut ?? ""}`.toLowerCase().includes(query);
78091
+ });
78092
+ if (commands.length === 0) {
78093
+ return [{
78094
+ name: "No commands found",
78095
+ description: commandPaletteQuery,
78096
+ value: null
78097
+ }];
78098
+ }
78099
+ return commands.map((cmd) => ({
78100
+ name: cmd.name,
78101
+ description: cmd.shortcut ? `${cmd.description} · ${cmd.shortcut}` : cmd.description,
78102
+ value: cmd
78103
+ }));
78104
+ }
78105
+ function updateCommandPaletteOptions() {
78106
+ if (!commandPalette)
78107
+ return;
78108
+ commandPalette.options = getCommandPaletteSelectOptions();
78109
+ commandPalette.setSelectedIndex(0);
78110
+ }
78098
78111
  function closeCommandPalette() {
78099
78112
  if (commandPalette) {
78100
78113
  renderer.root.remove("command-palette-container");
78101
78114
  commandPalette = null;
78115
+ commandPaletteQuery = "";
78102
78116
  inputField?.focus();
78103
78117
  }
78104
78118
  }
78105
78119
  function handleKeypress(key) {
78106
78120
  const commands = getCommandPaletteOptions();
78107
- if (key.ctrl && key.name === "y") {
78108
- const levels = ["moderate", "strict", "relaxed"];
78109
- const currentIndex = levels.indexOf(config2.safetyLevel);
78110
- const nextIndex = (currentIndex + 1) % levels.length;
78111
- config2.safetyLevel = levels[nextIndex];
78112
- saveConfig(config2);
78113
- statusBarText.content = getStatusBarContent();
78114
- const descriptions = {
78115
- strict: "confirms ALL potentially dangerous commands",
78116
- moderate: "confirms high/critical severity commands",
78117
- relaxed: "only confirms critical commands"
78118
- };
78119
- addSystemMessage(`Safety level: ${config2.safetyLevel} (${descriptions[config2.safetyLevel]})`);
78121
+ if (key.ctrl && key.name === "p") {
78122
+ showCommandPalette();
78120
78123
  return;
78121
78124
  }
78122
- if (key.ctrl && key.name === "k") {
78125
+ if (key.ctrl && key.name === "t") {
78123
78126
  cycleThinkingLevel();
78124
78127
  return;
78125
78128
  }
78126
- if (key.ctrl && key.name === "z") {
78129
+ if (key.ctrl && key.name === "d") {
78127
78130
  renderer.destroy();
78128
78131
  process.exit(0);
78129
78132
  }
@@ -78136,21 +78139,21 @@ function handleKeypress(key) {
78136
78139
  const keyName2 = key.name || key.sequence;
78137
78140
  const cmd = commands.find((c) => c.chord === keyName2);
78138
78141
  if (cmd) {
78139
- if (cmd.key === "p") {
78140
- showCommandPalette();
78141
- } else {
78142
- cmd.action();
78143
- }
78142
+ cmd.action();
78144
78143
  return;
78145
78144
  }
78146
78145
  return;
78147
78146
  }
78148
78147
  if (commandPalette) {
78149
- const keyName2 = key.name || key.sequence;
78150
- const cmd = commands.find((c) => c.key === keyName2);
78151
- if (cmd) {
78152
- closeCommandPalette();
78153
- cmd.action();
78148
+ if (key.name === "backspace" || key.name === "delete") {
78149
+ commandPaletteQuery = commandPaletteQuery.slice(0, -1);
78150
+ updateCommandPaletteOptions();
78151
+ return;
78152
+ }
78153
+ const sequence = key.sequence ?? "";
78154
+ if (!key.ctrl && !key.meta && sequence.length === 1 && sequence >= " ") {
78155
+ commandPaletteQuery += sequence;
78156
+ updateCommandPaletteOptions();
78154
78157
  return;
78155
78158
  }
78156
78159
  }
@@ -78177,12 +78180,8 @@ function handleKeypress(key) {
78177
78180
  inputField.focus();
78178
78181
  return;
78179
78182
  }
78180
- if (providerSelector) {
78181
- renderer.destroy();
78182
- process.exit(0);
78183
- }
78184
- addSystemMessage("Press Ctrl+Z to exit.");
78185
- return;
78183
+ renderer.destroy();
78184
+ process.exit(0);
78186
78185
  }
78187
78186
  if (key.name === "escape") {
78188
78187
  chordMode = "none";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@austinthesing/magic-shell",
3
- "version": "0.2.25",
3
+ "version": "0.2.27",
4
4
  "description": "Natural language to terminal commands with safety features. Supports OpenCode Zen, OpenRouter, AI gateways, Workers AI, and custom models.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",