Skip to content

[Bug] ! shell escape only provides autocomplete but does not execute the command #36

@Prodesire

Description

@Prodesire

Bug Description

The ! shell escape feature is only partially implemented. The autocomplete/suggestion layer recognizes the ! trigger and provides shell history completions, but the REPL does not intercept !-prefixed input for execution. Instead, the input is sent to the LLM as a regular chat message.

Steps to Reproduce

  1. Run iac-code
  2. Type !ls (or any !<command>)
  3. Observe that shell history suggestions appear as expected
  4. Press Enter to submit

Expected Behavior

The command after ! (e.g. ls) should be executed in the user's shell, with stdout/stderr displayed in the conversation. The output should ideally be injected into the conversation context so the LLM can reference it in subsequent turns.

Actual Behavior

The !ls input is sent directly to the LLM as a chat message. No shell command is executed.

Root Cause

The suggestion layer is fully wired up:

  • ShellHistoryProvider (src/iac_code/ui/suggestions/shell_history_provider.py) handles the ! trigger and returns history-based completions.
  • TokenExtractor (src/iac_code/ui/suggestions/token_extractor.py:66-74) recognizes ! at line start as a valid trigger.

However, the REPL input loop (src/iac_code/ui/repl.py:358-366) only checks for / (slash commands) before falling through to chat:

user_input = user_input.strip()
if not user_input:
    continue

if self.command_registry.is_command(user_input):   # only matches "/"
    self._record_command_history(user_input)
    await self._handle_command(user_input)
    continue
# ... falls through to _handle_chat()

There is no branch to intercept !-prefixed input, strip the prefix, execute it as a subprocess, and display the result.

Suggested Fix

Add a ! check in the REPL input loop (between the empty-input guard and the / command check), e.g.:

if user_input.startswith("!"):
    shell_cmd = user_input[1:].strip()
    if shell_cmd:
        await self._handle_shell_escape(shell_cmd)
        continue

Where _handle_shell_escape runs the command via subprocess, prints stdout/stderr, and optionally appends the output to the conversation context.

Operating System

macOS

Python Version

3.12.7

iac-code Version

0.2.3

LLM Provider

No response

IaC Type

Not applicable

Additional Context

This feature mirrors the ! <command> shell escape convention used in tools like Claude Code, vim, and Python's REPL, where prefixing input with ! runs it in the host shell.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions