pi-spawnkit

Child Pi executable resolver and diagnostics for reliable Pi sub-process launches.

Packages

Package details

extension

Install pi-spawnkit from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-spawnkit
Package
pi-spawnkit
Version
0.2.0
Published
Aug 12, 2026
Downloads
433/mo · 297/wk
Author
eiei114
License
MIT
Types
extension
Size
56.4 KB
Dependencies
0 dependencies · 5 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-spawnkit

Join dotfield.xyz on Discord

CI Publish npm version npm downloads License: MIT Pi package Trusted Publishing

Pi gstack専用 companion. Resolve and smoke-test the right child pi executable before gstack review flows try to spawn it. This package is maintained for gstack running inside Pi. It is not a general shell or process-management tool.

What this is

pi-spawnkit is a companion extension for the Pi + gstack setup. It fixes the child-agent launch path used when gstack runs a Codex review or starts another Pi agent for a review. In those flows, the interactive shell may find pi while the parent Pi process fails with spawn pi ENOENT because pi.cmd or the npm global bin is missing from the child process PATH.

The package resolves the executable, applies a process-local environment patch, and runs a harmless smoke test before the review flow starts. On macOS and Linux, the resolved Pi executable is spawned directly. On Windows, npm .cmd shims are dispatched through ComSpec and Git Bash-style pi shims use bash.exe; the smoke test exercises the same launch path used by the consumer.

Why install it with Pi gstack?

Install pi-spawnkit alongside Pi gstack when you use any of these paths:

  • gstack Codex reviews;
  • gstack reviews delegated to another Pi agent;
  • Agent/Task fallback that launches a child Pi process.

The common failure is spawn pi ENOENT (or a Windows npm-shim launch failure), not a gstack review error. pi-spawnkit owns that executable-resolution boundary; gstack owns the review workflow.

Recommendation: when installing a Pi gstack extension, install pi-spawnkit at the same time.

Status

The /spawnkit:doctor walking skeleton, spawnkit_resolve_pi resolver, and spawn smoke diagnostics are shipped. Session-start process-local env patching and consumer integration notes are also shipped. The session-start patch is intentionally conservative: when high-confidence (or explicit configured) resolution passes smoke, only the current Pi process gets an idempotent PATH prepend, PI_BIN, and PI_SPAWNKIT_RESOLVED=1.

Install

Install from npm for normal consumer use:

pi install npm:pi-spawnkit

Install from GitHub when testing an unreleased branch:

pi install git:github.com/eiei114/pi-spawnkit

For local development, load the checkout for the current run without changing global settings:

git clone https://github.com/eiei114/pi-spawnkit
cd pi-spawnkit
npm install
pi -e .

If you intentionally want a local package entry, install the path explicitly. Use -l only when you want to write project-local .pi/settings.json; otherwise Pi writes the user settings file.

pi install ./path/to/pi-spawnkit
pi install -l ./path/to/pi-spawnkit

Doctor command

Run /spawnkit:doctor inside Pi after loading the package to print platform, PATH entry count, process.execPath, PI_BIN, resolver candidates, the selected SpawnPlan, session env patch status, smoke status, bounded stdout/stderr snippets, version text when available, and warnings. Use /spawnkit:doctor --json for structured diagnostics. Missing candidates are diagnostics warnings rather than hard failures.

Example summary:

spawnkit doctor
platform: win32
PATH entries: 42
PI_BIN: <unset>
selected SpawnPlan:
  command: C:\Users\alice\AppData\Roaming\npm\pi.cmd
  argsPrefix: []
  confidence: high
  envPatch: PI_BIN, Path
spawn smoke:
  status: ok
  args: ["--version"]
  version: 0.83.0
warnings:
  - none

If smoke is not ok, copy the selected SpawnPlan, smoke status, and warnings into the consuming package issue before falling back to ambient pi PATH lookup.

Session-start env patch

On session_start, the extension resolves and smoke-tests the child Pi executable. It mutates only the current process process.env, and only when resolver confidence is high (or explicit configured) and smoke status is ok. Set PI_SPAWNKIT_SESSION_PATCH=0 or PI_SPAWNKIT_DISABLE_SESSION_PATCH=1 before starting Pi to opt out.

SpawnPlan contract

spawnkit_resolve_pi returns a child-launch SpawnPlan:

{
  command: string;
  argsPrefix: string[];
  envPatch: Record<string, string>;
  confidence: "configured" | "high" | "medium" | "missing";
  warnings: string[];
}

Resolution prefers configured overrides in this order: override, explicit piBin, environment PI_BIN, then package setting. A Windows bare PI_BIN=pi is resolved against npm global bins and PATH before it is used, so a stale shell command does not mask the usable pi.cmd shim. If no configured value is present, the resolver checks process/npm hints, npm global bin candidates, and PATH lookup. On Windows, pi.cmd and pi.exe are preferred over bare pi when multiple candidates are plausible.

Consumer responsibilities:

  • launch with spawnWithSpawnPlan(plan, args, options), not hard-coded spawn("pi", args);
  • merge plan.envPatch over the parent environment for the child process;
  • run runSpawnSmokeTest(plan) before starting a long-lived child;
  • treat confidence: "missing" and any smoke failure as diagnostics to surface, not as a reason to silently retry ambient PATH lookup.

gstack integration

The gstack integration can import the helpers from the package and pass its own package setting as a lower-priority fallback. Per-call override, explicit piBin, and environment PI_BIN still win over packageSetting.

import { runSpawnSmokeTest, spawnWithSpawnPlan, spawnkit_resolve_pi } from "pi-spawnkit/extensions/index.ts";

export async function launchChildPi(args: string[], packageSetting?: string) {
  const plan = await spawnkit_resolve_pi({ packageSetting });

  if (plan.confidence === "missing") {
    throw new Error(`Unable to resolve child pi executable: ${plan.warnings.join("; ")}`);
  }

  const smoke = await runSpawnSmokeTest(plan);
  if (smoke.status !== "ok") {
    throw new Error(`Child pi smoke failed (${smoke.status}): ${smoke.errorMessage ?? smoke.versionText ?? "no detail"}`);
  }

  const childEnv = {
    ...process.env,
    ...plan.envPatch,
  };

  return spawnWithSpawnPlan(plan, args, {
    env: childEnv,
    stdio: "inherit",
    windowsHide: true,
  });
}

spawnWithSpawnPlan is the important part: it keeps macOS/Linux direct execution and applies the Windows shim adapter consistently. The package also registers the spawnkit_resolve_pi tool for agent-side diagnostics. The rendered tool result is human-readable, and details.spawnPlan carries the same SpawnPlan shape for tooling that reads structured details.

gstack launch path: replace spawn("pi", args)

Before:

import { spawn } from "node:child_process";

spawn("pi", args, {
  env: process.env,
  stdio: "inherit",
});

After, using the package launch adapter:

import { runSpawnSmokeTest, spawnWithSpawnPlan, spawnkit_resolve_pi } from "pi-spawnkit/extensions/index.ts";

const plan = await spawnkit_resolve_pi();
const env = { ...process.env, ...plan.envPatch };
const smoke = await runSpawnSmokeTest(plan);

if (smoke.status !== "ok") {
  throw new Error(`Child pi smoke failed: ${smoke.status}`);
}

spawnWithSpawnPlan(plan, args, {
  env,
  stdio: "inherit",
  windowsHide: true,
});

The adapter prepends argsPrefix before consumer args and routes Windows npm shims through the appropriate launcher. Do not reconstruct the command with a shell in each consumer.

gstack review integration

Agent/Task fallback

When falling back from a direct Agent/Task API to a child Pi process, cache the SpawnPlan for the current process and re-run /spawnkit:doctor on failure. If the plan is missing, report the resolver warnings with the fallback error rather than attempting an unbounded shell search.

Windows Git Bash / PowerShell npm shims

Windows npm installs commonly create pi.cmd, sometimes pi.exe, and a bare POSIX-style pi shim. Git Bash and PowerShell may find different shims because their startup files and PATH normalization differ. SpawnKit checks configured overrides, process hints, npm global bins, and PATH entries, then returns a SpawnPlan plus an env patch; consumers should use that plan instead of relying on whichever shell happened to launch the parent Pi.

Dogfood evidence

Local dogfood evidence for this repository is recorded in docs/dogfood.md.

Development

npm install
npm run ci

Boundaries and non-goals

  • SpawnKit is maintained for child pi process resolution in Pi gstack review flows.
  • It is not a general-purpose process manager or standalone gstack replacement.
  • It is not a generic shell execution wrapper; use pi-winshell for arbitrary command execution, shell-specific quoting, argv, stdin, or profile behavior.
  • It is not a broad environment probe; use pi-env-probe for one-shot PATH/env diagnostics outside child Pi launch planning.
  • It does not edit shell profiles, registry keys, permanent PATH, npm global installs, or package manager state.
  • It does not publish packages; npm publish, OTP, credentials, and release promotion remain human-owned.

Links

License

MIT