Skip to content

Make CLI flags override their [run] counterparts in bunfig.toml - #33198

Open
robobun wants to merge 2 commits into
mainfrom
farm/2ea7acd6/run-bunfig-cli-precedence
Open

robobun wants to merge 2 commits into
mainfrom
farm/2ea7acd6/run-bunfig-cli-precedence

Conversation

@robobun

@robobun robobun commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Problem

The [run] section in bunfig.toml silently overrides explicit CLI flags for bun run <script> and bun <script>, inverting the documented precedence ("CLI flags override bunfig settings where applicable").

# bunfig.toml
[run]
bun = false
bun run --bun where-node   # runs the real node: the --bun flag is ignored

Reproduced on 1.4.0 and current main with --bun vs run.bun, --silent vs run.silent, and --shell vs run.shell:

$ cat bunfig.toml
[run]
shell = "system"
$ bun run --shell=bun start
/usr/bin/bash: line 1: cli-precedence-command-not-found: command not found

Cause

Arguments::parse applies --silent / --bun / --shell / --elide-lines to the context after load_config, which is correct when bunfig.toml is loaded during argument parsing (-c=..., bun file.ts, bun test, ...). But for bun run <script> and bun <script-name> the local bunfig.toml is only loaded later, inside RunCommand::exec (#16664), and its [run] keys overwrote the values the CLI flags had already set. That is why bun run -c=bunfig.toml --bun x behaved correctly while bun run --bun x did not.

Fix

Record which of the four [run]-related CLI flags were explicitly passed (*_from_cli, the same pattern test.pathIgnorePatterns already uses) and have the bunfig [run] parser skip a key whose flag was passed. This keeps the deferred bunfig load for bun run (so [run] settings still apply when no flag is given) while restoring CLI > bunfig precedence in both load orders.

run.elide-lines gets the same guard for consistency; its only consumer is the --filter runner, which re-applies the CLI value today, so it is not observable in a test without a PTY.

Verification

New tests in test/cli/install/bun-run-bunfig.test.ts, for both bun run <script> and bun <script>:

  • --bun overrides run.bun = false (node resolves to the bun-node-* shim)
  • --silent overrides run.silent = false (no $ echo 1 echo)
  • --shell=bun overrides run.shell = "system" (bun shell error message)

All 6 fail on the unfixed build and pass with this change; the 28 pre-existing tests in the file (including run.bun/run.silent/run.shell without flags, and the bunfig autoload tests) still pass, as do test/cli/run/filter-workspace.test.ts, test/cli/run/run_command.test.ts, and test/cli/bunfig-test-options.test.ts.

For `bun run <script>` and `bun <script>`, bunfig.toml is loaded after
argument parsing (RunCommand::exec), so the [run] section overwrote values
that --silent, --bun, --shell, and --elide-lines had already set, inverting
the documented precedence. Record which of those flags were passed and have
the bunfig parser skip the corresponding [run] keys.
@github-actions github-actions Bot added the claude label Jul 1, 2026
@robobun

robobun commented Jul 1, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 1:36 PM PT - Jul 1st, 2026

❌ @robobun, your commit 4a37be2 has 5 failures in Build #67636 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 33198

That installs a local version of the PR into your bun-33198 executable, so you can run:

bun-33198 --bun

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Found 4 issues this PR may fix:

  1. bun run --filter ignores bunfig.toml [run] elide-lines #31479 - bun run --filter ignores bunfig.toml [run] elide-lines; the elide_lines_from_cli guard fixes this precedence bug
  2. Ellide-lines toml config #17918 - elide-lines in bunfig.toml ignored when using --filter; same late-loading root cause this PR addresses
  3. --silent doesn't work together with --filter #17140 - --silent doesn't work together with --filter; the silent_from_cli tracking fixes this
  4. Allow --bun=false #31497 - Allow --bun=false to override run.bun = true in bunfig; the run_in_bun_from_cli mechanism enables CLI-over-config precedence

If this is helpful, copy the block below into the PR description to auto-close these issues on merge.

Fixes #31479
Fixes #17918
Fixes #17140
Fixes #31497

🤖 Generated with Claude Code

@robobun

robobun commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

None of these four are closed by this PR, so I'm not adding the Fixes block:

What this PR fixes (explicit --bun / --silent / --shell / --elide-lines losing to the corresponding [run] key when bun run auto-loads bunfig.toml) has no open issue that I could find.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a28e0ee6-852f-4b14-b2cb-33d13f147da0

📥 Commits

Reviewing files that changed from the base of the PR and between 174cf1e and 4a37be2.

📒 Files selected for processing (1)
  • test/cli/install/bun-run-bunfig.test.ts

Walkthrough

Adds "*_from_cli" boolean tracking fields to BundlerOptions and DebugOptions context structs, sets them during CLI argument parsing for --elide-lines, --silent, --bun, and --shell flags, and updates bunfig.toml [run] parsing to skip overwriting values already set via CLI. Adds tests validating this precedence.

Changes

CLI flag precedence over bunfig run settings

Layer / File(s) Summary
Context fields for CLI tracking
src/options_types/context.rs
Adds elide_lines_from_cli to BundlerOptions and silent_from_cli, run_in_bun_from_cli, use_system_shell_from_cli to DebugOptions, with default values initialized to false.
CLI parsing sets from-cli markers
src/runtime/cli/Arguments.rs
When --elide-lines, --silent, --bun, or --shell (bun/system) are parsed, the corresponding *_from_cli field is now also set to true alongside the existing option value.
Bunfig [run] parsing respects CLI precedence
src/bunfig/bunfig.rs
[run] keys silent, elide-lines, shell, and bun in bunfig.toml/json are now only applied when the corresponding *_from_cli flag was not already set by the CLI.
Tests for CLI override behavior
test/cli/install/bun-run-bunfig.test.ts
New concurrent test suite spawns bun run/bun with --bun, --silent, and --shell=bun and asserts these override conflicting [run] settings in bunfig.toml.

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Arguments
  participant Context as DebugOptions/BundlerOptions
  participant BunfigParser

  CLI->>Arguments: parse --silent/--bun/--shell/--elide-lines
  Arguments->>Context: set option value + *_from_cli = true
  Context->>BunfigParser: pass ctx with from_cli flags
  BunfigParser->>BunfigParser: read [run] keys from bunfig.toml
  alt from_cli flag is true
    BunfigParser->>BunfigParser: skip overwrite, keep CLI value
  else from_cli flag is false
    BunfigParser->>Context: set value from bunfig
  end
Loading

Estimated code review effort: 2 🔵🔵⚪⚪⚪

Related PRs: None identified.

Suggested labels: bug, cli, bunfig

Suggested reviewers: None identified.

🐰 A flag from the shell now outranks the file,
No more silent overwrite, no more bunfig guile,
Four little booleans keep watch at the gate,
Guarding what the CLI declared as fate,
Hop by hop, precedence set just right! 🥕

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main behavior change: CLI flags now override matching bunfig [run] settings.
Description check ✅ Passed The description covers the problem, root cause, fix, and verification, matching the template's intent even though the headings differ.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/cli/install/bun-run-bunfig.test.ts`:
- Around line 255-328: Add a precedence test for `--elide-lines` in the
`describe.concurrent.each` block that already covers `--bun`, `--silent`, and
`--shell=bun`, using the same `bunExe()`/`Bun.spawn` pattern and a `bunfig.toml`
with `run.elide-lines`. Verify that the CLI flag overrides the bunfig setting by
asserting the expected output behavior from the relevant script command and that
the process exits successfully. Use the existing `runArg` setup and mirror the
style of the neighboring tests so the new case is easy to locate and maintain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e61b6b6d-23e7-4453-9cb5-630c8b21009f

📥 Commits

Reviewing files that changed from the base of the PR and between d816daf and 174cf1e.

📒 Files selected for processing (4)
  • src/bunfig/bunfig.rs
  • src/options_types/context.rs
  • src/runtime/cli/Arguments.rs
  • test/cli/install/bun-run-bunfig.test.ts

Comment thread test/cli/install/bun-run-bunfig.test.ts

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — straightforward precedence fix following the existing path_ignore_patterns_from_cli pattern.

Extended reasoning...

Overview

This PR fixes a precedence bug where [run] keys in bunfig.toml (silent, bun, shell, elide-lines) would override their explicit CLI flag counterparts, because bun run loads bunfig.toml after CLI args are parsed. The fix adds four *_from_cli bool fields to DebugOptions/BundlerOptions, sets them in Arguments.rs when the flag is passed, and gates the bunfig assignment on them in bunfig.rs. Six new subprocess tests cover --bun, --silent, and --shell for both bun run and bun invocations.

Security risks

None. This only touches CLI-flag / config-file precedence for local run options; no auth, network, or untrusted-input parsing is involved.

Level of scrutiny

Low-to-moderate. The change follows the exact pattern already established in the same file for test_options.path_ignore_patterns_from_cli, so there's no new design surface. The shell block refactor is behavior-preserving: invalid values still error regardless of the _from_cli flag, and valid values map to the same use_system_shell state as before. Both --elide-lines handlers in Arguments.rs set the new flag. Struct Default impls are updated consistently.

Other factors

The one inline nit (stdout piped but not drained in the shell test) has no functional impact — the failing command writes nothing to stdout, so it can't deadlock — it's just a consistency cleanup with the sibling tests. --elide-lines precedence isn't covered by a new test, but the code path is identical to the three tested flags. CLI > config-file is the conventional precedence, so no design question here.

Comment thread test/cli/install/bun-run-bunfig.test.ts

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — the stdout nit is addressed and the fix follows the existing path_ignore_patterns_from_cli pattern.

Extended reasoning...

Overview

Restores the documented CLI > bunfig precedence for four [run] keys (silent, bun, shell, elide-lines) by adding *_from_cli tracking booleans to DebugOptions/BundlerOptions, setting them in Arguments::parse, and guarding the corresponding assignments in the bunfig [run] parser. Six new tests in bun-run-bunfig.test.ts cover --bun/--silent/--shell for both bun run <script> and bun <script>.

Security risks

None. This is CLI option precedence plumbing — no auth, crypto, network, path validation, or untrusted input parsing is touched. Type validation in the bunfig parser is preserved (invalid values still error even when the CLI flag was set).

Level of scrutiny

Low. The change is mechanical and copies the exact pattern already used for test.path_ignore_patterns_from_cli in the same three files. New struct fields default to false, so behavior is unchanged when flags are absent. The shell branch refactor (value == b"bun" || value == b"system" → use_system_shell = value == b"system") is semantically identical to the two-branch original and still rejects unknown values. No CODEOWNER-protected paths are touched.

Other factors

  • My previous inline comment (undrained stdout: "pipe" in the --shell test) was addressed in 4a37be2 by switching to stdout: "ignore"; the thread is resolved.
  • CodeRabbit's nitpick about a missing --elide-lines test is already answered in the PR description: the only consumer is the --filter runner, which re-applies the CLI value and is not observable without a PTY. That's a reasonable justification for a consistency-only guard.
  • The bug hunting system found no issues on the current revision.
  • Tests follow harness conventions (bunEnv, bunExe, tempDirWithFiles, concurrent pipe draining, await using), and the pre-existing 28 tests in the file — including the ones that assert bunfig [run] keys still apply without flags — remain in place.

@robobun

robobun commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

CI status for build 67636 (head 4a37be2): every failing lane is a test unrelated to this change, and the same tests are failing on other PRs' concurrent builds (67634, 67626, 67611, 67605):

  • test/bake/dev/production.test.ts ("works with sourcemaps - error thrown in React component" times out after 270s) on most platforms
  • test/bake/dev-and-prod.test.ts (Windows, auto-retried as flaky)
  • test/js/node/test/parallel/test-net-connect-memleak.js (Alpine)
  • test/js/sql/sql-mysql-column-name-digits.test.ts (Alpine aarch64, MySQL container startup noise)
  • test/js/bun/http/serve-body-leak.test.ts and test/js/node/http/node-http-backpressure-max.test.ts (timeouts)
  • one darwin 26 aarch64 lane failed before running any test: buildkite-agent artifact download timed out after 120s

None of these exercise the CLI or bunfig code paths touched here, and test/cli/install/bun-run-bunfig.test.ts is not in any failure list (it passed on every lane). The diff is ready for review.

Jarred-Sumner pushed a commit that referenced this pull request Aug 28, 2026
…quential (#40621)

Fixes #17918
Fixes #31479
Supersedes #31480

### Problem
- `bun run --filter <pkg> <script>`, `bun --filter`, `--workspaces`,
`--parallel` and `--sequential` ignore an auto-discovered `bunfig.toml`.
`[run] bun = true`, `elide-lines`, `shell`, `silent` and `noOrphans` are
dead for these runners unless `--config=` is passed. Copying the file
into each package directory does not help: the parent process decides
these settings.
- Cause: `exec_auto_or_run` (`src/runtime/cli/mod.rs:1430`) dispatches
to `multi_run::run` and `filter_run::run_scripts_with_filter` right
after argument parsing. The lazy `bunfig.toml` load for `bun run
<script>` lives in `RunCommand::exec_with_cfg`
(`src/runtime/cli/run_command.rs:2312`), which these paths never reach.
`load_config` (`src/bunfig/arguments.rs:169`) only auto-loads for `bun
test`, `bun <file>` and the install commands.

### Fix
- Extend the auto-load condition in `load_config` with: run or auto
command, and one of `parallel`, `sequential`, `workspaces`, or a
non-empty `filters`. These fields are set before
`load_config_with_cmd_args` runs.
- The file now loads inside `Arguments::parse`, the same place `bun
test` and `bun <file>` load it. `--bun`, `--elide-lines`, `--shell` and
`--silent` are applied after that call, so a CLI flag still wins over
its `[run]` key.
- A malformed `bunfig.toml` now fails these runs with the parser error
and exit code 1, the same as `bun test` and `bun run -c=bunfig.toml`.
- Verified: `test/cli/run/filter-workspace.test.ts` (7 new tests, 5 fail
on 1.4.1) and `test/cli/run/multi-run.test.ts` (5 new, 4 fail on 1.4.1).
Also `test/cli/install/bun-run-bunfig.test.ts`, `test/config/bunfig/`,
`test/cli/run/env.test.ts`, `no-envfile.test.ts`, `run-shell.test.ts`.

### Background
- `bunfig.toml` is read from the working directory. `Arguments::parse`
loads it for commands in `ALWAYS_LOADS_CONFIG`. `bun run <script>` is
not in that table and loads it later, in `exec_with_cfg`.
- `[run] bun = true` puts a `node` shim that points at bun on `PATH`.
The tests use `node -e "console.log(typeof Bun)"` to see which binary
ran.
- Elision (`elide-lines`) only happens when stdout is a terminal. On
POSIX, `FORCE_COLOR=1` turns the terminal renderer on for a pipe, which
the existing elision tests rely on.

<details><summary>Notes</summary>

- Repro on 1.4.1: workspace root `bunfig.toml` with `[run]\nbun = true`,
package script `node -e "console.log('Bun is', typeof Bun)"`. `bun run
--filter a hello` prints `Bun is undefined`. `bun run -c=bunfig.toml
--filter a hello` prints `Bun is object`. `bun run --parallel hello
hello2` and `--sequential` print `Bun is undefined` too. Plain `bun run
hello` prints `Bun is object`.
- Two precedence tests (`--bun` over `bun = false`, `--elide-lines 15`
over `elide-lines = 0`) pass before and after. They guard against the
inverted precedence that the exec-time load has for plain `bun run`
(#33198).
- Top-level keys in the same file (`env = false`, `preload`, `define`)
are parsed for the parent too. Only `env` changes what the parent does:
it stops loading the root `.env` files that the child scripts otherwise
inherit, which is what the key documents.
- #31480 added the same load inside `run_scripts_with_filter` with a
snapshot of the two CLI values. It covered `--filter` only and predates
the `tempDirWithFiles` removal. Loading during argument parsing needs no
snapshot and covers `--parallel` and `--sequential`.
- Debug builds recreate `/tmp/bun-node-debug` on every `--bun` run
(`src/install/lib.rs:564`), so concurrent `--bun` processes can race
each other. The multi-run tests are serial because of that. Reported
separately.
</details>

<!-- robobun:evidence:begin -->

---

**no test proof** · iteration 0 · platform-specific test(s) that do not
run on this machine, deferring to CI, which covers all platforms:
test/cli/run/multi-run.test.ts, test/cli/run/filter-workspace.test.ts

<!-- robobun:evidence:end -->
@robobun

robobun commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator Author

Stale PR review: keep open, rework.

The bug is still on main and the fix is wanted. Take an auto-discovered bunfig.toml with [run] keys bun = false, silent = false and shell = "system". On a 1.4.3 canary, bun run --silent --bun <script> still echoes the command and runs the real node, and --shell=bun still runs bash. The same flags win with -c=bunfig.toml. docs/runtime/bunfig.mdx:19 says that CLI flags override bunfig settings.

#40621 merged tests that assert this order for --filter runs (test/cli/run/filter-workspace.test.ts:1304). Its commit message names this PR for the plain bun run path. #12216 reports the same class of bug for [test] keys. #38599 guards other flags (define, loader, jsx, console depth, install, macros), not the [run] keys.

The current diff is not ready to merge, although GitHub reports no conflict:

  • The three new tests call tempDirWithFiles. test: convert tempDirWithFiles callers to using tempDir #36194 converted test/cli/install/bun-run-bunfig.test.ts to using dir = tempDir(...), and the file on main no longer imports tempDirWithFiles. After a merge, the new tests throw ReferenceError.
  • elide_lines_from_cli has no effect on main. The only reader of bundler_options.elide_lines is src/runtime/cli/filter_run.rs:904. On that path bunfig.toml loads at src/runtime/cli/Arguments.rs:925, before the second --elide-lines parse at line 1568. The CLI value already wins there. cli: add BUN_CONFIG_ELIDE_LINES env var #28978 also touches --elide-lines.

The wanted shape is the same mechanism in one rebase:

  • Rebase on main. Port the three tests to using dir = tempDir(...) with cwd: String(dir).
  • Keep the guards silent_from_cli, run_in_bun_from_cli and use_system_shell_from_cli. They follow the merged path_ignore_patterns_from_cli pattern (src/bunfig/bunfig.rs:674).
  • Drop elide_lines_from_cli.
  • Keep the deferred bunfig load in src/runtime/cli/run_command.rs:2316 as it is.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant