{"id":24580,"library":"shfmt-py","title":"shfmt-py","description":"A Python wrapper around shfmt, the shell script formatter. Downloads and manages the shfmt binary automatically. Current version 3.12.0.2, wraps mvdan/sh v3.12.0. Supports Python >=3.9. Releases follow upstream shfmt versions with a patch suffix.","status":"active","version":"3.12.0.2","language":"python","source_language":"en","source_url":"https://github.com/maxwinterstein/shfmt-py","tags":["shell","formatter","shfmt","wrapper","linting","bash"],"install":[{"cmd":"pip install shfmt-py","lang":"bash","label":"Install from PyPI"}],"dependencies":[],"imports":[{"note":"Wrong package base; the distribution name uses hyphen but import uses underscore.","wrong":"from shfmt import shfmt","symbol":"shfmt","correct":"from shfmt_py import shfmt"},{"note":"ShfmtError is exported at package level, not in a submodule.","wrong":"from shfmt_py.shfmt import ShfmtError","symbol":"ShfmtError","correct":"from shfmt_py import ShfmtError"}],"quickstart":{"code":"from shfmt_py import shfmt\n\n# Format a string\ncode = 'if [ $foo = bar ]; then echo hello ; fi'\nformatted = shfmt(code, lang='bash', space_redirects=True)\nprint(formatted)\n\n# Format a file\nshfmt(code, write=True, filename='script.sh')\n\n# Check for formatting differences (intended for CI)\nimport sys\nfrom shfmt_py import ShfmtError\ntry:\n    shfmt(code, filename='script.sh')  # raises ShfmtError if not formatted\nexcept ShfmtError as e:\n    print(e.diff())\n    sys.exit(1)","lang":"python","description":"Basic usage: call shfmt() with code string and optional arguments. Use write=True to overwrite file. Use filename= to pass filename for error detection context."},"warnings":[{"fix":"Set environment variable SHPATH to a pre-downloaded binary path, or use the binary caching mechanism (see docs).","message":"The shfmt binary is downloaded automatically on first use, which may fail in air-gapped environments. Cache the binary manually.","severity":"gotcha","affected_versions":"all"},{"fix":"Always provide a filename (e.g., 'script.sh') when calling shfmt() to ensure correct language detection.","message":"Passing a string to the 'lang' parameter without specifying 'filename' may produce incorrect formatting. In future versions, 'filename' will be required for proper language detection.","severity":"deprecated","affected_versions":"<4.0.0"},{"fix":"Check upstream shfmt release notes for breaking changes. The fourth number is the wrapper patch.","message":"The package version includes the upstream shfmt version plus a patch number (e.g., 3.12.0.2). This can cause confusion when comparing versions. Breaking changes in shfmt reflect in the first three numbers.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-01T00:00:00.000Z","next_check":"2026-07-30T00:00:00.000Z","problems":[{"fix":"Use 'from shfmt_py import shfmt' or 'import shfmt_py'.","cause":"Importing the package using the PyPI name (shfmt) instead of the Python module name (shfmt_py).","error":"ModuleNotFoundError: No module named 'shfmt'"},{"fix":"Delete the cached binary and let shfmt-py re-download. Alternatively, set SHPATH to a valid binary for the current platform.","cause":"The downloaded shfmt binary is not compatible with the OS/architecture. The wrapper downloads a binary for the current platform, but if you manually set SHPATH to a binary for a different platform, this error occurs.","error":"OSError: [Errno 8] Exec format error: '/path/to/shfmt'"},{"fix":"Fix the shell syntax errors indicated in the error output.","cause":"The provided shell code contains syntax errors that shfmt cannot parse. The error message from shfmt is included.","error":"shfmt_py.exceptions.ShhhFormatError: shfmt reported errors"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}