Repository navigation
feat: add the builtin builtin - #174
Merged
ferdingler merged 2 commits intoOct 23, 2026
Merged
Conversation
`builtin NAME [args...]` runs the shell builtin NAME and skips a shell function of the same name. A name that is not a builtin fails with status 1 and a "not a shell builtin" message, and `builtin` with no arguments returns 0. The prefix is dropped before the control-flow builtins that exec.rs handles itself (exit, return, eval, source, ...), so they keep their effect on the shell.
10 tasks done
zastrowm
approved these changes
Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
builtindidn't exist, so the commonbuiltin cd "$@"line inside a wrapper function failed with command not found. Scripts written for bash (and the preambles some agent harnesses run before every command) hit this all the time.Now
builtin NAME argsruns the shell's own builtin NAME with the same arguments, output and exit status, and ignores any function with that name. It also works for the control-flow ones likeexit,returnandeval. A name that isn't a builtin here, likecat, fails with a "not a shell builtin" message the way bash does, and a barebuiltinreturns 0. I counted "builtin" as anything in the shell's builtin table (which already includesechoandprintf), not the coreutils-style commands.How we fixed it in Box
We already added
builtinto Box's copy of Shell (here), and this brings it upstream.Related Issues
None.
Documentation PR
None.
Type of Change
New feature
Testing
I added tests for each of those cases. All of them failed on main and pass with the change, and I also took out just the control-flow part to check the
exit/returntests catch it. One thing I noticed but left alone: a function named after a builtin never runs today, because the builtin always wins, so acd()wrapper doesn't actually wrap anything yet. That needs its own fix.cargo test --workspace --all-targets,pytest tests/python,npm test)cargo fmtandcargo clippyChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.