#!/usr/bin/env just set shell := ["nu", "-c"] set windows-shell := ["nu", "-c"] set positional-arguments := true set allow-duplicate-variables := true project_root := justfile_directory() msrv := "1.92.0" # ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ # # Recipes # # ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ # [doc('List all available recipes')] default: @just --list [doc('Check workspace for compilation errors')] [group('build')] check *flags: @echo "🔎 Checking workspace..." cargo check --workspace {{ flags }} [doc('Build workspace (all targets, debug)')] [group('build')] build *flags: @echo "🔨 Building workspace..." cargo build --workspace --all-targets {{ flags }} [doc('Build workspace in release mode')] [group('build')] build-release *flags: @echo "🚀 Building workspace (release)..." cargo build --workspace --release {{ flags }} [doc('Build Linux-specific crates')] [group('build')] build-linux: @echo "🐧 Building Linux crates..." cargo build -p gpui_linux [doc('Build macOS-specific crates')] [group('build')] build-mac: @echo "🍎 Building macOS crates..." cargo build -p gpui_macos [doc('Build Windows-specific crates')] [group('build')] build-windows: @echo "🪟 Building Windows crates..." cargo build -p gpui_windows [doc('Build all GPUI examples')] [group('build')] build-examples: @echo "📐 Building examples..." cargo build --package gpui --examples [doc('Check WASM target (stable) — requires wasm32-unknown-unknown target to be installed')] [group('build')] check-wasm: @echo "🕸️ Checking WASM target (stable)..." cargo check --target wasm32-unknown-unknown --no-default-features -p gpui_platform [doc('Check WASM target with atomics (nightly) — requires nightly + rust-src component')] [group('build')] check-wasm-atomics: #!/usr/bin/env nu if ((which rustup | length) == 0) { print "⚠️ Skipping WASM atomics: rustup not installed (required for +nightly)" exit 0 } print "🕸️ Checking WASM target with atomics (nightly)..." with-env {CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS: "-C target-feature=+atomics,+bulk-memory,+mutable-globals"} { cargo +nightly -Zbuild-std=std,panic_abort check --target wasm32-unknown-unknown -p gpui_platform } [doc('Check examples + WASM web package — requires wasm32-unknown-unknown target to be installed')] [group('build')] check-examples: @echo "📐 Checking examples..." cargo build --package gpui --examples cargo check --package gpui_web --target wasm32-unknown-unknown [doc('Run all workspace unit and integration tests')] [group('testing')] test *flags: @echo "🧪 Running workspace tests..." cargo test --workspace --no-fail-fast {{ flags }} [doc('Run all workspace doc tests')] [group('testing')] test-doc: @echo "🧪 Running doc tests..." cargo test --workspace --doc --no-fail-fast [doc('Run tests with nextest (faster parallel runner)')] [group('testing')] test-nextest: @echo "🧪 Running tests with nextest..." cargo nextest run --workspace [doc('Run workspace tests with a fixed seed for reproducibility')] [group('testing')] test-with-seed seed="12345": #!/usr/bin/env nu print $"🧪 Running tests with seed {{ seed }}..." with-env {SEED: '{{ seed }}'} { cargo test --workspace } [doc('Run workspace tests with additional arguments')] [group('testing')] test-with +args: @echo "🧪 Running workspace tests with args..." cargo test --workspace -- {{ args }} [doc('Format all Rust code in the workspace')] [group('quality')] fmt: @echo "💅 Formatting Rust code..." cargo fmt --all [doc('Check Rust code formatting without modifying files')] [group('quality')] fmt-check: @echo "💅 Checking Rust code formatting..." cargo fmt --all -- --check [doc('Lint with Clippy (all targets, deny warnings)')] [group('quality')] clippy *flags: @echo "🔍 Running Clippy..." cargo clippy --workspace --all-targets -- -D warnings {{ flags }} [doc('Run Clippy for a specific target triple')] [group('quality')] clippy-target target: @echo "🔍 Running Clippy for target {{ target }}..." cargo clippy --workspace --all-targets --target {{ target }} -- -D warnings [doc('Automatically fix Clippy lints where possible')] [group('quality')] clippy-fix: @echo "🩹 Fixing Clippy lints..." cargo clippy --workspace --all-targets --fix --allow-dirty --allow-staged -- -D warnings [doc('Run typos spell checker')] [group('quality')] typos: @echo "🔤 Checking for typos..." typos [doc('Check TOML formatting with taplo')] [group('quality')] taplo: @echo "📋 Checking TOML formatting..." taplo fmt --check [doc('Check for unused dependencies')] [group('quality')] machete: @echo "⚙️ Checking for unused dependencies..." cargo machete [doc('Check workspace against MSRV — requires {{ msrv }} toolchain to be installed')] [group('quality')] msrv-check: @echo "🦀 Checking MSRV ({{ msrv }})..." cargo +{{ msrv }} check --workspace [doc('Run all quality checks: fmt-check, clippy, typos, taplo, machete')] [group('quality')] lint: fmt-check clippy typos taplo machete [doc('Verify packages conform to workspace standards')] [group('quality')] check-packages: @echo "✅ Package conformity checks passed." [doc('Run full CI suite locally — mirrors GitHub Actions, reports all failures before exiting')] [group('ci')] ci: #!/usr/bin/env nu def run-check [name: string, block: closure] { print $"\n▶ ($name)" let code = try { do $block; $env.LAST_EXIT_CODE } catch { 1 } if $code == 0 { print $"✅ ($name)" {name: $name, ok: true} } else { print $"❌ ($name)" {name: $name, ok: false} } } def available [tool: string] { (which $tool | length) > 0 } def skip [name: string, reason: string] { print $"\n⚠️ Skipping ($name): ($reason)" {name: $name, ok: true} } let msrv = '{{ msrv }}' let results = [ (run-check "cargo fmt" { cargo fmt --all -- --check }) (run-check "cargo clippy" { cargo clippy --workspace --all-targets -- -D warnings }) (run-check "cargo build" { cargo build --workspace --all-targets }) (run-check "cargo test" { cargo test --workspace --no-fail-fast }) (run-check "doc tests" { cargo test --workspace --doc --no-fail-fast }) (run-check "WASM stable" { cargo check --target wasm32-unknown-unknown --no-default-features -p gpui_platform }) (if (available "rustup") { run-check "WASM atomics" { with-env {CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS: "-C target-feature=+atomics,+bulk-memory,+mutable-globals"} { cargo +nightly -Zbuild-std=std,panic_abort check --target wasm32-unknown-unknown -p gpui_platform } } } else { skip "WASM atomics" "rustup not installed (required for +nightly)" }) (run-check "check examples" { cargo build --package gpui --examples cargo check --package gpui_web --target wasm32-unknown-unknown }) (if (available "typos") { run-check "typos" { typos } } else { skip "typos" "not installed" }) (if (available "taplo") { run-check "taplo" { taplo fmt --check } } else { skip "taplo" "not installed" }) (if (available "cargo-machete") { run-check "cargo machete" { cargo machete } } else { skip "cargo machete" "install: cargo install cargo-machete" }) (if (available "rustup") { run-check $"MSRV ($msrv)" { run-external "cargo" $"+($msrv)" "check" "--workspace" } } else { skip $"MSRV ($msrv)" "rustup not installed" }) ] let failures = ($results | where ok == false | get name) if ($failures | length) > 0 { let failed_list = ($failures | str join ", ") print $"\n❌ ($failures | length) checks failed: ($failed_list)" exit 1 } print "\n✅ All checks passed!" [doc('Run tidy checks only: fmt, clippy, typos, taplo, machete, MSRV')] [group('ci')] ci-tidy: #!/usr/bin/env nu def run-check [name: string, block: closure] { print $"\n▶ ($name)" let code = try { do $block; $env.LAST_EXIT_CODE } catch { 1 } if $code == 0 { print $"✅ ($name)" {name: $name, ok: true} } else { print $"❌ ($name)" {name: $name, ok: false} } } def available [tool: string] { (which $tool | length) > 0 } def skip [name: string, reason: string] { print $"\n⚠️ Skipping ($name): ($reason)" {name: $name, ok: true} } let msrv = '{{ msrv }}' let results = [ (run-check "cargo fmt" { cargo fmt --all -- --check }) (run-check "cargo clippy" { cargo clippy --workspace --all-targets -- -D warnings }) (if (available "typos") { run-check "typos" { typos } } else { skip "typos" "not installed" }) (if (available "taplo") { run-check "taplo" { taplo fmt --check } } else { skip "taplo" "not installed" }) (if (available "cargo-machete") { run-check "cargo machete" { cargo machete } } else { skip "cargo machete" "install: cargo install cargo-machete" }) (if (available "rustup") { run-check $"MSRV ($msrv)" { run-external "cargo" $"+($msrv)" "check" "--workspace" } } else { skip $"MSRV ($msrv)" "rustup not installed" }) ] let failures = ($results | where ok == false | get name) if ($failures | length) > 0 { let failed_list = ($failures | str join ", ") print $"\n❌ ($failures | length) checks failed: ($failed_list)" exit 1 } print "\n✅ Tidy checks passed!" [doc('Run build + unit tests + doc tests')] [group('ci')] ci-test: #!/usr/bin/env nu def run-check [name: string, block: closure] { print $"\n▶ ($name)" let code = try { do $block; $env.LAST_EXIT_CODE } catch { 1 } if $code == 0 { print $"✅ ($name)" {name: $name, ok: true} } else { print $"❌ ($name)" {name: $name, ok: false} } } let results = [ (run-check "cargo build" { cargo build --workspace --all-targets }) (run-check "cargo test" { cargo test --workspace --no-fail-fast }) (run-check "doc tests" { cargo test --workspace --doc --no-fail-fast }) ] let failures = ($results | where ok == false | get name) if ($failures | length) > 0 { let failed_list = ($failures | str join ", ") print $"\n❌ ($failures | length) checks failed: ($failed_list)" exit 1 } print "\n✅ Tests passed!" [doc('Check both WASM targets: stable and nightly atomics')] [group('ci')] ci-wasm: check-wasm check-wasm-atomics [doc('Clear the target directory if it exceeds a size threshold in MB')] [group('maintenance')] clear-target threshold_mb="300" target_dir="target": #!/usr/bin/env nu let threshold_mb = ('{{ threshold_mb }}' | into int) let target_dir = '{{ target_dir }}' if not ($target_dir | path exists) { print $"Target directory '($target_dir)' does not exist, skipping." exit 0 } let size_bytes = (du $target_dir | get physical | first | into int) let size_mb = ($size_bytes / 1048576 | into int) print $"Target directory size: ($size_mb) MB [threshold: ($threshold_mb) MB]" if $size_mb > $threshold_mb { print "Exceeds threshold, clearing build caches..." let debug_dir = ($target_dir | path join "debug") if ($debug_dir | path exists) { let stale = ( [ (glob $"($debug_dir)/**/*.d") (glob $"($debug_dir)/**/*.o") (glob $"($debug_dir)/**/*.rlib") ] | flatten | first 10000 ) $stale | each { |f| rm --force $f } } print "Cleanup complete." } else { print "Target directory is within acceptable size." } [doc('Update Cargo dependencies')] [group('maintenance')] update: @echo "🔄 Updating dependencies..." cargo update [doc('Show outdated dependencies')] [group('maintenance')] outdated: @echo "📋 Checking for outdated dependencies..." cargo outdated [doc('Clean build artifacts')] [group('maintenance')] clean: @echo "🧹 Cleaning build artifacts..." cargo clean [doc('Publish GPUI crates to crates.io in dependency order (dry="true" for a dry run)')] [group('release')] publish dry="false": #!/usr/bin/env nu let dry_run = ('{{ dry }}' == "true") let status = (^git status --porcelain | str trim) if ($status | str length) > 0 { error make {msg: "Working directory is not clean. Commit or stash changes before publishing."} } if not ("CARGO_REGISTRY_TOKEN" in $env) { error make {msg: "CARGO_REGISTRY_TOKEN is not set"} } # Topological publish order. Vendored support crates first, then core, # then renderers/platform leaves, with gpui_platform LAST (it has # target-conditional deps on every platform crate). let crates = [ "crates/gpui_ce_util/Cargo.toml" "crates/gpui_collections/Cargo.toml" "crates/gpui_derive_refineable/Cargo.toml" "crates/gpui_refineable/Cargo.toml" "crates/gpui_sum_tree/Cargo.toml" "crates/gpui_scheduler/Cargo.toml" "crates/gpui_media/Cargo.toml" "crates/gpui_zed_util/Cargo.toml" # core "crates/gpui_shared_string/Cargo.toml" "crates/gpui_macros/Cargo.toml" "crates/gpui/Cargo.toml" # renderers / platform leaves "crates/gpui_wgpu/Cargo.toml" "crates/gpui_tokio/Cargo.toml" "crates/gpui_macos/Cargo.toml" "crates/gpui_linux/Cargo.toml" "crates/gpui_windows/Cargo.toml" "crates/gpui_web/Cargo.toml" "crates/gpui_elements/Cargo.toml" "crates/gpui_platform/Cargo.toml" ] let dry_flag = if $dry_run { ["--dry-run"] } else { [] } for manifest in $crates { let name = ($manifest | path dirname | path basename) print $"\n📦 Publishing ($name)..." run-external "cargo" "publish" "--manifest-path" $manifest "--allow-dirty" ...$dry_flag if $env.LAST_EXIT_CODE != 0 { error make {msg: $"Failed to publish ($name)"} } } print "\n✅ All crates published!" [doc('Sync upstream Zed GPUI changes into this fork (local-only, never pushes)')] [group('sync')] sync-upstream *args: @python3 {{ project_root }}/scripts/sync-upstream/sync_upstream.py sync {{ args }} [doc('One-time: record the upstream baseline to sync from (defaults to the pinned zed dep rev)')] [group('sync')] sync-upstream-bootstrap *args: @python3 {{ project_root }}/scripts/sync-upstream/sync_upstream.py bootstrap {{ args }} [doc('Show how far behind upstream Zed GPUI this fork is')] [group('sync')] sync-upstream-status: @python3 {{ project_root }}/scripts/sync-upstream/sync_upstream.py status [doc('Generate project documentation')] [group('docs')] doc *flags: @echo "📚 Generating documentation..." cargo doc --workspace --no-deps {{ flags }} [doc('Generate and open project documentation in browser')] [group('docs')] doc-open: @echo "📚 Opening documentation in browser..." cargo doc --workspace --no-deps --open [doc('Run a specific example by name')] [group('development')] example name: @echo "▶️ Running example {{ name }}..." cargo run --example {{ name }} alias b := build alias br := build-release alias c := check alias t := test alias td := test-doc alias f := fmt alias fc := fmt-check alias clp := clippy alias clf := clippy-fix alias l := lint alias d := doc alias up := update alias cl := clean alias sync := sync-upstream