0.23.0 (2026-04-19)
Release Description
Overview
A major release focused on reliability and language capabilities. The process subsystem has been reworked with proper thread safety, file descriptor management, and pipe handling across all platforms. The parser now supports PEP 701 f-strings, the walrus operator for env variables, and positional-only arguments. Completions are smarter — sorted by substring match position with visual highlighting. Callable aliases gained a local env overlay, decorator-based configuration, and full help/superhelp support. Globbing is unified under $DOTGLOB with a new regex match glob m. Over 100 potential breaking cases were identified and resolved, making this the most stable release of xonsh to date.
Changes requiring attention
Process subsystem reworked (#6159)
Pipe file descriptor management, thread safety, and signal handling have been extensively investigated, rigorously tested, and corrected. The internal thread management mechanisms for callable aliases have been stabilized and thoroughly stress-tested. Terminal handshake has been added, along with additional OS signal handling to improve behavior when xonsh process groups run in the foreground, background, or as child processes. We ask you to report any issues related to I/O and file descriptors to the issue tracker, so we can catch potential edge cases.
Error handling for subprocess chains enabled by default (#6267)
Xonsh now treats subprocess commands like real code. Every subprocess chain raises an exception on non-zero exit by default ($XONSH_SUBPROC_RAISE_ERROR=True), so a failing command in a function or loop stops execution immediately instead of silently letting subsequent logic run on invalid state:
ls nofile # exception
ls nofile || echo fallback # no exception — chain handled the error
echo ok && ls nofile ; echo done # exception on the first chain
def func():
echo Start
ls nofile # exception
echo End
func()
# BEFORE: Start <stderr> End
# NOW: Start <stderr> <exception>Captured subprocess !() does not raise — full control is on the user:
if !(ls nofile): # no exception — user handles the result
passFor granular error handling, use command decorators and env swap:
@error_ignore ls nofile # suppress for this command
with @.env.swap(XONSH_SUBPROC_RAISE_ERROR=False):
ls nofile # suppress for this block
!(@error_raise ls nofile) # raise exceptionThe old $RAISE_SUBPROC_ERROR (raise exception on every command) is renamed to $XONSH_SUBPROC_CMD_RAISE_ERROR (default False).
Globbing: $DOTGLOB now controls all globs including regex (#6234)
Previously regex globs (r`\..*`) and backtick globs always matched dotfiles regardless of $DOTGLOB. Now all glob forms respect it uniformly. Since $DOTGLOB defaults to False, existing scripts that use regex globs to match hidden files will stop finding them. Set $DOTGLOB = True if you want to match hidden files.
Prompt: Completions match by substring, not just prefix (#6125)
Completions now match by substring, not just by prefix. Typing deploy will find dev-xonsh-deploy, and results are sorted by the position of the match — earlier occurrences rank higher.
Don’t forget about $COMPLETION_MODE = "menu-complete" if you want to select the first option immediately.
Shining Features
Substring Completions (#6125)
aliases |= {'dev-xonsh-deploy': 'echo'}
deploy<Tab>
# dev-xonsh-deploy # matched by substring, sorted by positionPEP 701 f-strings (#6202)
echo f"{"$HOME"}"
# /home/snail
echo f"{'hello':>10}"
# helloCompile XSH Files, Xontribs and Imports (#6167)
# ~/.xonshrc compiled on first load
import mymod # mymod.xsh compiled and cached
xontrib load gitinfo # xontrib gitinfo.xsh compiled and cachedNon-blocking Prompt (#6183)
Syntax highlighting is now non-blocking — typing, completion and navigating through history feel instant regardless of $PATH size. Especially noticeable on Windows with slow directories. Slow $PATH directories can be cached using $XONSH_COMMANDS_CACHE_READ_DIR_ONCE.
Regex glob m with match groups and chain processing (#6235)
for parent, file in m`src/(.*)/(.*\.png)`: # return match groups
print(parent, file)
m`src/.*`.files().paths() # chain processing
m`src/(.*)/(.*\.py)`.select(1).unique().sorted() # group chain processingHelp and Superhelp for Environment Variables and Aliases (#6222, #6263)
$PATH? # shows variable description
my-ls? # shows alias, resolved alias and executable path
my-callable-alias?? # + shows source code and file location of callable aliasInstant Click CLI for Callable Aliases (#6265)
@aliases.register_click_command
@aliases.click.option('--name', default='World')
def _hello(ctx, name):
"""Greet someone."""
print(f'Hello {name}!', file=ctx.stdout)
print(f'Callable alias args like stdout are available in ctx.', file=ctx.stdout)
ctx.click.echo('And click too.')
hello --name Snail # Hello Snail
hello --help # shows usage, options, description
hello?? # shows source code and file location if it was importedCommand Decorators List Extended (#6212)
Added @path, @paths, @error_ignore, @error_raise.
$(@path echo '/bin') # Path('/bin')
echo 1 && @error_ignore ls nonono # no exception that stopped the script executionTake a look at the documentation if you want to create your own.
Emoji and Symbols (#6246)
Activate completer:
$XONSH_COMPLETER_EMOJI_PREFIX = "::" # disabled by default
$XONSH_COMPLETER_SYMBOLS_PREFIX = ":::" # disabled by default
::<Tab> # shows emoji picker: 🌓✨
::cat<Tab> # shows 🐈 related emoji
::<Tab> # shows symbols picker: ⚝
:::arr<Tab> # shows arr symbols: →, ↔, ↗.Take a look at the documentation if you want to add random emoji to prompt.
Prompt: Tab/Shift-Tab indent and Shift+Enter newline (#6213)
IDE-like experience in the prompt: select lines of a multiline command with Shift+Arrow, then Tab/Shift-Tab to indent/dedent the selection. Shift+Enter inserts a newline without submitting.
Cursor Position for Next Command (#6244)
$XONSH_PROMPT_NEXT_CMD = 'echo My name is @(<edit>)'Windows Script Execution (#6180)
$PATHEXT = ['.xsh', '.py']
./myscript.xsh # runs in xonsh
./myscript.py # runs in python
./myscript # resolved by PATHEXTXonsh Activator in virtualenv
Support for the xonsh activator will be restored in virtualenv soon.
Xonsh Packaging for Nix (#6288)
Now we have Nix Flake that builds xonsh from git source (thanks @SamLukeYes!):
nix build 'github:xonsh/xonsh'Xonsh Installer for Windows
Experimental. Now we have Xonsh installers for Windows 8.1+.
Xonsh Nightly Build
We introduced continuous nightly build that has Xonsh AppImage, Windows Installers and experimental Flatpak and Linux Nuitka Binary.
Xonsh Documentation
Now xonsh documentation has much more information, examples and code.
Xonsh Merch
Our friends at HELLOTUX have created an awesome collection for us — including bags, backpacks, T-shirts, and hoodies. Check it out - https://www.hellotux.com/xonsh
Release Notes
Important changes
- Error Handling: Raising exceptions for subprocess chains is enabled by default. Logical operations (
||,&&) are handled correctly.$RAISE_SUBPROC_ERRORdeprecated in favor of$XONSH_SUBPROC_CMD_RAISE_ERROR(#6267) - Processes: Major improvements to core logic for threads, pipes, file descriptors, and process output management across all platforms (#6159)
- Parser: First version with support of PEP 701 f-strings (#6202)
- Completer: Order completions by both prefix and substring matches, sort by substring position. Remove
$CASE_SENSITIVE_COMPLETIONS(#6125) - Glob:
$DOTGLOBnow controls all forms of globbing uniformly (normal, regex) with a dedicated documentation page (#6234) - Performance: Compile xsh xontribs and imports (#6167)
- Windows/WSL: Improved execution performance and prompt highlighting with commands cache (#6183)
- Windows: Fixed executing scripts and binary files (#6180)
Features
- Error Handling: Raising exceptions for subprocess chains is enabled by default. Logical operations (
||,&&) are handled correctly. Captured!()does not raise.@error_ignore/@error_raisedecorators for per-command control (#6267), @anki-code (@nbecker, @AstraLuma, @certik, @gforsyth, @melund, @scopatz, @hexagonrecursion, @carhe, @ading2210, @zhuoqun-chen, @petergaultney, @Qyriad, @buster-blue, @jmdesprez, @thelittlebug) - Parser: First version with support of PEP 701 f-strings (#6202), @anki-code
- Parser: Added walrus operator support for env variables e.g.
echo @($TMP := '/tmp') && ls $TMP(#6226), @anki-code - Parser: Introduced python macro substitution
@!()e.g.echo @!(2+2)returns the expression as a string (#6271), @anki-code (@daniel-shimon, @Qyriad, @aeshna-cyanea, @elgow, @inmaldrerah, @mtalexan, @rtomaszewski, @singpolyma) - Parser: Reduce shadowing by using experimental
$XONSH_BUILTINS_TO_CMD=True(#6227), @anki-code (@elgow, @sawolford, @bestlem, @gforsyth, @laloch, @qwenger, @scopatz) - Callable Alias: Refactoring:
envarg as local overlay,(called_)alias_nameargs. Added@aliases.(un)(threadable/capturable)decorators. Added distinct Callable Alias page in docs (#6245), @anki-code (@dysfungi) - Callable Alias: Better help (
?) and superhelp (??) for aliases and callable aliases (#6263), @anki-code - Callable Alias: Added Click CLI interface support via
@aliases.register_click_command(#6265), @anki-code (@AstraLuma, @deeuu, @halloleo, @jnoortheen, @micimize, @scopatz, @wasertech) - Subprocess: Added support for subprocess substitution in the middle of a string e.g.
echo prefix_$(whoami)_suffix(#6166), @anki-code (@xylin-dev) - Command Decorators: Added
@path,@paths,@error_raise,@error_ignore(#6212), @anki-code - CommandPipeline: Added
pipecodeandpipestatus(#6228), @anki-code (@hexagonrecursion, @carhe, @Qyriad, @buster-blue, @jmdesprez, @thelittlebug) - CommandPipeline: Added
a>p,e>pto redirect all/err to pipe (#6317), @anki-code (@Qyriad) - Completer: Order completions by both prefix and substring matches, sort by substring position. Remove
$CASE_SENSITIVE_COMPLETIONS(#6125), @costajohnt (@anki-code, @wajdiJomaa, @inmaldrerah, @pewill) - Completer: Underline matched substring in completion menu (#6149), @costajohnt (@anki-code)
- Completer: Support emoji and symbols inserting via
$XONSH_COMPLETER_EMOJI_PREFIXand$XONSH_COMPLETER_SYMBOLS_PREFIX(#6246), @anki-code - Env: Added help and superhelp support for env variables i.e.
$VAR?and$VAR??(#6222), @anki-code (@jdjohnston) - Env: Added VarPattern that provides typing by name pattern for environment variables (#6223), @anki-code (@dhhdhshdja)
- Env: Added
$XONSH_SUBPROC_ARG_EXPANDUSERto switch expanding off (#6240), @anki-code (@agoose77) - Glob: Added regex glob
mthat returns match groups as XonshList instead of paths e.g.for path, file in m'(.*)/(.*)\.png': print(path, file)(#6235), @anki-code (@yohan-pg) - Prompt-toolkit: Added
Tab/Shift-Tabto (de)indent selected lines. AddedShift+Enterto start next line (#6213), @anki-code - Prompt: Ability to set cursor position for the next command via
$XONSH_PROMPT_NEXT_CMD(#6244), @anki-code (@slacksystem) - Prompt: Added
Ctrl+Cin selection mode to copy selected text (#6247), @anki-code - Prompt: Support OSC7 escape sequences. Now modern terminal apps can restore shell cwd state after reboot. (#6300) @anki-code (@coolcoder613eb)
- Prompt: Fixed comment highlighting in subproc mode (#5159) @anki-code (@rpdelaney, @alaestor)
- Events: Now
on_command_not_foundevent supports a dict with env overlay. - Source foreign: Added parsing of multiline env variables (#6253), @anki-code (@agoose77)
- Performance: Compile xsh xontribs and imports (#6167), @anki-code (@AsafFisher, @scopatz, @micahdlamb, @aloony, @720415, @Minabsapi, @dyuri, @raddessi, @zscholl, @inmaldrerah, @jnoortheen)
- Windows/WSL: Improved execution performance and prompt highlighting with commands cache (#6183), @anki-code (@ndemou, @gforsyth, @scopatz, @jaraco, @KoStard, @BYK, @AsafFisher, @NotTheDr01ds, @bestlem, @daddycocoaman, @geoffreyvanwyk, @kodjac, @danielcranford, @toihr, @laloch, @melund, @DeadlySquad13, @egigoka, @panki27, @willothy)
- Windows: Added installation script and instructions to the installation guide (#6196), @anki-code
- Builtins: Added
xxonsh- launches exactly the same xonsh that was used to start the current session. Also tmux example in the docs. (#6283), @anki-code - Builtins:
xcontextnow resolves the paths before showing and highlights green if python/xpython, xonsh/xxonsh have the same real path. #6286 - Builtins: Added
uvtoxcontext(18f67b7) @anki-code - Xontrib: Show xontrib description in
xontrib listoutput (#6181), @knQzx (@anki-code) - Package: Flatpak support. Xonsh Flatpak build in https://github.com/xonsh/xonsh-flatpak, @anki-code
Fixes
- Processes: Major improvements to core logic for threads, pipes, file descriptors, and process output management across all platforms (#6159), @anki-code (@gforsyth, @jaraco, @jnoortheen, @scopatz, @AstraLuma, @Qyriad, @doronz88, @AdamJamil, @davidxmoody, @andry81, @blahgeek, @wlritchi, @Harding-Stardust, @arkhan, @mitnk, @whitelynx, @junegunn, @dev2718, @deeuu, @laloch, @beetleb, @cottrell, @ediphy-dwild, @nedsociety, @gnat, @nahoj, @andrew222651, @lambda-abstraction, @lunrenyi, @greenbech, @taw, @bestlem, @jlevy, @kokeshing, @FlyingWombat, @rosalogia, @CaremOstor, @krissik, @Techcable, @tkossak, @inmaldrerah, @Cadair, @720415, @Minabsapi, @dyuri, @raddessi, @zscholl)
- Process: Close only writer in case of reading from stdin in callable alias (#6266), @anki-code
- Process: Implement post command error handling (b07d831), @anki-code
- Process: Reopen stdin from /dev/tty so that child processes (e.g. fzf, vim) can interact with the terminal when xonsh reads a script from stdin (#6274), @anki-code
- Parser: Fix check_for_partial_string: unmatched/unclosed quotes inside
#comments prevent the prompt from being submitted (#6264), @anki-code - Parser: Fix error handling in case of wrong dict
{'A':5,6}(#6269), @anki-code (@yaxollum, @Techcable) - Parser: Fix loop on
\sequence (#6194), @anki-code (@MajoranaOedipus, @sharktide) - Parser: Fix parsing macro block with comments (#6216), @anki-code (@yaxollum, @alextremblay)
- Parser: Fix parsing path with num in case
cd /tmp/123 && ...(#6193), @anki-code (@JamesParrott, @PodioSpaz) - Parser: Fix single word gulping after block with indent (#6217), @anki-code
- Parser: Fix try_subproc_toks issue with wrong wrapping a command with parentheses (#6233), @anki-code (@jun0, @gnewson, @cyb3rmonk)
- Parser: Fix ValueError in typed inline env variables e.g.
$QWE=False xonsh --no-rc(#6221), @anki-code (@jnoortheen) - Parser: Fix regress with parsing
a#b;c(#6168), @anki-code (@azazel75, @jnoortheen, @Cadair) - Parser: PEP 570 positional-only args support (#6268), @anki-code (@lambda-abstraction)
- Callable Alias: Treat unthreadable callable alias exiting (#6252), @anki-code
- Callable Alias: Added exception with workaround in case of using explicit unthreadable callable alias in pipe (#6165), @anki-code (@Qyriad, @gforsyth, @jnoortheen)
- Completer: Add
@aliases.completerdecorator and fix FuncAlias support (#6238), @anki-code - Completer: Fix CommandPipeline completion: no hanging on blocking properties (#6229), @anki-code (@vadym-shavalda)
- Completer: Fix
xpipcompletion. Add public API for python modules completion. Add API to register file matching (#6239), @anki-code (@nahoj) - Completer: Fixed completion of file names with newlines (#6335), @anki-code (@luziferius)
- Completer: Fixed TAB path completion creating multiple single quotes. (#5102), @anki-code (@kouhe3)
- Completer: Added modern locations to bash completions: Nix, Linuxbrew, Darwin (#6347), @anki-code
- Prompt: Fix async prompt race condition when
$ENABLE_ASYNC_PROMPT=True(#6250), @anki-code - Prompt: Restore terminal state after using captured subprocess in key bindings (#6182), @anki-code (@wotsushi, @bobhy, @deeuu, @laloch, @melund, @scopatz, @pigasus55)
- Prompt: Support retry on EINTR (errno 4) in ptk. Fix exceptions when xonsh runs as a child process (#6192), @anki-code (@vrzh, @dysfungi)
- Prompt: Now MULTILINE_PROMPT supports ptk
{COLOR}notation as well as ANSI escape codes and callable has line number and width #6308, @anki-code (@deftasparagusanaconda) - Readline: Fix the case when output disappears in case of no newline character (#6177), @anki-code (@ladyrick, @JamesParrott, @yaxollum)
- Readline: Fix the case when completion can remove prefix (#6230), @anki-code (@Nesar21)
- History: Switch JSON history backend to atomic file replacing and remove race condition on flushing history at exit (#6249), @anki-code (@hplar, @InfiniteCoder01, @jaraco)
- History: Reimplement sqlite history backend
erasedupsand add json history backend support #6293 @anki-code (@FlyingWombat) - Glob:
$DOTGLOBnow controls all forms of globbing uniformly (normal, regex) with a dedicated documentation page (#6234), @anki-code (@inventhouse, @AstraLuma, @gforsyth, @scopatz) - Glob: Remove legacy glob logic that produced issue (#6231), @anki-code (@t184256, @agoose77)
- Env: Fix empty path in
$PATH(#6169), @anki-code - Env: Fix EnvPath (e.g.
$PATH) mirroring toos.environin case of update and$UPDATE_OS_ENVIRON=True(#6171), @anki-code (@NorthIsUp, @AstraLuma, @jaraco, @scopatz) - Env: Detype and detype_all now in sync (#6195), @anki-code (@dconeybe)
- Env: Fix
TERM environment variable not setinxonsh --no-env(#6220), @anki-code - Env: Fix RESET in
$XONSH_STDERR_POSTFIXto colorize stderr properly (#6218), @anki-code (@alvarv, @slacksystem) - Env: Fix
$XONSH_STDERR_PREFIX(b7d3298), @anki-code - Events: Edge case: subprocess call in @events.on_post_rc leads to suspension by the OS (#5244), @anki-code (@skaphi, @bestlem, @lf-, @Lunaphied)
- Mac: Fix
xonsh.platforms.sysctlbynamereturns bytes instead of string whenreturn_str=True(#6190), @Manhhoangvp95 - Exec: Fix
execalias to prevent issues with recursive calls and ENOEXEC processing (#6198), @anki-code (@sae13, @g33kex, @lexbailey, @tacaswell, @FlyingWombat, @MajoranaOedipus) - Import: Fix CPython sys_path_init requirement to have current directory in sys.path for executed script (#6219), @anki-code
- Builtins:
xcontextis working on Windows without exception (#6199), @anki-code - Style: Fix #5163 (register_custom_style KeyError) (ae0c54e), @anki-code (@andrew222651, @dysfungi, @thallium)
- Performance: Reduce expensive operations around getting VCS branch on every prompt (#6184), @anki-code
- Performance: Reduce startup time for non-interactive running by ptk shape lazy loading (#6185), @anki-code
- Stability: Fix code issues: #6191, #6215, #6254, #6257, #6251, #6276, #6281, #6282, @anki-code (@jaraco, @SirNickolas, @Juncheng-wq)
- Stability: Fix _xhj_get_data_dir_files: skip unreadable file instead of exit (bfacf94), @anki-code
- Stability: Fix is_file check (38162f4), @anki-code
- Stability: Handle broken pygments plugins in cache discovery #6295 @anki-code (@Marin-Kitagawa)
- Stability: Use getuid to detect root instead of user #6296, @anki-code (@jaymehta-g)
- Windows: Fix executing scripts and binary files (#6180), @anki-code (@gforsyth, @kalyan860, @jaraco, @dawidsowa, @samueldg, @tahir-hassan)
- Windows: Fix raw paths completion (#6179), @anki-code (@zstg, @mwiebe, @adqm, @jaraco, @scopatz, @Ethkuil)
- Windows: Fix unstable tests (#6163), @anki-code
- Windows: Fix CDLL exception in MSYS2 when running xonsh (#6176), @anki-code
- Install: Update mamba git+extras install docs and script (#6151), @ReinerBRO (@jdjohnston, @MrIridescent, @anki-code)
- Tests: Add strict check of using
python -m pytestinstead ofpytest(#6173), @anki-code (@rautyrauty) - Tests: Fix unwanted output and exceptions from tests (#6178), @anki-code
- Tests: If you actually read this huge amount of awesome release notes, you're amazing, thanks, @anki-code
- Tests: Split integration tests into fast integration tests and slow stress tests (#6224), @anki-code
- Docs: Fix envvars page and update the main page (#6214), @anki-code
- Python 3.14: Fix DeprecationWarning on Python 3.14 (#6279), @anki-code (@jaraco, @JamesParrott, @simonLeary42)
- Python 3.15: Fix ResourceWarning in sqlite history backend (#6323), @anki-code
- Python 3.15: Fix ResourceWarning in procs/specs (#6324), @anki-code
Documentation
- Website: Added dark mode on landing (#6261), @anki-code
- Docs: Complete update: new pages, the sections structure, xonshcon blocks parser, @anki-code