@procedures/shell 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +421 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/command/index.d.ts +18 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.js +17 -0
- package/dist/command/index.js.map +1 -0
- package/dist/command/output.d.ts +22 -0
- package/dist/command/output.d.ts.map +1 -0
- package/dist/command/output.js +67 -0
- package/dist/command/output.js.map +1 -0
- package/dist/command/processes.d.ts +89 -0
- package/dist/command/processes.d.ts.map +1 -0
- package/dist/command/processes.js +223 -0
- package/dist/command/processes.js.map +1 -0
- package/dist/command/run.d.ts +48 -0
- package/dist/command/run.d.ts.map +1 -0
- package/dist/command/run.js +89 -0
- package/dist/command/run.js.map +1 -0
- package/dist/command/spawn.d.ts +26 -0
- package/dist/command/spawn.d.ts.map +1 -0
- package/dist/command/spawn.js +28 -0
- package/dist/command/spawn.js.map +1 -0
- package/dist/command/stream.d.ts +42 -0
- package/dist/command/stream.d.ts.map +1 -0
- package/dist/command/stream.js +158 -0
- package/dist/command/stream.js.map +1 -0
- package/dist/command/tree-kill.d.ts +26 -0
- package/dist/command/tree-kill.d.ts.map +1 -0
- package/dist/command/tree-kill.js +122 -0
- package/dist/command/tree-kill.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +13 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +79 -0
- package/dist/module.js.map +1 -0
- package/dist/procedures/shell/exec.d.ts +21 -0
- package/dist/procedures/shell/exec.d.ts.map +1 -0
- package/dist/procedures/shell/exec.js +45 -0
- package/dist/procedures/shell/exec.js.map +1 -0
- package/dist/procedures/shell/index.d.ts +5 -0
- package/dist/procedures/shell/index.d.ts.map +1 -0
- package/dist/procedures/shell/index.js +5 -0
- package/dist/procedures/shell/index.js.map +1 -0
- package/dist/procedures/shell/run.d.ts +14 -0
- package/dist/procedures/shell/run.d.ts.map +1 -0
- package/dist/procedures/shell/run.js +40 -0
- package/dist/procedures/shell/run.js.map +1 -0
- package/dist/procedures/shell/stream.d.ts +20 -0
- package/dist/procedures/shell/stream.d.ts.map +1 -0
- package/dist/procedures/shell/stream.js +39 -0
- package/dist/procedures/shell/stream.js.map +1 -0
- package/dist/procedures/shell/which.d.ts +10 -0
- package/dist/procedures/shell/which.d.ts.map +1 -0
- package/dist/procedures/shell/which.js +21 -0
- package/dist/procedures/shell/which.js.map +1 -0
- package/dist/register.d.ts +8 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +14 -0
- package/dist/register.js.map +1 -0
- package/dist/types.d.ts +79 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +89 -0
- package/dist/types.js.map +1 -0
- package/package.json +78 -3
- package/src/command/index.ts +24 -0
- package/src/command/output.ts +67 -0
- package/src/command/processes.ts +271 -0
- package/src/command/run.ts +127 -0
- package/src/command/spawn.ts +44 -0
- package/src/command/stream.ts +186 -0
- package/src/command/tree-kill.ts +121 -0
- package/src/index.ts +53 -0
- package/src/module.ts +102 -0
- package/src/procedures/shell/exec.ts +55 -0
- package/src/procedures/shell/index.ts +4 -0
- package/src/procedures/shell/run.ts +47 -0
- package/src/procedures/shell/stream.ts +43 -0
- package/src/procedures/shell/which.ts +26 -0
- package/src/register.ts +17 -0
- package/src/types.ts +172 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Mark Russell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,422 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @procedures/shell
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@procedures/shell)
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @procedures/shell
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](https://www.typescriptlang.org/)
|
|
11
|
+
[](https://nodejs.org/)
|
|
12
|
+
|
|
13
|
+
> Generic shell command execution procedures - the foundation layer for all CLI wrapper packages in the Mark ecosystem.
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
- [Overview](#overview)
|
|
18
|
+
- [Installation](#installation)
|
|
19
|
+
- [Architecture](#architecture)
|
|
20
|
+
- [Quick Start](#quick-start)
|
|
21
|
+
- [API Reference](#api-reference)
|
|
22
|
+
- [shell.run](#shellrun)
|
|
23
|
+
- [shell.exec](#shellexec)
|
|
24
|
+
- [shell.which](#shellwhich)
|
|
25
|
+
- [Use Cases](#use-cases)
|
|
26
|
+
- [Cross-Platform Notes](#cross-platform-notes)
|
|
27
|
+
- [Integration](#integration)
|
|
28
|
+
- [Requirements](#requirements)
|
|
29
|
+
- [License](#license)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Overview
|
|
34
|
+
|
|
35
|
+
**client-shell** provides low-level shell command execution as RPC procedures:
|
|
36
|
+
|
|
37
|
+
- **shell.run** - Spawn processes with arguments (no shell interpretation, safer)
|
|
38
|
+
- **shell.exec** - Execute command strings via shell (supports pipes, redirects)
|
|
39
|
+
- **shell.which** - Find command paths cross-platform
|
|
40
|
+
- **shell.stream** - Run a command with arguments, and give each output line while it runs
|
|
41
|
+
|
|
42
|
+
This package is the **foundation** for all CLI wrapper packages.
|
|
43
|
+
|
|
44
|
+
### Command helpers
|
|
45
|
+
|
|
46
|
+
The wrapper packages start their programs with the helpers of `@procedures/shell/command`. This entry point registers no procedures.
|
|
47
|
+
|
|
48
|
+
| Helper | What it does |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `runCommand(command, options)` | It runs a program to its end and gives `exitCode`, `stdout`, `stderr` and `duration`. It does not throw. |
|
|
51
|
+
| `streamCommand(command, options)` | It gives each output line while the program runs, then an `exit` item. |
|
|
52
|
+
| `processes` | It records a long-running program: `start`, `list`, `waitFor`, `output`, `stop`. |
|
|
53
|
+
| `killTree(child)` | It kills a child process and all the processes that it started. |
|
|
54
|
+
|
|
55
|
+
The rules of the helpers:
|
|
56
|
+
|
|
57
|
+
- A helper passes the arguments as a list. No shell reads them.
|
|
58
|
+
- The `timeout` and the `signal` kill the whole process tree. Windows uses `taskkill /T /F`. The other systems use a process group.
|
|
59
|
+
- Each output stream has a limit (`maxOutputBytes`, 64 MiB by default). The helper keeps the first bytes, or the last bytes with `keep: "tail"`.
|
|
60
|
+
- A program without an `input` gets an empty stdin.
|
|
61
|
+
- When the reader of `streamCommand` is slow, the helper stops reading the pipes, so the program waits.
|
|
62
|
+
- When the host ends, the helpers kill each child that still runs.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { runCommand } from "@procedures/shell/command";
|
|
66
|
+
|
|
67
|
+
const result = await runCommand("git", { args: ["status", "--porcelain"], cwd, signal: ctx.signal });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install github:mark1russell7/client-shell#main
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Architecture
|
|
81
|
+
|
|
82
|
+
### System Overview
|
|
83
|
+
|
|
84
|
+
```mermaid
|
|
85
|
+
graph TB
|
|
86
|
+
subgraph "Application Layer"
|
|
87
|
+
App[Your Application]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
subgraph "client-shell"
|
|
91
|
+
Run[shell.run<br/>Spawn with args]
|
|
92
|
+
Exec[shell.exec<br/>Shell string]
|
|
93
|
+
Which[shell.which<br/>Find command]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
subgraph "Node.js"
|
|
97
|
+
Spawn[child_process.spawn]
|
|
98
|
+
ExecFn[child_process.exec]
|
|
99
|
+
WhichFn[which / where]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
subgraph "Output"
|
|
103
|
+
Result[exitCode, stdout, stderr,<br/>success, duration]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
App --> Run
|
|
107
|
+
App --> Exec
|
|
108
|
+
App --> Which
|
|
109
|
+
Run --> Spawn
|
|
110
|
+
Exec --> ExecFn
|
|
111
|
+
Which --> WhichFn
|
|
112
|
+
Spawn --> Result
|
|
113
|
+
ExecFn --> Result
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Command Execution Flow
|
|
117
|
+
|
|
118
|
+
```mermaid
|
|
119
|
+
sequenceDiagram
|
|
120
|
+
participant App as Application
|
|
121
|
+
participant Shell as client-shell
|
|
122
|
+
participant Node as Node.js
|
|
123
|
+
participant OS as Operating System
|
|
124
|
+
|
|
125
|
+
App->>Shell: shell.run({ command: "git", args: ["status"] })
|
|
126
|
+
Shell->>Shell: Validate input
|
|
127
|
+
Shell->>Node: spawn("git", ["status"], options)
|
|
128
|
+
Node->>OS: Execute process
|
|
129
|
+
OS-->>Node: stdout, stderr, exitCode
|
|
130
|
+
Node-->>Shell: Process result
|
|
131
|
+
Shell->>Shell: Build output
|
|
132
|
+
Shell-->>App: { success, stdout, stderr, exitCode, duration }
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Dependency Tree
|
|
136
|
+
|
|
137
|
+
```mermaid
|
|
138
|
+
graph TB
|
|
139
|
+
subgraph "CLI Wrapper Packages"
|
|
140
|
+
CLI[client-cli]
|
|
141
|
+
Pnpm[client-pnpm]
|
|
142
|
+
Git[client-git]
|
|
143
|
+
Docker[client-docker]
|
|
144
|
+
Vitest[client-vitest]
|
|
145
|
+
Cue[client-cue]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
subgraph "Foundation"
|
|
149
|
+
Shell[client-shell]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
subgraph "Core"
|
|
153
|
+
Client[client]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
CLI --> Shell
|
|
157
|
+
Pnpm --> Shell
|
|
158
|
+
Git --> Shell
|
|
159
|
+
Docker --> Shell
|
|
160
|
+
Vitest --> Shell
|
|
161
|
+
Cue --> Shell
|
|
162
|
+
Shell --> Client
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Quick Start
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { Client, LocalTransport, PROCEDURE_REGISTRY } from "@procedures/client";
|
|
171
|
+
import "@procedures/shell"; // registers its procedures // Auto-registers procedures
|
|
172
|
+
|
|
173
|
+
const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
|
|
174
|
+
|
|
175
|
+
// Run a command with arguments
|
|
176
|
+
const result = await client.exec(["shell", "run"], {
|
|
177
|
+
command: "git",
|
|
178
|
+
args: ["status", "--short"],
|
|
179
|
+
cwd: "/path/to/repo",
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
console.log(result.stdout);
|
|
183
|
+
// M src/index.ts
|
|
184
|
+
// ?? new-file.ts
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## API Reference
|
|
190
|
+
|
|
191
|
+
### Procedures Summary
|
|
192
|
+
|
|
193
|
+
| Path | Description |
|
|
194
|
+
|------|-------------|
|
|
195
|
+
| `shell.run` | Spawn process with arguments (no shell) |
|
|
196
|
+
| `shell.exec` | Execute command string through shell |
|
|
197
|
+
| `shell.which` | Find full path to a command |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### shell.run
|
|
202
|
+
|
|
203
|
+
Spawn a process directly without shell interpretation. **Safer for untrusted input.**
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
interface ShellRunInput {
|
|
207
|
+
command: string; // Command to run
|
|
208
|
+
args?: string[]; // Arguments (default: [])
|
|
209
|
+
cwd?: string; // Working directory
|
|
210
|
+
env?: Record<string, string>; // Environment variables
|
|
211
|
+
timeout?: number; // Timeout in ms
|
|
212
|
+
encoding?: string; // Output encoding (default: "utf8")
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
interface ShellRunOutput {
|
|
216
|
+
exitCode: number;
|
|
217
|
+
stdout: string;
|
|
218
|
+
stderr: string;
|
|
219
|
+
success: boolean; // true if exitCode === 0
|
|
220
|
+
duration: number; // ms
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Example:**
|
|
225
|
+
```typescript
|
|
226
|
+
await client.exec(["shell", "run"], {
|
|
227
|
+
command: "npm",
|
|
228
|
+
args: ["install", "--save-dev", "typescript"],
|
|
229
|
+
cwd: "/my/project",
|
|
230
|
+
timeout: 60000,
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### shell.exec
|
|
237
|
+
|
|
238
|
+
Execute a command string through the system shell. Supports pipes, redirects, etc.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
interface ShellExecInput {
|
|
242
|
+
command: string; // Full command string
|
|
243
|
+
cwd?: string; // Working directory
|
|
244
|
+
env?: Record<string, string>; // Environment variables
|
|
245
|
+
timeout?: number; // Timeout in ms
|
|
246
|
+
shell?: boolean | string; // Shell to use (default: true)
|
|
247
|
+
maxBuffer?: number; // Max stdout/stderr buffer
|
|
248
|
+
stdin?: string; // Input to pipe to stdin
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
interface ShellExecOutput {
|
|
252
|
+
exitCode: number;
|
|
253
|
+
stdout: string;
|
|
254
|
+
stderr: string;
|
|
255
|
+
success: boolean;
|
|
256
|
+
duration: number;
|
|
257
|
+
signal?: string; // Signal that terminated process
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Example:**
|
|
262
|
+
```typescript
|
|
263
|
+
await client.exec(["shell", "exec"], {
|
|
264
|
+
command: "git log --oneline | head -5",
|
|
265
|
+
cwd: "/my/repo",
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
### shell.which
|
|
272
|
+
|
|
273
|
+
Find the full path to a command. Uses `where` on Windows, `which` on Unix.
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
interface ShellWhichInput {
|
|
277
|
+
command: string; // Command to find
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
interface ShellWhichOutput {
|
|
281
|
+
path: string | null; // Full path or null if not found
|
|
282
|
+
found: boolean;
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Example:**
|
|
287
|
+
```typescript
|
|
288
|
+
const { path, found } = await client.exec(["shell", "which"], {
|
|
289
|
+
command: "node",
|
|
290
|
+
});
|
|
291
|
+
// { path: "/usr/local/bin/node", found: true }
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Use Cases
|
|
297
|
+
|
|
298
|
+
### Building CLI Wrappers
|
|
299
|
+
|
|
300
|
+
The `shell.run` procedure is the foundation for CLI wrapper packages:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
// In client-git/src/procedures/git/status.ts
|
|
304
|
+
export async function gitStatus(input: GitStatusInput, ctx: ProcedureContext) {
|
|
305
|
+
const args = ["status"];
|
|
306
|
+
if (input.short) args.push("--short");
|
|
307
|
+
|
|
308
|
+
const result = await ctx.client.call(["shell", "run"], {
|
|
309
|
+
command: "git",
|
|
310
|
+
args,
|
|
311
|
+
cwd: input.cwd,
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
return parseGitStatus(result.stdout);
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Checking Command Availability
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
async function ensureGitAvailable() {
|
|
322
|
+
const { found } = await client.exec(["shell", "which"], { command: "git" });
|
|
323
|
+
if (!found) {
|
|
324
|
+
throw new Error("Git is not installed or not in PATH");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Piping Commands
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// Using shell.exec for pipes
|
|
333
|
+
const result = await client.exec(["shell", "exec"], {
|
|
334
|
+
command: "cat package.json | jq '.dependencies'",
|
|
335
|
+
cwd: "/my/project",
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Cross-Platform Notes
|
|
342
|
+
|
|
343
|
+
### shell.which Behavior
|
|
344
|
+
|
|
345
|
+
```mermaid
|
|
346
|
+
graph LR
|
|
347
|
+
subgraph "Unix/macOS"
|
|
348
|
+
UnixWhich["which command"]
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
subgraph "Windows"
|
|
352
|
+
WinWhere["where command"]
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
subgraph "Result"
|
|
356
|
+
Path["/usr/bin/git<br/>or C:\\Program Files\\Git\\bin\\git.exe"]
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
UnixWhich --> Path
|
|
360
|
+
WinWhere --> Path
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### shell.run vs shell.exec
|
|
364
|
+
|
|
365
|
+
| Feature | shell.run | shell.exec |
|
|
366
|
+
|---------|-----------|------------|
|
|
367
|
+
| Shell interpretation | No | Yes |
|
|
368
|
+
| Pipes & redirects | No | Yes |
|
|
369
|
+
| Argument safety | Safer | Less safe |
|
|
370
|
+
| Use case | Known commands | Shell scripts |
|
|
371
|
+
| Platform quoting | Handled | Manual |
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Integration
|
|
376
|
+
|
|
377
|
+
### With Other Packages
|
|
378
|
+
|
|
379
|
+
```mermaid
|
|
380
|
+
graph TB
|
|
381
|
+
subgraph "High-Level"
|
|
382
|
+
Lib[client-lib<br/>lib.refresh]
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
subgraph "Mid-Level"
|
|
386
|
+
Git[client-git<br/>git.commit]
|
|
387
|
+
Pnpm[client-pnpm<br/>pnpm.install]
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
subgraph "Foundation"
|
|
391
|
+
Shell[client-shell<br/>shell.run]
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
Lib --> Git
|
|
395
|
+
Lib --> Pnpm
|
|
396
|
+
Git --> Shell
|
|
397
|
+
Pnpm --> Shell
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### With MCP (Claude)
|
|
401
|
+
|
|
402
|
+
When using the MCP server with bundle-dev, Claude has access to shell.* procedures:
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
User: "Run npm install in /my/project"
|
|
406
|
+
Claude: [Uses shell.run with command: "npm", args: ["install"]]
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Requirements
|
|
412
|
+
|
|
413
|
+
- **Node.js** >= 22
|
|
414
|
+
- **Dependencies:**
|
|
415
|
+
- `@procedures/client` (peer dependency)
|
|
416
|
+
- `zod` ^3.24.0
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## License
|
|
421
|
+
|
|
422
|
+
MIT
|