### Install and Run ShellGuide Source: https://github.com/walrusquant/shellguide/blob/main/README.md Instructions for cloning the repository, setting up a virtual environment, installing dependencies, and running the ShellGuide application. ```bash git clone https://github.com/WalrusQuant/shellguide.git cd shellguide python -m venv .venv source .venv/bin/activate pip install -e . shellguide ``` -------------------------------- ### Development Environment Setup and Execution Source: https://github.com/walrusquant/shellguide/blob/main/CLAUDE.md Standard commands for initializing the virtual environment, installing the package in development mode, and launching the application in different operational modes. ```bash source .venv/bin/activate pip install -e . shellguide shellguide --teach python -m shellguide ``` -------------------------------- ### Install and Launch ShellGuide Source: https://github.com/walrusquant/shellguide/blob/main/landing/index.html Commands to clone, install, and run the ShellGuide Python package. It supports both a file browser mode and an interactive teaching mode. ```bash git clone https://github.com/WalrusQuant/shellguide.git cd shellguide python -m venv .venv && source .venv/bin/activate pip install -e . # Launch file browser shellguide # Start interactive lessons shellguide --teach ``` -------------------------------- ### Launch ShellGuide Teach Mode Source: https://github.com/walrusquant/shellguide/blob/main/README.md Command to launch ShellGuide in teach mode, which provides guided interactive lessons on shell commands within a sandboxed directory. ```bash shellguide --teach ``` -------------------------------- ### GET /reference/commands Source: https://context7.com/walrusquant/shellguide/llms.txt Retrieves documentation, flag definitions, and help text for supported shell commands. ```APIDOC ## GET /reference/commands ### Description Fetches detailed reference information for a specific shell command, including flag descriptions and usage help. ### Method GET ### Endpoint /reference/commands/{command_name} ### Parameters #### Path Parameters - **command_name** (string) - Required - The name of the command (e.g., 'rm', 'ls') ### Response #### Success Response (200) - **description** (string) - Command purpose - **flags** (object) - Map of flags to their descriptions - **help_text** (string) - Formatted help string #### Response Example { "description": "Remove (delete) files and directories", "flags": {"-r": "Recursive deletion"}, "help_text": "rm — Remove files and directories..." } ``` -------------------------------- ### Access Command Reference and Help in Python Source: https://context7.com/walrusquant/shellguide/llms.txt Shows how to access a dictionary of command references, retrieve formatted help text for specific commands, and get descriptions for command strings using Python. This is useful for understanding command functionalities and their flags. ```Python from shellguide.core.command_explainer import ( COMMAND_REFERENCE, get_command_help, explain_command ) # Access command reference dictionary ls_info = COMMAND_REFERENCE["ls"] print(ls_info["description"]) # "List directory contents..." print(ls_info["flags"]["-l"]) # "Long format — shows permissions, owner, size..." print(ls_info["flags"]["-a"]) # "All files — reveals hidden files..." # Get formatted help text for a command help_text = get_command_help("rm") print(help_text) # Output: # rm — Remove (delete) files and directories — permanently, with no Trash and no undo # Flags: # -r Recursive — required for directories... # -f Force — suppresses errors and confirmation prompts... # -i Interactive — ask before each deletion... # Get command description from a command string desc = explain_command("ls -la") print(desc) # "List directory contents — see what files and folders exist..." ``` -------------------------------- ### Perform Directory Listing and Search Source: https://context7.com/walrusquant/shellguide/llms.txt Provides examples for listing directory contents with optional hidden file inclusion and performing recursive file searches. ```python from pathlib import Path from shellguide.core.file_utils import list_directory, search_files, get_disk_usage # List directory contents path = Path.home() / "Projects" files = list_directory(path, show_hidden=False) # Recursive file search results = search_files(root=Path.home() / "Projects", query="test", show_hidden=False, max_results=100) # Get disk usage usage = get_disk_usage(Path.home() / "Documents") ``` -------------------------------- ### Initialize and Launch ShellGuide Application Source: https://context7.com/walrusquant/shellguide/llms.txt Demonstrates how to instantiate the ShellGuide application class and launch it in either the default file browser mode or the interactive teach mode. ```python from shellguide.app import ShellGuideApp, main # Launch in file browser mode (default) app = ShellGuideApp() app.run() # Launch directly into teach mode app = ShellGuideApp(teach_mode=True) app.run() ``` -------------------------------- ### Python: Create Custom Challenge Validators Source: https://context7.com/walrusquant/shellguide/llms.txt Demonstrates how to create custom validators for challenge verification using ShellGuide's core components. This includes exact command matching, accepting multiple equivalent commands, handling suboptimal solutions with warnings, validating based on filesystem effects, and explaining common mistakes. ```python from shellguide.core.challenges import ( Feedback, FeedbackKind, Validator, _exact_command, _any_of, _command_with_warnings, _check_effect, _starts_with_command, _common_mistakes ) from shellguide.core.sandbox import SandboxState # Exact command match validator = _exact_command( "pwd", explanation="pwd shows your current location" ) # Accept multiple equivalent commands validator = _any_of( ["ls", "ls .", "ls ./"], explanation="ls lists directory contents" ) # Accept with warnings for suboptimal solutions validator = _command_with_warnings( accepted=["rm -r folder"], warned={"rm -rf folder": "Works, but -f is unnecessary"}, explanation="rm -r removes directories recursively" ) # Validate by checking filesystem effect validator = _check_effect( checker=lambda before, after: "newfile.txt" in after.files, explanation="File was created successfully" ) # Explain common mistakes validator = _common_mistakes( accepted=["cp -r src backup"], mistakes={ "cp src backup": ( "Without -r, cp refuses to copy directories", "cp -r src backup" ), "mv src backup": ( "mv would move the directory, not copy it", "cp -r src backup" ) }, explanation="cp -r copies directories recursively" ) ``` -------------------------------- ### Launch ShellGuide File Browser Source: https://github.com/walrusquant/shellguide/blob/main/README.md Command to launch the ShellGuide application in its default file browser mode. This mode displays a three-panel file manager and shows equivalent shell commands for user actions. ```bash shellguide ``` -------------------------------- ### Build Shell Commands with Python Source: https://context7.com/walrusquant/shellguide/llms.txt Demonstrates how to use Python functions to construct shell commands for various operations like listing directories, changing directories, creating directories, deleting files, copying files, and finding files. It also shows how to access command explanations and danger levels. ```Python from pathlib import Path from shellguide.core.command_builder import build_ls, build_cd, build_mkdir, build_rm, build_trash, build_cp, build_find # List directory cmd = build_ls(Path.home() / "Documents", show_hidden=True) print(cmd.command) # "ls -la ~/Documents" print(cmd.explanation) # "List the contents of 'Documents' in long format including hidden files..." print(cmd.danger_level) # DangerLevel.SAFE print(cmd.gui_equivalent) # "Opening a Finder window to see folder contents" # Change directory cmd = build_cd(Path.home() / "Projects") print(cmd.command) # "cd ~/Projects" # Create directory cmd = build_mkdir(Path.home() / "new_project") print(cmd.command) # "mkdir ~/new_project" print(cmd.danger_level) # DangerLevel.CAUTION # Delete commands (with danger levels) cmd = build_rm(Path.home() / "temp.txt", is_dir=False) print(cmd.command) # "rm ~/temp.txt" print(cmd.danger_level) # DangerLevel.DESTRUCTIVE cmd = build_rm(Path.home() / "temp_folder", is_dir=True) print(cmd.command) # "rm -rf ~/temp_folder" # Safe delete to trash cmd = build_trash(Path.home() / "file.txt") print(cmd.command) # "mv ~/file.txt ~/.Trash/" print(cmd.danger_level) # DangerLevel.CAUTION # Copy (with recursive flag for directories) cmd = build_cp(Path("src"), Path("backup"), is_dir=True) print(cmd.command) # "cp -r src backup" # Find files cmd = build_find(Path.home() / "Projects", "*.py") print(cmd.command) # "find ~/Projects -name '**.py*'" ``` -------------------------------- ### Sandbox Command Execution in Python Source: https://context7.com/walrusquant/shellguide/llms.txt Demonstrates how to run commands within a sandbox environment using Python. It shows how to check command success, capture errors, and handle blocked paths, commands, and operators. It also illustrates how to allow specific shell operators for chained commands. ```python result, _ = run_in_sandbox("cat /etc/passwd", cwd) print(result.success) # False print(result.error) # "Path '/etc/passwd' resolves outside the sandbox." result, _ = run_in_sandbox("curl example.com", cwd) print(result.success) # False print(result.error) # "'curl' is not available in the sandbox..." result, _ = run_in_sandbox("ls && pwd", cwd) print(result.success) # False print(result.error) # "Shell operator '&&' is not allowed..." result, new_cwd = run_in_sandbox( "mkdir test && cd test && touch main.py", cwd, allowed_operators=frozenset({"&&"}) ) print(result.success) # True (all three commands executed) result, _ = run_in_sandbox("help ls", cwd) print(result.stdout) # Detailed help for ls command ``` -------------------------------- ### Execute Safe File Operations Source: https://context7.com/walrusquant/shellguide/llms.txt Demonstrates how to perform common file system operations while retrieving the equivalent shell command and explanation for educational purposes. ```python from pathlib import Path from shellguide.core.file_ops import create_file, create_directory, rename, delete_to_trash, copy_file # Create a new empty file result = create_file(Path.home() / "new_file.txt") if result.success: print(result.shell_command.command) # Rename a file result = rename(src=Path.home() / "old_name.txt", dst=Path.home() / "new_name.txt") # Delete to trash result = delete_to_trash(Path.home() / "unwanted.txt") ``` -------------------------------- ### Execute Commands Safely within Sandbox using Python Source: https://context7.com/walrusquant/shellguide/llms.txt Demonstrates how to execute shell commands securely within a sandbox environment using Python's `run_in_sandbox` function. It shows how to check command success, capture stdout, and manage the current working directory after execution. ```Python from pathlib import Path from shellguide.core.executor import ( run_in_sandbox, ALLOWED_COMMANDS, ExecResult ) from shellguide.core.sandbox import SANDBOX_ROOT, reset_sandbox # Allowed commands in sandbox print(ALLOWED_COMMANDS) # {'ls', 'cd', 'pwd', 'mkdir', 'touch', 'rm', 'mv', 'cp', 'cat', # 'head', 'tail', 'find', 'stat', 'du', 'echo', 'wc', 'sort', # 'chmod', 'rmdir', 'help'} # Set up sandbox and execute commands reset_sandbox({"file.txt": "Hello world\n", "src": None}) cwd = SANDBOX_ROOT # Execute a command result, new_cwd = run_in_sandbox("ls -l", cwd) print(result.success) # True print(result.stdout) # "total 4\n-rw-r--r-- 1 user group 12 Jan 15 file.txt..." print(result.return_code) # 0 # cd updates the working directory result, new_cwd = run_in_sandbox("cd src", cwd) print(result.success) # True print(new_cwd) # Path("~/shellguide_sandbox/src") ``` -------------------------------- ### Challenge and Lesson System in Python Source: https://context7.com/walrusquant/shellguide/llms.txt Details the structure and usage of the Challenge and Lesson system for interactive learning. It shows how to access lessons and challenges, retrieve their properties, and validate user commands against expected outcomes, providing feedback. ```python from shellguide.core.challenges import ( Challenge, Lesson, Feedback, FeedbackKind, ALL_LESSONS, get_lesson, total_lessons ) from shellguide.core.sandbox import snapshot_sandbox, reset_sandbox print(total_lessons()) # 10 lesson = get_lesson(0) # First lesson: "Looking Around" print(lesson.id) # "looking-around" print(lesson.title) # "Looking Around" print(lesson.description) # "You just cloned a project from GitHub..." print(lesson.requires_lesson) # None (first lesson) challenge = lesson.challenges[0] print(challenge.id) # "l1-c1" print(challenge.prompt) # "See what files came with this project." print(challenge.hint) # "The command is 'ls'." print(challenge.teaching) # "When you first open a project..." print(challenge.gui_equivalent) # "Opening a Finder window..." print(challenge.mastered_command) # "ls" print(challenge.mastered_description) # "List files in current directory" print(challenge.difficulty) # 1 print(challenge.allowed_operators) # frozenset() reset_sandbox(challenge.sandbox_layout) before = snapshot_sandbox() after = snapshot_sandbox() feedback: Feedback = challenge.validate("ls", before, after) print(feedback.kind) # FeedbackKind.CORRECT print(feedback.message) # "Correct!" print(feedback.explanation) # "ls shows what's in the current directory..." feedback = challenge.validate("pwd", before, after) print(feedback.kind) # FeedbackKind.INCORRECT print(feedback.message) # "Not quite. Try again!" for i, lesson in enumerate(ALL_LESSONS): print(f"{i+1}. {lesson.title}") ``` -------------------------------- ### Implement Progressive Difficulty (Python) Source: https://github.com/walrusquant/shellguide/blob/main/ROADMAP.md Introduces progressive difficulty levels (1-3) and lesson prerequisites to the challenge system. This involves modifying the Challenge and Lesson data models, enhancing the command executor to handle chained commands, and implementing lesson gating in the UI. ```python from dataclasses import dataclass, field from typing import FrozenSet, Optional @dataclass class Challenge: difficulty: int = 1 # 1–3 allowed_operators: FrozenSet[str] = field(default_factory=frozenset) # e.g., frozenset({"&&"}) @dataclass class Lesson: requires_lesson: Optional[str] | None = None # id of prerequisite lesson ``` ```python from shellguide.core.command_builder import ShellCommand class Executor: def _check_blocked_operators(self, command_parts: list[str], allowed: frozenset[str]): # ... existing logic ... pass def _run_chained(self, commands: list[str], allowed_operators: frozenset[str]) -> bool: # Returns success status for cmd_str in commands: # Execute cmd_str, potentially using a modified run_in_sandbox # Stop on first failure success = self.run_in_sandbox(cmd_str, allowed_operators=allowed_operators) if not success: return False return True def run_in_sandbox(self, command_string: str, allowed_operators: frozenset[str]) -> bool: # Check for '&&' and if it's allowed and present if "&&" in command_string and "&&" in allowed_operators: parts = command_string.split("&&") return self._run_chained(parts, allowed_operators) else: # ... existing single command execution ... return True # Placeholder ``` ```python # In TeachScreen class (conceptual) class TeachScreen: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._completed_lessons: set[str] = set() def start_lesson(self, lesson_id): lesson = self.get_lesson(lesson_id) # Assume method to get lesson data if lesson.requires_lesson and lesson.requires_lesson not in self._completed_lessons: print(f"Please complete lesson {lesson.requires_lesson} first.") return # ... proceed to start lesson ... def on_lesson_complete(self, lesson_id): self._completed_lessons.add(lesson_id) # ... other completion logic ... def on_feedback(self, feedback_type, challenge): # ... existing logic ... if feedback_type in ("CORRECT", "ACCEPTABLE"): # Pass allowed_operators to the executor self.executor.run_in_sandbox(challenge.command, challenge.allowed_operators) # ... other logic ... ``` -------------------------------- ### Implement Dynamic Cheat Sheet (Python) Source: https://github.com/walrusquant/shellguide/blob/main/ROADMAP.md Introduces a CheatSheet data model and widget to dynamically build a cheat sheet of mastered commands as the user progresses. This involves changes to the Challenge data model and the TeachScreen. ```python from dataclasses import dataclass, field from typing import Dict, List @dataclass class CheatSheetEntry: command: str description: str lesson_id: str category: str class CheatSheet: def __init__(self): self._entries: Dict[str, CheatSheetEntry] = {} def add(self, entry: CheatSheetEntry): self._entries[entry.command] = entry def entries(self) -> List[CheatSheetEntry]: return list(self._entries.values()) def count(self) -> int: return len(self._entries) ``` ```python @dataclass class Challenge: # ... existing fields ... mastered_command: str = "" # e.g., "ls -l" mastered_description: str = "" # e.g., "List files with details" ``` ```python # In TeachScreen class (conceptual) class TeachScreen: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cheat_sheet = CheatSheet() self.cheat_sheet_panel = CheatSheetPanel() # Assume CheatSheetPanel widget exists self.query_one(App).bind_keys({"tab": self.toggle_cheat_sheet}) def toggle_cheat_sheet(self, event): self.cheat_sheet_panel.display = not self.cheat_sheet_panel.display # Toggle visibility def on_feedback(self, feedback_type, challenge): if feedback_type in ("CORRECT", "ACCEPTABLE"): if challenge.mastered_command: entry = CheatSheetEntry( command=challenge.mastered_command, description=challenge.mastered_description, lesson_id=challenge.lesson_id, # Assuming lesson_id exists category="General" # Or derive category ) self.cheat_sheet.add(entry) self.cheat_sheet_panel.update(self.cheat_sheet.entries_by_category()) # Assume update method ``` -------------------------------- ### Cheat Sheet System in Python Source: https://context7.com/walrusquant/shellguide/llms.txt Illustrates the creation and management of a cheat sheet to track mastered commands. It shows how to add entries with command details, descriptions, lesson IDs, and categories, and how to access and group these entries. ```python from shellguide.core.cheat_sheet import CheatSheet, CheatSheetEntry sheet = CheatSheet() sheet.add(CheatSheetEntry( command="ls", description="List files in current directory", lesson_id="looking-around", category="Looking Around" )) sheet.add(CheatSheetEntry( command="ls -l", description="List files with details", lesson_id="looking-around", category="Looking Around" )) sheet.add(CheatSheetEntry( command="cd ", description="Change into a directory", lesson_id="navigation", category="Navigation" )) print(sheet.count) # 3 for entry in sheet.entries: print(f"{entry.command}: {entry.description}") by_category = sheet.entries_by_category() for category, entries in by_category.items(): print(f"\n{category}:") for entry in entries: print(f" {entry.command}") ``` -------------------------------- ### Manage Sandboxes with Python Source: https://context7.com/walrusquant/shellguide/llms.txt Provides Python functions for creating, resetting, snapshotting, and destroying isolated sandbox directories. These sandboxes are used for teach mode lessons and ensure a controlled environment for executing commands. ```Python from pathlib import Path from shellguide.core.sandbox import ( SANDBOX_ROOT, ensure_sandbox, reset_sandbox, snapshot_sandbox, is_inside_sandbox, destroy_sandbox, SandboxState ) # SANDBOX_ROOT is ~/shellguide_sandbox/ # Ensure sandbox exists sandbox_path = ensure_sandbox() print(sandbox_path) # Path("~/shellguide_sandbox") # Reset sandbox with a specific layout # Keys are relative paths; None = directory, string = file content layout = { "README.md": "# My Project\nA sample project.\n", "src": None, # directory "src/main.py": "print('hello')\n", "tests": None, "tests/test_main.py": "def test_example(): pass\n", } reset_sandbox(layout) # Take a snapshot of current sandbox state state: SandboxState = snapshot_sandbox() print(state.root) # Path("~/shellguide_sandbox") print(state.files) # frozenset({'README.md', 'src/main.py', 'tests/test_main.py'}) print(state.dirs) # frozenset({'src', 'tests'}) # Check if a path is inside the sandbox print(is_inside_sandbox(SANDBOX_ROOT / "src")) # True print(is_inside_sandbox(Path.home() / "Documents")) # False print(is_inside_sandbox(SANDBOX_ROOT / ".." / "other")) # False (resolves outside) # Clean up sandbox when done destroy_sandbox() ``` -------------------------------- ### Initialize Widget State on Mount Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Ensures that mutable lists in widgets are initialized per instance during the component mount lifecycle. ```python def on_mount(self) -> None: self._files = [] ``` -------------------------------- ### Retrieve File Metadata with FileInfo Source: https://context7.com/walrusquant/shellguide/llms.txt Shows how to use the FileInfo dataclass to extract and format metadata from a file path, including human-readable sizes and modification times. ```python from pathlib import Path from shellguide.core.file_utils import FileInfo # Create a FileInfo object from a path info = FileInfo(Path.home() / "Documents" / "example.py") # Access metadata print(info.name) print(info.is_dir) print(info.size) print(info.human_size) print(info.human_modified) ``` -------------------------------- ### Implement Frontend UI Animations Source: https://github.com/walrusquant/shellguide/blob/main/landing/index.html JavaScript code for handling scroll-triggered reveal animations, navigation bar styling on scroll, and terminal typing effects on the landing page. ```javascript const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } }); }, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' }); document.querySelectorAll('.reveal').forEach(el => observer.observe(el)); const nav = document.getElementById('nav'); window.addEventListener('scroll', () => { nav.classList.toggle('scrolled', window.scrollY > 50); }, { passive: true }); function animateTerminal() { const lines = document.querySelectorAll('#hero-terminal .terminal-line'); lines.forEach(line => { const delay = parseInt(line.dataset.delay, 10) || 0; setTimeout(() => { line.classList.add('shown'); }, delay); }); } ``` -------------------------------- ### Map Root Directory to Sandbox Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Corrects the executor to treat the root directory as the sandbox root, ensuring consistency between challenge validation and command execution. ```python if target in ("~", "/"): return ExecResult(success=True), SANDBOX_ROOT ``` -------------------------------- ### POST /sandbox/execute Source: https://context7.com/walrusquant/shellguide/llms.txt Executes shell commands within an isolated sandbox environment with validation and security constraints. ```APIDOC ## POST /sandbox/execute ### Description Runs a shell command inside the pre-configured sandbox directory. Commands are validated against an allow-list. ### Method POST ### Endpoint /sandbox/execute ### Parameters #### Request Body - **command** (string) - Required - The command to execute - **cwd** (string) - Optional - Current working directory within the sandbox ### Request Example { "command": "ls -l", "cwd": "~/shellguide_sandbox" } ### Response #### Success Response (200) - **success** (boolean) - Execution status - **stdout** (string) - Standard output of the command - **return_code** (integer) - Process exit code #### Response Example { "success": true, "stdout": "total 4\n-rw-r--r-- 1 user group 12 Jan 15 file.txt", "return_code": 0 } ``` -------------------------------- ### Initialize Instance-Specific Attributes Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Moves mutable class-level attributes into the __init__ method to ensure each class instance maintains its own independent state. ```python def __init__(self, **kwargs): super().__init__(**kwargs) self.current_path = Path.home() self.learn_mode = True self._clipboard = None self._clipboard_cut = False ``` -------------------------------- ### POST /commands/generate Source: https://context7.com/walrusquant/shellguide/llms.txt Generates shell command strings based on high-level Python functions, including danger level assessment and GUI equivalents. ```APIDOC ## POST /commands/generate ### Description Generates a shell command string based on the requested operation (ls, cd, mkdir, rm, cp, etc.). ### Method POST ### Endpoint /commands/generate ### Parameters #### Request Body - **operation** (string) - Required - The type of command (e.g., 'ls', 'mkdir', 'rm') - **path** (string) - Required - Target file or directory path - **options** (object) - Optional - Command-specific flags (e.g., is_dir, show_hidden) ### Request Example { "operation": "ls", "path": "~/Documents", "options": {"show_hidden": true} } ### Response #### Success Response (200) - **command** (string) - The generated shell command - **danger_level** (string) - Safety classification (SAFE, CAUTION, DESTRUCTIVE) - **explanation** (string) - Human-readable explanation of the command #### Response Example { "command": "ls -la ~/Documents", "danger_level": "SAFE", "explanation": "List the contents of 'Documents' in long format including hidden files." } ``` -------------------------------- ### File Browser Keyboard Shortcuts Source: https://context7.com/walrusquant/shellguide/llms.txt Lists the keyboard shortcuts available in the file browser mode of the application. These shortcuts enable navigation, file operations, and mode switching. ```python # Key bindings available in MainScreen file browser: BINDINGS = { "Arrow Keys": "Navigate file list", "Enter": "Open directory / select file", "Backspace": "Go to parent directory", "g": "Go to home directory", "n": "New file", "N": "New folder (Shift+N)", "r": "Rename selected item", "d": "Delete (moves to Trash)", "c": "Copy to clipboard", "m": "Cut (move) to clipboard", "p": "Paste from clipboard", "o": "Open with default macOS app", "u": "Show disk usage", "/": "Search files", "l": "Toggle learn mode on/off", "h": "Toggle hidden files", "t": "Switch to teach mode", "F1": "Help screen", "q": "Quit application", } ``` -------------------------------- ### Add GUI Equivalents to Shell Commands (Python) Source: https://github.com/walrusquant/shellguide/blob/main/ROADMAP.md Enhances the ShellCommand data model to include a 'gui_equivalent' field, mapping shell commands to their graphical user interface counterparts. This change affects command building, logging, and challenge definitions. ```python from dataclasses import dataclass @dataclass class ShellCommand: command: str args: list[str] gui_equivalent: str = "" # New field for GUI mapping ``` ```python # Example of updating a build function (conceptual) def build_ls(self) -> ShellCommand: return ShellCommand(command="ls", args=[], gui_equivalent="Opening a Finder window to see folder contents") ``` ```python # Example of updating CommandLog (conceptual) class CommandLog: def log_command(self, cmd: ShellCommand): # ... existing logging ... if cmd.gui_equivalent: print(f" (GUI: {cmd.gui_equivalent})") # Display GUI equivalent ``` ```python @dataclass class Challenge: # ... existing fields ... gui_equivalent: str = "" # New field for Challenge ``` -------------------------------- ### Validate Sandbox Path Arguments Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Ensures that flag-based arguments containing paths are correctly parsed and validated against the sandbox root to prevent directory traversal attacks. ```python if arg.startswith("-"): if "=" in arg: flag, _, val = arg.partition("=") resolved = _resolve_path_arg(val, sandbox_cwd) if not is_inside_sandbox(resolved): return (ExecResult(success=False, error=f"Path in '{arg}' resolves outside the sandbox."), sandbox_cwd) validated_tokens.append(f"{flag}={resolved}") else: validated_tokens.append(arg) continue ``` -------------------------------- ### Refactor Recursive _next_lesson to Iterative Loop Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md The _next_lesson method in teach_screen.py is prone to stack overflow errors when processing consecutive lessons with unmet prerequisites. Converting the recursion to a while loop prevents stack exhaustion. ```python def _next_lesson(self): while self.has_unmet_prerequisites(): self.skip_lesson() return self.get_next_valid_lesson() ``` -------------------------------- ### Secure Sandbox Directory Deletion Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Prevents symlink attacks during sandbox reset by verifying that the target directory is not a symlink and contains a valid marker file before deletion. ```python if SANDBOX_ROOT.is_symlink(): raise RuntimeError("Sandbox root is a symlink -- refusing to delete") marker = SANDBOX_ROOT / _MARKER if not marker.exists(): raise RuntimeError("Sandbox marker missing -- refusing to delete unknown directory") ``` -------------------------------- ### Implement Exception Handling for relative_to Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md The relative_to method raises a ValueError when paths fall outside the sandbox root. Adding a try-except block ensures the application remains stable when encountering invalid path operations. ```python try: path = current_path.relative_to(SANDBOX_ROOT) except ValueError: handle_invalid_path_error() ``` -------------------------------- ### Prevent Zombie Processes Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Replaces unmanaged Popen objects with subprocess.run to ensure processes are properly cleaned up and do not leak. ```python subprocess.run(["open", str(path)], check=False, timeout=10) ``` -------------------------------- ### Fix Challenge Validator Logic in challenges.py Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md The current challenge validator uses a lambda that always returns True, allowing any input to pass. The fix involves implementing specific command prefix validation to ensure user input matches expected command patterns. ```python # Current buggy implementation validator = lambda b, a: True # Proposed fix: validate command prefix def validate_command(command, expected_prefix): return command.startswith(expected_prefix) ``` -------------------------------- ### Smooth Anchor Scrolling Source: https://github.com/walrusquant/shellguide/blob/main/landing/index.html JavaScript utility to enable smooth scrolling to page anchors with a specific offset to account for fixed navigation bars. ```javascript document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { const offset = 80; const position = target.getBoundingClientRect().top + window.pageYOffset - offset; window.scrollTo({ top: position, behavior: 'smooth' }); } }); }); ``` -------------------------------- ### Extend Feedback Dataclass for Mistake Handling Source: https://github.com/walrusquant/shellguide/blob/main/ROADMAP.md Updates the Feedback dataclass in Python to include fields for attempted effects and suggestions, allowing the system to provide more descriptive error messages to users. ```python @dataclass(frozen=True) class Feedback: kind: FeedbackKind message: str explanation: str = "" attempted_effect: str = "" # NEW: what the user's command would have done suggestion: str = "" # NEW: what they should try instead ``` -------------------------------- ### Validate User-Provided Filenames Source: https://github.com/walrusquant/shellguide/blob/main/CODE_REVIEW_FIXES.md Sanitizes input filenames to prevent directory traversal or invalid characters from being used in file operations. ```python if not name or '/' in name or name in ('.', '..') or '\x00' in name: self.notify("Invalid filename", severity="error") return ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.