From 8f4cc03faf8805dd43ad6ef6402b8e52c9d6515a Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Thu, 28 May 2026 16:08:09 -0700 Subject: [PATCH 01/12] Make justfile recipes Windows-aware --- justfile | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/justfile b/justfile index d5e9fc3a36e1..6db5c774ee4f 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,5 @@ set working-directory := "codex-rs" -set positional-arguments +set windows-shell := ["powershell.exe", "-NoLogo", "-NoProfile", "-Command"] rust_min_stack := "8388608" # 8 MiB @@ -9,39 +9,85 @@ help: # `codex` alias c := codex +[unix] +[positional-arguments] codex *args: cargo run --bin codex -- "$@" +[windows] +codex *args: + cargo run --bin codex -- {{args}} + # `codex exec` +[unix] +[positional-arguments] exec *args: cargo run --bin codex -- exec "$@" +[windows] +exec *args: + cargo run --bin codex -- exec {{args}} + # Start `codex exec-server` and run codex-tui. +[unix] [no-cd] +[positional-arguments] tui-with-exec-server *args: {{ justfile_directory() }}/scripts/run_tui_with_exec_server.sh "$@" # Run the CLI version of the file-search crate. +[unix] +[positional-arguments] file-search *args: cargo run --bin codex-file-search -- "$@" +[windows] +file-search *args: + cargo run --bin codex-file-search -- {{args}} + # Build the CLI and run the app-server test client +[unix] +[positional-arguments] app-server-test-client *args: cargo build -p codex-cli cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex "$@" +[windows] +app-server-test-client *args: + cargo build -p codex-cli + cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex {{args}} + +[unix] # Format Rust and Python SDK code. fmt: cargo fmt -- --config imports_granularity=Item 2>/dev/null uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python uv run --frozen --project ../sdk/python --extra dev ruff format ../sdk/python +[windows] +fmt: + cargo fmt -- --config imports_granularity=Item 2>$null; exit $LASTEXITCODE + uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python + uv run --frozen --project ../sdk/python --extra dev ruff format ../sdk/python + +[unix] +[positional-arguments] fix *args: cargo clippy --fix --tests --allow-dirty "$@" +[windows] +fix *args: + cargo clippy --fix --tests --allow-dirty {{args}} + +[unix] +[positional-arguments] clippy *args: cargo clippy --tests "$@" +[windows] +clippy *args: + cargo clippy --tests {{args}} + install: rustup show active-toolchain cargo fetch @@ -51,40 +97,68 @@ install: # Run `cargo install --locked cargo-nextest` if you don't have it installed. # Prefer this for routine local runs. Workspace crate features are banned, so # there should be no need to add `--all-features`. +[unix] +[positional-arguments] test *args: RUST_MIN_STACK={{ rust_min_stack }} cargo nextest run --no-fail-fast "$@" just bench-smoke +[windows] +test *args: + $env:RUST_MIN_STACK = "{{ rust_min_stack }}"; cargo nextest run --no-fail-fast {{args}} + just bench-smoke + # Run explicit workspace benchmark targets. +[unix] +[positional-arguments] bench *args: cargo bench --workspace --bench '*' "$@" +[windows] +bench *args: + cargo bench --workspace --bench '*' {{args}} + # Run benchmark targets once to ensure they start successfully. bench-smoke: just bench -- --test # Build and run Codex from source using Bazel. -# Note we have to use the combination of `[no-cd]` and `--run_under="cd $PWD &&"` -# to ensure that Bazel runs the command in the current working directory. +# On Unix, use `[no-cd]` and `--run_under="cd $PWD &&"` to ensure Bazel runs +# the command in the current working directory. +[unix] [no-cd] +[positional-arguments] bazel-codex *args: bazel run //codex-rs/cli:codex --run_under="cd $PWD &&" -- "$@" +[windows] +[no-cd] +bazel-codex *args: + bazel run //codex-rs/cli:codex -- {{args}} + [no-cd] bazel-lock-update: bazel mod deps --lockfile_mode=update +[unix] [no-cd] bazel-lock-check: {{ justfile_directory() }}/scripts/check-module-bazel-lock.sh +[windows] +[no-cd] +bazel-lock-check: + bazel mod deps --lockfile_mode=error; if ($LASTEXITCODE -ne 0) { Write-Error "MODULE.bazel.lock is out of date. Run 'just bazel-lock-update' and commit the updated lockfile."; exit 1 } + bazel-test: bazel test --test_tag_filters=-argument-comment-lint //... --keep_going +[unix] [no-cd] bazel-clippy: bazel_targets="$({{ justfile_directory() }}/scripts/list-bazel-clippy-targets.sh)" && bazel build --config=clippy -- ${bazel_targets} +[unix] [no-cd] bazel-argument-comment-lint: bazel build --config=argument-comment-lint -- $({{ justfile_directory() }}/tools/argument-comment-lint/list-bazel-targets.sh) @@ -96,23 +170,37 @@ build-for-release: bazel build //codex-rs/cli:release_binaries --config=remote # Run the MCP server +[unix] +[positional-arguments] mcp-server-run *args: cargo run -p codex-mcp-server -- "$@" +[windows] +mcp-server-run *args: + cargo run -p codex-mcp-server -- {{args}} + # Regenerate the json schema for config.toml from the current config types. write-config-schema: cargo run -p codex-core --bin codex-write-config-schema # Regenerate vendored app-server protocol schema artifacts. +[unix] +[positional-arguments] write-app-server-schema *args: cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- "$@" +[windows] +write-app-server-schema *args: + cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- {{args}} + [no-cd] write-hooks-schema: cargo run --manifest-path {{ justfile_directory() }}/codex-rs/Cargo.toml -p codex-hooks --bin write_hooks_schema_fixtures # Run the argument-comment Dylint checks across codex-rs. +[unix] [no-cd] +[positional-arguments] argument-comment-lint *args: if [ "$#" -eq 0 ]; then \ bazel build --config=argument-comment-lint -- $({{ justfile_directory() }}/tools/argument-comment-lint/list-bazel-targets.sh); \ @@ -120,10 +208,23 @@ argument-comment-lint *args: {{ justfile_directory() }}/tools/argument-comment-lint/run-prebuilt-linter.py "$@"; \ fi +[unix] [no-cd] +[positional-arguments] argument-comment-lint-from-source *args: {{ justfile_directory() }}/tools/argument-comment-lint/run.py "$@" +[windows] +[no-cd] +argument-comment-lint-from-source *args: + python {{ justfile_directory() }}/tools/argument-comment-lint/run.py {{args}} + # Tail logs from the state SQLite database +[unix] +[positional-arguments] log *args: if [ "${1:-}" = "--" ]; then shift; fi; cargo run -p codex-state --bin logs_client -- "$@" + +[windows] +log *args: + cargo run -p codex-state --bin logs_client -- {{args}} From d5a70cf47789759cd5cab13b2b236803719b0210 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Thu, 28 May 2026 16:29:35 -0700 Subject: [PATCH 02/12] Address Windows justfile review feedback --- justfile | 6 +++--- sdk/python/tests/test_artifact_workflow_and_binaries.py | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index 6db5c774ee4f..4a8a13788ca5 100644 --- a/justfile +++ b/justfile @@ -57,8 +57,8 @@ app-server-test-client *args: cargo build -p codex-cli cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex {{args}} -[unix] # Format Rust and Python SDK code. +[unix] fmt: cargo fmt -- --config imports_granularity=Item 2>/dev/null uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python @@ -134,7 +134,7 @@ bazel-codex *args: [windows] [no-cd] bazel-codex *args: - bazel run //codex-rs/cli:codex -- {{args}} + bazel run //codex-rs/cli:codex --run_under='cd /d "{{invocation_directory_native()}}" &&' -- {{args}} [no-cd] bazel-lock-update: @@ -227,4 +227,4 @@ log *args: [windows] log *args: - cargo run -p codex-state --bin logs_client -- {{args}} + cargo run -p codex-state --bin logs_client -- {{replace(args, "-- ", "")}} diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index d3f2f8d0ec1a..f673f910815a 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -81,12 +81,16 @@ def test_root_fmt_recipe_formats_rust_and_python_sdk() -> None: fmt_recipe = lines[fmt_index:next_recipe_index] actual = { "working_directory": lines[0], - "previous_attribute": lines[fmt_index - 1], + "previous_comment": next( + line + for line in reversed(lines[:fmt_index]) + if line.startswith("#") + ), "commands": [line.strip() for line in fmt_recipe[1:] if line.strip()], } expected = { "working_directory": 'set working-directory := "codex-rs"', - "previous_attribute": "# Format Rust and Python SDK code.", + "previous_comment": "# Format Rust and Python SDK code.", "commands": [ "cargo fmt -- --config imports_granularity=Item 2>/dev/null", "uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python", From 5810eed0d772062b0daea7cc7c2d617308742ccd Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Thu, 28 May 2026 16:35:17 -0700 Subject: [PATCH 03/12] Format SDK justfile test update --- sdk/python/tests/test_artifact_workflow_and_binaries.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index f673f910815a..8c6dac135973 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -81,11 +81,7 @@ def test_root_fmt_recipe_formats_rust_and_python_sdk() -> None: fmt_recipe = lines[fmt_index:next_recipe_index] actual = { "working_directory": lines[0], - "previous_comment": next( - line - for line in reversed(lines[:fmt_index]) - if line.startswith("#") - ), + "previous_comment": next(line for line in reversed(lines[:fmt_index]) if line.startswith("#")), "commands": [line.strip() for line in fmt_recipe[1:] if line.strip()], } expected = { From 24c41147ec2bd938a391792fab15e558a7de5121 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Thu, 28 May 2026 16:43:30 -0700 Subject: [PATCH 04/12] Format SDK justfile test --- sdk/python/tests/test_artifact_workflow_and_binaries.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index 8c6dac135973..3342c28a3cbe 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -81,7 +81,9 @@ def test_root_fmt_recipe_formats_rust_and_python_sdk() -> None: fmt_recipe = lines[fmt_index:next_recipe_index] actual = { "working_directory": lines[0], - "previous_comment": next(line for line in reversed(lines[:fmt_index]) if line.startswith("#")), + "previous_comment": next( + line for line in reversed(lines[:fmt_index]) if line.startswith("#") + ), "commands": [line.strip() for line in fmt_recipe[1:] if line.strip()], } expected = { From 101855ee0c3413596b80a185330c5f6eb761fde2 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Thu, 28 May 2026 17:12:10 -0700 Subject: [PATCH 05/12] Require pwsh for Windows just recipes --- justfile | 75 ++++++++++++++++++++++++++-------- scripts/just-windows-shell.ps1 | 26 ++++++++++++ 2 files changed, 84 insertions(+), 17 deletions(-) create mode 100644 scripts/just-windows-shell.ps1 diff --git a/justfile b/justfile index 4a8a13788ca5..4fe50b9c1270 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,5 @@ set working-directory := "codex-rs" -set windows-shell := ["powershell.exe", "-NoLogo", "-NoProfile", "-Command"] +set windows-shell := ["powershell.exe", "-NoLogo", "-NoProfile", "-File", "../scripts/just-windows-shell.ps1"] rust_min_stack := "8388608" # 8 MiB @@ -15,8 +15,9 @@ codex *args: cargo run --bin codex -- "$@" [windows] +[positional-arguments] codex *args: - cargo run --bin codex -- {{args}} + cargo run --bin codex -- @($args | Select-Object -Skip 1) # `codex exec` [unix] @@ -25,8 +26,9 @@ exec *args: cargo run --bin codex -- exec "$@" [windows] +[positional-arguments] exec *args: - cargo run --bin codex -- exec {{args}} + cargo run --bin codex -- exec @($args | Select-Object -Skip 1) # Start `codex exec-server` and run codex-tui. [unix] @@ -42,8 +44,9 @@ file-search *args: cargo run --bin codex-file-search -- "$@" [windows] +[positional-arguments] file-search *args: - cargo run --bin codex-file-search -- {{args}} + cargo run --bin codex-file-search -- @($args | Select-Object -Skip 1) # Build the CLI and run the app-server test client [unix] @@ -53,9 +56,10 @@ app-server-test-client *args: cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex "$@" [windows] +[positional-arguments] app-server-test-client *args: cargo build -p codex-cli - cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex {{args}} + cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex @($args | Select-Object -Skip 1) # Format Rust and Python SDK code. [unix] @@ -76,8 +80,9 @@ fix *args: cargo clippy --fix --tests --allow-dirty "$@" [windows] +[positional-arguments] fix *args: - cargo clippy --fix --tests --allow-dirty {{args}} + cargo clippy --fix --tests --allow-dirty @($args | Select-Object -Skip 1) [unix] [positional-arguments] @@ -85,12 +90,34 @@ clippy *args: cargo clippy --tests "$@" [windows] +[positional-arguments] clippy *args: - cargo clippy --tests {{args}} + cargo clippy --tests @($args | Select-Object -Skip 1) + +[unix] +install: + rustup show active-toolchain + cargo fetch +[windows] install: + #!powershell.exe -File + $pwsh = Get-Command pwsh.exe -ErrorAction SilentlyContinue + if (-not $pwsh) { + winget install --exact --id Microsoft.PowerShell --source winget --accept-package-agreements --accept-source-agreements + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + } else { + $version = & $pwsh.Source -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + if ([version] $version -lt [version] "7.4") { + winget upgrade --exact --id Microsoft.PowerShell --source winget --accept-package-agreements --accept-source-agreements + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + } + } rustup show active-toolchain + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } cargo fetch + exit $LASTEXITCODE # Run nextest with --no-fail-fast so all tests are run. # @@ -104,8 +131,9 @@ test *args: just bench-smoke [windows] +[positional-arguments] test *args: - $env:RUST_MIN_STACK = "{{ rust_min_stack }}"; cargo nextest run --no-fail-fast {{args}} + $env:RUST_MIN_STACK = "{{ rust_min_stack }}"; cargo nextest run --no-fail-fast @($args | Select-Object -Skip 1) just bench-smoke # Run explicit workspace benchmark targets. @@ -115,8 +143,9 @@ bench *args: cargo bench --workspace --bench '*' "$@" [windows] +[positional-arguments] bench *args: - cargo bench --workspace --bench '*' {{args}} + cargo bench --workspace --bench '*' @($args | Select-Object -Skip 1) # Run benchmark targets once to ensure they start successfully. bench-smoke: @@ -132,21 +161,25 @@ bazel-codex *args: bazel run //codex-rs/cli:codex --run_under="cd $PWD &&" -- "$@" [windows] -[no-cd] +[positional-arguments] bazel-codex *args: - bazel run //codex-rs/cli:codex --run_under='cd /d "{{invocation_directory_native()}}" &&' -- {{args}} + bazel run //codex-rs/cli:codex --run_under='cd /d "{{invocation_directory_native()}}" &&' -- @($args | Select-Object -Skip 1) +[unix] [no-cd] bazel-lock-update: bazel mod deps --lockfile_mode=update +[windows] +bazel-lock-update: + bazel mod deps --lockfile_mode=update + [unix] [no-cd] bazel-lock-check: {{ justfile_directory() }}/scripts/check-module-bazel-lock.sh [windows] -[no-cd] bazel-lock-check: bazel mod deps --lockfile_mode=error; if ($LASTEXITCODE -ne 0) { Write-Error "MODULE.bazel.lock is out of date. Run 'just bazel-lock-update' and commit the updated lockfile."; exit 1 } @@ -176,8 +209,9 @@ mcp-server-run *args: cargo run -p codex-mcp-server -- "$@" [windows] +[positional-arguments] mcp-server-run *args: - cargo run -p codex-mcp-server -- {{args}} + cargo run -p codex-mcp-server -- @($args | Select-Object -Skip 1) # Regenerate the json schema for config.toml from the current config types. write-config-schema: @@ -190,13 +224,19 @@ write-app-server-schema *args: cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- "$@" [windows] +[positional-arguments] write-app-server-schema *args: - cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- {{args}} + cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- @($args | Select-Object -Skip 1) +[unix] [no-cd] write-hooks-schema: cargo run --manifest-path {{ justfile_directory() }}/codex-rs/Cargo.toml -p codex-hooks --bin write_hooks_schema_fixtures +[windows] +write-hooks-schema: + cargo run --manifest-path {{ justfile_directory() }}/codex-rs/Cargo.toml -p codex-hooks --bin write_hooks_schema_fixtures + # Run the argument-comment Dylint checks across codex-rs. [unix] [no-cd] @@ -215,9 +255,9 @@ argument-comment-lint-from-source *args: {{ justfile_directory() }}/tools/argument-comment-lint/run.py "$@" [windows] -[no-cd] +[positional-arguments] argument-comment-lint-from-source *args: - python {{ justfile_directory() }}/tools/argument-comment-lint/run.py {{args}} + python {{ justfile_directory() }}/tools/argument-comment-lint/run.py @($args | Select-Object -Skip 1) # Tail logs from the state SQLite database [unix] @@ -226,5 +266,6 @@ log *args: if [ "${1:-}" = "--" ]; then shift; fi; cargo run -p codex-state --bin logs_client -- "$@" [windows] +[positional-arguments] log *args: - cargo run -p codex-state --bin logs_client -- {{replace(args, "-- ", "")}} + $forwarded_args = @($args | Select-Object -Skip 1); if ($forwarded_args.Count -gt 0 -and $forwarded_args[0] -eq "--") { $forwarded_args = @($forwarded_args | Select-Object -Skip 1) }; cargo run -p codex-state --bin logs_client -- @forwarded_args diff --git a/scripts/just-windows-shell.ps1 b/scripts/just-windows-shell.ps1 new file mode 100644 index 000000000000..b484f6bf9e85 --- /dev/null +++ b/scripts/just-windows-shell.ps1 @@ -0,0 +1,26 @@ +if ($args.Count -eq 0) { + [Console]::Error.WriteLine("Windows just shell adapter expected a recipe command.") + exit 1 +} + +$Command = $args[0] +$ForwardedArgs = @($args | Select-Object -Skip 1) + +$pwsh = Get-Command pwsh.exe -ErrorAction SilentlyContinue +if (-not $pwsh) { + [Console]::Error.WriteLine("PowerShell 7.4+ ('pwsh') is required for Windows just recipes. Run 'just install' to install it.") + exit 1 +} + +$version = & $pwsh.Source -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} + +if ([version] $version -lt [version] "7.4") { + [Console]::Error.WriteLine("PowerShell 7.4+ ('pwsh') is required for Windows just recipes. Run 'just install' to update it.") + exit 1 +} + +& $pwsh.Source -NoLogo -NoProfile -CommandWithArgs $Command @ForwardedArgs +exit $LASTEXITCODE From c28620aaf6c2b4a753dc05aa2916a838a8b8cac9 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 29 May 2026 11:23:47 -0700 Subject: [PATCH 06/12] Use cross-platform just shell adapter --- justfile | 108 ++++----------------------------- scripts/just-shell.py | 70 +++++++++++++++++++++ scripts/just-windows-shell.ps1 | 26 -------- 3 files changed, 83 insertions(+), 121 deletions(-) create mode 100644 scripts/just-shell.py delete mode 100644 scripts/just-windows-shell.ps1 diff --git a/justfile b/justfile index 4fe50b9c1270..56a501dd554a 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,8 @@ set working-directory := "codex-rs" -set windows-shell := ["powershell.exe", "-NoLogo", "-NoProfile", "-File", "../scripts/just-windows-shell.ps1"] +set positional-arguments +python_shell := 'import pathlib, runpy, sys; p = pathlib.Path.cwd().resolve(); script = next((d / "scripts" / "just-shell.py" for d in (p, *p.parents) if (d / "scripts" / "just-shell.py").is_file()), None); sys.exit("could not find scripts/just-shell.py") if script is None else runpy.run_path(str(script), run_name="__main__")' +set shell := ["python3", "-c", python_shell] +set windows-shell := ["python", "-c", python_shell] rust_min_stack := "8388608" # 8 MiB @@ -9,26 +12,12 @@ help: # `codex` alias c := codex -[unix] -[positional-arguments] codex *args: - cargo run --bin codex -- "$@" - -[windows] -[positional-arguments] -codex *args: - cargo run --bin codex -- @($args | Select-Object -Skip 1) + cargo run --bin codex -- {args} # `codex exec` -[unix] -[positional-arguments] -exec *args: - cargo run --bin codex -- exec "$@" - -[windows] -[positional-arguments] exec *args: - cargo run --bin codex -- exec @($args | Select-Object -Skip 1) + cargo run --bin codex -- exec {args} # Start `codex exec-server` and run codex-tui. [unix] @@ -38,28 +27,13 @@ tui-with-exec-server *args: {{ justfile_directory() }}/scripts/run_tui_with_exec_server.sh "$@" # Run the CLI version of the file-search crate. -[unix] -[positional-arguments] -file-search *args: - cargo run --bin codex-file-search -- "$@" - -[windows] -[positional-arguments] file-search *args: - cargo run --bin codex-file-search -- @($args | Select-Object -Skip 1) + cargo run --bin codex-file-search -- {args} # Build the CLI and run the app-server test client -[unix] -[positional-arguments] app-server-test-client *args: cargo build -p codex-cli - cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex "$@" - -[windows] -[positional-arguments] -app-server-test-client *args: - cargo build -p codex-cli - cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex @($args | Select-Object -Skip 1) + cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex {args} # Format Rust and Python SDK code. [unix] @@ -74,25 +48,11 @@ fmt: uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python uv run --frozen --project ../sdk/python --extra dev ruff format ../sdk/python -[unix] -[positional-arguments] fix *args: - cargo clippy --fix --tests --allow-dirty "$@" - -[windows] -[positional-arguments] -fix *args: - cargo clippy --fix --tests --allow-dirty @($args | Select-Object -Skip 1) - -[unix] -[positional-arguments] -clippy *args: - cargo clippy --tests "$@" + cargo clippy --fix --tests --allow-dirty {args} -[windows] -[positional-arguments] clippy *args: - cargo clippy --tests @($args | Select-Object -Skip 1) + cargo clippy --tests {args} [unix] install: @@ -106,13 +66,6 @@ install: if (-not $pwsh) { winget install --exact --id Microsoft.PowerShell --source winget --accept-package-agreements --accept-source-agreements if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - } else { - $version = & $pwsh.Source -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - if ([version] $version -lt [version] "7.4") { - winget upgrade --exact --id Microsoft.PowerShell --source winget --accept-package-agreements --accept-source-agreements - if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - } } rustup show active-toolchain if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } @@ -125,27 +78,18 @@ install: # Prefer this for routine local runs. Workspace crate features are banned, so # there should be no need to add `--all-features`. [unix] -[positional-arguments] test *args: RUST_MIN_STACK={{ rust_min_stack }} cargo nextest run --no-fail-fast "$@" just bench-smoke [windows] -[positional-arguments] test *args: $env:RUST_MIN_STACK = "{{ rust_min_stack }}"; cargo nextest run --no-fail-fast @($args | Select-Object -Skip 1) just bench-smoke # Run explicit workspace benchmark targets. -[unix] -[positional-arguments] -bench *args: - cargo bench --workspace --bench '*' "$@" - -[windows] -[positional-arguments] bench *args: - cargo bench --workspace --bench '*' @($args | Select-Object -Skip 1) + cargo bench --workspace --bench '*' {args} # Run benchmark targets once to ensure they start successfully. bench-smoke: @@ -156,12 +100,10 @@ bench-smoke: # the command in the current working directory. [unix] [no-cd] -[positional-arguments] bazel-codex *args: bazel run //codex-rs/cli:codex --run_under="cd $PWD &&" -- "$@" [windows] -[positional-arguments] bazel-codex *args: bazel run //codex-rs/cli:codex --run_under='cd /d "{{invocation_directory_native()}}" &&' -- @($args | Select-Object -Skip 1) @@ -203,44 +145,24 @@ build-for-release: bazel build //codex-rs/cli:release_binaries --config=remote # Run the MCP server -[unix] -[positional-arguments] mcp-server-run *args: - cargo run -p codex-mcp-server -- "$@" - -[windows] -[positional-arguments] -mcp-server-run *args: - cargo run -p codex-mcp-server -- @($args | Select-Object -Skip 1) + cargo run -p codex-mcp-server -- {args} # Regenerate the json schema for config.toml from the current config types. write-config-schema: cargo run -p codex-core --bin codex-write-config-schema # Regenerate vendored app-server protocol schema artifacts. -[unix] -[positional-arguments] write-app-server-schema *args: - cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- "$@" + cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- {args} -[windows] -[positional-arguments] -write-app-server-schema *args: - cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- @($args | Select-Object -Skip 1) - -[unix] [no-cd] write-hooks-schema: cargo run --manifest-path {{ justfile_directory() }}/codex-rs/Cargo.toml -p codex-hooks --bin write_hooks_schema_fixtures -[windows] -write-hooks-schema: - cargo run --manifest-path {{ justfile_directory() }}/codex-rs/Cargo.toml -p codex-hooks --bin write_hooks_schema_fixtures - # Run the argument-comment Dylint checks across codex-rs. [unix] [no-cd] -[positional-arguments] argument-comment-lint *args: if [ "$#" -eq 0 ]; then \ bazel build --config=argument-comment-lint -- $({{ justfile_directory() }}/tools/argument-comment-lint/list-bazel-targets.sh); \ @@ -250,22 +172,18 @@ argument-comment-lint *args: [unix] [no-cd] -[positional-arguments] argument-comment-lint-from-source *args: {{ justfile_directory() }}/tools/argument-comment-lint/run.py "$@" [windows] -[positional-arguments] argument-comment-lint-from-source *args: python {{ justfile_directory() }}/tools/argument-comment-lint/run.py @($args | Select-Object -Skip 1) # Tail logs from the state SQLite database [unix] -[positional-arguments] log *args: if [ "${1:-}" = "--" ]; then shift; fi; cargo run -p codex-state --bin logs_client -- "$@" [windows] -[positional-arguments] log *args: $forwarded_args = @($args | Select-Object -Skip 1); if ($forwarded_args.Count -gt 0 -and $forwarded_args[0] -eq "--") { $forwarded_args = @($forwarded_args | Select-Object -Skip 1) }; cargo run -p codex-state --bin logs_client -- @forwarded_args diff --git a/scripts/just-shell.py b/scripts/just-shell.py new file mode 100644 index 000000000000..4ca61309cb1d --- /dev/null +++ b/scripts/just-shell.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""Cross-platform shell launcher for `just` recipes. + +This keeps recipe bodies as normal shell snippets while giving the justfile one +portable placeholder, `{args}`, for forwarding variadic recipe arguments. +""" + +from __future__ import annotations + +import os +import shutil +import subprocess +import sys + + +ARGS_TOKEN = "{args}" +POWERSHELL_ARGS = "@($args | Select-Object -Skip 1)" +SH_ARGS = '"$@"' + + +def main() -> int: + if len(sys.argv) < 2: + print("just shell adapter expected a recipe command.", file=sys.stderr) + return 1 + + command = sys.argv[1] + recipe_name = sys.argv[2] if len(sys.argv) > 2 else "" + recipe_args = sys.argv[3:] + + if os.name == "nt": + return run_powershell(command, recipe_name, recipe_args) + else: + return run_sh(command, recipe_name, recipe_args) + + +def run_sh(command: str, recipe_name: str, recipe_args: list[str]) -> int: + command = command.replace(ARGS_TOKEN, SH_ARGS) + return subprocess.run( + ["sh", "-cu", command, recipe_name, *recipe_args], + check=False, + ).returncode + + +def run_powershell(command: str, recipe_name: str, recipe_args: list[str]) -> int: + pwsh = shutil.which("pwsh.exe") or shutil.which("pwsh") + if pwsh is None: + print( + "PowerShell ('pwsh') is required for Windows just recipes. " + "Run 'just install' to install it.", + file=sys.stderr, + ) + return 1 + + command = command.replace(ARGS_TOKEN, POWERSHELL_ARGS) + return subprocess.run( + [ + pwsh, + "-NoLogo", + "-NoProfile", + "-CommandWithArgs", + command, + recipe_name, + *recipe_args, + ], + check=False, + ).returncode + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/just-windows-shell.ps1 b/scripts/just-windows-shell.ps1 deleted file mode 100644 index b484f6bf9e85..000000000000 --- a/scripts/just-windows-shell.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -if ($args.Count -eq 0) { - [Console]::Error.WriteLine("Windows just shell adapter expected a recipe command.") - exit 1 -} - -$Command = $args[0] -$ForwardedArgs = @($args | Select-Object -Skip 1) - -$pwsh = Get-Command pwsh.exe -ErrorAction SilentlyContinue -if (-not $pwsh) { - [Console]::Error.WriteLine("PowerShell 7.4+ ('pwsh') is required for Windows just recipes. Run 'just install' to install it.") - exit 1 -} - -$version = & $pwsh.Source -NoLogo -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' -if ($LASTEXITCODE -ne 0) { - exit $LASTEXITCODE -} - -if ([version] $version -lt [version] "7.4") { - [Console]::Error.WriteLine("PowerShell 7.4+ ('pwsh') is required for Windows just recipes. Run 'just install' to update it.") - exit 1 -} - -& $pwsh.Source -NoLogo -NoProfile -CommandWithArgs $Command @ForwardedArgs -exit $LASTEXITCODE From d6ce69481e89b718a5dd841838b99663c287fb06 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 29 May 2026 15:18:58 -0700 Subject: [PATCH 07/12] Simplify just shell adapter lookup --- justfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/justfile b/justfile index 56a501dd554a..e9f9e966f7ee 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,7 @@ set working-directory := "codex-rs" set positional-arguments -python_shell := 'import pathlib, runpy, sys; p = pathlib.Path.cwd().resolve(); script = next((d / "scripts" / "just-shell.py" for d in (p, *p.parents) if (d / "scripts" / "just-shell.py").is_file()), None); sys.exit("could not find scripts/just-shell.py") if script is None else runpy.run_path(str(script), run_name="__main__")' +export JUST_SHELL := justfile_directory() / "scripts/just-shell.py" +python_shell := 'import os, runpy; runpy.run_path(os.environ["JUST_SHELL"], run_name="__main__")' set shell := ["python3", "-c", python_shell] set windows-shell := ["python", "-c", python_shell] From 65a021073cacb924048438c84e7dc9a248946091 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 29 May 2026 15:21:57 -0700 Subject: [PATCH 08/12] Unify bazel lock update recipe --- justfile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/justfile b/justfile index e9f9e966f7ee..b27d5651d7ab 100644 --- a/justfile +++ b/justfile @@ -108,15 +108,10 @@ bazel-codex *args: bazel-codex *args: bazel run //codex-rs/cli:codex --run_under='cd /d "{{invocation_directory_native()}}" &&' -- @($args | Select-Object -Skip 1) -[unix] [no-cd] bazel-lock-update: bazel mod deps --lockfile_mode=update -[windows] -bazel-lock-update: - bazel mod deps --lockfile_mode=update - [unix] [no-cd] bazel-lock-check: From 957aca2ef2e62be3fc4bfa69ae3624096708d2d6 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 29 May 2026 15:23:40 -0700 Subject: [PATCH 09/12] Unify argument comment lint source recipe --- justfile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/justfile b/justfile index b27d5651d7ab..9eaff2425fcc 100644 --- a/justfile +++ b/justfile @@ -6,6 +6,7 @@ set shell := ["python3", "-c", python_shell] set windows-shell := ["python", "-c", python_shell] rust_min_stack := "8388608" # 8 MiB +python := if os_family() == "windows" { "python" } else { "python3" } # Display help help: @@ -166,14 +167,9 @@ argument-comment-lint *args: {{ justfile_directory() }}/tools/argument-comment-lint/run-prebuilt-linter.py "$@"; \ fi -[unix] [no-cd] argument-comment-lint-from-source *args: - {{ justfile_directory() }}/tools/argument-comment-lint/run.py "$@" - -[windows] -argument-comment-lint-from-source *args: - python {{ justfile_directory() }}/tools/argument-comment-lint/run.py @($args | Select-Object -Skip 1) + {{ python }} {{ justfile_directory() }}/tools/argument-comment-lint/run.py {args} # Tail logs from the state SQLite database [unix] From fce27d47544a07422fb57c5e48532d7a4cc8a853 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 29 May 2026 15:33:54 -0700 Subject: [PATCH 10/12] Unify fmt just recipe --- justfile | 9 +-------- scripts/just-shell.py | 5 +++++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/justfile b/justfile index 9eaff2425fcc..a319bf147274 100644 --- a/justfile +++ b/justfile @@ -38,15 +38,8 @@ app-server-test-client *args: cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex {args} # Format Rust and Python SDK code. -[unix] -fmt: - cargo fmt -- --config imports_granularity=Item 2>/dev/null - uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python - uv run --frozen --project ../sdk/python --extra dev ruff format ../sdk/python - -[windows] fmt: - cargo fmt -- --config imports_granularity=Item 2>$null; exit $LASTEXITCODE + cargo fmt -- --config imports_granularity=Item {stderr-null} uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python uv run --frozen --project ../sdk/python --extra dev ruff format ../sdk/python diff --git a/scripts/just-shell.py b/scripts/just-shell.py index 4ca61309cb1d..ba7595123e44 100644 --- a/scripts/just-shell.py +++ b/scripts/just-shell.py @@ -14,8 +14,11 @@ ARGS_TOKEN = "{args}" +STDERR_NULL_TOKEN = "{stderr-null}" POWERSHELL_ARGS = "@($args | Select-Object -Skip 1)" +POWERSHELL_STDERR_NULL = '2>$null; exit $LASTEXITCODE' SH_ARGS = '"$@"' +SH_STDERR_NULL = "2>/dev/null" def main() -> int: @@ -35,6 +38,7 @@ def main() -> int: def run_sh(command: str, recipe_name: str, recipe_args: list[str]) -> int: command = command.replace(ARGS_TOKEN, SH_ARGS) + command = command.replace(STDERR_NULL_TOKEN, SH_STDERR_NULL) return subprocess.run( ["sh", "-cu", command, recipe_name, *recipe_args], check=False, @@ -52,6 +56,7 @@ def run_powershell(command: str, recipe_name: str, recipe_args: list[str]) -> in return 1 command = command.replace(ARGS_TOKEN, POWERSHELL_ARGS) + command = command.replace(STDERR_NULL_TOKEN, POWERSHELL_STDERR_NULL) return subprocess.run( [ pwsh, From 1ed627cf1b8488d926817cf68e2b3d46833ef8e8 Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Fri, 29 May 2026 15:38:25 -0700 Subject: [PATCH 11/12] Fix justfile CI checks --- justfile | 5 ++--- sdk/python/tests/test_artifact_workflow_and_binaries.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/justfile b/justfile index a319bf147274..53b37e24caa4 100644 --- a/justfile +++ b/justfile @@ -1,9 +1,8 @@ set working-directory := "codex-rs" set positional-arguments export JUST_SHELL := justfile_directory() / "scripts/just-shell.py" -python_shell := 'import os, runpy; runpy.run_path(os.environ["JUST_SHELL"], run_name="__main__")' -set shell := ["python3", "-c", python_shell] -set windows-shell := ["python", "-c", python_shell] +set shell := ["python3", "-c", 'import os, runpy; runpy.run_path(os.environ["JUST_SHELL"], run_name="__main__")'] +set windows-shell := ["python", "-c", 'import os, runpy; runpy.run_path(os.environ["JUST_SHELL"], run_name="__main__")'] rust_min_stack := "8388608" # 8 MiB python := if os_family() == "windows" { "python" } else { "python3" } diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index 3342c28a3cbe..a6a338bb9866 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -90,7 +90,7 @@ def test_root_fmt_recipe_formats_rust_and_python_sdk() -> None: "working_directory": 'set working-directory := "codex-rs"', "previous_comment": "# Format Rust and Python SDK code.", "commands": [ - "cargo fmt -- --config imports_granularity=Item 2>/dev/null", + "cargo fmt -- --config imports_granularity=Item {stderr-null}", "uv run --frozen --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python", "uv run --frozen --project ../sdk/python --extra dev ruff format ../sdk/python", ], From 9c9e30529edbb5626b22ef32b4250be62455057c Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Mon, 1 Jun 2026 11:16:57 -0700 Subject: [PATCH 12/12] Exec Unix just shell adapter --- scripts/just-shell.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/just-shell.py b/scripts/just-shell.py index ba7595123e44..423e56dafec9 100644 --- a/scripts/just-shell.py +++ b/scripts/just-shell.py @@ -39,10 +39,7 @@ def main() -> int: def run_sh(command: str, recipe_name: str, recipe_args: list[str]) -> int: command = command.replace(ARGS_TOKEN, SH_ARGS) command = command.replace(STDERR_NULL_TOKEN, SH_STDERR_NULL) - return subprocess.run( - ["sh", "-cu", command, recipe_name, *recipe_args], - check=False, - ).returncode + os.execvp("sh", ["sh", "-cu", command, recipe_name, *recipe_args]) def run_powershell(command: str, recipe_name: str, recipe_args: list[str]) -> int: