Skip to content

Commit 3767efa

Browse files
branchseerclaude
andcommitted
docs: add stdio plan for --log flag
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4a5c9bc commit 3767efa

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

docs/stdio.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Task Standard I/O
2+
3+
How stdin, stdout, and stderr are connected to task processes, controlled by the `--log` flag.
4+
5+
## The `--log` Flag
6+
7+
```
8+
vp run build --log=<mode>
9+
```
10+
11+
| Mode | Description |
12+
| --------------------------- | ----------------------------------------------------------------------------- |
13+
| `interleaved` **(default)** | Output streams directly to the terminal as tasks produce it. |
14+
| `labeled` | Each line is prefixed with `[packageName#taskName]`. |
15+
| `grouped` | Output is buffered per task and printed as a block after each task completes. |
16+
17+
### Examples
18+
19+
#### `interleaved`
20+
21+
Output goes to the terminal as soon as it's produced. When running multiple tasks in parallel, lines from different tasks may intermix:
22+
23+
```
24+
~/packages/app$ vp dev
25+
~/packages/docs$ vp dev
26+
VITE v6.0.0 ready in 200 ms
27+
28+
➜ Local: http://localhost:5173/
29+
VITE v6.0.0 ready in 150 ms
30+
31+
➜ Local: http://localhost:5174/
32+
```
33+
34+
#### `labeled`
35+
36+
Each line of stdout and stderr is prefixed with the task identifier. Output is still streamed as it arrives (not buffered):
37+
38+
```
39+
[app#dev] ~/packages/app$ vp dev
40+
[docs#dev] ~/packages/docs$ vp dev
41+
[app#dev] VITE v6.0.0 ready in 200 ms
42+
[app#dev]
43+
[app#dev] ➜ Local: http://localhost:5173/
44+
[docs#dev] VITE v6.0.0 ready in 150 ms
45+
[docs#dev]
46+
[docs#dev] ➜ Local: http://localhost:5174/
47+
```
48+
49+
#### `grouped`
50+
51+
All output (stdout and stderr) for each task is buffered and printed as a single block when the task completes. Nothing is shown for a task until it finishes:
52+
53+
```
54+
[app#dev] ~/packages/app$ vp dev
55+
[docs#dev] ~/packages/docs$ vp dev
56+
── app#dev ──
57+
VITE v6.0.0 ready in 200 ms
58+
59+
➜ Local: http://localhost:5173/
60+
61+
── docs#dev ──
62+
VITE v6.0.0 ready in 150 ms
63+
64+
➜ Local: http://localhost:5174/
65+
```
66+
67+
## stdio by Mode
68+
69+
| Mode | stdin | stdout | stderr |
70+
| ------------------------ | ----------- | ---------------------------- | ---------------------------- |
71+
| `interleaved`, cache on | `/dev/null` | Piped (streamed + collected) | Piped (streamed + collected) |
72+
| `interleaved`, cache off | Inherited | Inherited | Inherited |
73+
| `labeled` | `/dev/null` | Piped (prefixed + collected) | Piped (prefixed + collected) |
74+
| `grouped` | `/dev/null` | Piped (buffered + collected) | Piped (buffered + collected) |
75+
76+
### Key Rules
77+
78+
1. **stdin is `/dev/null` except for uncached tasks in `interleaved` mode.** Cached tasks must have deterministic behavior — inheriting stdin would make output dependent on interactive input, breaking cache correctness. Uncached `interleaved` tasks inherit stdin, allowing interactive prompts.
79+
80+
2. **stdout and stderr are piped (collected) when caching is enabled.** The collected output is stored in the cache and replayed on cache hits. In `interleaved` mode, output is still streamed to the terminal as it arrives — piping is transparent to the user. Uncached `interleaved` tasks inherit stdout/stderr directly.
81+
82+
3. **stderr follows the same rules as stdout in all modes.** Unlike npm-run-all2 where `--aggregate-output` only groups stdout while inheriting stderr, `grouped` mode buffers both stdout and stderr, keeping a task's error output together with its regular output.
83+
84+
## Cache Replay
85+
86+
When a cached task is replayed, its stored stdout and stderr are written to the terminal using the same formatting rules as the current `--log` mode. For example, a task cached in `interleaved` mode can be replayed in `labeled` mode and will receive the appropriate prefix.
87+
88+
## Appendix: npm-run-all2 Behavior
89+
90+
For reference, npm-run-all2 controls stdio via two independent flags:
91+
92+
| Mode | stdin | stdout | stderr |
93+
| -------------------- | --------- | ------------------------------------------ | ------------------------------------ |
94+
| Default | Inherited | Inherited | Inherited |
95+
| `--print-label` | Inherited | Each line prefixed with `[taskName]` | Each line prefixed with `[taskName]` |
96+
| `--aggregate-output` | Inherited | Grouped per task, printed after completion | Inherited (not grouped) |
97+
98+
Notable differences from vite-task:
99+
100+
- **stdin is always inherited.** npm-run-all2 does not have a caching system, so there is no need to prevent interactive input.
101+
- **`--aggregate-output` only groups stdout.** stderr is inherited and streams directly to the terminal, meaning error output from parallel tasks can still intermix. vite-task's `grouped` mode buffers both streams.
102+
- **Two separate flags** (`--print-label`, `--aggregate-output`) instead of a single `--log` enum. The flags are mutually exclusive in practice but this isn't enforced.

0 commit comments

Comments
 (0)