Skip to content

[High] Interactive Mode Enhancements #21

@marklicata

Description

@marklicata

Summary

Enhance interactive mode with input prefixes (! for bash, # for memory), vim keybindings, multi-line input support, and improved keyboard shortcuts.

Current State

Amplifier CLI interactive mode has basic prompt-toolkit integration but lacks:

  • Input prefixes for quick actions
  • Vim mode for efficient editing
  • Multi-line input with backslash continuation
  • Advanced keyboard shortcuts

Proposed Implementation

1. Input Prefixes

Prefix Action Example
! Execute bash directly !git status
# Append to memory # Remember: use pytest-asyncio
/ Slash command (exists) /help
? Quick help/search ?how do I run tests
amplifier> !ls -la
drwxr-xr-x  10 user  staff   320 Jan 15 10:30 src
-rw-r--r--   1 user  staff  1024 Jan 15 10:25 README.md

amplifier> # The project uses FastAPI 0.100+
[Added to session memory]

amplifier> ?pytest fixtures
[Quick search: "pytest fixtures" - showing brief answer]

2. Vim Mode

Enable vim keybindings in interactive mode:

# In amplifier.yaml
interactive:
  editing_mode: "vi"  # Options: "emacs" (default), "vi"

Or via CLI:

amplifier --vim
amplifier -V  # Short flag

Vim mode features:

  • Normal/insert mode switching
  • Motion commands (w, b, e, 0, $, etc.)
  • Delete/change/yank operations
  • Search within line
  • Visual mode for selection

3. Multi-Line Input

Use backslash \ at end of line to continue:

amplifier> Create a Python function that \
... takes a list of numbers and \
... returns the sum of even numbers

[Processing multi-line input...]

Or use triple backticks for code blocks:

amplifier> ```
... def calculate_sum(numbers):
...     return sum(n for n in numbers if n % 2 == 0)
... ```
Please review this function.

[Processing with code block...]

4. Keyboard Shortcuts

Shortcut Current Proposed
Ctrl+C Cancel Cancel current (exists)
Ctrl+D Exit Exit if empty (exists)
Ctrl+L - Clear screen
Ctrl+R - Search history
Ctrl+Z - Undo last edit
Esc Esc - Rewind to checkpoint
Ctrl+K - Clear to end of line
Ctrl+U - Clear to start of line
Ctrl+W - Delete word backward
Tab - Autocomplete (paths, commands)
Up/Down History History (exists)
Ctrl+P/N - History (vim style)

5. Status Line

Add a persistent status line at bottom of terminal:

┌─────────────────────────────────────────────────────────────┐
│ amplifier> write a function to parse JSON                   │
│                                                             │
│ [AI response here...]                                       │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│ claude-sonnet │ 15.2k/200k tokens │ $0.043 │ session: abc12 │
└─────────────────────────────────────────────────────────────┘

Status line shows:

  • Current model
  • Token usage (used/limit)
  • Session cost
  • Session ID (truncated)
  • Optional: git branch, working directory

6. Autocomplete

Tab completion for:

  • File paths (with fuzzy matching)
  • Slash commands (/help, /clear, etc.)
  • Tool names in prompts
  • History search
amplifier> /he[TAB]
/help  /history

amplifier> look at src/[TAB]
src/main.py  src/utils/  src/api/

amplifier> !git [TAB]
status  commit  push  pull  branch  checkout

7. New Module Updates

src/amplifier_app_cli/ui/
├── interactive.py    # UPDATE - add prefixes, vim mode
├── keybindings.py    # NEW - custom key bindings
├── multiline.py      # NEW - multi-line input handling
├── autocomplete.py   # NEW - tab completion
├── statusline.py     # NEW - bottom status bar
└── prefixes.py       # NEW - prefix handlers (!, #, ?)

8. Core Interfaces

from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.completion import Completer

class PrefixHandler(Protocol):
    prefix: str
    
    def matches(self, text: str) -> bool:
        """Check if input starts with this prefix."""
        return text.startswith(self.prefix)
    
    async def handle(self, text: str, session: Session) -> HandleResult:
        """Handle the prefixed input."""
        ...

@dataclass
class HandleResult:
    consumed: bool              # Was input fully handled?
    output: str | None          # Output to display
    continue_prompt: bool       # Should we prompt again?

class BashPrefixHandler(PrefixHandler):
    prefix = "!"
    
    async def handle(self, text: str, session: Session) -> HandleResult:
        command = text[1:].strip()
        result = subprocess.run(command, shell=True, capture_output=True)
        return HandleResult(
            consumed=True,
            output=result.stdout.decode(),
            continue_prompt=True
        )

class MemoryPrefixHandler(PrefixHandler):
    prefix = "#"
    
    async def handle(self, text: str, session: Session) -> HandleResult:
        memory_text = text[1:].strip()
        session.memory.append(memory_text)
        return HandleResult(
            consumed=True,
            output="[Added to session memory]",
            continue_prompt=True
        )

class AmplifierCompleter(Completer):
    def __init__(
        self,
        slash_commands: list[str],
        working_dir: Path,
        history: list[str]
    ): ...
    
    def get_completions(self, document, complete_event):
        """Provide context-aware completions."""
        ...

9. Configuration

interactive:
  # Editing mode
  editing_mode: "emacs"         # emacs | vi
  
  # Prefixes
  prefixes:
    bash: "!"
    memory: "#"
    quick_help: "?"
    
  # Status line
  status_line:
    enabled: true
    show_model: true
    show_tokens: true
    show_cost: true
    show_session_id: true
    
  # Multi-line
  multiline:
    continuation_char: "\\"
    code_block_delimiters: ["```", "'''"]
    
  # Autocomplete
  autocomplete:
    enabled: true
    fuzzy_paths: true
    min_chars: 2
    
  # History
  history:
    max_entries: 1000
    search_enabled: true
    persist: true

10. CLI Flags

# Enable vim mode
amplifier --vim
amplifier -V

# Disable status line
amplifier --no-status-line

# Disable autocomplete
amplifier --no-autocomplete

# Simple mode (no prefixes, no status line)
amplifier --simple

Acceptance Criteria

  • ! prefix executes bash commands directly
  • # prefix appends to session memory
  • ? prefix provides quick help/search
  • Vim mode works with common motions/operations
  • Multi-line input with \ continuation
  • Multi-line input with triple backticks
  • Ctrl+L clears screen
  • Ctrl+R searches history
  • Esc Esc triggers checkpoint restore
  • Tab completion for paths and commands
  • Status line shows model, tokens, cost
  • All features configurable via YAML
  • All features toggleable via CLI flags
  • Unit tests for prefix handlers
  • Integration tests for interactive mode

Related

  • Depends on: Memory Files (for # prefix)
  • Depends on: Checkpointing (for Esc Esc)
  • Enhances: User experience

Estimated Effort

Medium - 1.5-2 weeks

Files to Create/Modify

  • src/amplifier_app_cli/ui/interactive.py (major updates)
  • src/amplifier_app_cli/ui/keybindings.py (new)
  • src/amplifier_app_cli/ui/multiline.py (new)
  • src/amplifier_app_cli/ui/autocomplete.py (new)
  • src/amplifier_app_cli/ui/statusline.py (new)
  • src/amplifier_app_cli/ui/prefixes.py (new)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions