agent-halter

Session-budget extension for AI coding agents.

Package details

extension

Install agent-halter from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:agent-halter
Package
agent-halter
Version
0.0.1
Published
May 5, 2026
Downloads
not available
Author
fgrehm
License
MIT
Types
extension
Size
104.7 KB
Dependencies
0 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./src/adapters/pi/index.ts"
  ]
}

Security note

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

README

agent-halter

A session-budget extension for AI coding agents. Set a wall-clock time, a turn count, or both. The agent gets a soft nudge as the budget approaches and stops responding for the current turn when it runs out. Budget state survives reload.

Today this ships as a pi-coding-agent extension. A Claude Code adapter is planned next; see FUTURE-CLAUDE.md.

Status

v0.0.1: Core logic is fully tested (100% coverage) and has been tested against a few pi sessions. It's also worth noting that some models might simply ignore the "time to wrap up nudges" sent by the extension, something I'm still investigating.

Installation

Option 1: from npm (recommended)

pi install npm:agent-halter

This installs the latest published version from npm. Run pi update to get new versions.

Option 2: from git

pi install git:github.com/fgrehm/agent-halter

This clones the repo to ~/.pi/agent/git/ and adds it to your settings.

For project-local install (stored in .pi/git/):

pi install git:github.com/fgrehm/agent-halter --local

Option 3: -e flag (try without installing)

pi -e npm:agent-halter

Option 4: Clone manually (if you want to make changes and "try it live")

Pi auto-discovers subdirectories under ~/.pi/agent/extensions/:

git clone git@github.com:fgrehm/agent-halter.git ~/.pi/agent/extensions/agent-halter

Usage (pi)

# from inside a pi session
/timebox 15m                            # 15-minute budget
/timebox turns:5                        # 5-turn budget
/timebox 15m turns:3                    # combined; whichever fires first wins
/timebox 15m -- lmk -m "Timebox done"   # also run a shell command on hard stop
/timebox status                         # show remaining budget
/timebox off                            # disable

Anything after -- is the literal command. It runs detached via /bin/sh -c, so quoting, pipes, and env vars work as in your shell. It fires once on hard stop (not on the soft nudge or on /timebox off). lmk is a good fit since it pops a blocking desktop dialog. For tests / CI you can neutralize lmk with LMK_DRY_RUN=1.

While active, a status-bar entry under the timebox key updates every second:

Timebox: 12m 34s left (15m budget) | 3 turns left (2/5)

At 80% of either dimension the user gets a one-shot warning notification, and every subsequent agent turn has a budget-warning block appended to the system prompt. At 100%, the next agent turn is blocked with an error notification. The chat continues; the user can set a new timebox or keep talking.

For the full behavior contract, see SPEC.md.

Project layout

src/
  core/               host-agnostic logic
    parse.ts          /timebox argument parsing
    decide.ts         budget decisions (ok / nudge / stop)
    format.ts         status string + system-prompt suffix
    persist.ts        record-based restore on reload
    types.ts          shared types
  adapters/
    pi/               pi-coding-agent adapter
      index.ts        default-export factory
      controller.ts   in-memory budget state
      command.ts      /timebox handler
      events.ts       session_start / turn_start / before_agent_start / session_shutdown
      entries.ts      custom session-entry helpers
      status-timer.ts setInterval-based status refresher
tests/
  core/               unit tests for pure helpers
  adapters/pi/        integration tests with a fake ExtensionAPI
SPEC.md               full behavioral spec
FUTURE-CLAUDE.md      Claude Code adapter sketch

Development

npm install
npm test                # vitest
npm run test:coverage   # v8 coverage with thresholds
npm run check           # biome --write + tsc --noEmit
npm run lint            # biome (no writes)

The host runtime, the network, and any LLM provider are fully faked. The test suite is hermetic and runs in under a second.

Roadmap

  • pi adapter
  • polish + make it work properly for less capable models
  • Claude Code adapter (see FUTURE-CLAUDE.md).

License

MIT. Copyright (c) Fabio Rehm.