Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
ca3f9a7
feat(cli): global -C flag and workspace-root target elicitation for a…
fengmk2 Jul 3, 2026
fea02f4
refactor(cli): dedupe interactivity gate and vite config probing, nor…
fengmk2 Jul 3, 2026
419fdcc
refactor: memoized terminal checks behind a clippy rule, document -C …
fengmk2 Jul 3, 2026
d278b23
rfc: global -C flag for working-directory switching
fengmk2 Jul 3, 2026
c03af20
fix(snap): sort vite_shared exports, show raw error output in root fi…
fengmk2 Jul 3, 2026
1f60fbb
docs(monorepo): document the workspace-root app-command experience
fengmk2 Jul 3, 2026
b77d83a
test(snap): add -C to the vp --help snapshot
fengmk2 Jul 4, 2026
fb19167
test(snap): reset dist between pack forms to avoid platform-dependent…
fengmk2 Jul 4, 2026
aad2eb5
test(snapshot): PTY coverage for app-root resolution
fengmk2 Jul 5, 2026
67a9e75
feat(cli): interactive package picker for bare app commands at the wo…
fengmk2 Jul 5, 2026
97f7ce5
test(snapshot): migrate cwd-flag and app-root snap tests to the PTY h…
fengmk2 Jul 5, 2026
66aaa9a
fix(cli): document -C in the local CLI help
fengmk2 Jul 5, 2026
54a185c
fix(cli): pack runnable ranking requires a pack block or the tsdown d…
fengmk2 Jul 5, 2026
0f4d744
rfc: cite upstream defaults behind the runnable heuristic
fengmk2 Jul 5, 2026
a865799
test(snapshot): vp pack auto-select via tsdown default entry
fengmk2 Jul 5, 2026
037cf9d
test(snapshot): single-package repos bypass elicitation
fengmk2 Jul 5, 2026
5b42a1a
refactor(cli): apply cleanup review to app-target elicitation
fengmk2 Jul 5, 2026
f99d6b7
test(snapshot): re-record for byte-size redaction
fengmk2 Jul 5, 2026
3b684f9
fix(cli): address Codex review round 1
fengmk2 Jul 5, 2026
fe8d4b8
fix(cli): address Codex review round 2
fengmk2 Jul 5, 2026
c3851cf
fix(cli): address Codex review round 3
fengmk2 Jul 5, 2026
fbff0ee
fix(cli): address Codex review round 4
fengmk2 Jul 5, 2026
358c487
fix(cli): address Codex review round 5
fengmk2 Jul 5, 2026
946f173
fix(cli): address Codex review round 6
fengmk2 Jul 5, 2026
6cdf76d
test(snapshot): pin the member defaultPackage regression on a real wo…
fengmk2 Jul 5, 2026
0c5a6fe
fix(cli): address Codex review round 7
fengmk2 Jul 5, 2026
5f6a506
fix(cli): restore parse_leading_chdir test import lost in a restack
fengmk2 Jul 5, 2026
21151fb
fix(cli): address Codex review round 9
fengmk2 Jul 5, 2026
8a7d2e1
fix(cli): treat pack --root as an explicit target
fengmk2 Jul 6, 2026
f4b2bdf
fix(cli): gate picker milestones behind VP_EMIT_MILESTONES
fengmk2 Jul 6, 2026
039224c
fix(cli): make chdir the single -C validation point in bin.ts
fengmk2 Jul 6, 2026
e4f1abd
refactor(cli): apply cleanup review across the -C and elicitation code
fengmk2 Jul 6, 2026
9508897
fix(cli): keep normalize_args doc off apply_chdir
fengmk2 Jul 6, 2026
54e2751
fix(cli): a runnable workspace root runs in place, TTY or not
fengmk2 Jul 6, 2026
ac1bed1
test(snapshot): pin the non-TTY runnable-root rule on tsdown output only
fengmk2 Jul 6, 2026
7e74967
test(snapshot): re-record runnable-root headers for the comment change
fengmk2 Jul 6, 2026
486cc2f
build: bump vite-task pin to the #510 head (ca55bb232aa8) after v0.2.…
fengmk2 Jul 7, 2026
4d10d75
perf(cli): reuse the workspace root across target resolution
fengmk2 Jul 8, 2026
516ae04
ci: bound the PTY snapshot step with a 10-min timeout
fengmk2 Jul 8, 2026
2f80ce0
test(snapshot): cover vpr -C and the dev/build positional (Vite root)
fengmk2 Jul 9, 2026
8ab0433
fix(cli): honor TS-wrapped defaultPackage and config-only root builds
fengmk2 Jul 9, 2026
e9152e6
fix(cli): refine defaultPackage/root-build/config-flag handling per r…
fengmk2 Jul 9, 2026
61eca4b
test(snapshots): PTY-render the two build cases for Windows stability
fengmk2 Jul 9, 2026
68e62e6
fix(cli): address Codex review round 6
fengmk2 Jul 9, 2026
fe05f65
style: rustfmt the round-6 defaultPackage extractor tests
fengmk2 Jul 9, 2026
e8b69f6
test(snapshots): remove the temporary PTY step trace
fengmk2 Jul 9, 2026
9c4cde0
fix(cli): hand-emit picker milestones after the vite-task cb580c2 rebase
fengmk2 Jul 10, 2026
75b5e8d
fix(cli): deliver PWD to -C children on the non-JS spawn paths
fengmk2 Jul 10, 2026
57db0c3
chore(snapshots): drop a stray .md.new runner artifact
fengmk2 Jul 10, 2026
51802f5
test(snapshots): skip the PWD env-exec case on Windows
fengmk2 Jul 10, 2026
e3e287c
refactor(cli): apply simplify-review cleanups across the -C code
fengmk2 Jul 10, 2026
9211a3a
refactor(cli): use cfg! branches for the unix-only PWD sync
fengmk2 Jul 10, 2026
fd3c322
docs: tighten the -C RFC and monorepo guide prose
fengmk2 Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clippy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ disallowed-methods = [
{ path = "str::replace", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_replace` instead." },
{ path = "str::replacen", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_replacen` instead." },
{ path = "std::env::current_dir", reason = "To get an `AbsolutePathBuf`, Use `vite_path::current_dir` instead." },
{ path = "std::io::IsTerminal::is_terminal", reason = "Use `vite_powershell::is_stdin_terminal` for stdin, or `vite_shared::is_stdout_terminal` / `vite_shared::is_stderr_terminal`, which memoize the lookup." },
Comment thread
fengmk2 marked this conversation as resolved.
Comment thread
fengmk2 marked this conversation as resolved.
]

disallowed-types = [
Expand Down
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ vite_shared = { path = "crates/vite_shared" }
vite_static_config = { path = "crates/vite_static_config" }
vite_path = { git = "https://github.com/voidzero-dev/vite-task.git", rev = "cb580c214bb2314fc1f633a3812782c9b3a1d956" }
vite_powershell = { git = "https://github.com/voidzero-dev/vite-task.git", rev = "cb580c214bb2314fc1f633a3812782c9b3a1d956" }
vite_select = { git = "https://github.com/voidzero-dev/vite-task.git", rev = "cb580c214bb2314fc1f633a3812782c9b3a1d956" }
vite_str = { git = "https://github.com/voidzero-dev/vite-task.git", rev = "cb580c214bb2314fc1f633a3812782c9b3a1d956" }
vite_task = { git = "https://github.com/voidzero-dev/vite-task.git", rev = "cb580c214bb2314fc1f633a3812782c9b3a1d956" }
vite_workspace = { git = "https://github.com/voidzero-dev/vite-task.git", rev = "cb580c214bb2314fc1f633a3812782c9b3a1d956" }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html>
<body>
<h1>web</h1>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "web", "private": true }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "app-root-auto-select", "private": true, "workspaces": ["apps/*", "packages/*"] }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "ui", "private": true, "type": "module", "main": "src/index.ts" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function hello(name: string): string {
return `hello ${name}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[[case]]
name = "auto_select"
vp = ["local", "global"]
comment = """
With exactly one likely-runnable package, a bare app command in an interactive
terminal auto-selects it, prints the Selected/Tip teaching lines, and runs
there (rfcs/cwd-flag.md). This TTY-only branch was untestable in the legacy
snap runner.
"""
steps = [["vp", "build"]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# auto_select

With exactly one likely-runnable package, a bare app command in an interactive
terminal auto-selects it, prints the Selected/Tip teaching lines, and runs
there (rfcs/cwd-flag.md). This TTY-only branch was untestable in the legacy
snap runner.

## `vp build`

```
VITE+ - The Unified Toolchain for the Web

Selected package: web (apps/web)
Tip: run this directly with `vp -C apps/web build`
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB

✓ built in <duration>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# auto_select

With exactly one likely-runnable package, a bare app command in an interactive
terminal auto-selects it, prints the Selected/Tip teaching lines, and runs
there (rfcs/cwd-flag.md). This TTY-only branch was untestable in the legacy
snap runner.

## `vp build`

```
Selected package: web (apps/web)
Tip: run this directly with `vp -C apps/web build`
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB

✓ built in <duration>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html>
<body>
<h1>frontend</h1>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "frontend", "private": true }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "dc-wrapper-config", "private": true }
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineConfig, type UserConfig } from 'vite-plus';

export default defineConfig({
defaultPackage: './frontend',
} satisfies UserConfig);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "missing-default", "private": true }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
defaultPackage: './packages/nope',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "app-root-default-package", "private": true }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "ui", "private": true, "type": "module", "main": "src/index.ts" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function hello(name: string): string {
return `hello ${name}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[[case]]
name = "default_package"
vp = ["local", "global"]
comment = """
defaultPackage in the root config acts as an implicit -C for bare app
commands, including at a root that is not a JS workspace; vp prints a note
line and runs in the configured directory (rfcs/cwd-flag.md).
"""
steps = [
["vp", "pack"],
{ argv = ["vpt", "list-dir", "packages/ui/dist"], comment = "output lands in the configured package" },
]

[[case]]
name = "default_package_missing"
vp = ["local", "global"]
comment = "defaultPackage pointing at a missing directory errors before any workspace lookup."
steps = [{ argv = ["vp", "build"], cwd = "missing" }]

[[case]]
name = "unanalyzable_config_ignored"
vp = ["local", "global"]
comment = """
Regression guard for spread/unanalyzable configs: a config that only parses
as an open map might hide defaultPackage behind the spread, but that must
not fail the command. Bare vp build falls through and runs in place.
"""
# PTY-rendered (not tty = false): non-TTY steps record raw bytes, and the
# raw Windows byte stream of a vite build differs invisibly from macOS; the
# grid rendering normalizes that and is what the assertion needs anyway.
steps = [{ argv = ["vp", "build"], cwd = "spread" }]

[[case]]
name = "default_package_ts_wrapper"
vp = ["local", "global"]
comment = """
Regression: defaultPackage declared through a TypeScript wrapper
(`satisfies UserConfig`, `as const`) is still a static string literal and
must be honored. vp builds ./frontend, not the wrapper root.
"""
steps = [{ argv = ["vp", "build"], cwd = "ts_wrapper" }]

[[case]]
name = "default_package_value_wrapper"
vp = ["local", "global"]
comment = """
Regression: the TypeScript wrapper is on the defaultPackage VALUE
(`'./frontend' as const`), not the config object. Static extraction must
unwrap it too, so vp builds ./frontend rather than erroring that
defaultPackage is not a static string literal.
"""
steps = [{ argv = ["vp", "build"], cwd = "value_wrapper" }]

[[case]]
name = "default_package_define_config_wrapper"
vp = ["local", "global"]
comment = """
defaultPackage inside `defineConfig({ ... } satisfies UserConfig)` is also
honored: the wrapper on the defineConfig argument is unwrapped too.
"""
steps = [{ argv = ["vp", "build"], cwd = "dc_wrapper" }]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# default_package

defaultPackage in the root config acts as an implicit -C for bare app
commands, including at a root that is not a JS workspace; vp prints a note
line and runs in the configured directory (rfcs/cwd-flag.md).

## `vp pack`

```
VITE+ - The Unified Toolchain for the Web

note: vp pack: using ./packages/ui (defaultPackage)
ℹ entry: src/index.ts
ℹ Build start
ℹ dist/index.mjs <size> kB │ gzip: <size> kB
ℹ 1 files, total: <size> kB
✔ Build complete in <duration>
```

## `vpt list-dir packages/ui/dist`

output lands in the configured package

```
index.mjs
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# default_package

defaultPackage in the root config acts as an implicit -C for bare app
commands, including at a root that is not a JS workspace; vp prints a note
line and runs in the configured directory (rfcs/cwd-flag.md).

## `vp pack`

```
note: vp pack: using ./packages/ui (defaultPackage)
ℹ entry: src/index.ts
ℹ Build start
ℹ dist/index.mjs <size> kB │ gzip: <size> kB
ℹ 1 files, total: <size> kB
✔ Build complete in <duration>
```

## `vpt list-dir packages/ui/dist`

output lands in the configured package

```
index.mjs
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# default_package_define_config_wrapper

defaultPackage inside `defineConfig({ ... } satisfies UserConfig)` is also
honored: the wrapper on the defineConfig argument is unwrapped too.

## `cd dc_wrapper && vp build`

```
VITE+ - The Unified Toolchain for the Web
note: vp build: using ./frontend (defaultPackage)
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB
✓ built in <duration>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# default_package_define_config_wrapper

defaultPackage inside `defineConfig({ ... } satisfies UserConfig)` is also
honored: the wrapper on the defineConfig argument is unwrapped too.

## `cd dc_wrapper && vp build`

```
note: vp build: using ./frontend (defaultPackage)
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB
✓ built in <duration>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# default_package_missing

defaultPackage pointing at a missing directory errors before any workspace lookup.

## `cd missing && vp build`

**Exit code:** 1

```
VITE+ - The Unified Toolchain for the Web
error: defaultPackage points to a missing directory: ./packages/nope
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# default_package_missing

defaultPackage pointing at a missing directory errors before any workspace lookup.

## `cd missing && vp build`

**Exit code:** 1

```
error: defaultPackage points to a missing directory: ./packages/nope
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# default_package_ts_wrapper

Regression: defaultPackage declared through a TypeScript wrapper
(`satisfies UserConfig`, `as const`) is still a static string literal and
must be honored. vp builds ./frontend, not the wrapper root.

## `cd ts_wrapper && vp build`

```
VITE+ - The Unified Toolchain for the Web

note: vp build: using ./frontend (defaultPackage)
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB

✓ built in <duration>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# default_package_ts_wrapper

Regression: defaultPackage declared through a TypeScript wrapper
(`satisfies UserConfig`, `as const`) is still a static string literal and
must be honored. vp builds ./frontend, not the wrapper root.

## `cd ts_wrapper && vp build`

```
note: vp build: using ./frontend (defaultPackage)
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB
✓ built in <duration>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# default_package_value_wrapper

Regression: the TypeScript wrapper is on the defaultPackage VALUE
(`'./frontend' as const`), not the config object. Static extraction must
unwrap it too, so vp builds ./frontend rather than erroring that
defaultPackage is not a static string literal.

## `cd value_wrapper && vp build`

```
VITE+ - The Unified Toolchain for the Web

note: vp build: using ./frontend (defaultPackage)
vite <version> building client environment for production...
✓ 2 modules transformed.
computing gzip size...
dist/index.html <size> kB │ gzip: <size> kB

✓ built in <duration>
```
Loading
Loading