strapkit
API Reference

Processes

Run commands and capture stdout, stderr, and exit code.

Strapkit gives you two ways to run commands:

  • sk.exec(script, opts?) — run a script, capture { stdout, stderr, exitCode }.
  • sk.shellExec(command) — fire-and-forget into the interactive terminal.

sk.exec(script, opts?)

exec(
  script: string,
  opts?: {
    env?: Record<string, string>;
    cwd?: string;
    stdin?: string;
    args?: string[];
    terminal?: Terminal;
    onStdout?: (text: string) => void;
    onStderr?: (text: string) => void;
  },
): Promise<{ stdout: string; stderr: string; exitCode: number }>

Runs script as a shell snippet. Returns the captured stdout, stderr, and the exit code of the last command in the script.

const result = await sk.exec('echo hello');
console.log(result.stdout);   // "hello\n"
console.log(result.exitCode);  // 0

Multi-line scripts work the same way, including pipes and chains:

await sk.exec(`
  cd /app
  echo "{ \\"name\\": \\"demo\\" }" > package.json
  cat package.json | grep name
`);

opts.env

Environment variables for this call only:

await sk.exec('echo $NODE_ENV', { env: { NODE_ENV: 'production' } });

opts.cwd

Working directory for this call:

await sk.exec('npm install', { cwd: '/app' });

opts.stdin (alias: opts.input)

Feed text to the script's stdin:

const { stdout } = await sk.exec('grep TODO', {
  stdin: 'one\nTODO: two\nthree\n',
});

input is accepted as an alias for stdin. When both are present, stdin wins.

opts.args

Additional argv appended to the script, shell-quoted automatically. Use this when arguments come from user input — no escaping needed:

const search = document.querySelector('#search').value;
const { stdout } = await sk.exec('grep', {
  args: ['-r', search, '/app/src'],
});

opts.terminal

Mirror output live into an xterm.js Terminal as it streams in. The terminal gets raw bytes (with ANSI colors and spinner animations); the captured stdout/stderr are ANSI-stripped.

await sk.exec('npm install', { terminal: term });

opts.onStdout / opts.onStderr

Per-chunk callbacks for streaming output. Called with raw bytes (ANSI included), same as what terminal receives.

await sk.exec('npm install', {
  onStdout: (chunk) => console.log(chunk),
});

Calls run one at a time

exec calls are queued — a second call waits for the first to finish. This is by design: the runtime has a small pool of child slots that can be exhausted by big commands (npx create-next-app uses all of them while it works).

If you want to run commands in parallel, run them as one script with & and wait:

await sk.exec(`
  long-task-1 &
  long-task-2 &
  wait
`);

Limitations

  • Long-running servers block. exec("node server.js") won't resolve until the server exits. For servers, use shellExec and watch onPortOpen.
  • Each call starts fresh. A cd inside one exec doesn't carry over to the next (unless you use opts.cwd). Put related commands in the same script if you need shared state.

sk.shellExec(command)

shellExec(command: string): void

Type command into the running shell, followed by a newline — exactly as if the user had pressed enter at the prompt. Output goes to the xterm.js terminal (or wherever the shell's output is wired); nothing is returned. Throws if no shell is running.

This is the right tool for long-running or interactive flows: starting a dev server, running a TUI, or wiring a "run this" button in your UI.

sk.shellExec('npm run dev');

For everything else, prefer exec — you get the output back as a value instead of having to scrape it from the terminal.

On this page