Skip to main content

safe-whale

Run Python command-line tools in hardened container images, with a small Tkinter UI for discovery, profiles, launch wrappers, history, and cleanup.

safe-whale is meant to feel like pipx where that vocabulary fits, but the isolation boundary is a container image rather than a virtual environment. Pick a PyPI CLI tool, inspect what kind of tool it is, build it once, then run it safely or install a wrapper command.

Status

  • Catalog search with usage patterns for one-shot CLIs, wrapper-first tools, pipe filters, and TUI apps.
  • A pipx-shaped CLI for run, install, list, rebuild, uninstall, cleanup, diagnostics, and wrapper PATH guidance.
  • PyPI metadata enrichment and local metadata caching.
  • Saved profiles with stale-wrapper detection.
  • pipx-style entry-point discovery: every console_scripts / gui_scripts command a package exposes gets its own wrapper (probed from inside the built image with importlib.metadata).
  • .cmd + .ps1 (Windows) or executable shell wrapper generation, one per discovered command.
  • Interactive install setup (when run in a terminal): prompts for the tool's usage pattern and makes the read-only vs. writable filesystem trade-off explicit. Use --yes / --no-input to accept defaults non-interactively.
  • Managed cleanup for safe-whale-tracked images, Dockerfiles, and wrappers.
  • Docker-first execution. Podman/nerdctl/finch are detected, but Docker is the most exercised path.
  • Browser-hosted PyScript and direct Pyodide experiments. The Browser Python tab auto-loads a pure-Python package demo so package installation is visible on first run.

Quick Start

Install dependencies and launch the app:

uv sync
uv run safe-whale

The CLI can also be used directly. It intentionally mirrors the pipx command vocabulary where that maps to container-backed tools:

uv run safe-whale run --dry-run ruff -- --version
uv run safe-whale install ruff --wrapper-dir .\.tmp\bin --skip-build
uv run safe-whale list
uv run safe-whale uninstall ruff --dry-run

When installed from PyPI, use the console script directly:

safe-whale --help
safe-whale run ruff -- --version
safe-whale install ruff

install builds the image, then discovers every command the package ships and installs a wrapper for each — e.g. safe-whale install httpie produces both http and https. In a terminal it first asks for the tool's usage pattern and whether to run with a read-only root filesystem; pass --yes (or --no-input) to skip the prompts and accept defaults plus any flags you supplied.

Global options work before or after subcommands:

  • --dry-run shows Dockerfiles, build commands, run commands, profile changes, and cleanup actions without performing them.
  • --log-level DEBUG|INFO|WARNING|ERROR|CRITICAL controls logging.
  • -v / --verbose is a shorthand for more detailed logging.
  • --engine docker|podman|nerdctl|finch selects the container engine.
  • --no-history skips run history.

safe-whale-specific runtime options include --entrypoint, --apt, --interaction, --stdin-file, --mount, --memory, --cpus, --network / --block-network, --read-only / --writable, --non-root / --root, --cap-drop-all / --keep-caps, --tmpfs-tmp / --no-tmpfs-tmp, and --limit-pids / --no-limit-pids.

Other useful commands:

uv run safe-whale environment
uv run safe-whale ensurepath
uv run safe-whale cleanup
uv run safe-whale list --catalog --query ruff
uv run safe-whale install-all pipx-list.json

Useful development checks:

uv run pytest -q
uv run ruff check safe_whale tests
uv run mypy --hide-error-context safe_whale tests

In the Codex desktop sandbox on Windows, use the workspace-local cache/temp recipe in spec/codex.md.

Host Runtime Preliminaries

You need at least one runtime. Docker is the recommended default today.

Host Docker Podman Browser Python
Windows Install Docker Desktop, enable WSL 2, verify with docker info. Install Podman Desktop/Podman CLI, then podman machine init and podman machine start. Avoid making Podman mimic Docker while Docker Desktop is also active unless you know which socket your tools use. PyScript/Pyodide run in the browser and do not need Node.js.
macOS Install Docker Desktop and verify docker info. Install Podman, then podman machine init and podman machine start. PyScript/Pyodide run in the browser.
Linux Install Docker Engine from Docker’s distro docs, or Docker Desktop if you prefer. Verify docker info. Install podman from your distro packages and verify podman info. PyScript/Pyodide run in the browser.

Long version: docs/hosts.md.

Usage Patterns

Catalog entries carry a usage pattern so the UI can suggest the right action:

  • single_run_cli: works well in the in-app output panel.
  • wrapper_cli: best installed as a shell/editor wrapper.
  • pipe_filter: best as a wrapper, with optional file-based sample runs.
  • tui_terminal: needs a real terminal; curses/full-screen apps cannot render correctly in the output panel.
  • Browser Pyodide/PyScript experiments: run in a generated browser app, not in the Tkinter output panel and not in Docker. They are useful for browser-compatible Python, not arbitrary PyPI CLI tools.

pipx Compatibility

safe-whale borrows pipx command names for familiar workflows, but it does not create per-tool virtual environments. The main difference is:

pipx safe-whale
Installs apps into managed virtual environments. Builds apps into managed container images.
Wrappers call venv entry points. Wrappers run hardened containers.
Uses pip inside managed venvs. Uses pip during image build, then runs the image.

Implemented container-backed commands include run, install, install-all, list, profiles, uninstall, uninstall-all, reinstall, reinstall-all, upgrade, upgrade-all, cleanup, environment, ensurepath, completions, and help.

The commands inject, uninject, pin, unpin, runpip, interpreter, and upgrade-shared are recognized for compatibility, but currently return an explicit unsupported-operation message because they do not map cleanly to the container model yet.

Long version: docs/usage/pipx-compatibility.md.

Safety Model

safe-whale builds a Dockerfile first, then applies runtime hardening when running the already-built image:

  • read-only root filesystem
  • non-root UID
  • no-new-privileges
  • capability drop
  • PID, CPU, and memory limits
  • optional network blocking
  • optional bind mount and stdin file for tools that need local input

Cleanup only targets assets safe-whale created or explicitly tracked.

Project Docs

Published documentation is configured through mkdocs.yml and .readthedocs.yaml.

Metadata

Release files for safe-whale 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for safe-whale 0.1.0
File Size Uploaded
safe_whale-0.1.0.tar.gz 64.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for safe-whale 0.1.0
File Interpreter ABI Platform
safe_whale-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 124.5 kB

Release files / safe_whale-0.1.0.tar.gz

Download URL safe_whale-0.1.0.tar.gz
Size 64.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d59dbf9fbcdfbb12a95707e89f14c28dff8110e689f7387fd57bd7955bcfe4eb
BLAKE2b-256 checksum
How to use checksums
a3581258df650f419cda9d3148480752762ba9ce7d5c2901f851a7b9911c23ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 31, 2026.

Transparency log

Release files / safe_whale-0.1.0-py3-none-any.whl

Download URL safe_whale-0.1.0-py3-none-any.whl
Size 60.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
57cf623f8190a6edf9f7c46c89323939e4bda29e780356c29ac381c8e0c881c6
BLAKE2b-256 checksum
How to use checksums
da0ed2ba3a09215b0a1fd34f5c08085a15af588b6122494dc9da4e96d58221d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 31, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page