Skip to content

Commit 185e479

Browse files
antfuclaude
andcommitted
docs: add terminals and subprocesses guide
Documents the ctx.terminals API for spawning child processes, streaming output via xterm.js, and managing process lifecycle. Includes launcher dock integration, custom terminal sessions, and a Nuxt DevTools migration comparison. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bfd8da3 commit 185e479

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

docs/.vitepress/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const DevToolsKitNav = [
1515
{ text: 'RPC', link: '/kit/rpc' },
1616
{ text: 'Shared State', link: '/kit/shared-state' },
1717
{ text: 'Logs & Notifications', link: '/kit/logs' },
18+
{ text: 'Terminals & Processes', link: '/kit/terminals' },
1819
{ text: 'Examples', link: '/kit/examples' },
1920
]
2021

@@ -70,6 +71,7 @@ export default extendConfig(withMermaid(defineConfig({
7071
{ text: 'Shared State', link: '/kit/shared-state' },
7172
{ text: 'Logs', link: '/kit/logs' },
7273
{ text: 'JSON Render', link: '/kit/json-render' },
74+
{ text: 'Terminals', link: '/kit/terminals' },
7375
{ text: 'Examples', link: '/kit/examples' },
7476
],
7577
},

docs/kit/terminals.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# Terminals & Subprocesses
6+
7+
DevTools Kit includes a built-in terminal host that lets your plugin spawn and manage child processes. Output is streamed in real-time to an xterm.js UI inside DevTools.
8+
9+
## Starting a Child Process
10+
11+
The primary API is `ctx.terminals.startChildProcess()`:
12+
13+
```ts
14+
const session = await ctx.terminals.startChildProcess(
15+
{
16+
command: 'vite',
17+
args: ['build', '--watch'],
18+
cwd: process.cwd(),
19+
env: { NODE_ENV: 'development' },
20+
},
21+
{
22+
id: 'my-plugin:build-watcher',
23+
title: 'Build Watcher',
24+
icon: 'ph:terminal-duotone',
25+
},
26+
)
27+
```
28+
29+
The first argument describes what to execute:
30+
31+
```ts
32+
interface DevToolsChildProcessExecuteOptions {
33+
command: string
34+
args: string[]
35+
cwd?: string
36+
env?: Record<string, string>
37+
}
38+
```
39+
40+
The second argument provides terminal metadata (id, title, and optional description/icon).
41+
42+
### Returned Session
43+
44+
`startChildProcess()` returns a `DevToolsChildProcessTerminalSession` with lifecycle controls:
45+
46+
```ts
47+
// Terminate the process
48+
await session.terminate()
49+
50+
// Restart (kill + re-spawn)
51+
await session.restart()
52+
53+
// Access the underlying Node.js ChildProcess
54+
const cp = session.getChildProcess()
55+
```
56+
57+
> [!NOTE]
58+
> Color output is enabled automatically — `FORCE_COLOR` and `COLORS` environment variables are set to `'true'` by default.
59+
60+
## Combining with Launcher Docks
61+
62+
A common pattern is pairing a [launcher dock entry](/kit/dock-system#launcher-entries) with a terminal session. The launcher gives the user a button to start the process on demand:
63+
64+
```ts
65+
ctx.docks.register({
66+
id: 'my-plugin:launcher',
67+
title: 'My App',
68+
icon: 'ph:rocket-launch-duotone',
69+
type: 'launcher',
70+
launcher: {
71+
title: 'Start My App',
72+
description: 'Launch the dev server',
73+
onLaunch: async () => {
74+
await ctx.terminals.startChildProcess(
75+
{
76+
command: 'vite',
77+
args: ['dev'],
78+
cwd: process.cwd(),
79+
},
80+
{
81+
id: 'my-plugin:dev-server',
82+
title: 'Dev Server',
83+
},
84+
)
85+
},
86+
},
87+
})
88+
```
89+
90+
## Custom Terminal Sessions
91+
92+
For scenarios that don't involve spawning a child process (e.g. streaming logs from an external source), you can register a session directly with a custom `ReadableStream`:
93+
94+
```ts
95+
let controller: ReadableStreamDefaultController<string>
96+
97+
const stream = new ReadableStream<string>({
98+
start(c) {
99+
controller = c
100+
},
101+
})
102+
103+
ctx.terminals.register({
104+
id: 'my-plugin:custom-stream',
105+
title: 'Custom Output',
106+
status: 'running',
107+
stream,
108+
})
109+
110+
// Push data to the terminal
111+
controller.enqueue('Hello from custom stream!\n')
112+
```
113+
114+
## Session Lifecycle
115+
116+
Each terminal session has a `status` field:
117+
118+
| Status | Description |
119+
|--------|-------------|
120+
| `running` | Process is active and streaming output |
121+
| `stopped` | Process exited normally |
122+
| `error` | Process exited with an error |
123+
124+
Update a session's metadata or status at any time:
125+
126+
```ts
127+
ctx.terminals.update({
128+
id: 'my-plugin:build-watcher',
129+
status: 'stopped',
130+
title: 'Build Watcher (done)',
131+
})
132+
```

0 commit comments

Comments
 (0)