hey-cli-python 1.1.0__py3-none-any.whl → 1.1.1__py3-none-any.whl
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.
- hey_cli/cli.py +33 -0
- hey_cli/governance.py +1 -1
- hey_cli/runner.py +34 -4
- {hey_cli_python-1.1.0.dist-info → hey_cli_python-1.1.1.dist-info}/METADATA +20 -2
- hey_cli_python-1.1.1.dist-info/RECORD +14 -0
- hey_cli_python-1.1.0.dist-info/RECORD +0 -14
- {hey_cli_python-1.1.0.dist-info → hey_cli_python-1.1.1.dist-info}/WHEEL +0 -0
- {hey_cli_python-1.1.0.dist-info → hey_cli_python-1.1.1.dist-info}/entry_points.txt +0 -0
- {hey_cli_python-1.1.0.dist-info → hey_cli_python-1.1.1.dist-info}/licenses/LICENSE +0 -0
- {hey_cli_python-1.1.0.dist-info → hey_cli_python-1.1.1.dist-info}/top_level.txt +0 -0
hey_cli/cli.py
CHANGED
|
@@ -68,6 +68,9 @@ def main():
|
|
|
68
68
|
parser.add_argument(
|
|
69
69
|
"--check-cache", type=str, help="Check local cache for instant fix"
|
|
70
70
|
)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--shell-init", action="store_true", help="Output shell function for directory persistence"
|
|
73
|
+
)
|
|
71
74
|
|
|
72
75
|
args = parser.parse_args()
|
|
73
76
|
|
|
@@ -95,6 +98,36 @@ def main():
|
|
|
95
98
|
if args.check_cache:
|
|
96
99
|
sys.exit(0)
|
|
97
100
|
|
|
101
|
+
if args.shell_init:
|
|
102
|
+
is_windows = os.name == "nt"
|
|
103
|
+
if is_windows:
|
|
104
|
+
shell_func = r"""
|
|
105
|
+
function hey {
|
|
106
|
+
& hey.exe @args
|
|
107
|
+
$handoff = Join-Path $HOME ".hey_cwd_handoff"
|
|
108
|
+
if (Test-Path $handoff) {
|
|
109
|
+
$target = Get-Content $handoff -Raw
|
|
110
|
+
Remove-Item $handoff
|
|
111
|
+
if (Test-Path $target.Trim()) {
|
|
112
|
+
Set-Location $target.Trim()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
"""
|
|
117
|
+
else:
|
|
118
|
+
shell_func = r"""
|
|
119
|
+
hey() {
|
|
120
|
+
command hey "$@"
|
|
121
|
+
if [ -f "$HOME/.hey_cwd_handoff" ]; then
|
|
122
|
+
local target=$(cat "$HOME/.hey_cwd_handoff")
|
|
123
|
+
rm -f "$HOME/.hey_cwd_handoff"
|
|
124
|
+
[ -d "$target" ] && cd "$target"
|
|
125
|
+
fi
|
|
126
|
+
}
|
|
127
|
+
"""
|
|
128
|
+
print(shell_func.strip())
|
|
129
|
+
sys.exit(0)
|
|
130
|
+
|
|
98
131
|
# Only check Ollama when we're about to call the LLM
|
|
99
132
|
check_ollama()
|
|
100
133
|
|
hey_cli/governance.py
CHANGED
|
@@ -21,7 +21,7 @@ DEFAULT_RULES = {
|
|
|
21
21
|
"kubectl delete"
|
|
22
22
|
],
|
|
23
23
|
"allowed": [
|
|
24
|
-
"ls", "cat", "pwd", "grep", "find", "echo", "tail"
|
|
24
|
+
"ls", "cat", "pwd", "grep", "find", "echo", "tail", "cd"
|
|
25
25
|
],
|
|
26
26
|
"high_risk_keywords": [
|
|
27
27
|
"reset", "delete", "drop", "truncate", "prune", "rm", "-exec", ">"
|
hey_cli/runner.py
CHANGED
|
@@ -2,6 +2,9 @@ import subprocess
|
|
|
2
2
|
import sys
|
|
3
3
|
import json
|
|
4
4
|
import dataclasses
|
|
5
|
+
import os
|
|
6
|
+
import platform
|
|
7
|
+
import re
|
|
5
8
|
from typing import Optional
|
|
6
9
|
|
|
7
10
|
from .governance import GovernanceEngine, Action
|
|
@@ -17,17 +20,44 @@ class CommandRunner:
|
|
|
17
20
|
self.history_mgr = history_mgr
|
|
18
21
|
self.console = Console()
|
|
19
22
|
|
|
20
|
-
def run_command(self, cmd: str) -> tuple[int, str]:
|
|
23
|
+
def run_command(self, cmd: str, capture_pwd: bool = False) -> tuple[int, str]:
|
|
21
24
|
"""Executes a command and returns exit code and combined output."""
|
|
25
|
+
is_windows = platform.system() == "Windows"
|
|
22
26
|
try:
|
|
27
|
+
full_cmd = cmd
|
|
28
|
+
if capture_pwd:
|
|
29
|
+
if is_windows:
|
|
30
|
+
# Windows CMD syntax for capturing PWD
|
|
31
|
+
full_cmd = f'("{cmd}") & echo. & echo HEY_CWD_HANDOFF:%CD%'
|
|
32
|
+
else:
|
|
33
|
+
# Unix shell syntax
|
|
34
|
+
full_cmd = f'{{ {cmd} ; }} ; printf "\\nHEY_CWD_HANDOFF:%s\\n" "$(pwd)"'
|
|
35
|
+
|
|
23
36
|
result = subprocess.run(
|
|
24
|
-
|
|
37
|
+
full_cmd,
|
|
25
38
|
shell=True,
|
|
26
39
|
stdout=subprocess.PIPE,
|
|
27
40
|
stderr=subprocess.STDOUT,
|
|
28
41
|
text=True
|
|
29
42
|
)
|
|
30
|
-
|
|
43
|
+
|
|
44
|
+
out = result.stdout
|
|
45
|
+
if capture_pwd and "HEY_CWD_HANDOFF:" in out:
|
|
46
|
+
match = re.search(r"HEY_CWD_HANDOFF:(.*)", out)
|
|
47
|
+
if match:
|
|
48
|
+
cwd = match.group(1).strip()
|
|
49
|
+
# Clean up output to hide the marker and the extra newline
|
|
50
|
+
out = re.sub(r"\n?HEY_CWD_HANDOFF:.*", "", out, flags=re.DOTALL).strip()
|
|
51
|
+
|
|
52
|
+
# Normalize paths for comparison (especially on Windows)
|
|
53
|
+
norm_cwd = os.path.normpath(cwd).lower() if is_windows else os.path.normpath(cwd)
|
|
54
|
+
norm_actual = os.path.normpath(os.getcwd()).lower() if is_windows else os.path.normpath(os.getcwd())
|
|
55
|
+
|
|
56
|
+
if norm_cwd != norm_actual:
|
|
57
|
+
with open(os.path.expanduser("~/.hey_cwd_handoff"), "w") as f:
|
|
58
|
+
f.write(cwd)
|
|
59
|
+
|
|
60
|
+
return result.returncode, out
|
|
31
61
|
except Exception as e:
|
|
32
62
|
return -1, str(e)
|
|
33
63
|
|
|
@@ -146,7 +176,7 @@ class CommandRunner:
|
|
|
146
176
|
if self.level in (1, 2):
|
|
147
177
|
if self._check_governance(cmd):
|
|
148
178
|
self.console.print(f"[bold green]● Running:[/bold green] {cmd}")
|
|
149
|
-
code, out = self.run_command(cmd)
|
|
179
|
+
code, out = self.run_command(cmd, capture_pwd=True)
|
|
150
180
|
if out.strip():
|
|
151
181
|
print(out.strip())
|
|
152
182
|
sys.exit(code)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hey-cli-python
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: A secure, zero-bloat CLI companion that turns natural language and error logs into executable commands.
|
|
5
5
|
Author: Mohit Singh Sinsniwal
|
|
6
6
|
Project-URL: Homepage, https://github.com/sinsniwal/hey-cli
|
|
@@ -136,7 +136,25 @@ hey <your objective in plain English>
|
|
|
136
136
|
| `npm run build 2>&1 \| hey what broke?` | Reads piped stderr and explains the error |
|
|
137
137
|
| `hey --clear` | Wipes conversational memory |
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Shell Integration (Recommended)
|
|
142
|
+
|
|
143
|
+
By default, CLI tools cannot change your terminal's directory because they run in a subshell. To enable `hey` to change your directory (e.g., `hey go to desktop`), add the following to your shell configuration (`~/.zshrc` or `~/.bashrc`):
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
eval "$(hey --shell-init)"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**For Windows (PowerShell):**
|
|
150
|
+
|
|
151
|
+
```powershell
|
|
152
|
+
hey --shell-init | Out-String | iex
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Execution Levels
|
|
140
158
|
|
|
141
159
|
| Level | Flag | Behavior |
|
|
142
160
|
| ----- | ----------- | -------------------------------------------------------------------- |
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
hey_cli/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
2
|
+
hey_cli/cli.py,sha256=vD8qvCbY3txQBZd4c0qiYRDj28xIV1Ji_wJk76l7DQ0,6090
|
|
3
|
+
hey_cli/governance.py,sha256=vQF_4e-eXVLnuRPeBJm-wKpJho5Hs145epocwrkY3hY,2647
|
|
4
|
+
hey_cli/history.py,sha256=a7xnUMthQQlzeTwfsORpsTBFPMBgo0wcubU603HBrRE,928
|
|
5
|
+
hey_cli/llm.py,sha256=dFy7iYvYE9_ikOblapp0Ehvj-Nk4iqQ47avi9lzg5d4,8757
|
|
6
|
+
hey_cli/models.py,sha256=Jye_btuL39R7BA5bG59JbJFtpDUS0ZrSw0veUUTf0kM,302
|
|
7
|
+
hey_cli/runner.py,sha256=j8eJytN5a6OFvXhjNVI0NpaQoZhaXaaY8nzPtdEHan4,9897
|
|
8
|
+
hey_cli/skills.py,sha256=RX6rSnkQ6FG_hogKUhASI5dazvNAphi2n2c1Rw_NAxw,3569
|
|
9
|
+
hey_cli_python-1.1.1.dist-info/licenses/LICENSE,sha256=15ubdFS3laW1SETf6f8fd8-sbqZeGz_FFdJgJATDAVI,1065
|
|
10
|
+
hey_cli_python-1.1.1.dist-info/METADATA,sha256=sorZ02K8qPY9KENp42oVOwLs9Em_GQkjz5K_VBVG7D8,10011
|
|
11
|
+
hey_cli_python-1.1.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
12
|
+
hey_cli_python-1.1.1.dist-info/entry_points.txt,sha256=N4bcRze9-LYaO624Gpg5Th_4CSQCDN04EXUHFve7uGw,41
|
|
13
|
+
hey_cli_python-1.1.1.dist-info/top_level.txt,sha256=UNOjINF-x81p5IeEawLMkXdUnlybKKYKx8UGTzP6IuU,8
|
|
14
|
+
hey_cli_python-1.1.1.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
hey_cli/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
2
|
-
hey_cli/cli.py,sha256=FpBeh9A4_V5-HIZ1SiKLXNlTl4HaL3_hodz4PZ14lrQ,5236
|
|
3
|
-
hey_cli/governance.py,sha256=jRgI9kUtldJFUTTNbRAj6kACKnVZMe_ak-7lmCgz5EA,2641
|
|
4
|
-
hey_cli/history.py,sha256=a7xnUMthQQlzeTwfsORpsTBFPMBgo0wcubU603HBrRE,928
|
|
5
|
-
hey_cli/llm.py,sha256=dFy7iYvYE9_ikOblapp0Ehvj-Nk4iqQ47avi9lzg5d4,8757
|
|
6
|
-
hey_cli/models.py,sha256=Jye_btuL39R7BA5bG59JbJFtpDUS0ZrSw0veUUTf0kM,302
|
|
7
|
-
hey_cli/runner.py,sha256=cEF9vePK-g9VOW-8XrsafR7lyRSHQGMOl45hC2nA7sg,8431
|
|
8
|
-
hey_cli/skills.py,sha256=RX6rSnkQ6FG_hogKUhASI5dazvNAphi2n2c1Rw_NAxw,3569
|
|
9
|
-
hey_cli_python-1.1.0.dist-info/licenses/LICENSE,sha256=15ubdFS3laW1SETf6f8fd8-sbqZeGz_FFdJgJATDAVI,1065
|
|
10
|
-
hey_cli_python-1.1.0.dist-info/METADATA,sha256=p_eGnMTvHcsrAZqFAGR4DP5JEBZ_JZ30CN3U13cT1WQ,9600
|
|
11
|
-
hey_cli_python-1.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
12
|
-
hey_cli_python-1.1.0.dist-info/entry_points.txt,sha256=N4bcRze9-LYaO624Gpg5Th_4CSQCDN04EXUHFve7uGw,41
|
|
13
|
-
hey_cli_python-1.1.0.dist-info/top_level.txt,sha256=UNOjINF-x81p5IeEawLMkXdUnlybKKYKx8UGTzP6IuU,8
|
|
14
|
-
hey_cli_python-1.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|