shellmate-cli 3.0.0__py3-none-any.whl → 3.0.2__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.
@@ -107,6 +107,8 @@ print(json.dumps({
107
107
  suggested_fix=$(python3 -c "import sys,json; d=json.loads(sys.argv[1]); print(d.get('suggested_fix',''))" "$raw" 2>/dev/null)
108
108
  severity=$(python3 -c "import sys,json; d=json.loads(sys.argv[1]); print(d.get('severity','MEDIUM'))" "$raw" 2>/dev/null)
109
109
 
110
+ # Color scheme mirrors shellmate/ui/colors.py: caution=91 red, warning=93
111
+ # yellow, suggestion/safe=92 green.
110
112
  local color="\e[93m"
111
113
  [[ "$severity" == "HIGH" || "$severity" == "CRITICAL" || "$severity" == "blocking" ]] && color="\e[91m"
112
114
  [[ "$severity" == "SAFE" || "$severity" == "LOW" ]] && color="\e[92m"
@@ -114,7 +116,8 @@ print(json.dumps({
114
116
  local line1 line2 line3=""
115
117
  line1="${color} → ${what_happens}\e[m"
116
118
  line2="${color} → Reversible: ${reversible} | ${scope}\e[m"
117
- [[ -n "$suggested_fix" ]] && line3="\e[90m → Safe alt: ${suggested_fix}\e[m"
119
+ # A suggested fix is a suggestion -> green (92), not dim.
120
+ [[ -n "$suggested_fix" ]] && line3="\e[92m → Safe alt: ${suggested_fix}\e[m"
118
121
 
119
122
  # Gate HIGH/CRITICAL on second Enter
120
123
  if [[ "$severity" == "HIGH" || "$severity" == "CRITICAL" || "$severity" == "blocking" ]]; then
@@ -328,10 +331,11 @@ print('\n'.join(get_completions(sys.argv[1])))
328
331
  _SHELLMATE_TAB_CMD="$first"
329
332
  _SHELLMATE_TAB_STATE="suggested"
330
333
  local suffix="${first#$line}"
334
+ # Autocomplete ghost-text is a suggestion -> green (92), per shellmate/ui/colors.py.
331
335
  if [[ -n "$suffix" ]] && type ble/canvas/put.draw &>/dev/null; then
332
- ble/canvas/put.draw "\e[90m${suffix}\e[m"
336
+ ble/canvas/put.draw "\e[92m${suffix}\e[m"
333
337
  elif [[ -n "$suffix" ]]; then
334
- printf '\e[90m%s\e[m' "$suffix" >/dev/tty
338
+ printf '\e[92m%s\e[m' "$suffix" >/dev/tty
335
339
  printf '\e[%dD' "${#suffix}" >/dev/tty
336
340
  fi
337
341
  fi
@@ -70,11 +70,13 @@ function Show-ShellMateConsequence {
70
70
  elseif ($Severity -in @("SAFE","LOW")) { "${ESC}[92m" } `
71
71
  else { "${ESC}[93m" }
72
72
  $reset = "${ESC}[0m"
73
- $dim = "${ESC}[90m"
73
+ # Color scheme mirrors shellmate/ui/colors.py: caution=91 red, warning=93
74
+ # yellow, suggestion/safe=92 green. A suggested fix is a suggestion -> green.
75
+ $green = "${ESC}[92m"
74
76
 
75
77
  $line1 = "${color} -> ${WhatHappens}${reset}"
76
78
  $line2 = "${color} -> Reversible: ${Reversible} | ${Scope}${reset}"
77
- $line3 = if ($SuggestedFix) { "${dim} -> Safe alt: ${SuggestedFix}${reset}" } else { "" }
79
+ $line3 = if ($SuggestedFix) { "${green} -> Safe alt: ${SuggestedFix}${reset}" } else { "" }
78
80
 
79
81
  # Save cursor, write 3 lines below prompt, restore
80
82
  [Console]::Write("${ESC}[s")
@@ -368,7 +370,9 @@ if (-not $script:ShellMatePredictorRegistered) {
368
370
  $ESC = [char]27
369
371
  $suffix = ([string]$suggestion).Substring([Math]::Min($prefix.Length, ([string]$suggestion).Length))
370
372
  if ($suffix) {
371
- [Console]::Write("${ESC}[90m${suffix}${ESC}[0m")
373
+ # Autocomplete ghost-text is a suggestion -> green (92),
374
+ # matching shellmate/ui/colors.py.
375
+ [Console]::Write("${ESC}[92m${suffix}${ESC}[0m")
372
376
  [Console]::Write("${ESC}[$($suffix.Length)D")
373
377
  }
374
378
  return
@@ -89,6 +89,9 @@ if ($py -and (Test-Path $client)) {
89
89
  $predictor
90
90
  )
91
91
  Set-PSReadLineOption -PredictionSource Plugin -PredictionViewStyle InlineView -ErrorAction SilentlyContinue
92
+ # Render predictions green — they are suggestions (mirrors shellmate/ui/colors.py).
93
+ $smEsc = [char]27
94
+ Set-PSReadLineOption -Colors @{ InlinePrediction = "${smEsc}[92m" } -ErrorAction SilentlyContinue
92
95
  $script:ShellMatePredictorRegistered = $true
93
96
  } catch {
94
97
  Write-Verbose "ShellMate: predictor registration failed: $_"
shellmate/cli/version.py CHANGED
@@ -1 +1 @@
1
- VERSION = "3.0.0"
1
+ VERSION = "3.0.2"
@@ -4,6 +4,8 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any, Dict, Optional
6
6
 
7
+ from shellmate.ui import colors
8
+
7
9
  # Emoji mappings for risk levels (short inline / Unix terminals)
8
10
  RISK_ICONS = {
9
11
  "SAFE": "✅",
@@ -105,6 +107,7 @@ def format_consequence_annotation(
105
107
  risk: str = "MEDIUM",
106
108
  *,
107
109
  ascii_safe: bool = False,
110
+ color: bool = False,
108
111
  ) -> str:
109
112
  """Format annotation using structured consequence preview + badges."""
110
113
  env_context = env_context or {}
@@ -137,7 +140,12 @@ def format_consequence_annotation(
137
140
  if not consequence.get("reversible", True):
138
141
  parts.append("[IRREVERSIBLE]")
139
142
 
140
- return " ".join(parts) if len(parts) > 1 else ""
143
+ if len(parts) <= 1:
144
+ return ""
145
+ text = " ".join(parts)
146
+ # Consequence severity ("blocking"/"warning"/"info") or risk level both map
147
+ # through SEVERITY_ROLE -> caution=red / warning=yellow / safe=green.
148
+ return colors.by_severity(text, severity if severity in colors.SEVERITY_ROLE else risk) if color else text
141
149
 
142
150
 
143
151
  def format_legacy_pipeline_annotation(
@@ -146,6 +154,7 @@ def format_legacy_pipeline_annotation(
146
154
  chain_patterns: Optional[Dict[str, Any]] = None,
147
155
  *,
148
156
  ascii_safe: bool = False,
157
+ color: bool = False,
149
158
  ) -> str:
150
159
  """Format annotation from pipeline result without consequence_preview."""
151
160
  env_context = env_context or {}
@@ -186,7 +195,10 @@ def format_legacy_pipeline_annotation(
186
195
  msg = msg[:37] + "..."
187
196
  parts.append(msg)
188
197
 
189
- return " ".join(parts) if len(parts) > 1 else ""
198
+ if len(parts) <= 1:
199
+ return ""
200
+ text = " ".join(parts)
201
+ return colors.by_severity(text, risk) if color else text
190
202
 
191
203
 
192
204
  def format_pipeline_annotation(
@@ -195,6 +207,7 @@ def format_pipeline_annotation(
195
207
  chain_patterns: Optional[Dict[str, Any]] = None,
196
208
  *,
197
209
  ascii_safe: bool = False,
210
+ color: bool = False,
198
211
  ) -> str:
199
212
  """Prefer consequence_preview; fall back to legacy pipeline formatting."""
200
213
  consequence = risk_result.get("consequence_preview") or {}
@@ -205,13 +218,16 @@ def format_pipeline_annotation(
205
218
  chain_patterns,
206
219
  risk_result.get("risk", "MEDIUM"),
207
220
  ascii_safe=ascii_safe,
221
+ color=color,
208
222
  )
209
223
  return format_legacy_pipeline_annotation(
210
- risk_result, env_context, chain_patterns, ascii_safe=ascii_safe
224
+ risk_result, env_context, chain_patterns, ascii_safe=ascii_safe, color=color
211
225
  )
212
226
 
213
227
 
214
- def format_cached_annotation(cached_result: Dict[str, Any], *, ascii_safe: bool = False) -> str:
228
+ def format_cached_annotation(
229
+ cached_result: Dict[str, Any], *, ascii_safe: bool = False, color: bool = False
230
+ ) -> str:
215
231
  """Format a simple annotation from a cache hit payload."""
216
232
  msg = cached_result.get("explanation", "") or ""
217
233
  risk = cached_result.get("risk", "MEDIUM")
@@ -229,4 +245,7 @@ def format_cached_annotation(cached_result: Dict[str, Any], *, ascii_safe: bool
229
245
 
230
246
  if len(msg) > 50:
231
247
  msg = msg[:47] + "..."
232
- return f"{icon} {msg}" if msg else ""
248
+ if not msg:
249
+ return ""
250
+ text = f"{icon} {msg}"
251
+ return colors.by_severity(text, risk) if color else text
shellmate/ui/colors.py ADDED
@@ -0,0 +1,109 @@
1
+ """Semantic terminal colors for suggestions and cautions.
2
+
3
+ Single source of truth for ShellMate's inline color scheme so every surface
4
+ agrees on what red / yellow / green mean:
5
+
6
+ caution -> red (dangerous: HIGH / CRITICAL / blocking)
7
+ warning -> yellow (proceed with care: MEDIUM)
8
+ suggestion -> green (a safer alternative / "Safe alt")
9
+ safe -> green (SAFE / LOW — nothing to worry about)
10
+ info -> cyan (neutral information)
11
+ dim -> grey (de-emphasized)
12
+
13
+ The shell adapters (``powershell_adapter.ps1`` / ``ble_adapter.sh``) mirror these
14
+ SGR codes directly since they render ANSI themselves; keep them in sync with
15
+ ``ROLE_SGR`` below. Python-side rendering should use this module.
16
+
17
+ Honors the https://no-color.org convention: if the ``NO_COLOR`` environment
18
+ variable is set (to anything), colorizing becomes a no-op.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import os
24
+ from typing import Optional
25
+
26
+ ESC = "\033"
27
+ RESET = f"{ESC}[0m"
28
+
29
+ # Role -> SGR (Select Graphic Rendition) code. Bright variants read well on both
30
+ # dark and light terminals. Mirror these in the shell adapters.
31
+ ROLE_SGR = {
32
+ "caution": 91, # bright red
33
+ "warning": 93, # bright yellow
34
+ "suggestion": 92, # bright green
35
+ "safe": 92, # bright green
36
+ "info": 96, # bright cyan
37
+ "dim": 90, # grey
38
+ }
39
+
40
+ # Role -> rich style name, for Console/Text rendering in the CLI scenes.
41
+ ROLE_RICH = {
42
+ "caution": "bold red",
43
+ "warning": "yellow",
44
+ "suggestion": "green",
45
+ "safe": "green",
46
+ "info": "cyan",
47
+ "dim": "bright_black",
48
+ }
49
+
50
+ # Risk/severity label -> semantic role.
51
+ SEVERITY_ROLE = {
52
+ "CRITICAL": "caution",
53
+ "HIGH": "caution",
54
+ "blocking": "caution",
55
+ "MEDIUM": "warning",
56
+ "warning": "warning",
57
+ "LOW": "safe",
58
+ "SAFE": "safe",
59
+ "info": "info",
60
+ }
61
+
62
+
63
+ def color_enabled(no_color: Optional[bool] = None) -> bool:
64
+ """Whether color should be emitted.
65
+
66
+ Explicit ``no_color`` wins; otherwise honor the ``NO_COLOR`` env var.
67
+ """
68
+ if no_color is not None:
69
+ return not no_color
70
+ return os.environ.get("NO_COLOR") is None
71
+
72
+
73
+ def role_for_severity(severity: Optional[str]) -> str:
74
+ """Map a risk/severity label to a semantic role (defaults to ``warning``)."""
75
+ return SEVERITY_ROLE.get(severity or "", "warning")
76
+
77
+
78
+ def colorize(text: str, role: str, *, no_color: Optional[bool] = None) -> str:
79
+ """Wrap ``text`` in the ANSI color for ``role``.
80
+
81
+ Returns ``text`` unchanged when color is disabled, the text is empty, or the
82
+ role is unknown — so it is always safe to call.
83
+ """
84
+ if not text or not color_enabled(no_color):
85
+ return text
86
+ sgr = ROLE_SGR.get(role)
87
+ if sgr is None:
88
+ return text
89
+ return f"{ESC}[{sgr}m{text}{RESET}"
90
+
91
+
92
+ def caution(text: str, *, no_color: Optional[bool] = None) -> str:
93
+ """Red — a dangerous command or consequence."""
94
+ return colorize(text, "caution", no_color=no_color)
95
+
96
+
97
+ def warning(text: str, *, no_color: Optional[bool] = None) -> str:
98
+ """Yellow — proceed with care."""
99
+ return colorize(text, "warning", no_color=no_color)
100
+
101
+
102
+ def suggestion(text: str, *, no_color: Optional[bool] = None) -> str:
103
+ """Green — a safer alternative to offer."""
104
+ return colorize(text, "suggestion", no_color=no_color)
105
+
106
+
107
+ def by_severity(text: str, severity: Optional[str], *, no_color: Optional[bool] = None) -> str:
108
+ """Colorize ``text`` using the role implied by a risk/severity label."""
109
+ return colorize(text, role_for_severity(severity), no_color=no_color)
@@ -0,0 +1,326 @@
1
+ Metadata-Version: 2.4
2
+ Name: shellmate-cli
3
+ Version: 3.0.2
4
+ Summary: Intelligent shell autocomplete with consequence preview
5
+ Author: ShellMate Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sayan-does/shellmate
8
+ Project-URL: Repository, https://github.com/sayan-does/shellmate
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Environment :: Console
17
+ Classifier: Topic :: Utilities
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: click>=8.0
22
+ Requires-Dist: pyyaml>=6.0
23
+ Requires-Dist: aiohttp>=3.9.0
24
+ Requires-Dist: groq>=0.4.0
25
+ Requires-Dist: openai>=1.0.0
26
+ Requires-Dist: numpy>=1.24.0
27
+ Requires-Dist: langgraph>=1.2.0
28
+ Requires-Dist: langchain-core>=1.4.0
29
+ Requires-Dist: rich>=13.0.0
30
+ Requires-Dist: psutil>=5.9.0
31
+ Requires-Dist: watchdog>=4.0.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: build; extra == "dev"
34
+ Requires-Dist: twine; extra == "dev"
35
+ Requires-Dist: pytest; extra == "dev"
36
+ Requires-Dist: pytest-asyncio; extra == "dev"
37
+ Provides-Extra: windows-test
38
+ Requires-Dist: pywinpty>=2.0.0; sys_platform == "win32" and extra == "windows-test"
39
+ Requires-Dist: pyte>=0.8.1; extra == "windows-test"
40
+ Dynamic: license-file
41
+
42
+ # ShellMate
43
+
44
+ **A friendly safety net for your terminal.**
45
+
46
+ [![PyPI](https://img.shields.io/pypi/v/shellmate-cli)](https://pypi.org/project/shellmate-cli/)
47
+ [![Python](https://img.shields.io/pypi/pyversions/shellmate-cli)](https://pypi.org/project/shellmate-cli/)
48
+ [![License: MIT](https://img.shields.io/pypi/l/shellmate-cli)](LICENSE)
49
+
50
+ The terminal is powerful — and a little scary when you're starting out. One wrong
51
+ command can delete files, wipe a branch, or break something you didn't mean to touch.
52
+
53
+ ShellMate is like having an experienced friend looking over your shoulder. As you
54
+ type, it quietly checks your command and, **before you press Enter**, tells you in
55
+ plain English what it will do, whether it's risky, and if there's a safer way. It
56
+ never runs anything for you — **you're always the one in control.**
57
+
58
+ ```text
59
+ $ rm -rf /
60
+ [!!] BLOCKING — this would erase everything. Press Enter again only if you're sure.
61
+
62
+ $ git push --force
63
+ → This rewrites history on the remote branch (others may lose work).
64
+ → Reversible: No | target: origin/main
65
+ → Safer option: git push --force-with-lease
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Why you'll like it
71
+
72
+ - **Stops the scary stuff.** Genuinely dangerous commands (like `rm -rf /`) are
73
+ caught instantly and ask you to confirm before they run.
74
+ - **Explains commands in plain English.** No more guessing what a command does —
75
+ ShellMate tells you what will happen and whether you can undo it.
76
+ - **Suggests safer alternatives.** When there's a gentler way to do the same thing,
77
+ it offers it.
78
+ - **Autocomplete that helps you learn.** Press Tab for suggestions as you type.
79
+ - **Stays out of your way.** Safe commands run normally — no pop-ups, no nagging.
80
+ - **You stay in control.** ShellMate only *shows* you things. It never executes
81
+ commands on its own.
82
+
83
+ ---
84
+
85
+ ## Get started in 3 steps
86
+
87
+ ### 1. Install it
88
+
89
+ ```bash
90
+ pip install shellmate-cli
91
+ ```
92
+
93
+ ### 2. Give it a brain (a free API key)
94
+
95
+ ShellMate uses an AI service to explain commands. The easiest free option is **Groq**:
96
+
97
+ 1. Grab a free key at **[console.groq.com](https://console.groq.com)** (takes a minute).
98
+ 2. Tell ShellMate about it:
99
+
100
+ ```bash
101
+ sm config
102
+ ```
103
+
104
+ It'll ask you to pick a provider and paste your key. That's it — the key is
105
+ stored privately on your computer, not in your command history.
106
+
107
+ ### 3. Turn it on
108
+
109
+ ```bash
110
+ sm install # connects ShellMate to your shell (one time)
111
+ sm enable # starts the helper in the background
112
+ ```
113
+
114
+ Now just **use your terminal normally.** Little notes will appear under your
115
+ commands as you type.
116
+
117
+ > **What you need:** Python 3.10+, and either **Windows PowerShell** or, on
118
+ > **Linux/WSL**, [ble.sh](https://github.com/akinomyoga/ble.sh). ShellMate sets up
119
+ > the rest for you.
120
+
121
+ ---
122
+
123
+ ## What it feels like to use
124
+
125
+ As you type, ShellMate shows a tiny note under your command:
126
+
127
+ | You type | You see | What it means |
128
+ |----------|---------|---------------|
129
+ | `ls` | *(nothing)* | Totally safe — ShellMate stays quiet. |
130
+ | `git push --force` | `[!] rewrites history [PROD]` | Heads up: this is risky and you're on production. |
131
+ | `rm -rf /` | `[!!] BLOCKING — Enter again to confirm` | Dangerous. It won't run until you really mean it. |
132
+
133
+ **Dangerous commands don't run on the first Enter.** You'll get a clear warning, and
134
+ only a *second* Enter actually runs them — a gentle "are you sure?" that has saved
135
+ many people from a bad day.
136
+
137
+ **Want to understand a command?** Press **Tab** for a suggestion, and a short
138
+ "here's what this will do" preview appears before you commit to it.
139
+
140
+ ---
141
+
142
+ ## Everyday commands
143
+
144
+ These are the only commands you need day to day:
145
+
146
+ | Command | What it does |
147
+ |---------|--------------|
148
+ | `sm enable` | Turn ShellMate on. |
149
+ | `sm disable` | Turn it off. |
150
+ | `sm status` | Check if it's running and healthy. |
151
+ | `sm config` | Set or update your API key. |
152
+ | `sm uninstall` | Remove ShellMate from your shell (keeps your settings). |
153
+ | `sm --help` | See everything. |
154
+
155
+ ---
156
+
157
+ ## A note on your privacy
158
+
159
+ Being honest about how it works:
160
+
161
+ - The **instant danger checks** (like catching `rm -rf /`) run **entirely on your
162
+ computer** — no internet needed.
163
+ - When ShellMate needs AI help to explain a trickier command, the **command text you
164
+ typed** is sent to the AI provider you chose (e.g. Groq) so it can analyze it.
165
+ - Your API key is stored locally in a private config file, never in your shell history.
166
+ - As with any tool that talks to a cloud service, **avoid typing passwords or secret
167
+ keys directly on the command line.**
168
+
169
+ ---
170
+
171
+ ## Troubleshooting
172
+
173
+ - **"I don't see any notes."** Run `sm status` to confirm the daemon is running, and
174
+ make sure you ran `sm enable`. On a brand-new install, open a fresh terminal so the
175
+ shell hook loads.
176
+ - **"It says my AI model isn't available."** Some free accounts can't use every model.
177
+ ShellMate will warn you at startup and `sm status` lists the models your key *can*
178
+ use — set one with `sm config`.
179
+ - **"Is it slowing me down?"** Safe commands get an instant local check (under 10ms).
180
+ Only genuinely unclear commands ever wait on the AI.
181
+
182
+ ---
183
+
184
+ <details>
185
+ <summary><b>Under the hood</b> (for the curious / power users)</summary>
186
+
187
+ ### How it works
188
+
189
+ ```
190
+ You type in the shell
191
+ → ble.sh (Linux/WSL) or PSReadLine (Windows) adapter
192
+ → IPC to a background daemon (TCP 127.0.0.1:9823)
193
+ → LangGraph analysis pipeline
194
+ → Inline annotation / confirmation gate
195
+ ```
196
+
197
+ Three tiers, fastest first:
198
+
199
+ 1. **Instant catastrophic check** — local YAML rules (`shellmate/rules/catastrophic.yaml`), no API, <10ms.
200
+ 2. **Debounced partial analysis** — ~300ms after you pause typing (`/analyze-partial`).
201
+ 3. **Full analysis** — rules → exact-match cache → AI + context agents when risk is unclear.
202
+
203
+ ### Install from source
204
+
205
+ ```bash
206
+ git clone https://github.com/sayan-does/shellmate.git
207
+ cd shellmate
208
+ pip install -e ".[dev]"
209
+ python -m build
210
+ ```
211
+
212
+ ### Annotation badges
213
+
214
+ | Kind | Examples |
215
+ |------|----------|
216
+ | Risk | `[OK]` `[i]` `[!]` `[!!]` `[X]` |
217
+ | Environment | `[PROD]` `[STAGE]` `[DEV]` `[CI]` |
218
+ | Time | `BH` (business hours) · `AH` (after hours) |
219
+ | Chain / consequence | `[BROKEN]` `[ESCALATION]` `[IRREVERSIBLE]` |
220
+
221
+ ### Bracket syntax (typed inline; adapters strip and honor them)
222
+
223
+ | Syntax | Purpose | Example |
224
+ |--------|---------|---------|
225
+ | `[?…]` | Ask a question about the command | `docker rm $(docker ps -aq) [?why dangerous]` |
226
+ | `[!…]` | Directive to the analyzer | `rm -rf /tmp [!force]` |
227
+ | `[@key=value]` | Override context | `git reset --hard [@env=production]` |
228
+
229
+ ### Full CLI
230
+
231
+ | Command | Description |
232
+ |---------|-------------|
233
+ | `sm install` | Install shell hooks (bash/zsh → ble adapter, PowerShell → PS adapter) |
234
+ | `sm uninstall` | Remove shell hooks (keeps config) |
235
+ | `sm config` | Configure API keys and settings |
236
+ | `sm enable` | Start daemon (autocomplete mode) |
237
+ | `sm disable` | Stop daemon and clean session |
238
+ | `sm status` | Daemon, agents, providers, credentials |
239
+ | `sm --help` / `sm --version` | Help / version |
240
+ | `sm --no-color <cmd>` | Plain-text output |
241
+
242
+ ```bash
243
+ sm install --dry-run # preview changes without touching files
244
+ sm config --show # masked credentials
245
+ sm config provider risk_analysis xai grok-3-mini # set a provider role
246
+ sm config cache.max_entries 200 # YAML override (dotted key)
247
+ ```
248
+
249
+ Exit codes: `0` success · `2` usage error · `3` temporary error · `4` internal error.
250
+
251
+ ### Analysis pipeline
252
+
253
+ Defined in `shellmate/orchestration/analysis_graph.py` (LangGraph `StateGraph`):
254
+
255
+ ```mermaid
256
+ flowchart TD
257
+ START([start]) --> sanitize --> parse --> command_chain --> rules --> cache
258
+ cache -->|early exit| format
259
+ cache -->|needs AI| supervisor
260
+ supervisor -->|gather context| context_worker
261
+ supervisor -->|env only| env_context
262
+ context_worker --> risk_analyzer
263
+ env_context --> risk_analyzer
264
+ risk_analyzer --> consequence_builder --> remediation --> command_guide --> format
265
+ format --> query
266
+ query --> END([end])
267
+ ```
268
+
269
+ **Early exits** (skip AI): sanitizer correction, high-confidence rule match, cache hit.
270
+
271
+ ### Daemon agents (started by `sm enable`)
272
+
273
+ | Agent | Purpose |
274
+ |-------|---------|
275
+ | Watcher | OS, shell, git, tech-stack snapshot |
276
+ | Librarian | Project file index + search |
277
+ | Environment | Environment / staging signals |
278
+ | CommandChain | Chain-pattern analysis |
279
+ | Query | Answers `[?…]` queries |
280
+
281
+ ### Providers
282
+
283
+ | Stage | Default | Fallback |
284
+ |-------|---------|----------|
285
+ | Supervisor / risk / guide | Groq | Grok (xAI) / heuristic |
286
+ | Remediation | OpenRouter | Grok (xAI) / Groq guide / generic text |
287
+
288
+ Configure **at least one** of Groq, OpenRouter, or Grok (xAI). Instant catastrophic
289
+ gating always uses local rules, with or without a key.
290
+
291
+ ### Where things live
292
+
293
+ | Purpose | Linux / macOS | Windows |
294
+ |---------|---------------|---------|
295
+ | Config + `.env` | `~/.config/shellmate` | `%APPDATA%\ShellMate` |
296
+ | State / sessions / logs | `~/.local/state/shellmate` | `%LOCALAPPDATA%\ShellMate` |
297
+ | Cache | `~/.cache/shellmate` | `%LOCALAPPDATA%\ShellMate\cache` |
298
+ | Installed adapters | `~/.shellmate/adapters/` | `%USERPROFILE%\.shellmate\adapters\` |
299
+
300
+ ### Environment variables
301
+
302
+ | Variable | Required | Purpose |
303
+ |----------|----------|---------|
304
+ | `GROQ_API_KEY` | one of the three | Risk analysis, supervisor, command guide |
305
+ | `OPENROUTER_API_KEY` | one of the three | Remediation alternatives |
306
+ | `XAI_API_KEY` | one of the three | Risk + remediation via Grok |
307
+ | `CONTEXT7_API_KEY` | no | Optional docs lookup |
308
+ | `GROQ_SUPERVISOR_MODEL` | no | Override supervisor model (default `qwen/qwen3.8-27b`) |
309
+ | `XAI_MODEL` | no | Override Grok model (default `grok-3-mini`) |
310
+
311
+ Optional YAML overrides live in `<config_dir>/config.yaml`.
312
+
313
+ ### Dependencies (authoritative: `pyproject.toml`)
314
+
315
+ `click`, `rich`, `pyyaml` (CLI/UI) · `langgraph`, `langchain-core` (orchestration) ·
316
+ `groq`, `openai`, `aiohttp` (providers) · `psutil`, `watchdog` (runtime) · `numpy`.
317
+
318
+ CI builds and smoke-tests the wheel on Python 3.10–3.12. Publishing runs on `v*` tags
319
+ via Trusted Publishing (`.github/workflows/publish.yml`).
320
+
321
+ </details>
322
+
323
+ ---
324
+
325
+ Made to make the terminal a little less scary. **MIT licensed** — contributions welcome at
326
+ [github.com/sayan-does/shellmate](https://github.com/sayan-does/shellmate).
@@ -1,9 +1,9 @@
1
1
  shellmate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  shellmate/adapters/__init__.py,sha256=4gnk5hxRGFfKS9NM0oHVFPczZe7wK-4pu7pVHDlhqWc,2292
3
3
  shellmate/adapters/bash_adapter.sh,sha256=8n7DeBS_vy1_dwTmulY3wvsqhUEMYNy8Huz4gUh771M,312
4
- shellmate/adapters/ble_adapter.sh,sha256=tBgsJmVDbFfIKtxwB8bx32W0lh1ybWEPxySTr09TLjk,11268
5
- shellmate/adapters/powershell_adapter.ps1,sha256=4ngc0fFWfa46b5sOB5CPYzX5iPmMoAiect5KtPPmkzE,15782
6
- shellmate/adapters/powershell_predictor.ps1,sha256=W3NAsqYI0gOQ-qyMAgplfgTz0VxpsWBf4MTNTHh1zWU,4136
4
+ shellmate/adapters/ble_adapter.sh,sha256=yAVdAYOV3e7HNiqXtmRCg3nJCt2TkrrHsddPAQY3eDo,11539
5
+ shellmate/adapters/powershell_adapter.ps1,sha256=XfLWswjYOFbSY86rXHKtWLFIn1NM8cTiMxEIbZVWJ9U,16084
6
+ shellmate/adapters/powershell_predictor.ps1,sha256=C52Ds-2seMGd_jWjazOaaoHO6YdhnH3Qk1OzTVKPDHI,4362
7
7
  shellmate/adapters/zsh_adapter.zsh,sha256=NBqP4d0JxkjlyAbRt95JqNe99o3YSHcT18R_nX2qeVg,342
8
8
  shellmate/agents/__init__.py,sha256=L1p1AT5XqnijplQv23G4OrzyAGlGTGfVX4StsNj_6Cc,515
9
9
  shellmate/agents/base.py,sha256=vfwvln6P2_qk054udxf0jGE921mMOxZJh0OjBYCH4JA,8140
@@ -20,7 +20,7 @@ shellmate/cache/semantic_cache.py,sha256=d9Je0gRFW1ASau8xemGBbbJfxk08C3QkIl_HtCI
20
20
  shellmate/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  shellmate/cli/main.py,sha256=_gljAQLkDgYgukkyYNVjjow7d-FIOtWbFufnFhsNr7A,3815
22
22
  shellmate/cli/parser.py,sha256=Lh3mo6aHwn6ISmXoFKMfROF--tSe7Rpig_3rpjTGgi0,5747
23
- shellmate/cli/version.py,sha256=qckxTKowVHHdLYuDeVRWcIaYVKeKZEw0YwwUIm6QtNY,18
23
+ shellmate/cli/version.py,sha256=obmd3VOGkno3g89HIX3XZWI2xsdprkRqSyf-ntBilNg,18
24
24
  shellmate/cli/commands/__init__.py,sha256=MFJrPc6Yrhe6eFxTAJI8dnOnqUdILoh3JnBRCevVOwU,1032
25
25
  shellmate/cli/commands/analyze.py,sha256=t5BxxGBrPizJvgsbrvOpsF327DxgunoN7QefaBXIc3k,270
26
26
  shellmate/cli/commands/config.py,sha256=DI22jVKEwaFLqQIA3ps-ZFRz6lNML_DYBWBtyh70ISA,10168
@@ -84,8 +84,9 @@ shellmate/sanitizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
84
84
  shellmate/sanitizer/typo_detector.py,sha256=ZBhOzB7ZSv4hctbu60tu_iBMjcBIP4TLjQ20aoCLVVQ,2957
85
85
  shellmate/ui/__init__.py,sha256=i8MvY7xFXCg9WRXFJcny3iiNBUnHoNW8U82t4tjqSrs,252
86
86
  shellmate/ui/analysis.py,sha256=U5WrGXSrBfR2Q_xOZ_nxi6frouTU6CrmHu-t7afLpmc,5905
87
- shellmate/ui/annotations.py,sha256=ztf3PlPcCeainX4Hi7qQW30pJ9T1zY5aaxC6IlyHwoI,6914
87
+ shellmate/ui/annotations.py,sha256=1qp2zhD6bmRKG2TtSVvS7KaG5U0ZZ9TMOLvWYoCwAy8,7525
88
88
  shellmate/ui/banner.py,sha256=gOT8hYnO6pRqPW_tWx5KPInw9TOcByLthdmKz8uneaI,1752
89
+ shellmate/ui/colors.py,sha256=1qzvODW1rpAlkH_02HgCbh5WY_hGOycJsMQydeQXzx4,3576
89
90
  shellmate/ui/progress.py,sha256=5rLtBR4VM9CUs7phTz6VJqVSIou0hGTk9YDRE-E0nvc,4020
90
91
  shellmate/ui/status.py,sha256=EmsWCd5R_h-rQ9nApBBUFPhhZurfKoXY3_te4h7LIJo,134
91
92
  shellmate/ui/runtime/__init__.py,sha256=G2tRJWagzRJSUYRVmyb0cBVxPr5XKwoXibVmSdXkA4Y,448
@@ -98,9 +99,9 @@ shellmate/ui/scenes/enable.py,sha256=wrKSyGg_aSU3anvCAMPQOBq9E13KDCtQT3GRDbCSalA
98
99
  shellmate/ui/scenes/help.py,sha256=ozg_JosfzpA4cNCSWHazETiRuU9gPO_-Y04arYmgUUU,1904
99
100
  shellmate/ui/scenes/stages.py,sha256=pK396uMatWxJm_XbWCJTWsvx7W6Sx0s7G95S3ec1ffQ,4048
100
101
  shellmate/ui/scenes/status.py,sha256=nC-wAC8cdE3UC2QXeK9zD8fOAMpdLogHK67h74a9Nek,6427
101
- shellmate_cli-3.0.0.dist-info/licenses/LICENSE,sha256=_eDrSi0nYhgVjipoIJoiUEdbARagURo6nVbTGBzqvD4,1079
102
- shellmate_cli-3.0.0.dist-info/METADATA,sha256=MjD_jybwTY6cc6eqjxQAgk-x0Qp4Ocdi0QiK-D72pDg,12187
103
- shellmate_cli-3.0.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
104
- shellmate_cli-3.0.0.dist-info/entry_points.txt,sha256=lBMog9g17_P4iSXr6Akfg_QTVzswLWXUeGnuq66Wwhw,83
105
- shellmate_cli-3.0.0.dist-info/top_level.txt,sha256=0htuoy1ZSdVSt_0l2mO-mPPvSp2veo6dbr3h0K_AmIw,10
106
- shellmate_cli-3.0.0.dist-info/RECORD,,
102
+ shellmate_cli-3.0.2.dist-info/licenses/LICENSE,sha256=_eDrSi0nYhgVjipoIJoiUEdbARagURo6nVbTGBzqvD4,1079
103
+ shellmate_cli-3.0.2.dist-info/METADATA,sha256=AXJSeTRRhxe3wCX6cqNS5uc7fJAQl8PKi5Pr86w9BRA,11788
104
+ shellmate_cli-3.0.2.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
105
+ shellmate_cli-3.0.2.dist-info/entry_points.txt,sha256=lBMog9g17_P4iSXr6Akfg_QTVzswLWXUeGnuq66Wwhw,83
106
+ shellmate_cli-3.0.2.dist-info/top_level.txt,sha256=0htuoy1ZSdVSt_0l2mO-mPPvSp2veo6dbr3h0K_AmIw,10
107
+ shellmate_cli-3.0.2.dist-info/RECORD,,
@@ -1,352 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: shellmate-cli
3
- Version: 3.0.0
4
- Summary: Intelligent shell autocomplete with consequence preview
5
- Author: ShellMate Contributors
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/sayan-does/shellmate
8
- Project-URL: Repository, https://github.com/sayan-does/shellmate
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Environment :: Console
17
- Classifier: Topic :: Utilities
18
- Requires-Python: >=3.10
19
- Description-Content-Type: text/markdown
20
- License-File: LICENSE
21
- Requires-Dist: click>=8.0
22
- Requires-Dist: pyyaml>=6.0
23
- Requires-Dist: aiohttp>=3.9.0
24
- Requires-Dist: groq>=0.4.0
25
- Requires-Dist: openai>=1.0.0
26
- Requires-Dist: numpy>=1.24.0
27
- Requires-Dist: langgraph>=1.2.0
28
- Requires-Dist: langchain-core>=1.4.0
29
- Requires-Dist: rich>=13.0.0
30
- Requires-Dist: psutil>=5.9.0
31
- Requires-Dist: watchdog>=4.0.0
32
- Provides-Extra: dev
33
- Requires-Dist: build; extra == "dev"
34
- Requires-Dist: twine; extra == "dev"
35
- Requires-Dist: pytest; extra == "dev"
36
- Requires-Dist: pytest-asyncio; extra == "dev"
37
- Provides-Extra: windows-test
38
- Requires-Dist: pywinpty>=2.0.0; sys_platform == "win32" and extra == "windows-test"
39
- Requires-Dist: pyte>=0.8.1; extra == "windows-test"
40
- Dynamic: license-file
41
-
42
- # ShellMate
43
-
44
- Intelligent shell autocomplete with consequence preview.
45
-
46
- **Version:** 3.0.0
47
- **Package:** [`shellmate-cli`](https://pypi.org/project/shellmate-cli/)
48
- **License:** MIT
49
- **Python:** 3.10+
50
-
51
- ShellMate watches what you type and shows **inline risk annotations** before you press Enter. A background daemon analyzes commands with deterministic rules, an exact-match cache, and a LangGraph pipeline that pulls project context plus Groq / OpenRouter / Grok (xAI) for AI risk and remediation.
52
-
53
- ## How it works
54
-
55
- ```
56
- You type in the shell
57
- → ble.sh (Linux/WSL) or PSReadLine (Windows) adapter
58
- → IPC to daemon (TCP 127.0.0.1:9823)
59
- → LangGraph analysis pipeline
60
- → Inline annotation / confirmation gate
61
- ```
62
-
63
- 1. **Instant catastrophic check** — local YAML rules (`rules/catastrophic.yaml`), no API.
64
- 2. **Debounced partial analysis** — after a short pause while typing.
65
- 3. **Full analysis** — rules → cache → AI + context agents when risk is unclear.
66
-
67
- ## Installation
68
-
69
- ### From PyPI
70
-
71
- ```bash
72
- pip install shellmate-cli
73
- ```
74
-
75
- ### From source
76
-
77
- ```bash
78
- git clone https://github.com/sayan-does/shellmate.git
79
- cd shellmate
80
- pip install -e .
81
- ```
82
-
83
- ## Quick start
84
-
85
- ### 1. Prerequisites
86
-
87
- | Platform | Required |
88
- |----------|----------|
89
- | Linux / WSL | [ble.sh](https://github.com/akinomyoga/ble.sh) (e.g. under `~/.local/share/blesh/ble.sh`) |
90
- | Windows | PowerShell with PSReadLine |
91
- | All | At least one of `GROQ_API_KEY`, `OPENROUTER_API_KEY`, or `XAI_API_KEY` |
92
-
93
- ### 2. Install hooks and configure keys
94
-
95
- ```bash
96
- sm install # copy adapter → ~/.shellmate/adapters/ and append RC/profile hook
97
- sm config # select provider (Groq / OpenRouter / Grok xAI), paste API key
98
- ```
99
-
100
- Dry-run without changing files:
101
-
102
- ```bash
103
- sm install --dry-run
104
- ```
105
-
106
- ### 3. Start the daemon
107
-
108
- ```bash
109
- sm enable
110
- ```
111
-
112
- Starts the daemon for the current directory (Watcher, Librarian, and other agents). Check with `sm status`.
113
-
114
- ### 4. Type normally
115
-
116
- Inline annotations appear under the line as you type. Catastrophic commands require a second Enter to confirm.
117
-
118
- ### 5. Stop / remove
119
-
120
- ```bash
121
- sm disable # stop daemon
122
- sm uninstall # remove shell hooks (keeps config)
123
- ```
124
-
125
- ## Autocomplete features
126
-
127
- ShellMate’s main UX is **in-shell autocomplete annotations** (not a separate `sm -a` command). Adapters hook ble.sh or PSReadLine and talk to the daemon over IPC.
128
-
129
- ### Two-phase typing feedback
130
-
131
- | Phase | Latency | What happens |
132
- |-------|---------|--------------|
133
- | **1 — Instant** | &lt;10ms, no API | `/instant-check` against `rules/catastrophic.yaml`. Blocking commands get an immediate annotation. |
134
- | **2 — Debounced** | ~300ms after you pause | `/analyze-partial` runs the analysis pipeline and **replaces** the annotation in place with risk + badges. |
135
-
136
- ```bash
137
- $ git push --force
138
- [!] rewrites history [PROD] BH
139
-
140
- $ rm -rf /
141
- [!] BLOCKING - Type again to confirm
142
- ```
143
-
144
- ### Consequence preview (Tab × 2)
145
-
146
- 1. **First Tab** — completion / ghost-text suggestion
147
- 2. **Second Tab** — accept suggestion and show a **consequence preview** below the prompt:
148
-
149
- ```text
150
- → Force-pushes and rewrites remote history
151
- → Reversible: No | remote: origin/main
152
- → Safe alt: git push --force-with-lease
153
- ```
154
-
155
- On HIGH / CRITICAL / blocking severity, Enter is gated until you confirm again.
156
-
157
- | Platform | Completion surface |
158
- |----------|-------------------|
159
- | Linux / WSL (ble.sh) | Tab bound to ShellMate complete widget |
160
- | PowerShell 7.2+ | PSReadLine predictor (`powershell_predictor.ps1`) when available |
161
- | PowerShell 5.1 | Tab handler ghost-text fallback |
162
-
163
- ### Double-Enter confirmation
164
-
165
- Dangerous commands do not run on the first Enter:
166
-
167
- 1. First Enter → blocked; annotation asks you to confirm
168
- 2. Second Enter (same command) → allowed
169
-
170
- Applies to catastrophic instant matches and to HIGH/CRITICAL consequence previews.
171
-
172
- ### Annotation badges
173
-
174
- Short inline text under the command (ASCII-safe on all platforms):
175
-
176
- | Kind | Examples |
177
- |------|----------|
178
- | Risk | `[OK]` `[i]` `[!]` `[!!]` `[X]` |
179
- | Environment | `[PROD]` `[STAGE]` `[DEV]` `[CI]` |
180
- | Time | `BH` (business hours) · `AH` (after hours) |
181
- | Chain / consequence | `[BROKEN]` `[ESCALATION]` `[IRREVERSIBLE]` |
182
-
183
- ### Bracket syntax
184
-
185
- Typed as part of the command line; adapters/daemon strip and honor them:
186
-
187
- | Syntax | Purpose | Example |
188
- |--------|---------|---------|
189
- | `[?…]` | Ask a question about the command | `docker rm $(docker ps -aq) [?why dangerous]` |
190
- | `[!…]` | Directive to the analyzer | `rm -rf /tmp [!force]` |
191
- | `[@key=value]` | Override context (e.g. environment) | `git reset --hard [@env=production]` |
192
-
193
- ### Surfaces
194
-
195
- | Adapter | Shell | Role |
196
- |---------|-------|------|
197
- | `ble_adapter.sh` | bash/zsh + ble.sh | Primary Linux/WSL autocomplete |
198
- | `powershell_adapter.ps1` | PowerShell + PSReadLine | Primary Windows autocomplete |
199
- | `powershell_predictor.ps1` | PowerShell 7.2+ | Optional ghost-text predictor |
200
- | `bash_adapter.sh` / `zsh_adapter.zsh` | — | Deprecated stubs |
201
-
202
- Requires at least one of `GROQ_API_KEY`, `OPENROUTER_API_KEY`, or `XAI_API_KEY` for AI annotations and consequence previews. Instant catastrophic checks still use local rules.
203
-
204
- ## CLI
205
-
206
- | Command | Description |
207
- |---------|-------------|
208
- | `sm install` | Install shell hooks (bash/zsh → ble adapter, PowerShell → PS adapter) |
209
- | `sm uninstall` | Remove shell hooks |
210
- | `sm config` | Configure API keys and settings |
211
- | `sm enable` | Start daemon (autocomplete mode) |
212
- | `sm disable` | Stop daemon and clean session |
213
- | `sm status` | Daemon, agents, providers, credentials |
214
- | `sm --help` | Help |
215
- | `sm --version` | Version |
216
- | `sm --no-color <cmd>` | Plain text output |
217
-
218
- ### `sm config` usages
219
-
220
- ```bash
221
- sm config # validate existing keys; select provider → paste key
222
- sm config --show # masked credentials
223
- sm config provider risk_analysis xai grok-3-mini # set provider role
224
- sm config cache.max_entries 200 # YAML override (dotted key)
225
- ```
226
-
227
- Interactive setup asks you to pick Groq, OpenRouter, or Grok (xAI), then paste the key. Existing keys are checked against the provider API.
228
- ### Exit codes
229
-
230
- | Code | Meaning |
231
- |------|---------|
232
- | 0 | Success |
233
- | 2 | Usage error |
234
- | 3 | Temporary error (e.g. interrupt) |
235
- | 4 | Internal error |
236
-
237
- ## Shell adapters
238
-
239
- See [Autocomplete features](#autocomplete-features) for behavior. `sm install` copies the ble or PowerShell adapter into `~/.shellmate/adapters/` and appends a source line to your RC / profile.
240
-
241
- ## Architecture
242
-
243
- ### Analysis pipeline
244
-
245
- Defined in `shellmate/orchestration/analysis_graph.py` (LangGraph `StateGraph`):
246
-
247
- ```mermaid
248
- flowchart TD
249
- START([start]) --> sanitize --> parse --> command_chain --> rules --> cache
250
- cache -->|early exit| format
251
- cache -->|needs AI| supervisor
252
- supervisor -->|gather context| context_worker
253
- supervisor -->|env only| env_context
254
- context_worker --> risk_analyzer
255
- env_context --> risk_analyzer
256
- risk_analyzer --> consequence_builder --> remediation --> command_guide --> format
257
- format --> query
258
- query --> END([end])
259
- ```
260
-
261
- | Node | Role |
262
- |------|------|
263
- | `sanitize` / `parse` | Typo / syntax checks; tokenize |
264
- | `command_chain` | Multi-step / chain pattern detection |
265
- | `rules` | YAML rules under `shellmate/rules/definitions/` |
266
- | `cache` | Exact-match in-memory cache (no FAISS) |
267
- | `supervisor` | Groq (or heuristic) decides context needs |
268
- | `context_worker` / `env_context` | Parallel agent queries or env-only path |
269
- | `risk_analyzer` | Groq risk assessment |
270
- | `consequence_builder` | Structured consequence preview |
271
- | `remediation` | OpenRouter safer alternatives |
272
- | `command_guide` | Groq “what you meant” guide |
273
- | `format` / `query` | Final payload; optional `[?…]` query handling |
274
-
275
- **Early exits** (skip AI): sanitizer correction, high-confidence rule match, cache hit.
276
-
277
- ### Agents (daemon)
278
-
279
- Started with `sm enable`:
280
-
281
- | Agent | Purpose |
282
- |-------|---------|
283
- | Watcher | OS, shell, git, tech-stack snapshot |
284
- | Librarian | Project file index + search |
285
- | Environment | Environment / staging signals |
286
- | CommandChain | Chain-pattern analysis |
287
- | Query | Answers `[?…]` queries |
288
-
289
- Repomix-style pack search runs alongside Librarian in the context worker when needed.
290
-
291
- ### Providers
292
-
293
- | Stage | Default | Fallback |
294
- |-------|---------|----------|
295
- | Supervisor / risk / guide | Groq | Grok (xAI) / heuristic |
296
- | Remediation | OpenRouter | Grok (xAI) / Groq guide / generic text |
297
-
298
- Configure **at least one** of Groq, OpenRouter, or Grok (xAI). Groq covers risk analysis, supervisor routing, and command guide; OpenRouter covers remediation; xAI can cover both risk and remediation. Instant catastrophic gating still uses local rules either way.
299
- ## Configuration
300
-
301
- ### Directories
302
-
303
- | Purpose | Linux / macOS | Windows |
304
- |---------|---------------|---------|
305
- | Config + `.env` | `~/.config/shellmate` | `%APPDATA%\ShellMate` |
306
- | State / sessions / logs | `~/.local/state/shellmate` | `%LOCALAPPDATA%\ShellMate` |
307
- | Cache dir | `~/.cache/shellmate` | `%LOCALAPPDATA%\ShellMate\cache` |
308
- | Installed adapters | `~/.shellmate/adapters/` | `%USERPROFILE%\.shellmate\adapters\` |
309
-
310
- Credentials file: `<config_dir>/.env` (permissions restricted on Unix).
311
-
312
- ### Environment variables
313
-
314
- | Variable | Required | Purpose |
315
- |----------|----------|---------|
316
- | `GROQ_API_KEY` | At least one of Groq / OpenRouter / xAI | Risk analysis, supervisor, command guide |
317
- | `OPENROUTER_API_KEY` | At least one of Groq / OpenRouter / xAI | Remediation alternatives |
318
- | `XAI_API_KEY` | At least one of Groq / OpenRouter / xAI | Risk analysis and remediation via Grok |
319
- | `CONTEXT7_API_KEY` | No | Optional docs lookup |
320
- | `GROQ_SUPERVISOR_MODEL` | No | Override supervisor model (default `qwen/qwen3.8-27b`) |
321
- | `XAI_MODEL` | No | Override Grok model (default `grok-3-mini`) |
322
-
323
- Optional YAML overrides live in `<config_dir>/config.yaml`.
324
-
325
- ## Requirements
326
-
327
- - Python 3.10+
328
- - ble.sh (Linux/WSL) or PowerShell + PSReadLine (Windows)
329
- - At least one of `GROQ_API_KEY`, `OPENROUTER_API_KEY`, or `XAI_API_KEY` (Groq + OpenRouter recommended for full risk + remediation)
330
-
331
- ### Dependencies (authoritative: `pyproject.toml`)
332
-
333
- - `click`, `rich`, `pyyaml` — CLI / UI
334
- - `langgraph`, `langchain-core` — orchestration
335
- - `groq`, `openai`, `aiohttp` — providers
336
- - `psutil`, `watchdog` — runtime monitoring
337
- - `numpy` — declared runtime dependency
338
-
339
- ## Development
340
-
341
- ```bash
342
- git clone https://github.com/sayan-does/shellmate.git
343
- cd shellmate
344
- pip install -e ".[dev]"
345
- python -m build
346
- ```
347
-
348
- CI builds and smoke-tests the wheel on Python 3.10–3.12. Publishing runs on `v*` tags via Trusted Publishing (`.github/workflows/publish.yml`).
349
-
350
- ## License
351
-
352
- MIT