Files
temp/docs/reference/tui_shell_safety.md
freemo dd17d0f8e6 docs(tui): add shell safety, permission question widget, and first-run docs
Add reference documentation for three new TUI features:

- docs/reference/tui_shell_safety.md: Full reference for the shell danger
  detection subsystem (DangerousPatternDetector, ShellDangerLevel,
  DangerousPattern, DangerousCommandWarning, DEFAULT_PATTERNS registry).
  Covers all built-in patterns across CRITICAL/HIGH/MEDIUM/LOW levels,
  usage examples, and custom pattern extension.

- docs/reference/tui_permission_question.md: Full reference for the inline
  PermissionQuestionWidget (issue #997). Documents InlinePermissionQuestion,
  PermissionRequestType, PermissionDecision, render_permission_question(),
  PermissionDecisionEvent, and PermissionQuestionWidget with key bindings
  and usage examples.

- docs/reference/tui.md: Extended with First-Run Experience section
  (ActorSelectionOverlay, first_run helpers), Inline Permission Questions
  section, shell danger detection note in Shell Mode, updated module table,
  and links to new reference pages.
2026-04-03 18:01:26 +00:00

242 lines
9.0 KiB
Markdown

# TUI — Shell Danger Detection
The shell safety subsystem detects dangerous command patterns before execution
in the TUI shell mode (`!` prefix). When a dangerous pattern is matched, the
TUI surfaces a warning overlay so the user can confirm or abort before the
command runs.
Introduced in the [Unreleased] milestone (issue #1003).
See also [`tui.md`](tui.md) for the overall TUI architecture.
**Module**: `cleveragents.tui.shell_safety`
---
## Overview
When the user types a shell command in the TUI (prefixed with `!`), the
`DangerousPatternDetector` scans the command against a configurable registry
of patterns before execution. If any patterns match, a warning is displayed
with the danger level and a description of the risk.
```
┌─────────────────────────────────────────────────────────────────┐
│ ⚠ Dangerous command detected │
│ │
│ [Critical] rm -rf / recursively deletes the entire filesystem │
│ root. This will destroy the operating system and all data. │
│ │
│ Command: rm -rf / │
│ │
│ [c] Cancel [p] Proceed anyway │
└─────────────────────────────────────────────────────────────────┘
```
---
## Domain Models
### `ShellDangerLevel`
**Module**: `cleveragents.tui.shell_safety.danger_level`
`IntEnum` classifying the severity of a dangerous shell command. Levels are
ordered so that numeric comparisons work naturally
(`level >= ShellDangerLevel.HIGH`).
| Value | Int | Description |
|-------|-----|-------------|
| `LOW` | 1 | Minor risk — generally recoverable side-effects (e.g. `chmod 777` on a single file) |
| `MEDIUM` | 2 | Moderate risk — can cause data loss or security exposure in common scenarios |
| `HIGH` | 3 | High risk — significant, hard-to-reverse damage (e.g. `dd if=`, `mkfs`) |
| `CRITICAL` | 4 | Critical risk — can destroy the entire system or create a fork bomb |
### `DangerousPattern`
**Module**: `cleveragents.tui.shell_safety.dangerous_pattern`
Immutable frozen dataclass describing a single dangerous shell pattern.
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | `str` | — | Short human-readable identifier (e.g. `"rm_rf_root"`) |
| `pattern` | `str` | — | Regular expression matching the dangerous command text |
| `level` | `ShellDangerLevel` | — | Danger severity classification |
| `description` | `str` | — | Human-readable explanation of the risk |
| `case_sensitive` | `bool` | `False` | When `True`, the regex is compiled without `re.IGNORECASE` |
**Methods:**
| Method | Returns | Description |
|--------|---------|-------------|
| `matches(command)` | `bool` | `True` if `command` matches this pattern |
### `DangerousCommandWarning`
**Module**: `cleveragents.tui.shell_safety.warning`
Immutable frozen dataclass produced by `DangerousPatternDetector` when a
dangerous command is detected.
| Field | Type | Description |
|-------|------|-------------|
| `command` | `str` | The original command string that triggered the warning |
| `matched_pattern` | `DangerousPattern` | The pattern that matched |
| `danger_level` | `ShellDangerLevel` | Convenience alias for `matched_pattern.level` |
| `message` | `str` | Human-readable warning message for display |
**Class methods:**
| Method | Returns | Description |
|--------|---------|-------------|
| `from_pattern(command, pattern)` | `DangerousCommandWarning` | Construct a warning from a command and the matching pattern |
---
## `DangerousPatternDetector`
**Module**: `cleveragents.tui.shell_safety.pattern_detector`
Domain service that checks shell commands against a configurable registry of
dangerous patterns. Ships with built-in `DEFAULT_PATTERNS` but supports full
customisation.
### Constructor
```python
DangerousPatternDetector(patterns: list[DangerousPattern] | None = None)
```
When `patterns` is `None`, the built-in `DEFAULT_PATTERNS` are used.
### Registry Management
| Method | Returns | Description |
|--------|---------|-------------|
| `add_pattern(pattern)` | `None` | Append a pattern to the registry (checked in insertion order) |
| `remove_pattern(name)` | `bool` | Remove the pattern with the given name; returns `True` if removed |
| `replace_patterns(patterns)` | `None` | Replace the entire registry with a new list |
| `patterns` *(property)* | `tuple[DangerousPattern, ...]` | Read-only view of the current registry |
### Detection
| Method | Returns | Description |
|--------|---------|-------------|
| `check(command)` | `list[DangerousCommandWarning]` | All warnings for `command` (may be empty); ordered by insertion order |
| `check_first(command)` | `DangerousCommandWarning \| None` | First (highest-priority) warning, or `None` |
| `is_dangerous(command)` | `bool` | `True` if `command` matches any registered pattern |
| `max_danger_level(command)` | `ShellDangerLevel \| None` | Highest danger level matched, or `None` |
---
## Default Pattern Registry
**Module**: `cleveragents.tui.shell_safety.pattern_registry`
The `DEFAULT_PATTERNS` tuple ships with the following built-in patterns:
### Critical
| Name | Pattern | Description |
|------|---------|-------------|
| `rm_rf_root` | `rm -rf /` | Recursively deletes the entire filesystem root |
| `rm_rf_wildcard` | `rm -rf /*` or `rm -rf *` | Deletes large portions of the filesystem |
| `fork_bomb` | `:(){ :|:& };:` | Exhausts the process table, requiring a hard reboot |
### High
| Name | Pattern | Description |
|------|---------|-------------|
| `dd_if_device` | `dd if=` | Can overwrite disk devices or fill storage |
| `mkfs` | `mkfs` | Formats a filesystem, permanently erasing all data |
| `shred_device` | `shred /dev/` or `shred --remove` | Overwrites data in an unrecoverable way |
### Medium
| Name | Pattern | Description |
|------|---------|-------------|
| `chmod_777` | `chmod 777` | Grants world-readable/writable/executable permissions |
| `sudo_rm` | `sudo rm` | Runs `rm` with elevated privileges |
| `wget_pipe_sh` | `wget … \| sh` | Executes arbitrary remote code without inspection |
| `curl_pipe_sh` | `curl … \| sh` | Executes arbitrary remote code without inspection |
| `wget_pipe_bash` | `wget … \| bash` | Executes arbitrary remote code without inspection |
| `curl_pipe_bash` | `curl … \| bash` | Executes arbitrary remote code without inspection |
### Low
| Name | Pattern | Description |
|------|---------|-------------|
| `git_push_force` | `git push --force` | Overwrites remote history, causing data loss for collaborators |
| `chmod_recursive_permissive` | `chmod -R 6xx/7xx` | Exposes sensitive files to unintended access |
---
## Usage Examples
### Basic detection
```python
from cleveragents.tui.shell_safety.pattern_detector import DangerousPatternDetector
detector = DangerousPatternDetector()
# Check a command
warnings = detector.check("rm -rf /")
if warnings:
print(warnings[0].message)
# [Critical] Dangerous command detected: rm -rf / recursively deletes ...
# Quick boolean check
if detector.is_dangerous("sudo rm -rf /var/log"):
print("Dangerous!")
# Highest danger level
level = detector.max_danger_level("wget http://example.com/script.sh | bash")
print(level) # ShellDangerLevel.MEDIUM
```
### Custom patterns
```python
from cleveragents.tui.shell_safety.danger_level import ShellDangerLevel
from cleveragents.tui.shell_safety.dangerous_pattern import DangerousPattern
from cleveragents.tui.shell_safety.pattern_detector import DangerousPatternDetector
detector = DangerousPatternDetector()
# Add a custom pattern
detector.add_pattern(
DangerousPattern(
name="drop_database",
pattern=r"\bDROP\s+DATABASE\b",
level=ShellDangerLevel.CRITICAL,
description="DROP DATABASE permanently deletes the entire database.",
case_sensitive=False,
)
)
# Remove a built-in pattern
detector.remove_pattern("git_push_force")
```
---
## Integration with Shell Mode
The `DangerousPatternDetector` is invoked by the TUI shell mode handler
(`cleveragents.tui.input.shell_exec`) before any subprocess is started.
If `check_first()` returns a warning, the TUI presents a confirmation
overlay before proceeding.
The shell mode is entered by typing `!` at the prompt. See
[Shell Mode](tui.md#shell-mode) in the TUI reference for the full
shell mode documentation.
---
## Related Documentation
- [TUI Reference](tui.md) — overall TUI architecture and shell mode
- [TUI Permissions Screen](tui_permissions.md) — full-screen permission overlay
- [TUI Permission Question Widget](tui_permission_question.md) — inline permission widget