Skip to content

feat: add the builtin builtin - #174

Merged
ferdingler merged 2 commits into
strands-agents:mainfrom
ferdingler:feat/builtin-dispatch
Oct 23, 2026
Merged

ferdingler merged 2 commits into
strands-agents:mainfrom
ferdingler:feat/builtin-dispatch

Conversation

@ferdingler

@ferdingler ferdingler commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Description

builtin didn't exist, so the common builtin 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 args runs 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 like exit, return and eval. A name that isn't a builtin here, like cat, fails with a "not a shell builtin" message the way bash does, and a bare builtin returns 0. I counted "builtin" as anything in the shell's builtin table (which already includes echo and printf), not the coreutils-style commands.

How we fixed it in Box

We already added builtin to 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/return tests catch it. One thing I noticed but left alone: a function named after a builtin never runs today, because the builtin always wins, so a cd() wrapper doesn't actually wrap anything yet. That needs its own fix.

  • I ran the relevant test suites for the bindings I touched (cargo test --workspace --all-targets, pytest tests/python, npm test)
  • If I touched Rust, I ran cargo fmt and cargo clippy

Checklist

  • I have read the CONTRIBUTING document
  • I have reviewed and understand every line of code in this PR, including any generated by AI tools, and I can explain why it works
  • My change is focused and reasonably small; I have split unrelated work into separate PRs
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

`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.
@ferdingler
ferdingler requested a review from a team as a code owner October 21, 2026 04:57
@ferdingler
ferdingler requested review from pgrayy and removed request for a team October 21, 2026 04:57
@ferdingler
ferdingler requested a review from a team as a code owner October 23, 2026 00:24
@ferdingler
ferdingler merged commit a202be8 into strands-agents:main Oct 23, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants