Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions cortex/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,20 @@ def show_rich_help():
console.print("[dim]Learn more: https://cortexlinux.com/docs[/dim]")


def shell_suggest(text: str) -> int:
"""
Internal helper used by shell hotkey integration.
Prints a single suggested command to stdout.
"""
try:
from cortex.shell_integration import suggest_command
suggestion = suggest_command(text)
if suggestion:
print(suggestion)
return 0
except Exception:
return 1

def main():
parser = argparse.ArgumentParser(
prog='cortex',
Expand Down Expand Up @@ -655,5 +669,7 @@ def main():
print(f"❌ Unexpected error: {e}", file=sys.stderr)
return 1



if __name__ == '__main__':
sys.exit(main())
49 changes: 49 additions & 0 deletions cortex/shell_installer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
from pathlib import Path

BASH_MARKER = "# >>> cortex shell integration >>>"
ZSH_MARKER = "# >>> cortex shell integration >>>"


def _append_if_missing(rc_path: Path, block: str) -> bool:
if rc_path.exists():
content = rc_path.read_text()
if BASH_MARKER in content:
return False
else:
rc_path.touch()

with rc_path.open("a", encoding="utf-8") as f:
f.write("\n" + block + "\n")

return True


def install_shell_integration() -> str:
shell = os.environ.get("SHELL", "")
home = Path.home()

if shell.endswith("bash"):
rc = home / ".bashrc"
script_path = Path(__file__).resolve().parent.parent / "scripts" / "cortex_bash.sh"
block = f"""{BASH_MARKER}
source "{script_path}"
# <<< cortex shell integration <<<
"""
installed = _append_if_missing(rc, block)
return "bash", installed

Check warning on line 34 in cortex/shell_installer.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Return a value of type "str" instead of "tuple" or update function "install_shell_integration" type hint.

See more on https://sonarcloud.io/project/issues?id=cortexlinux_cortex&issues=AZsXux-4hFfV5pEjCBfl&open=AZsXux-4hFfV5pEjCBfl&pullRequest=297

elif shell.endswith("zsh"):
rc = home / ".zshrc"
script_path = Path(__file__).resolve().parent.parent / "scripts" / "cortex_zsh.zsh"
block = f"""{ZSH_MARKER}
source "{script_path}"
# <<< cortex shell integration <<<
"""
installed = _append_if_missing(rc, block)
return "zsh", installed

Check warning on line 44 in cortex/shell_installer.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Return a value of type "str" instead of "tuple" or update function "install_shell_integration" type hint.

See more on https://sonarcloud.io/project/issues?id=cortexlinux_cortex&issues=AZsXux-4hFfV5pEjCBfm&open=AZsXux-4hFfV5pEjCBfm&pullRequest=297

else:
raise RuntimeError("Unsupported shell. Only bash and zsh are supported.")


48 changes: 48 additions & 0 deletions cortex/shell_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""
Shell integration helpers for Cortex.
This module is used by Bash/Zsh hotkey bindings to convert
natural language input into a suggested shell command.
"""

from typing import Optional


def suggest_command(user_input: str) -> Optional[str]:
"""
Generate a shell command suggestion from free-form user input.
Args:
user_input (str): Text currently typed in the shell.
Returns:a
Optional[str]: Suggested shell command or None if no suggestion.
"""
user_input = user_input.strip()
if not user_input:
return None

# Import here to keep shell integration lightweight
try:
from cortex.interpreter import interpret
except Exception:
return None

try:
result = interpret(user_input)
except Exception:
return None

if not result:
return None

# Expected result structure:
# {
# "command": "sudo apt install docker",
# ...
# }
command = result.get("command")
if not isinstance(command, str):
return None

return command.strip()
20 changes: 20 additions & 0 deletions scripts/cortex_bash.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Cortex Bash shell integration
# Binds Ctrl+L to send current input to Cortex and replace it with a suggestion

_cortex_suggest() {

Check warning on line 4 in scripts/cortex_bash.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=cortexlinux_cortex&issues=AZsXuyERhFfV5pEjCBfn&open=AZsXuyERhFfV5pEjCBfn&pullRequest=297
# READLINE_LINE contains the current command line
local input="$READLINE_LINE"

# Call cortex shell suggestion helper
local suggestion
suggestion="$(cortex _shell_suggest "$input" 2>/dev/null)"

# If we got a suggestion, replace the current line
if [[ -n "$suggestion" ]]; then
READLINE_LINE="$suggestion"
READLINE_POINT=${#READLINE_LINE}
fi
}

# Bind Ctrl+L to cortex suggestion
bind -x '"\C-l": _cortex_suggest'
17 changes: 17 additions & 0 deletions scripts/cortex_zsh.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Cortex Zsh shell integration
# Binds Ctrl+L to send current input to Cortex and replace it with a suggestion

_cortex_suggest() {
local input="$BUFFER"
local suggestion

suggestion="$(cortex _shell_suggest "$input" 2>/dev/null)"

if [[ -n "$suggestion" ]]; then
BUFFER="$suggestion"
CURSOR=${#BUFFER}
fi
}

zle -N _cortex_suggest
bindkey '^L' _cortex_suggest
11 changes: 11 additions & 0 deletions tests/test_shell_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from cortex.shell_integration import suggest_command


def test_suggest_command_empty():
assert suggest_command("") is None


def test_suggest_command_text():
# We only check that it does not crash
result = suggest_command("install docker")
assert result is None or isinstance(result, str)
Loading