diff --git a/README.md b/README.md index 68a2bef..9656460 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,20 @@ CLI Tools / scripts that augment us when working on Void Projects >[!warning] Use at your own risk. This is firmly space trash. -Everything in this repo is completely vibe coded and likely never looked at. We use the tooling in here to augment our work and choose willingly to ignore the quality for the sake of quick tooling. \ No newline at end of file +Everything in this repo is completely vibe coded and likely never looked at. We use the tooling in here to augment our work and choose willingly to ignore the quality for the sake of quick tooling. + +## Installation + +Requires [uv](https://docs.astral.sh/uv/). + +```powershell +uv tool install -e . +``` + +## Usage + +``` +stcli [OPTIONS] COMMAND [ARGS]... +``` + +Blank `stcli` command prints help. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8910b66 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,19 @@ +[project] +name = "spacetrash" +version = "0.1.0" +description = "spacetrash CLI" +requires-python = ">=3.11" +dependencies = [ + "typer>=0.12", + "rich>=13", +] + +[project.scripts] +stcli = "stcli.main:app" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/stcli"] diff --git a/src/stcli/__init__.py b/src/stcli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/stcli/commands/__init__.py b/src/stcli/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/stcli/commands/wsl.py b/src/stcli/commands/wsl.py new file mode 100644 index 0000000..d7a597b --- /dev/null +++ b/src/stcli/commands/wsl.py @@ -0,0 +1,68 @@ +import ctypes +import subprocess +import sys + +import typer +from rich.console import Console + +app = typer.Typer( + no_args_is_help=True, + help="Commands for managing the WSL environment.", +) +console = Console() + + +def _is_admin() -> bool: + try: + return bool(ctypes.windll.shell32.IsUserAnAdmin()) + except Exception: + return False + + +def _relaunch_elevated() -> int: + # Spawns an elevated hidden PowerShell that runs the restart command, + # waits for it, and surfaces the exit code back to the caller. + ps_command = ( + "$p = Start-Process powershell " + "-Verb RunAs " + "-ArgumentList '-NoProfile -NonInteractive -Command " + "\"try { Get-Service vmcompute -ErrorAction Stop | Restart-Service -ErrorAction Stop } " + "catch { exit 1 }\"' " + "-Wait -PassThru -WindowStyle Hidden; " + "exit $p.ExitCode" + ) + result = subprocess.run( + ["powershell", "-NonInteractive", "-Command", ps_command], + text=True, + ) + return result.returncode + + +@app.command("fix") +def wsl_fix(): + """Restart the WSL vmcompute service (Windows only).""" + if sys.platform != "win32": + console.print("[yellow]wsl fix must be run from Windows, not from inside WSL.[/yellow]") + raise typer.Exit(1) + + console.print("[cyan]Restarting vmcompute service...[/cyan]") + + if _is_admin(): + result = subprocess.run( + ["powershell", "-NonInteractive", "-Command", "try { Get-Service vmcompute -ErrorAction Stop | Restart-Service -ErrorAction Stop } catch { exit 1 }"], + capture_output=True, + text=True, + ) + returncode = result.returncode + stderr = result.stderr.strip() + else: + console.print("[dim]Elevation required — UAC prompt will appear.[/dim]") + returncode = _relaunch_elevated() + stderr = "" + + if returncode == 0: + console.print("[green]vmcompute restarted successfully.[/green]") + else: + msg = f": {stderr}" if stderr else "" + console.print(f"[red]Failed to restart vmcompute{msg}[/red]") + raise typer.Exit(returncode) diff --git a/src/stcli/main.py b/src/stcli/main.py new file mode 100644 index 0000000..12832f6 --- /dev/null +++ b/src/stcli/main.py @@ -0,0 +1,9 @@ +import typer +from stcli.commands import wsl + +app = typer.Typer(name="stcli", no_args_is_help=True) +app.add_typer(wsl.app, name="wsl") + + +if __name__ == "__main__": + app()