原始内容
pi-bash-timeout
⏱️ Wraps pi's built-in bash tool with a 120-second default timeout.
The native bash tool has no default timeout — a hanging command blocks the agent forever. This extension injects timeout: 120 whenever the model omits the timeout parameter, while preserving the stock bash renderer ($ command + Took X.Xs) and delegating execution to pi's own bash implementation.
Install
Stable npm release:
pi install npm:@cad0p/pi-bash-timeout
Pre-release npm snapshots from main are published with the next dist-tag:
pi install npm:@cad0p/pi-bash-timeout@next
You can also install directly from the git source when testing unreleased branches:
pi install git:github.com/cad0p/pi-bash-timeout
What it does
| Scenario | Behavior |
|---|---|
Model omits timeout |
Uses 120s default |
Model passes explicit timeout |
Uses that timeout (explicit always wins) |
| Command exceeds timeout | Killed, shows Command timed out after N seconds |
The extension re-registers the bash tool by name (extension tools win over built-ins of the same name in pi's tool registry). It spreads the built-in ToolDefinition from createBashToolDefinition() and overrides only execute — so description, promptSnippet, parameters, renderCall, and renderResult all stay the stock built-in values. The TUI looks identical to the native bash tool.
A short (default timeout: 120s when omitted) note is appended to the description so the LLM knows the fallback when it omits the parameter.
How it works
const builtinBash = createBashToolDefinition(process.cwd());
pi.registerTool({
...builtinBash,
name: "bash",
description: `${builtinBash.description} (default timeout: ${DEFAULT_TIMEOUT_SECONDS}s when omitted)`,
async execute(toolCallId, params, signal, onUpdate, ctx) {
const effectiveParams = {
...params,
timeout: params.timeout ?? DEFAULT_TIMEOUT_SECONDS,
};
const bashTool = createBashToolDefinition(ctx.cwd);
return bashTool.execute(toolCallId, effectiveParams, signal, onUpdate, ctx);
},
});
Key points:
createBashToolDefinition()returns the fullToolDefinitionpi uses internally, including the renderers that produce the stock bash UI.- Spreading it and overriding only
executekeeps every other field the built-in default. ctx.cwdscopes execution to the correct project directory regardless of where pi was launched.ToolDefinition.executetakes 5 params (includingctx), unlikeAgentTool.executewhich takes 4 — we passctxthrough.
Requirements
- pi 0.74+ with at least one model provider configured.
- Peer dependencies (the source of truth is
package.jsonpeerDependencies):@earendil-works/pi-coding-agent >=0.74.0typebox ^1.0.0(used to declare the tool's parameter schema; bundled with pi but listed explicitly so a standalone install resolves correctly).
Configuration
The default timeout is hardcoded to 120 seconds. To change it, edit DEFAULT_TIMEOUT_SECONDS in extensions/pi-bash-timeout/index.ts and rebuild/reinstall.
Publishing
This repo uses cad0p/semver-calver-release's npm-package workflow:
- Pushes to
maincompute the next hybrid SemVer + CalVer version, tag a GitHub prerelease, and publish to npm with thenextdist-tag. - Curated release PRs from
release/from-v*branches bump the basepackage.jsonversion and publish stable npm releases. - npm publishing uses GitHub OIDC / npm trusted publishing via
.github/workflows/release.yml(id-token: write) andpublishConfig.access: public.
One-time: enable npm trusted publishing
Before the first npm publish from CI can succeed, the package must be linked to the GitHub workflow as a trusted publisher. This requires npm ≥ 11.15.0 and 2FA enabled on the account (granular tokens with bypass-2FA are not supported):
npm install -g npm@^11.15.0 # if older
npm trust github @cad0p/pi-bash-timeout --file release.yml --repository cad0p/pi-bash-timeout --allow-publish --yes
After this, every push to main publishes a calver snapshot to npm with the next dist-tag, and curated release/from-v* PRs publish stable releases. This is already configured — verify with npm trust list @cad0p/pi-bash-timeout.
License
MIT © Pier Carlo Cadoppi