NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Friendly misc/utils/convenience library
Last release 5 months ago
05 May 2026
Release timing varies
gaps range from 8 days to 7 months
Most releases are documented
notes for 43 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
8 years old
193 releases · first in 2018
Added PythonDepot.scanned_prefixes
Added PythonDepot.scanned_prefixes
Allow to split CamelCase words as well via runez.words(decamel=True)
Allow to split CamelCase words as well via runez.words(decamel=True)
Corrected diagnostics, added transform= argument to flattened()
One column per quarter.
Corrected diagnostics, added transform= argument to flattened()
* Corrected joined()
Corrected joined()
Corrected bug in cached_property
Corrected bug in cached_property
* PythonSpec is now hashable
PythonSpec is now hashable
Removed python_version() (runez.pyenv is better suited for this)
Removed python_version() (runez.pyenv is better suited for this)
Accept invoker as python spec
Removed @chill_property, not general/useful enough
Removed @chill_property, not general/useful enough
Properly handle multiple lines in flattened(split=...)
Properly handle multiple lines in flattened(split=...)
Removed origin and family from PythonDepot, allow to provide custom scanners
Removed origin and family from PythonDepot, allow to provide custom scanners
Added a reusable way of showing diagnostics
Added a reusable way of showing diagnostics
Moved
runez.TERMINAL_INFO -> runez.SYS_INFO.terminal
runez.log.current_test() -> runez.SYS_INFO.current_test()
runez.log.dev_folder() -> runez.SYS_INFO.dev_folder()
runez.log.program_path() -> runez.SYS_INFO.program_path
Added runez.shell() for quick shell command output grab
Allow to specify package in auto_import_siblings()
Complain if running as root (by default) in runez.log.setup()
Added passthrough option for runez.run() (capture output, and let it pass-through)
Added passthrough option for runez.run() (capture output, and let it pass-through)
Added TerminalProgram, detection of parent terminal (if any)
Export class PsInfo instead of function ps_info
Export class PsInfo instead of function ps_info
Allow to reorder python installation origins and families
Allow to reorder python installation origins and families
Use same PythonInstallation class for all origins
Nothing published for this version
Nothing published for this version
Don't use globals in PythonDepot
Don't use globals in PythonDepot
Better formalized what is logged by read_json() and readlines()
Respect logger=None (no log chatter at all), vs logger=False (fall back to trace)
* Added runez.pyenv module
Added runez.pyenv module
Corrected bug with progress stdout/err re-capture
Corrected bug with progress stdout/err re-capture
Show sorted import times in import-speed command
Nothing published for this version
Don't hide cursor in progress spinner, so we can't ever miss not showing it back
Don't hide cursor in progress spinner, so we can't ever miss not showing it back
Simplified how logsetup references are resolved
Nothing published for this version
Nothing published for this version
Nothing published for this version
Added ProgressBar, corrected flickering in spinner
Added ProgressBar, corrected flickering in spinner
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Added progress spinner, can be activated with runez.log.progress.start()
Added progress spinner, can be activated with runez.log.progress.start()
Corrected bug in {argv} expansion
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Renamed terminal_info() -> TERMINAL_INFO, moved is_tty() to it
Renamed terminal_info() -> TERMINAL_INFO, moved is_tty() to it
Using monkeypatch instead of mock
Added runez.log.trace()
Moved to https://github.com/codrsquad/runez
Moved to https://github.com/codrsquad/runez
Better signature for terminal_width()
Added @cached_property, @chill_property, is_basetype(), is_iterable(), joined(), parsed_tabular(), ps_info()
Added runez.click.prettify_epilogs()
Added attributes_by_type() to schema meta, Struct schema type (for non-root serializable objects)
Consistent signature for first_line(), flattened(), joined(), json_sanitized(), ini_to_dict(), quoted()
runez.run() strips newlines only on captured content
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Allow for workaround around py3 unable to sort None-keys in json.dumps(sort_keys=True)
Allow for workaround around py3 unable to sort None-keys in json.dumps(sort_keys=True)
short() defaults now to terminal width
represented_json() and save_json() have now a signature consistent with json_sanitized()
Accept optionally multiple paths at once in Anchored() context manager
Nothing published for this version
Nothing published for this version
Nothing published for this version
Correctly expand ~ in path, if provided
Correctly expand ~ in path, if provided
Allow to override the internal default logger, used in runez.run() etc
Restored default click.version() message, to minimize differences with click
Simplified default click.version() message, now simply outputs version (without fluff)
Use module's __version__ when available
Moved to github actions
Corrected edge case with cli.run(..., exe=)
Ignore errors when deleting temp folders in context managers
runez.log.dev_folder() now accepts relative path
Renamed runez.conftest.resource_path() to runez.log.tests_path()
Added runez.log.project_path()
Allow to override sys.executable in click test runs
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Adapted to latest pytest log wrapping
Adapted to latest pytest log wrapping
Corrected date conversion for empty string
Allow to not wait for spawned process with runez.run(fatal=None, stdout=None, stderr=None)
More consistent debug logging on file operations
Corrected edge case in py2 with coloring of μ character in represented_duration()
Added clean=True option to ensure_folder()
Added click.border() option
Bug fixes
Reviewed all IO related functions and made them respect the same signature, explained in doc:
Functions not returning content (run(), delete(), ...) all have this signature: fatal=True, logger=UNSET, dryrun=UNSET
Functions returning content (read_json(), readlines(), ...) are simplified to just a: default=UNSET (aborts on failure when no default is specified, default returned otherwise).
Simplified signatures of: ensure_folder, read_json, readlines
Made readlines consistent with all other IO related functions
Defined signature of abort(), not going via **kwargs anymore
Added adhoc "linter" to ensure IO related functions have a consistent signature
Bug fixes, renamed test_resource to resource_path (in runez.conftest), to avoid pytest thinking it is a test function when imported.
Fixed docstrings, RunResult properly evaluates to true-ish on success
runez.run() now always returns a RunResult
runez.run() now returns a RunResult object when called with fatal=None, with fields: .output, .error and .exit_code
Removed include_error kwarg from runez.run(), RunResult.full_output can now be used instead
Internal refactor to minimize import time (import time now tested, must be less than 3x slower than import sys)
Renamed:
first_meaningful_line() -> first_line() applies to strings or list (not file anymore)
shortened() -> short()
represented_args() -> quoted() (can quote a single string, or a list of strings)
Replaced named arg separator to be more indicative as to what it used for
delimiter when the string is used to .join() a list of things back to a string (eg: represented_bytesize(.., delimiter=" "))
split when the character is used to split strings (eg: flattened(.., split=",")
flattened() now has boolean optional parameters (instead of previously split enum)
Reduced number of things exported at top-level, removed:
heartbeat, use from runez.heartbeat import ...
prompt, use from runez.prompt import ...
represent, use from runez.render import ...
schema, use from runez.schema import ...
thread, use from runez.thread import ...
set_dryrun (better applied via runez.log.setup())
SANITIZED, SHELL, UNIQUE, function flattened() now accepts more explicit boolean flags
class_descendants(): not so useful after all, using decorators is better
auto_import_siblings, use from runez.inspector import auto_import_siblings
ActivateColors, use runez.colors.ActivateColors
is_coloring, use runez.color.is_coloring
SECONDS_IN_ONE_*, use runez.date.SECONDS_IN_ONE_*
ini_to_dict, use runez.file.ini_to_dict
is_younger, use runez.file.is_younger
current_test, use runez.log.current_test
dev_folder, use runez.log.dev_folder
find_parent_folder, use runez.log.find_parent_folder
program_path, use runez.log.program_path
require_installed, use runez.program.require_installed
align, use from runez.render import Align
header, use from runez.render import Header
PrettyTable, use from runez.render import PrettyTable
json_sanitized, use runez.serialize.json_sanitized
Enhanced:
quoted() can quote a single string, or a list of strings
readlines() can now ignore empty lines, and return up to N first lines
Relevant click decorators are not exposed anymore by default, and auto-apply themselves:
@runez.click.color()
@runez.click.config()
@runez.click.dryrun()
Added:
PrettyTable, more flexible than the now abandoned and similar https://pypi.org/project/PrettyTable
runez.inspector module, which mostly acts on context (auto-detects caller), and provide a few relevant features:
auto_import_siblings(): automatically finds all siblings of calling module, and ensure every single one is import-ed, this is useful to avoid having to manually register click sub-commands of a large group
run_cmds(): poor man's click-replacement, finds all cmd_ functions in caller module and makes a multi-command out of them, with --help etc
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →